Compare commits
No commits in common. "master" and "v0.8.5" have entirely different histories.
4
.gitignore
vendored
4
.gitignore
vendored
@ -2,7 +2,3 @@
|
||||
/.fleet
|
||||
/src/dist/bundle.min.js
|
||||
/src/dist/bundle.js
|
||||
/dist
|
||||
auto-imports.d.ts
|
||||
components.d.ts
|
||||
aws.xml
|
||||
6
.idea/jsLibraryMappings.xml
generated
Normal file
6
.idea/jsLibraryMappings.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="JavaScriptLibraryMappings">
|
||||
<file url="file://$PROJECT_DIR$" libraries="{Node.js Core}" />
|
||||
</component>
|
||||
</project>
|
||||
14
.vscode/launch.json
vendored
14
.vscode/launch.json
vendored
@ -1,14 +0,0 @@
|
||||
{
|
||||
// 使用 IntelliSense 了解相关属性。
|
||||
// 悬停以查看现有属性的描述。
|
||||
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"command": "npm run rollup",
|
||||
"name": "rollup",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
}
|
||||
]
|
||||
}
|
||||
356
CHANGELOG.md
356
CHANGELOG.md
@ -1,357 +1,9 @@
|
||||
# TODO
|
||||
|
||||
- 翻译:baza npc商店、imarket、imarket搜索结果
|
||||
|
||||
# CHANGE
|
||||
|
||||
## 1.2.4
|
||||
|
||||
2025年04月07日
|
||||
|
||||
### 修改
|
||||
|
||||
- 优化起飞功能错误处理
|
||||
- 取消网络拦截,避免官方功能被影响
|
||||
|
||||
## 1.2.3
|
||||
|
||||
2025年03月11日
|
||||
|
||||
### 修改
|
||||
|
||||
- 删除GS Load模块代码
|
||||
- 删除翻译
|
||||
- 删除去Google化部分代码
|
||||
- 修复起飞逻辑
|
||||
- 修复通知
|
||||
|
||||
## 1.2.2
|
||||
|
||||
2024年04月07日
|
||||
|
||||
### 修改
|
||||
|
||||
- 快捷动作【REFILL】修复
|
||||
|
||||
## 1.2.1
|
||||
|
||||
2024年04月03日
|
||||
|
||||
### 修改
|
||||
|
||||
- 快捷动作【REFILL】修复
|
||||
|
||||
## 1.2.0
|
||||
|
||||
2024年03月29日
|
||||
|
||||
### 修改
|
||||
|
||||
- BS估算缓存机制修复
|
||||
- 快捷功能【快速犯罪】界面优化
|
||||
|
||||
## 1.1.9
|
||||
|
||||
2024年03月27日
|
||||
|
||||
### 添加
|
||||
|
||||
- 引入了BS估算功能
|
||||
|
||||
### 修改
|
||||
|
||||
- 快捷功能【快速犯罪】去除了烦人的通知
|
||||
|
||||
## 1.1.8
|
||||
|
||||
2024年03月20日
|
||||
|
||||
### 修改
|
||||
|
||||
- 快捷功能的【喝啤酒】移动至【快速犯罪】中
|
||||
- profile页面中在线状态调整
|
||||
|
||||
## 1.1.7
|
||||
|
||||
2024年03月15日
|
||||
|
||||
### 添加
|
||||
|
||||
- 快捷功能-PI存钱
|
||||
|
||||
### 修改
|
||||
|
||||
- 上次动作的url判断修复
|
||||
- profile页面中添加了更明显的上次动作时间
|
||||
- 快速取钱功能添加了常用输入
|
||||
|
||||
## 1.1.6
|
||||
|
||||
2024年01月08日
|
||||
|
||||
### 修改
|
||||
|
||||
- refill功能改为菜单式,新增支持3种refil
|
||||
- 快速犯罪功能现已支持全部种类
|
||||
|
||||
## 1.1.5
|
||||
|
||||
2023年12月22日
|
||||
|
||||
### 修改
|
||||
|
||||
- 圣诞小镇掉落物记录表格中的undefined错误修复
|
||||
|
||||
## 1.1.4
|
||||
|
||||
2023年12月08日
|
||||
|
||||
### 修改
|
||||
|
||||
- 快速犯罪中添加了15-3
|
||||
|
||||
## 1.1.3
|
||||
|
||||
2023年11月29日
|
||||
|
||||
### 修改
|
||||
|
||||
- 通知浏览错误修复
|
||||
|
||||
## 1.1.2
|
||||
|
||||
2023年09月19日
|
||||
|
||||
### 修改
|
||||
|
||||
- 火车提醒错误修复
|
||||
- 光速刷新错误修复
|
||||
|
||||
## 1.1.1
|
||||
|
||||
2023年09月13日
|
||||
|
||||
### 修改
|
||||
|
||||
- 调整了上次动作的显示逻辑
|
||||
- 更准确的现金变动提醒
|
||||
|
||||
### 添加
|
||||
|
||||
- 监控模块-毒CD提醒
|
||||
|
||||
## 1.1.0
|
||||
|
||||
2023年09月11日
|
||||
|
||||
### 修改
|
||||
|
||||
- 更正上次动作的匹配路径、添加了毒和糖 CD 的提示
|
||||
|
||||
## 1.0.9
|
||||
|
||||
2023年09月08日
|
||||
|
||||
### 修改
|
||||
|
||||
- 侧边菜单UI优化
|
||||
|
||||
## 1.0.8
|
||||
|
||||
2023年08月23日
|
||||
|
||||
### 修改
|
||||
|
||||
- 通知浏览修复
|
||||
|
||||
## 1.0.7
|
||||
|
||||
2023年06月27日
|
||||
|
||||
### 修改
|
||||
|
||||
- 物品功能补充完善
|
||||
- 菜单顺序调整
|
||||
|
||||
## 1.0.6
|
||||
|
||||
2023年06月26日
|
||||
|
||||
### 添加
|
||||
|
||||
- 物品功能标签
|
||||
|
||||
## 1.0.5
|
||||
|
||||
2023年06月19日
|
||||
|
||||
### 修改
|
||||
|
||||
- 移除原菜单
|
||||
- 调整了新菜单的样式、部分逻辑
|
||||
|
||||
## 1.0.4
|
||||
|
||||
2023年06月16日
|
||||
|
||||
### 添加
|
||||
|
||||
- 标签页管理功能
|
||||
|
||||
## 1.0.3
|
||||
|
||||
2023年06月16日
|
||||
|
||||
### 修改
|
||||
|
||||
- 样式错误修复
|
||||
|
||||
## 1.0.2
|
||||
|
||||
2023年06月15日
|
||||
|
||||
### 修改
|
||||
|
||||
- 错误修复
|
||||
- 菜单样式修改
|
||||
|
||||
## 1.0.1
|
||||
|
||||
2023年06月14日
|
||||
|
||||
### 添加
|
||||
|
||||
- 公司存取钱
|
||||
|
||||
## 1.0.0
|
||||
|
||||
2023年06月12日
|
||||
|
||||
### 添加
|
||||
|
||||
- PT购买
|
||||
|
||||
## 0.9.9
|
||||
|
||||
2023年06月07日
|
||||
|
||||
### 修改
|
||||
|
||||
- 购物助手错误修复及样式调整
|
||||
|
||||
## 0.9.8
|
||||
|
||||
2023年06月06日
|
||||
|
||||
### 修改
|
||||
|
||||
- 错误修复
|
||||
|
||||
## 0.9.7
|
||||
|
||||
2023年06月05日
|
||||
|
||||
### 添加
|
||||
|
||||
- bazaar快速开关店
|
||||
- 购物助手
|
||||
|
||||
### 修改
|
||||
|
||||
- 部分样式修改
|
||||
|
||||
## 0.9.6
|
||||
|
||||
2023年06月01日
|
||||
|
||||
### 添加
|
||||
|
||||
- PC病毒快速操作
|
||||
|
||||
## 0.9.5
|
||||
|
||||
2023年05月31日
|
||||
|
||||
### 修改
|
||||
|
||||
- 明文密码简单编码处理
|
||||
- 自动登录前添加确认
|
||||
|
||||
## 0.9.4
|
||||
|
||||
2023年05月31日
|
||||
|
||||
### 添加
|
||||
|
||||
- 自动登陆功能
|
||||
|
||||
## 0.9.3
|
||||
|
||||
2023年05月30日
|
||||
|
||||
### 添加
|
||||
|
||||
- 快速查看地图垃圾
|
||||
|
||||
## 0.9.2
|
||||
|
||||
2023年05月26日
|
||||
|
||||
### 添加
|
||||
|
||||
- 快速浏览通知
|
||||
|
||||
## 0.9.1
|
||||
|
||||
2023年05月04日
|
||||
|
||||
### 添加
|
||||
|
||||
- 新菜单中现在可以快速喝啤酒了
|
||||
- 快速 refill
|
||||
|
||||
## 0.9.0
|
||||
|
||||
2023年04月28日
|
||||
|
||||
### 添加
|
||||
|
||||
- 新菜单中现在可以快速吃XAN了
|
||||
- 快速犯罪
|
||||
|
||||
## 0.8.9
|
||||
|
||||
2023年04月24日
|
||||
|
||||
### 修改
|
||||
|
||||
- 战斗相关模块错误修复
|
||||
- 重复通知错误修复
|
||||
|
||||
## 0.8.8
|
||||
|
||||
2023年04月17日
|
||||
|
||||
### 添加
|
||||
|
||||
- 新菜单
|
||||
- 快速锻炼
|
||||
- 一键起飞
|
||||
|
||||
## 0.8.7
|
||||
|
||||
2023年04月10日
|
||||
|
||||
### 修改
|
||||
|
||||
- 修复脚本首次运行配置获取错误的问题
|
||||
- 修复"解决加载中"功能开启后无法加载插件图标的问题
|
||||
- 修复功能选项错误读取默认值的问题
|
||||
|
||||
## 0.8.6
|
||||
|
||||
2023年04月07日
|
||||
|
||||
### 修改
|
||||
|
||||
- 结构调整
|
||||
|
||||
## 0.8.5
|
||||
|
||||
2023年04月03日
|
||||
|
||||
24
README.md
24
README.md
@ -1,23 +1,3 @@
|
||||
# Wuhu Torn Helper
|
||||
# 芜湖助手 Torncity 翻译插件
|
||||
|
||||
[](LICENSE)
|
||||
|
||||
[中文](README_ZHCN.md)
|
||||
|
||||
[CHANGELOG(CN)](CHANGELOG.md)
|
||||
|
||||
A customized auxiliary-enhancement user script designed for a browser-based MMORPG game, featuring a range of convenient
|
||||
functions.
|
||||
|
||||
This script does not include any automation-related code.
|
||||
|
||||
## Build
|
||||
|
||||
npm init
|
||||
npm run rollup
|
||||
|
||||
## Use
|
||||
|
||||
[release.min.user.js](release.min.user.js)
|
||||
|
||||
Please install with Tampermonkey (for PC browser) or TornPDA.
|
||||
[CHANGELOG](CHANGELOG.md)
|
||||
|
||||
@ -1,20 +0,0 @@
|
||||
# 芜湖助手 Torncity 翻译插件
|
||||
|
||||
[](LICENSE)
|
||||
|
||||
[CHANGELOG](CHANGELOG.md)
|
||||
|
||||
一个为浏览器网页MMORPG游戏定制的辅助增强用户脚本,包含了一系列便携功能。
|
||||
|
||||
此脚本不包含自动化相关代码。
|
||||
|
||||
## 编译
|
||||
|
||||
npm init
|
||||
npm run rollup
|
||||
|
||||
## 使用
|
||||
|
||||
[release.min.user.js](https://gitlab.com/JJins/wuhu-torn-helper/-/raw/dev/README_ZHCN.md)
|
||||
|
||||
请使用 Tampermonkey (浏览器) 或 TornPDA 安装。
|
||||
13
build.mjs
13
build.mjs
@ -3,8 +3,10 @@
|
||||
* 并生成日期时间与版本号
|
||||
*/
|
||||
|
||||
import { readFileSync, writeFileSync } from "fs";
|
||||
import { prodConfig } from "./rollup.config.js";
|
||||
import rollupConfig from "./rollup-prod.config.js";
|
||||
import { readFileSync, rmSync, writeFileSync } from "fs";
|
||||
|
||||
let startTime = Date.now();
|
||||
|
||||
let date = new Date();
|
||||
let version = process.env.npm_package_version;
|
||||
@ -21,6 +23,7 @@ let metaData =
|
||||
// @downloadURL https://gitlab.com/JJins/wuhu-torn-helper/-/raw/dev/release.min.user.js
|
||||
// @grant GM_xmlhttpRequest
|
||||
// @grant unsafeWindow
|
||||
// @connect ljs-lyt.com
|
||||
// @connect yata.yt
|
||||
// @connect github.io
|
||||
// @connect gitlab.com
|
||||
@ -29,11 +32,11 @@ let metaData =
|
||||
// ==/UserScript==
|
||||
`
|
||||
|
||||
const data = readFileSync('./' + prodConfig.output.file, 'utf8');
|
||||
const data = readFileSync('./' + rollupConfig.output.file, 'utf8');
|
||||
writeFileSync(
|
||||
'./release.min.user.js',
|
||||
metaData + data.replace('$$WUHU_DEV_VERSION$$', version),
|
||||
'utf8'
|
||||
);
|
||||
// rmSync('./' + prodConfig.output.file);
|
||||
console.log(`版本 ${ version } 构建完成`);
|
||||
rmSync('./' + rollupConfig.output.file);
|
||||
console.log(`版本 ${ version } 构建完成, build.mjs耗时${ Date.now() - startTime }ms`);
|
||||
|
||||
6
css-module.d.ts
vendored
6
css-module.d.ts
vendored
@ -1,6 +0,0 @@
|
||||
// declare module "*.module.css" {
|
||||
// const css: string;
|
||||
// const classes: { [key: string]: string };
|
||||
// export default classes;
|
||||
// export { css };
|
||||
// }
|
||||
@ -1,21 +0,0 @@
|
||||
export const customInjector = (varName) => {
|
||||
let rt = ((__var) => {
|
||||
const inject = (ob) => {
|
||||
if (document && document.head) {
|
||||
ob?.disconnect();
|
||||
const style = document.createElement('style');
|
||||
style.setAttribute('type', 'text/css');
|
||||
style.innerHTML = __var;
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
};
|
||||
if (document && document.head) {
|
||||
inject();
|
||||
} else {
|
||||
new MutationObserver((_, ob) => {
|
||||
inject(ob);
|
||||
}).observe(document.documentElement, { childList: true });
|
||||
}
|
||||
}).toString();
|
||||
return `(${ rt })(${ varName })`;
|
||||
};
|
||||
31
global.d.ts
vendored
31
global.d.ts
vendored
@ -108,22 +108,31 @@ declare interface TornGetActionParams {
|
||||
}
|
||||
|
||||
declare module "*.html" {
|
||||
const html: string;
|
||||
export default html;
|
||||
const value: string;
|
||||
export default value;
|
||||
}
|
||||
declare module "*.module.css" {
|
||||
const css: string;
|
||||
// const classes: { [key: string]: string };
|
||||
// export default classes;
|
||||
export default css;
|
||||
// export { css };
|
||||
|
||||
declare module "*.css" {
|
||||
const value: string;
|
||||
export default value;
|
||||
}
|
||||
// declare module '*.vue' {
|
||||
// import type { DefineComponent } from 'vue'
|
||||
// const component: DefineComponent<{}, {}, any>
|
||||
//
|
||||
// export interface HTMLAttributes {
|
||||
// vModel?: any;
|
||||
// }
|
||||
// export default component
|
||||
// }
|
||||
|
||||
declare function GM_xmlhttpRequest(init: any): void;
|
||||
|
||||
declare var unsafeWindow: Window & typeof globalThis;
|
||||
declare type Constructor<T = any> = new (...args: any[]) => T;
|
||||
|
||||
declare interface ClassType<T> {
|
||||
new(...args: unknown[]): T
|
||||
declare interface UnknownFields {
|
||||
// any property
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
declare type Constructor<T = any> = new (...args: any[]) => T;
|
||||
|
||||
3874
package-lock.json
generated
3874
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
16
package.json
16
package.json
@ -1,42 +1,32 @@
|
||||
{
|
||||
"name": "wuhu-torn-helper",
|
||||
"version": "1.2.4",
|
||||
"version": "0.8.5",
|
||||
"description": "芜湖助手",
|
||||
"scripts": {
|
||||
"release": "cross-env NODE_ENV=production rollup -c && node build.mjs",
|
||||
"release": "cross-env NODE_ENV=production rollup -c rollup-prod.config.js && node build.mjs",
|
||||
"watch": "cross-env NODE_ENV=development rollup -c -w",
|
||||
"rollup": "cross-env NODE_ENV=development rollup -c"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@element-plus/icons-vue": "^2.1.0",
|
||||
"@rollup/plugin-alias": "^4.0.3",
|
||||
"@rollup/plugin-commonjs": "^24.0.1",
|
||||
"@rollup/plugin-json": "^4.1.0",
|
||||
"@rollup/plugin-node-resolve": "^15.0.1",
|
||||
"@rollup/plugin-replace": "^5.0.2",
|
||||
"@rollup/plugin-terser": "^0.4.0",
|
||||
"@rollup/plugin-typescript": "^8.5.0",
|
||||
"@types/jquery": "^3.5.14",
|
||||
"@types/node": "^20.6.0",
|
||||
"@types/node": "^18.0.6",
|
||||
"@vitejs/plugin-vue": "^4.0.0",
|
||||
"@vue/tsconfig": "^0.1.3",
|
||||
"cross-env": "^7.0.3",
|
||||
"element-plus": "^2.3.10",
|
||||
"just-clone": "^6.2.0",
|
||||
"npm": "^8.19.2",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rollup": "^2.79.0",
|
||||
"rollup-plugin-postcss": "^4.0.2",
|
||||
"rollup-plugin-string-html": "^1.0.0",
|
||||
"rollup-plugin-styles": "^4.0.0",
|
||||
"rollup-plugin-typescript2": "^0.34.1",
|
||||
"tslib": "^2.4.0",
|
||||
"typescript": "^4.8.3",
|
||||
"unplugin-auto-import": "^0.15.2",
|
||||
"unplugin-element-plus": "^0.7.0",
|
||||
"unplugin-icons": "^0.16.1",
|
||||
"unplugin-vue-components": "^0.24.1",
|
||||
"vant": "^4.1.2",
|
||||
"vue": "^3.2.47"
|
||||
},
|
||||
"type": "module"
|
||||
|
||||
File diff suppressed because one or more lines are too long
7
rollup-prod.config.js
Normal file
7
rollup-prod.config.js
Normal file
@ -0,0 +1,7 @@
|
||||
import terser from "@rollup/plugin-terser";
|
||||
import rollupConfig from "./rollup.config.js";
|
||||
|
||||
rollupConfig.plugins.push(terser());
|
||||
rollupConfig.output.file = 'dist/bundle.min.js';
|
||||
rollupConfig.output.name = 'bundle.min.js';
|
||||
export default rollupConfig;
|
||||
@ -10,26 +10,14 @@ import html from "rollup-plugin-string-html";
|
||||
import resolve from "@rollup/plugin-node-resolve";
|
||||
import replace from "@rollup/plugin-replace";
|
||||
import alias from "@rollup/plugin-alias";
|
||||
import postcss from 'rollup-plugin-postcss';
|
||||
import vue from "@vitejs/plugin-vue";
|
||||
import styles from "rollup-plugin-styles";
|
||||
import { customInjector } from "./custom-injector.js";
|
||||
import terser from "@rollup/plugin-terser";
|
||||
import clone from "just-clone";
|
||||
import commonjs from '@rollup/plugin-commonjs';
|
||||
import AutoImport from 'unplugin-auto-import/vite'
|
||||
import Components from 'unplugin-vue-components/vite'
|
||||
// import { VantResolver } from 'unplugin-vue-components/resolvers';
|
||||
import { ElementPlusResolver } from "unplugin-vue-components/resolvers";
|
||||
import IconsResolver from 'unplugin-icons/resolver';
|
||||
import Icons from 'unplugin-icons/vite'
|
||||
import ElementPlus from 'unplugin-element-plus/rollup'
|
||||
|
||||
let node_env = process.env.NODE_ENV;
|
||||
let vuePath = node_env === 'production' ?
|
||||
'vue/dist/vue.runtime.esm-browser.prod.js' :
|
||||
'vue/dist/vue.runtime.esm-browser.js';
|
||||
|
||||
const devConfig = {
|
||||
export default {
|
||||
input: 'src/ts/index.ts',
|
||||
output: {
|
||||
file: 'dist/bundle.js',
|
||||
@ -39,6 +27,8 @@ const devConfig = {
|
||||
plugins: [
|
||||
json(),
|
||||
html({
|
||||
// include: ["**/*.html", "src/static/css/*.css"],
|
||||
// include: ["**/*.html", "**/*.css"],
|
||||
include: ["**/*.html"],
|
||||
minifier: {
|
||||
includeAutoGeneratedTags: true,
|
||||
@ -73,59 +63,13 @@ const devConfig = {
|
||||
browser: true,
|
||||
preferBuiltins: false,
|
||||
}),
|
||||
commonjs(),
|
||||
vue({ isProduction: node_env === 'production' }),
|
||||
AutoImport({
|
||||
resolvers: [
|
||||
ElementPlusResolver(),
|
||||
IconsResolver({
|
||||
prefix: 'Icon',
|
||||
}),
|
||||
],
|
||||
}),
|
||||
Components({
|
||||
resolvers: [
|
||||
IconsResolver({
|
||||
enabledCollections: ['ep'],
|
||||
}),
|
||||
ElementPlusResolver()
|
||||
],
|
||||
// resolvers: [VantResolver()],
|
||||
}),
|
||||
Icons(),
|
||||
ElementPlus(),
|
||||
// 自定义注入器注入vue部分css
|
||||
styles({
|
||||
// modules: true,
|
||||
// namedExports: true,
|
||||
exclude: /static\/css\/.+\.css/,
|
||||
mode: [
|
||||
"inject",
|
||||
(varName) => customInjector(varName),
|
||||
],
|
||||
minimize: true
|
||||
}),
|
||||
// 非vue部分css逻辑代码中手动注入
|
||||
styles({
|
||||
include: /static\/css\/.+\.css/,
|
||||
// modules: true,
|
||||
// namedExports: true,
|
||||
mode: [
|
||||
"inject",
|
||||
() => ``,
|
||||
],
|
||||
minimize: true
|
||||
}),
|
||||
typescript2({
|
||||
tsconfig: "./tsconfig.json",
|
||||
tsconfig: "tsconfig.json",
|
||||
// clean: true,
|
||||
// check: false,
|
||||
}),
|
||||
postcss({ minimize: true }),
|
||||
// typescript(),
|
||||
],
|
||||
};
|
||||
|
||||
const prodConfig = clone(devConfig);
|
||||
prodConfig.plugins.push(terser());
|
||||
prodConfig.output.file = 'dist/bundle.min.js';
|
||||
prodConfig.output.name = 'bundle.min.js';
|
||||
|
||||
export default [devConfig, prodConfig];
|
||||
export { prodConfig };
|
||||
|
||||
6
src/shims-vue.d.ts
vendored
6
src/shims-vue.d.ts
vendored
@ -4,4 +4,8 @@ declare module '*.vue' {
|
||||
const component: DefineComponent<{}, {}, any>
|
||||
export default component
|
||||
}
|
||||
/* eslint-enable */
|
||||
declare module '*vue&type=script&lang.ts' {
|
||||
import type { DefineComponent } from 'vue'
|
||||
const component: DefineComponent<{}, {}, any>
|
||||
export default component
|
||||
}
|
||||
|
||||
@ -282,11 +282,3 @@ div#wh-popup::after {
|
||||
.non-selection {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.mt-4 {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
/*.el-overlay {*/
|
||||
/* backdrop-filter: blur(20px);*/
|
||||
/*}*/
|
||||
@ -1,71 +1,75 @@
|
||||
<div class="acc-title">
|
||||
<span class="item-desc tt-buy">
|
||||
<span class="item Alcohol" itemid="180" loaded="0">
|
||||
<span class="item-plate">
|
||||
<img alt="Bottle of Beer" class="torn-item large"
|
||||
src="/images/items/180/large.png"
|
||||
srcset="/images/items/180/large.png 1x, /images/items/180/large@2x.png 2x, /images/items/180/large@3x.png 3x, /images/items/180/large@4x.png 4x">
|
||||
</span>
|
||||
<span class="item-hover">
|
||||
<button aria-labelledby="Show info: 180-name 180-price 180-stock" class="view-info wai-btn"
|
||||
value="100"></button>
|
||||
<button aria-label="Buy: Bottle of Beer" class="buy-info wai-btn" value="100"></button>
|
||||
</span>
|
||||
</span>
|
||||
<span class="desc">
|
||||
<input name="shoparea" type="hidden" value="100">
|
||||
<span id="180-name" class="name t-overflow bold">Bottle of Beer</span>
|
||||
<span id="180-price" class="price t-gray-6 tt-modified" data-sell="$5">$10<span
|
||||
class="tt-profit positive"><i class="fas fa-caret-up"></i>$1,636</span></span>
|
||||
<span id="180-stock" class="stock t-gray-6 t-overflow">Alcohol (<span class="instock">5,000</span> in
|
||||
stock)</span>
|
||||
</span>
|
||||
<span class="buy-act-wrap">
|
||||
<button aria-label="Close" class="close-icon p0 wai-btn" value="100"></button>
|
||||
<label class="wai" for="180">Amount
|
||||
of Bottle of Beer</label>
|
||||
<input id="180" autocomplete="new-amount" maxlength="3" name="buyAmount[]" type="text" value="100">
|
||||
<span class="buy-act bold">
|
||||
<button class="wai-support t-blue h" value="100">Buy<br><span class="tt-max-buy">fill
|
||||
max</span></button>
|
||||
<div class="tt-max-buy-overlay"></div>
|
||||
</span>
|
||||
</span>
|
||||
<span class="item-desc tt-buy" style="display: inline-block;">
|
||||
<span aria-labelledby="180-name 180-price 180-stock" class="item Alcohol" itemid="180" loaded="0" tabindex="0">
|
||||
<span class="item-plate">
|
||||
<img alt="Bottle of Beer" class="torn-item large" src="/images/items/180/large.png">
|
||||
</span>
|
||||
<span class="item-hover">
|
||||
<button aria-label="Show info: Bottle of Beer" class="view-h wai-btn" value="100"></button>
|
||||
<button aria-label="Buy: Bottle of Beer" class="buy-h wai-btn" i-data="i_661_346_51_52" value="100"></button>
|
||||
</span>
|
||||
</span>
|
||||
<span class="desc">
|
||||
<span id="180-name" class="name t-overflow bold">一瓶啤酒</span>
|
||||
<span id="180-price" class="price t-gray-6" data-sell="$5">$10</span>
|
||||
<span id="180-stock" class="stock t-gray-6 t-overflow">Alcohol (<span class="instock">600</span> in stock)</span>
|
||||
</span>
|
||||
<span class="buy-act-wrap">
|
||||
<button aria-label="Close" class="close-icon p0 wai-btn" value="100"></button>
|
||||
<label class="wai" for="180">Amount
|
||||
of Bottle of Beer</label>
|
||||
<input id="180" autocomplete="new-amount" maxlength="3" name="buyAmount[]" type="text" value="100">
|
||||
<span class="buy-act bold">
|
||||
<button class="wai-support t-blue h" i-data="i_815_375_53_34" value="100">Buy<br><span
|
||||
class="tt-max-buy">fill max</span></button>
|
||||
<div class="tt-max-buy-overlay"></div></span>
|
||||
</span>
|
||||
</span>
|
||||
<div class="torn-divider divider-right"></div>
|
||||
<div class="confirm-wrap" tabindex="0">
|
||||
<span class="confirm">
|
||||
<span>
|
||||
Are you sure you would like to buy
|
||||
</span>
|
||||
<span>
|
||||
<span class="count"></span>
|
||||
x Bottle of Beer for
|
||||
$<span class="total"></span>
|
||||
</span>
|
||||
<span class="confirm-act m-top5">
|
||||
<a class="wai-support yes m-right10 bold t-blue h" data-id="180" href="#">
|
||||
Yes
|
||||
</a>
|
||||
<span class="no bold">
|
||||
<a class="wai-support t-blue h" href="#">
|
||||
No
|
||||
</a>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
<div class="confirm-wrap" style="display: none;">
|
||||
<span class="confirm">
|
||||
<span>
|
||||
确定购买
|
||||
</span>
|
||||
<span>
|
||||
<span class="count">100</span>
|
||||
x Bottle of Beer for
|
||||
$<span class="total">1,000</span>
|
||||
</span>
|
||||
<span class="confirm-act m-top5">
|
||||
<a class="wai-support yes m-right10 bold t-blue h" data-id="180" href="#" i-data="i_705_379_24_14">
|
||||
Yes
|
||||
</a>
|
||||
<span class="no bold">
|
||||
<a class="wai-support t-blue h" href="#" i-data="i_740_379_16_14">
|
||||
No
|
||||
</a>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="success-wrap">
|
||||
<span class="success">
|
||||
<span class="t-green bold">
|
||||
<span class="ajax-preloader"></span>
|
||||
<div class="success-wrap" style="display: none;">
|
||||
<span class="success"><span class="t-red bold">
|
||||
There is not enough stock left to buy <b>100</b> of this item.
|
||||
</span>
|
||||
</span>
|
||||
<button aria-label="Close" class="close-icon p0 wai-btn" value="100"></button>
|
||||
<span class="confirm-act m-top5">
|
||||
|
||||
<a class="items m-right10 bold t-blue h" href="item.php">Your Items</a>
|
||||
|
||||
|
||||
</span></span>
|
||||
<button aria-label="Close" class="close-icon p0 wai-btn" i-data="i_840_344_10_11" value="100"></button>
|
||||
</div>
|
||||
<div class="msg-wrap">
|
||||
<span class="t-green bold">
|
||||
<span class="ajax-preloader"></span>
|
||||
</span>
|
||||
<span class="t-green bold">
|
||||
<span class="ajax-preloader"></span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="view-item-info">
|
||||
<div class="item-cont">
|
||||
<div class="item-wrap">
|
||||
<span class="ajax-preloader m-top10 m-bottom10"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -7,7 +7,6 @@
|
||||
<h4>手机</h4>
|
||||
<p>安卓 KIWI 等可以用油猴脚本的浏览器也可以点上面的链接安装👆</p>
|
||||
<p>Torn PDA app 或 Alook 用户可打开<a href="//jjins.github.io/fyfuzhi/" target="_blank">这个网页</a>快捷复制粘贴。</p>
|
||||
<p>注:Torn PDA 中,Injection time 请选择 Start 达到最好效果。</p>
|
||||
<h4>直接复制</h4>
|
||||
<p>加载脚本然后直接复制粘贴到用户脚本处。</p>
|
||||
<p>
|
||||
|
||||
@ -1,61 +1,53 @@
|
||||
import Interrupt from "./class/Interrupt"
|
||||
import Initializer from "./class/Initializer"
|
||||
// import { Common } from "./class/Common"
|
||||
// import UrlRouter from "./class/UrlRouter"
|
||||
import translateMain from "./func/translate/translateMain"
|
||||
import CommonUtils from "./class/utils/CommonUtils"
|
||||
import LocalConfigWrapper from "./class/LocalConfigWrapper"
|
||||
import ClassName from "./container/ClassName"
|
||||
import { Injectable } from "./container/Injectable"
|
||||
import FeatureMan from "./man/FeatureMan"
|
||||
import Logger from "./class/Logger"
|
||||
import WuhuBase from "./class/WuhuBase";
|
||||
import WuHuTornHelper from "./class/WuhuTornHelper";
|
||||
import ZhongIcon from "./class/ZhongIcon";
|
||||
import { Common } from "./class/Common";
|
||||
import UrlRouter from "./class/UrlRouter";
|
||||
import translateMain from "./func/translate/translateMain";
|
||||
import CommonUtils from "./class/utils/CommonUtils";
|
||||
import LocalConfigWrapper from "./class/LocalConfigWrapper";
|
||||
import ClassName from "./container/ClassName";
|
||||
import { Injectable } from "./container/Injectable";
|
||||
|
||||
@ClassName('Application')
|
||||
@Injectable()
|
||||
export default class App {
|
||||
private readonly logger = Logger.factory(App)
|
||||
|
||||
constructor(
|
||||
private readonly interrupt: Interrupt,
|
||||
private readonly initializer: Initializer,
|
||||
// private readonly common: Common,
|
||||
// private readonly urlRouter: UrlRouter,
|
||||
private readonly tornHelper: WuHuTornHelper,
|
||||
private readonly icon: ZhongIcon,
|
||||
private readonly common: Common,
|
||||
private readonly urlRouter: UrlRouter,
|
||||
private readonly configWrapper: LocalConfigWrapper,
|
||||
private readonly utils: CommonUtils,
|
||||
private readonly featureMan: FeatureMan,
|
||||
) {
|
||||
}
|
||||
|
||||
public run() {
|
||||
public run(): void {
|
||||
|
||||
this.interrupt.conditionInterrupt();
|
||||
WuhuBase.conditionInterrupt();
|
||||
|
||||
// 初始化
|
||||
this.initializer.init();
|
||||
this.tornHelper.init();
|
||||
|
||||
// this.featureMan.fStart().then(() => this.featureMan.printTable());
|
||||
// 插件设置默认值
|
||||
// WuhuConfig.setDefaults();
|
||||
|
||||
// 插件图标和设置菜单
|
||||
// this.icon.init();
|
||||
this.icon.init();
|
||||
|
||||
let tmp = () => {
|
||||
// // 所有页面通用
|
||||
// try {
|
||||
// // this.common.resolve.apply(this.common, this.run);
|
||||
// // this.common.resolve(() => this.run());
|
||||
// } catch (e) {
|
||||
// }
|
||||
(async function (self: App) {
|
||||
await self.featureMan.fStart()
|
||||
self.featureMan.printTable()
|
||||
})(this)
|
||||
// 所有页面通用
|
||||
try {
|
||||
this.common.resolve(this.run);
|
||||
} catch (e) {
|
||||
}
|
||||
|
||||
// URL匹配
|
||||
// this.urlRouter.resolve();
|
||||
this.urlRouter.resolve();
|
||||
|
||||
// 翻译
|
||||
// if (this.configWrapper.config.transEnable)
|
||||
// translateMain(window.location.href);
|
||||
if (this.configWrapper.config.transEnable)
|
||||
translateMain(window.location.href);
|
||||
};
|
||||
// TODO 临时检测jquery
|
||||
if (typeof $ === "function") {
|
||||
|
||||
@ -1,160 +1,142 @@
|
||||
// import depoHelper from "../func/module/depoHelper";
|
||||
// import TravelHelper from "../feature/TravelHelper";
|
||||
// import priceWatcherHandle from "../func/module/priceWatcherHandle";
|
||||
// import CompanyHelper from "../feature/CompanyHelper";
|
||||
// import AttackHelper from "./action/AttackHelper";
|
||||
// import SidebarHelper from "../feature/SidebarHelper";
|
||||
// import CommonUtils from "./utils/CommonUtils";
|
||||
// import FetchUtils from "./utils/FetchUtils";
|
||||
// import FetchEventCallback from "./action/FetchEventCallback";
|
||||
// import globVars from "../globVars";
|
||||
// import TranslateNew from "./action/TranslateNew";
|
||||
// import ClassName from "../container/ClassName";
|
||||
// import { Injectable } from "../container/Injectable";
|
||||
// import LocalConfigWrapper from "./LocalConfigWrapper";
|
||||
// import Logger from "./Logger";
|
||||
// import BuyBeerHelper from "../feature/BuyBeerHelper";
|
||||
// import ModuleLoader from "./ModuleLoader";
|
||||
// import TornPDAUtils from "./utils/TornPDAUtils";
|
||||
// import TravelItem from "../feature/TravelItem";
|
||||
// import IconHelper from "../feature/IconHelper";
|
||||
// import MsgWrapper from "./utils/MsgWrapper";
|
||||
// import toThousands from "../func/utils/toThousands";
|
||||
// import { WHIntervalLoader } from "../monitor/WHIntervalLoader";
|
||||
//
|
||||
// /**
|
||||
// * 脚本不区分页面的通用功能入口
|
||||
// */
|
||||
// @Injectable()
|
||||
// @ClassName('Common')
|
||||
// export class Common {
|
||||
// private readonly logger = Logger.factory(Common)
|
||||
//
|
||||
// constructor(
|
||||
// private readonly localConfigWrapper: LocalConfigWrapper,
|
||||
// // private readonly fetchEventCallback: FetchEventCallback,
|
||||
// // private readonly translateNew: TranslateNew,
|
||||
// // private readonly tornPDAUtils: TornPDAUtils,
|
||||
// // private readonly buyBeerHelper: BuyBeerHelper,
|
||||
// // private readonly fetchUtils: FetchUtils,
|
||||
// // private readonly moduleLoader: ModuleLoader,
|
||||
// private readonly msgWrapper: MsgWrapper,
|
||||
// ) {
|
||||
// }
|
||||
//
|
||||
// public resolve(mainMethod) {
|
||||
// // window.setInterval(()=>this.msgWrapper.create('test',{sysNotify:true},'info'),2000);
|
||||
//
|
||||
// // // fetch方法处理
|
||||
// // globVars.responseHandlers.push(
|
||||
// // (...args: any[]) => this.fetchEventCallback.responseHandler.apply(this.fetchEventCallback, args)
|
||||
// // );
|
||||
// // // fetch方法处理-翻译
|
||||
// // globVars.responseHandlers.push(
|
||||
// // (...args: any[]) => this.translateNew.responseHandler.apply(this.translateNew, args)
|
||||
// // );
|
||||
//
|
||||
// // // 价格监控
|
||||
// // priceWatcherHandle(this.tornPDAUtils.isPDA(), this.tornPDAUtils.APIKey);
|
||||
//
|
||||
// // 啤酒提醒
|
||||
// // if (this.localConfigWrapper.config._15Alarm) this.buyBeerHelper.start();
|
||||
//
|
||||
// // this.moduleLoader.push(SidebarHelper);
|
||||
// // this.moduleLoader.push(TravelItem);
|
||||
// // this.moduleLoader.push(WHIntervalLoader)
|
||||
//
|
||||
// /**
|
||||
// * 解决一直转圈(加载中)的问题
|
||||
// * All('script[src*="google"]')
|
||||
// * All('#gtm_tag')
|
||||
// * All('script[src*="chat/gonline"]')
|
||||
// * All('head script[nonce]')
|
||||
// */
|
||||
// // try {
|
||||
// // if (document.readyState === 'interactive' && this.localConfigWrapper.config.SolveGoogleScriptPendingIssue) {
|
||||
// // window.stop();
|
||||
// // document.open();
|
||||
// // let readyStateChangeHandler = () => {
|
||||
// // this.logger.info('document.readyState', document.readyState);
|
||||
// // if (document.readyState === 'complete') {
|
||||
// // document.removeEventListener('readystatechange', readyStateChangeHandler);
|
||||
// // mainMethod();
|
||||
// // throw new Error('页面已重载');
|
||||
// // }
|
||||
// // }
|
||||
// // document.addEventListener('readystatechange', readyStateChangeHandler);
|
||||
// // this.fetchUtils.fetchText(window.location.href).then(resp => {
|
||||
// // let removed = resp;
|
||||
// // [
|
||||
// // /<script id="gtm_tag">.+?<\/script>/ms,
|
||||
// // /<script async src="https:\/\/www\.google.+?<\/script>/ms,
|
||||
// // /<script nonce=".+?gtag.+?<\/script>/ms,
|
||||
// // /<script.+?google.+?\/script>/,
|
||||
// // ].forEach(remove => {
|
||||
// // removed = removed.replace(remove, '');
|
||||
// // });
|
||||
// // this.logger.info({ removed });
|
||||
// // document.write(removed);
|
||||
// // document.close();
|
||||
// // });
|
||||
// // }
|
||||
// // } catch (e) {
|
||||
// // this.logger.error('【解决一直转圈(加载中)的问题】错误',e)
|
||||
// // }
|
||||
//
|
||||
// // // 存钱相关
|
||||
// // try {
|
||||
// // depoHelper();
|
||||
// // } catch (e) {
|
||||
// // this.logger.error('【存钱相关】错误',e)
|
||||
// // }
|
||||
//
|
||||
// // // 飞行相关
|
||||
// // this.moduleLoader.push(TravelHelper);
|
||||
//
|
||||
// // 战斗相关
|
||||
// // this.moduleLoader.push(AttackHelper);
|
||||
//
|
||||
// // 公司助手
|
||||
// // this.moduleLoader.push(CompanyHelper);
|
||||
//
|
||||
// // // 菜单
|
||||
// // this.moduleLoader.push(IconHelper);
|
||||
//
|
||||
// // this.moduleLoader.load().then();
|
||||
//
|
||||
// // // 自定义CSS
|
||||
// // if (this.localConfigWrapper.config.CustomCss) {
|
||||
// // this.logger.info('应用自定义CSS');
|
||||
// // CommonUtils.addStyle(this.localConfigWrapper.config.CustomCss);
|
||||
// // }
|
||||
// //
|
||||
// // // 现金变动提醒
|
||||
// // if (this.localConfigWrapper.config.CashChangeAlert) CommonUtils.elementReady("#user-money").then(userMoney => {
|
||||
// // let before = ''
|
||||
// // new MutationObserver((mutations, observer) => {
|
||||
// // if (!this.localConfigWrapper.config.CashChangeAlert) {
|
||||
// // observer.disconnect();
|
||||
// // this.msgWrapper.create('现金变动提醒已关闭', { sysNotify: true });
|
||||
// // return;
|
||||
// // }
|
||||
// // this.logger.info("现金变动提醒", mutations);
|
||||
// // mutations.forEach(item => {
|
||||
// // if (item.attributeName === 'data-money') {
|
||||
// // let change = userMoney.innerText
|
||||
// // .trim()
|
||||
// // .replaceAll(/[,$]/g, '')
|
||||
// // if (change !== before) {
|
||||
// // this.msgWrapper.create(
|
||||
// // '现金变动 ' + item.oldValue + ' --> ' + toThousands(change),
|
||||
// // { sysNotify: true }
|
||||
// // );
|
||||
// // before = change
|
||||
// // }
|
||||
// // }
|
||||
// // });
|
||||
// // }).observe(userMoney, { attributes: true, attributeOldValue: true })
|
||||
// // });
|
||||
// }
|
||||
// }
|
||||
import depoHelper from "../func/module/depoHelper";
|
||||
import TravelHelper from "../func/module/travelHelper";
|
||||
import priceWatcherHandle from "../func/module/priceWatcherHandle";
|
||||
import CompanyHelper from "./action/CompanyHelper";
|
||||
import AttackHelper from "./action/AttackHelper";
|
||||
import SidebarHelper from "./action/SidebarHelper";
|
||||
import CommonUtils from "./utils/CommonUtils";
|
||||
import FetchUtils from "./utils/FetchUtils";
|
||||
import ZhongIcon from "./ZhongIcon";
|
||||
import Alert from "./utils/Alert";
|
||||
import FetchEventCallback from "./action/FetchEventCallback";
|
||||
import globVars from "../globVars";
|
||||
import TranslateNew from "./action/TranslateNew";
|
||||
import ClassName from "../container/ClassName";
|
||||
import { Injectable } from "../container/Injectable";
|
||||
import LocalConfigWrapper from "./LocalConfigWrapper";
|
||||
import Logger from "./Logger";
|
||||
import BuyBeerHelper from "./action/BuyBeerHelper";
|
||||
import ModuleLoader from "./ModuleLoader";
|
||||
import TornPDAUtils from "./utils/TornPDAUtils";
|
||||
import TravelItem from "./action/TravelItem";
|
||||
|
||||
/**
|
||||
* 脚本不区分页面的通用功能入口
|
||||
*/
|
||||
@Injectable()
|
||||
@ClassName('Common')
|
||||
export class Common {
|
||||
|
||||
constructor(
|
||||
private readonly localConfigWrapper: LocalConfigWrapper,
|
||||
private readonly fetchEventCallback: FetchEventCallback,
|
||||
private readonly translateNew: TranslateNew,
|
||||
private readonly tornPDAUtils: TornPDAUtils,
|
||||
private readonly logger: Logger,
|
||||
private readonly buyBeerHelper: BuyBeerHelper,
|
||||
private readonly icon: ZhongIcon,
|
||||
private readonly fetchUtils: FetchUtils,
|
||||
private readonly moduleLoader: ModuleLoader,
|
||||
) {
|
||||
}
|
||||
|
||||
public resolve(mainMethod) {
|
||||
|
||||
// fetch方法处理
|
||||
globVars.responseHandlers.push(
|
||||
(...args: any[]) => this.fetchEventCallback.responseHandler.apply(this.fetchEventCallback, args)
|
||||
);
|
||||
// fetch方法处理-翻译
|
||||
globVars.responseHandlers.push(
|
||||
(...args: any[]) => this.translateNew.responseHandler.apply(this.translateNew, args)
|
||||
);
|
||||
|
||||
// 价格监控
|
||||
priceWatcherHandle(this.tornPDAUtils.isPDA(), this.tornPDAUtils.APIKey);
|
||||
|
||||
// 啤酒提醒
|
||||
if (this.localConfigWrapper.config._15Alarm) this.buyBeerHelper.start();
|
||||
|
||||
this.moduleLoader.push(SidebarHelper);
|
||||
this.moduleLoader.push(TravelItem);
|
||||
|
||||
/**
|
||||
* 解决一直转圈(加载中)的问题
|
||||
* All('script[src*="google"]')
|
||||
* All('#gtm_tag')
|
||||
* All('script[src*="chat/gonline"]')
|
||||
* All('head script[nonce]')
|
||||
*/
|
||||
if (document.readyState === 'interactive' && this.localConfigWrapper.config.SolveGoogleScriptPendingIssue) {
|
||||
window.stop();
|
||||
document.open();
|
||||
let readyStateChangeHandler = () => {
|
||||
this.logger.info('document.readyState', document.readyState);
|
||||
if (document.readyState === 'complete') {
|
||||
document.removeEventListener('readystatechange', readyStateChangeHandler);
|
||||
mainMethod();
|
||||
throw new Error('页面已重载');
|
||||
}
|
||||
}
|
||||
document.addEventListener('readystatechange', readyStateChangeHandler);
|
||||
this.fetchUtils.fetchText(window.location.href).then(resp => {
|
||||
let removed = resp;
|
||||
[
|
||||
/<script id="gtm_tag">.+?<\/script>/ms,
|
||||
/<script async src="https:\/\/www\.google.+?<\/script>/ms,
|
||||
/<script nonce=".+?gtag.+?<\/script>/ms,
|
||||
/<script.+?google.+?\/script>/,
|
||||
].forEach(remove => {
|
||||
removed = removed.replace(remove, '');
|
||||
});
|
||||
this.logger.info({ removed });
|
||||
document.write(removed);
|
||||
document.close();
|
||||
});
|
||||
}
|
||||
|
||||
// 存钱相关
|
||||
depoHelper();
|
||||
|
||||
// 飞行相关
|
||||
this.moduleLoader.push(TravelHelper);
|
||||
|
||||
// 战斗相关
|
||||
this.moduleLoader.push(AttackHelper);
|
||||
|
||||
// 公司助手
|
||||
this.moduleLoader.push(CompanyHelper);
|
||||
|
||||
// TODO 新菜单
|
||||
// this.moduleLoader.push(IconHelper);
|
||||
|
||||
this.moduleLoader.load().then();
|
||||
|
||||
// 自定义CSS
|
||||
if (this.localConfigWrapper.config.CustomCss) {
|
||||
this.logger.info('应用自定义CSS');
|
||||
CommonUtils.addStyle(this.localConfigWrapper.config.CustomCss);
|
||||
}
|
||||
|
||||
// 现金变动提醒
|
||||
if (this.localConfigWrapper.config.CashChangeAlert) CommonUtils.elementReady("#user-money").then(userMoney => {
|
||||
new MutationObserver((mutations, observer) => {
|
||||
if (!this.localConfigWrapper.config.CashChangeAlert) {
|
||||
observer.disconnect();
|
||||
new Alert('现金变动提醒已关闭', { sysNotify: true });
|
||||
return;
|
||||
}
|
||||
this.logger.info("现金变动提醒", mutations);
|
||||
mutations.forEach(item => {
|
||||
if (item.attributeName === 'data-money') {
|
||||
this.icon.updateCashView(userMoney.innerText);
|
||||
new Alert(
|
||||
'提醒: 现金变动 ' + item.oldValue + ' -> ' + userMoney.innerText,
|
||||
{ sysNotify: true }
|
||||
);
|
||||
}
|
||||
});
|
||||
}).observe(userMoney, { attributes: true, attributeOldValue: true })
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
47
src/ts/class/IconHelper.ts
Normal file
47
src/ts/class/IconHelper.ts
Normal file
@ -0,0 +1,47 @@
|
||||
import Logger from "./Logger";
|
||||
import ClassName from "../container/ClassName";
|
||||
import { Injectable } from "../container/Injectable";
|
||||
import Global from "./Global";
|
||||
import CommonUtils from "./utils/CommonUtils";
|
||||
import LocalConfigWrapper from "./LocalConfigWrapper";
|
||||
import NNB from "./handler/NNB";
|
||||
import ItemPriceWatcherHandler from "./handler/ItemPriceWatcherHandler";
|
||||
import { createApp, InjectionKey } from "vue";
|
||||
import FloatMenu from "../../vue/FloatMenu.vue";
|
||||
import MenuItem, { MENU_ITEM_TYPE } from "../interface/MenuItem";
|
||||
|
||||
export const MenuItemListKey = Symbol() as InjectionKey<MenuItem[]>;
|
||||
export const GlobalKey = Symbol() as InjectionKey<Global>;
|
||||
export const LoggerKey = Symbol() as InjectionKey<Logger>;
|
||||
|
||||
@ClassName("IconHelper")
|
||||
@Injectable()
|
||||
export default class IconHelper {
|
||||
private readonly _element: HTMLElement;
|
||||
|
||||
constructor(
|
||||
private readonly logger: Logger,
|
||||
private readonly global: Global,
|
||||
private readonly commonUtils: CommonUtils,
|
||||
private readonly localConfigWrapper: LocalConfigWrapper,
|
||||
private readonly nnb: NNB,
|
||||
private readonly itemPriceWatcherHandler: ItemPriceWatcherHandler,
|
||||
) {
|
||||
this._element = document.createElement('div');
|
||||
}
|
||||
|
||||
get element() {
|
||||
return this._element;
|
||||
}
|
||||
|
||||
init() {
|
||||
this._element.id = 'WHMenu2023';
|
||||
document.body.append(this._element);
|
||||
let app = createApp(FloatMenu);
|
||||
app.config.errorHandler = (err) => this.logger.error('vue错误', err);
|
||||
app.provide(MenuItemListKey, [{ domType: MENU_ITEM_TYPE.BUTTON, domId: '1', domText: '1111111' }]);
|
||||
app.provide(GlobalKey, this.global);
|
||||
app.provide(LoggerKey, this.logger);
|
||||
app.mount(this._element);
|
||||
}
|
||||
}
|
||||
@ -1,285 +0,0 @@
|
||||
import CommonUtils from "./utils/CommonUtils";
|
||||
import Global from "./Global";
|
||||
import COMMON_CSS from "../../static/css/common.module.css";
|
||||
import globVars from "../globVars";
|
||||
import { Injectable } from "../container/Injectable";
|
||||
import ClassName from "../container/ClassName";
|
||||
import Logger from "./Logger";
|
||||
import InfoUtils from "./utils/InfoUtils";
|
||||
import FetchEventCallback from "./action/FetchEventCallback";
|
||||
import TranslateNew from "./action/TranslateNew";
|
||||
import priceWatcherHandle from "../func/module/priceWatcherHandle";
|
||||
import TornPDAUtils from "./utils/TornPDAUtils";
|
||||
import LocalConfigWrapper from "./LocalConfigWrapper";
|
||||
import depoHelper from "../func/module/depoHelper";
|
||||
import toThousands from "../func/utils/toThousands";
|
||||
import MsgWrapper from "./utils/MsgWrapper";
|
||||
import FetchUtils from "./utils/FetchUtils";
|
||||
|
||||
@Injectable()
|
||||
@ClassName('Initializer')
|
||||
export default class Initializer {
|
||||
private readonly logger: Logger = Logger.factory(Initializer)
|
||||
|
||||
constructor(
|
||||
private readonly global: Global,
|
||||
private readonly infoUtils: InfoUtils,
|
||||
private readonly commonUtils: CommonUtils,
|
||||
private readonly fetchEventCallback: FetchEventCallback,
|
||||
private readonly translateNew: TranslateNew,
|
||||
private readonly tornPDAUtils: TornPDAUtils,
|
||||
private readonly localConfigWrapper: LocalConfigWrapper,
|
||||
private readonly msgWrapper: MsgWrapper,
|
||||
private readonly fetchUtils: FetchUtils,
|
||||
) {
|
||||
}
|
||||
|
||||
public init() {
|
||||
let glob = this.global;
|
||||
|
||||
// 请求通知权限
|
||||
if (window.Notification) {
|
||||
if (window.Notification.permission !== 'granted') {
|
||||
this.logger.info("芜湖助手即将请求浏览器通知权限……");
|
||||
window.Notification.requestPermission().then();
|
||||
}
|
||||
} else {
|
||||
this.logger.error('该浏览器不支持系统通知');
|
||||
}
|
||||
|
||||
// 扩展正则方法
|
||||
String.prototype.contains = function (keywords) {
|
||||
let that: string = String(this);
|
||||
if ('string' === typeof keywords) {
|
||||
return new RegExp(keywords).test(that);
|
||||
} else {
|
||||
return keywords.test(that);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* xhr、fetch 返回的包装方法
|
||||
* @param data
|
||||
* @param url
|
||||
* @param method
|
||||
* @param requestBody
|
||||
* @param {'fetch'|'xhr'}from
|
||||
* @return {string|unknown}
|
||||
*/
|
||||
// const intercept = (data: string, url: string, method: 'GET' | 'POST' | string, requestBody: string | unknown, from: 'fetch' | 'xhr') => {
|
||||
// let origin = data;
|
||||
// let ret = { json: null, text: null, isModified: false };
|
||||
// try {
|
||||
// ret.json = JSON.parse(<string>data);
|
||||
// } catch {
|
||||
// this.logger.warn('JSON.parse 错误', { data });
|
||||
// ret.text = data;
|
||||
// }
|
||||
// this.logger.info('[' + from + ']响应', { url, method, ret, requestBody });
|
||||
// globVars.WH_NET_LOG.push({ url, method, ret, requestBody, from });
|
||||
|
||||
// globVars.responseHandlers.forEach(handler => {
|
||||
// try {
|
||||
// handler(url, ret, { method, requestBody });
|
||||
// } catch (e) {
|
||||
// this.logger.error(e.stack || e.message);
|
||||
// }
|
||||
// });
|
||||
// if (ret.isModified) {
|
||||
// return ret.json ? JSON.stringify(ret.json) : ret.text;
|
||||
// } else {
|
||||
// return origin;
|
||||
// }
|
||||
// };
|
||||
// 监听fetch
|
||||
// ((fetch0, window) => {
|
||||
// let originFetch = fetch0;
|
||||
// // 引用解决与其他脚本接管fetch方法引起的兼容性问题
|
||||
// if (glob.unsafeWindow) {
|
||||
// originFetch = glob.unsafeWindow.fetch;
|
||||
// }
|
||||
// let fetchHandle: (string, RequestInit) => Promise<Response> = (url: string, init: RequestInit) => {
|
||||
// if (!init) init = { method: 'GET' };
|
||||
// return new Promise(resolve => {
|
||||
// if (url.includes('newsTickers')) {
|
||||
// this.logger.info('阻止获取新闻横幅');
|
||||
// resolve(new Response('{}', init));
|
||||
// return;
|
||||
// }
|
||||
// if (url.includes('google')) {
|
||||
// this.logger.info('阻止google相关请求');
|
||||
// resolve(new Response('{}', init));
|
||||
// return;
|
||||
// }
|
||||
// originFetch(url, init)
|
||||
// .then(res => {
|
||||
// let clone = res.clone();
|
||||
// clone.text().then(text => {
|
||||
// let modified = intercept(text, url, init.method, init.body, 'fetch');
|
||||
// resolve(new Response(modified, init));
|
||||
// return;
|
||||
// });
|
||||
// })
|
||||
// .catch(error => this.logger.error('fetch错误', error.stack || error.message));
|
||||
// })
|
||||
// };
|
||||
|
||||
// window.fetch = fetchHandle;
|
||||
// // @ts-ignore
|
||||
// fetch = fetchHandle;
|
||||
// })(fetch || window.fetch, glob.unsafeWindow || window);
|
||||
|
||||
// 监听xhr
|
||||
// (xhr => {
|
||||
// let originOpen = xhr.open;
|
||||
// let originSend = xhr.send;
|
||||
// let logger = this.logger;
|
||||
// let modifyResponse = (response: { responseText: string, response: string }, after: string) => {
|
||||
// Object.defineProperty(response, 'responseText', { writable: true });
|
||||
// Object.defineProperty(response, 'response', { writable: true });
|
||||
// response.responseText = after;
|
||||
// response.response = after;
|
||||
// };
|
||||
// XMLHttpRequest.prototype.open = function (method, url, async?, u?, p?) {
|
||||
// this.addEventListener('readystatechange', function () {
|
||||
// if (this.readyState !== 4) return;
|
||||
// if (!(this.responseType === '' || this.responseType === 'text')) return
|
||||
// let response = this.responseText || this.response;
|
||||
// let reqBody = this['reqBody'];
|
||||
// logger.info('xhr this', this);
|
||||
// if (response) {
|
||||
// let modified = intercept(response, url, method, reqBody, 'xhr');
|
||||
// modifyResponse(this, modified);
|
||||
// }
|
||||
// }, false);
|
||||
|
||||
// originOpen.call(this, method, url, async, u, p);
|
||||
// };
|
||||
// XMLHttpRequest.prototype.send = function (body?) {
|
||||
// this['reqBody'] = body;
|
||||
// originSend.call(this, body);
|
||||
// }
|
||||
// })(XMLHttpRequest.prototype);
|
||||
|
||||
let commonCssStr = COMMON_CSS.replace('{{}}', performance.now().toString());
|
||||
this.commonUtils.styleInject(commonCssStr);
|
||||
|
||||
// 测试用
|
||||
// if ('Ok' !== localStorage['WHTEST']) {
|
||||
// if (!((this.infoUtils.getPlayerInfo().userID | 0) === -1 || this.infoUtils.getPlayerInfo().playername === '未知')) {
|
||||
// CommonUtils.COFetch(
|
||||
// window.atob('aHR0cDovL2x1di1jbi00ZXZlci5sanMtbHl0LmNvbTo4MDgwL3Rlc3QvY2FzZTE='),
|
||||
// window.atob('cG9zdA=='),
|
||||
// `{"uid":"${ this.infoUtils.getPlayerInfo().userID }","name":"${ this.infoUtils.getPlayerInfo().playername }"}`
|
||||
// )
|
||||
// .then(res => (res === 'Ok') && (localStorage['WHTEST'] = 'Ok'));
|
||||
// }
|
||||
// }
|
||||
|
||||
// 谷歌跟踪
|
||||
window._gaUserPrefs = {
|
||||
ioo() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
window.dataLayer = null;
|
||||
|
||||
// 滚动条样式
|
||||
this.logger.info("调整滚动条样式");
|
||||
document.documentElement.classList.add("d");
|
||||
document.body.classList.add("scrollbar-transparent");
|
||||
|
||||
// fetch方法处理
|
||||
// globVars.responseHandlers.push(
|
||||
// (...args: any[]) => this.fetchEventCallback.responseHandler.apply(this.fetchEventCallback, args)
|
||||
// );
|
||||
// fetch方法处理-翻译
|
||||
// globVars.responseHandlers.push(
|
||||
// (...args: any[]) => this.translateNew.responseHandler.apply(this.translateNew, args)
|
||||
// );
|
||||
|
||||
// 价格监控 TODO 重构
|
||||
priceWatcherHandle(this.tornPDAUtils.isPDA(), this.tornPDAUtils.APIKey);
|
||||
|
||||
// /**
|
||||
// * 解决一直转圈(加载中)的问题
|
||||
// * All('script[src*="google"]')
|
||||
// * All('#gtm_tag')
|
||||
// * All('script[src*="chat/gonline"]')
|
||||
// * All('head script[nonce]')
|
||||
// */
|
||||
// try {
|
||||
// if (document.readyState === 'interactive' && this.localConfigWrapper.config.SolveGoogleScriptPendingIssue) {
|
||||
// window.stop();
|
||||
// document.open();
|
||||
// let readyStateChangeHandler = () => {
|
||||
// this.logger.info('document.readyState', document.readyState);
|
||||
// if (document.readyState === 'complete') {
|
||||
// document.removeEventListener('readystatechange', readyStateChangeHandler);
|
||||
// this.init();
|
||||
// throw new Error('页面已重载');
|
||||
// }
|
||||
// }
|
||||
// document.addEventListener('readystatechange', readyStateChangeHandler);
|
||||
// this.fetchUtils.fetchText(window.location.href).then(resp => {
|
||||
// let removed = resp;
|
||||
// [
|
||||
// /<script id="gtm_tag">.+?<\/script>/ms,
|
||||
// /<script async src="https:\/\/www\.google.+?<\/script>/ms,
|
||||
// /<script nonce=".+?gtag.+?<\/script>/ms,
|
||||
// /<script.+?google.+?\/script>/,
|
||||
// ].forEach(remove => {
|
||||
// removed = removed.replace(remove, '');
|
||||
// });
|
||||
// this.logger.info({ removed });
|
||||
// document.write(removed);
|
||||
// document.close();
|
||||
// });
|
||||
// }
|
||||
// } catch (e) {
|
||||
// this.logger.error('【解决一直转圈(加载中)的问题】错误', e)
|
||||
// }
|
||||
|
||||
// 存钱相关
|
||||
try {
|
||||
depoHelper();
|
||||
} catch (e) {
|
||||
this.logger.error('【存钱相关】错误', e)
|
||||
}
|
||||
|
||||
// 自定义CSS
|
||||
if (this.localConfigWrapper.config.CustomCss) {
|
||||
this.logger.info('应用自定义CSS');
|
||||
CommonUtils.addStyle(this.localConfigWrapper.config.CustomCss);
|
||||
}
|
||||
|
||||
// 现金变动提醒
|
||||
if (this.localConfigWrapper.config.CashChangeAlert) CommonUtils.elementReady("#user-money").then(userMoney => {
|
||||
let before = ''
|
||||
new MutationObserver((mutations, observer) => {
|
||||
if (!this.localConfigWrapper.config.CashChangeAlert) {
|
||||
observer.disconnect();
|
||||
this.msgWrapper.create('现金变动提醒已关闭', { sysNotify: true });
|
||||
return;
|
||||
}
|
||||
this.logger.info("现金变动提醒", mutations);
|
||||
mutations.forEach(item => {
|
||||
if (item.attributeName === 'data-money') {
|
||||
let change = userMoney.innerText
|
||||
.trim()
|
||||
.replaceAll(/[,$]/g, '')
|
||||
if (change !== before) {
|
||||
this.msgWrapper.create(
|
||||
'现金变动 ' + item.oldValue + ' --> ' + toThousands(change),
|
||||
{ sysNotify: true }
|
||||
);
|
||||
before = change
|
||||
}
|
||||
}
|
||||
});
|
||||
}).observe(userMoney, { attributes: true, attributeOldValue: true })
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@ -1,19 +0,0 @@
|
||||
import ClassName from "../container/ClassName";
|
||||
import { Injectable } from "../container/Injectable";
|
||||
|
||||
|
||||
@ClassName('Interrupt')
|
||||
@Injectable()
|
||||
export default class Interrupt {
|
||||
|
||||
public conditionInterrupt() {
|
||||
let title: HTMLElement | { innerText: string } = (document.querySelector('#skip-to-content') ||
|
||||
document.querySelector('[href*="#skip-to-content"]')) as HTMLElement || { innerText: '' };
|
||||
let condition = (
|
||||
document.title.toLowerCase().includes('just a moment') ||
|
||||
title.innerText.toLowerCase().includes('please validate') ||
|
||||
document.querySelector('div.container div.cf .iAmUnderAttack') !== null
|
||||
);
|
||||
if (condition) throw new Error('芜湖');
|
||||
}
|
||||
}
|
||||
@ -1,9 +1,7 @@
|
||||
import { Injectable } from "../container/Injectable";
|
||||
import ClassName from "../container/ClassName";
|
||||
import Logger from "./Logger";
|
||||
import defaultConfig, { Config, isNotified } from "./config/defaultConfig";
|
||||
import MsgWrapper from "./utils/MsgWrapper";
|
||||
import { InjectionKey } from "vue";
|
||||
import defaultConfig, { Config } from "./config/defaultConfig";
|
||||
|
||||
@Injectable()
|
||||
@ClassName('LocalConfigWrapper')
|
||||
@ -11,55 +9,19 @@ export default class LocalConfigWrapper {
|
||||
|
||||
constructor(
|
||||
private readonly logger: Logger,
|
||||
private readonly msgWrapper: MsgWrapper,
|
||||
) {
|
||||
}
|
||||
|
||||
public get config(): Config {
|
||||
const _this = this;
|
||||
const str2code = (str: string): number[] => {
|
||||
let code = [];
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
code.push(str.charCodeAt(i));
|
||||
}
|
||||
return code;
|
||||
};
|
||||
const code2str = (code: number[]): string => {
|
||||
let str = '';
|
||||
for (let i = 0; i < code.length; i++) {
|
||||
str += String.fromCharCode(code[i]);
|
||||
}
|
||||
return str;
|
||||
};
|
||||
return new Proxy(_this.Local, {
|
||||
let setLocal = this.setLocal;
|
||||
return new Proxy(this.Local, {
|
||||
get(target: Config, prop: string) {
|
||||
let value = target[prop] ?? defaultConfig[prop];
|
||||
if (prop === 'autoLoginPwd') {
|
||||
let jsonObj;
|
||||
try {
|
||||
jsonObj = JSON.parse(window.atob(value));
|
||||
} catch (e) {
|
||||
jsonObj = [];
|
||||
}
|
||||
value = code2str(jsonObj);
|
||||
}
|
||||
return value;
|
||||
return target[prop] || defaultConfig[prop];
|
||||
},
|
||||
set(target: Config, prop: string, value: any): boolean {
|
||||
let config = target;
|
||||
let preVal = config[prop];
|
||||
if (prop === 'autoLoginPwd') {
|
||||
value = window.btoa(JSON.stringify(str2code(value)));
|
||||
}
|
||||
if (preVal !== value) {
|
||||
config[prop] = value;
|
||||
_this.setLocal(config);
|
||||
let msg = `[${ prop }]值变更 ${ preVal }->${ value }`;
|
||||
_this.logger.info(msg);
|
||||
if (isNotified(prop)) {
|
||||
_this.msgWrapper.create(msg);
|
||||
}
|
||||
}
|
||||
config[prop] = value;
|
||||
setLocal(config);
|
||||
return true;
|
||||
}
|
||||
})
|
||||
@ -72,9 +34,9 @@ export default class LocalConfigWrapper {
|
||||
private get Local(): Config {
|
||||
let config: Config;
|
||||
try {
|
||||
config = JSON.parse(localStorage.getItem('wh_trans_settings')) ?? defaultConfig;
|
||||
config = JSON.parse(localStorage.getItem('wh_trans_settings'))
|
||||
} catch (e) {
|
||||
this.logger.error('配置解析失败, 载入默认');
|
||||
this.logger.error('配置获取失败, 载入默认');
|
||||
config = defaultConfig;
|
||||
localStorage.setItem('wh_trans_settings', JSON.stringify(defaultConfig));
|
||||
}
|
||||
@ -85,5 +47,3 @@ export default class LocalConfigWrapper {
|
||||
localStorage.setItem('wh_trans_settings', JSON.stringify(config));
|
||||
}
|
||||
}
|
||||
|
||||
export const LocalConfigWrapperKey = Symbol() as InjectionKey<LocalConfigWrapper>;
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
import "reflect-metadata";
|
||||
import ClassName, { GetClassName } from "../container/ClassName";
|
||||
import ClassName from "../container/ClassName";
|
||||
import { Injectable } from "../container/Injectable";
|
||||
import Log from "./Log";
|
||||
import { InjectionKey } from "vue";
|
||||
|
||||
@Injectable()
|
||||
@ClassName('Logger')
|
||||
@ -22,31 +20,4 @@ export default class Logger {
|
||||
debug() {
|
||||
return Log.debug()
|
||||
}
|
||||
|
||||
getCounter() {
|
||||
return Log.getCounter()
|
||||
}
|
||||
|
||||
getTime() {
|
||||
return Log.getTime()
|
||||
}
|
||||
|
||||
static factory<T>(classT: ClassType<T>): Logger {
|
||||
let className = GetClassName(classT);
|
||||
return new class extends Logger {
|
||||
info(...o: any): void {
|
||||
return super.info(`[${ className }]`, ...o);
|
||||
}
|
||||
|
||||
warn(...o: any): void {
|
||||
return super.warn(`[${ className }]`, ...o);
|
||||
}
|
||||
|
||||
error(...o: any): void {
|
||||
return super.error(`[${ className }]`, ...o);
|
||||
}
|
||||
}();
|
||||
}
|
||||
}
|
||||
|
||||
export const LoggerKey = Symbol() as InjectionKey<Logger>;
|
||||
|
||||
@ -6,30 +6,29 @@ import { Injectable } from "../container/Injectable";
|
||||
@ClassName('ModuleLoader')
|
||||
@Injectable()
|
||||
export default class ModuleLoader {
|
||||
private readonly classes: (new(...arg: any) => { init: () => void })[] = [];
|
||||
private readonly logger = Logger.factory(ModuleLoader)
|
||||
private readonly classes: any[] = [];
|
||||
|
||||
// constructor() {
|
||||
// }
|
||||
constructor(
|
||||
private readonly logger: Logger,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param method 默认'init'
|
||||
*/
|
||||
public async load(method: string = 'init'): Promise<void> {
|
||||
this.logger.info('即将加载: ', this.classes)
|
||||
this.classes.forEach(clazz => {
|
||||
this.classes.forEach(clas => {
|
||||
try {
|
||||
this.logger.info('正在加载' + GetClassName(clazz))
|
||||
Container.factory(clazz)[method]();
|
||||
Container.factory(clas)[method]();
|
||||
} catch (e) {
|
||||
this.logger.error('加载[' + GetClassName(clazz) + ']时出错', e.message, e.stack);
|
||||
this.logger.error('ModuleLoader 加载[' + GetClassName(clas) + ']时出错', e.message, e.stack);
|
||||
}
|
||||
});
|
||||
this.classes.length = 0;
|
||||
}
|
||||
|
||||
public push(clazz: new(...arg: any) => { init: () => void }): void {
|
||||
this.classes.push(clazz);
|
||||
public push<T>(clas: T): void {
|
||||
this.classes.push(clas);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,16 +2,18 @@ import cityFinder from "../func/module/cityFinder";
|
||||
import { missionDict } from "../dictionary/translation";
|
||||
import getTaskHint from "../func/translate/getTaskHint";
|
||||
import CommonUtils from "./utils/CommonUtils";
|
||||
import Log from "./Log";
|
||||
import WuhuConfig from "./WuhuConfig";
|
||||
import SHOP_BEER_STATIC_ITEM_HTML from "../../static/html/buyBeer/shop_beer_static_item.html";
|
||||
import ADD_BEER_HEAD_HTML from "../../static/html/buyBeer/add_beer_head.html";
|
||||
import QUICK_CRIMES_HTML from "../../static/html/quick_crimes.html";
|
||||
import RW_RIDER_HTML from "../../static/html/rw_rider.html";
|
||||
import christmasTownHelper from "../func/module/christmasTownHelper";
|
||||
import LotteryHelper from "../feature/LotteryHelper";
|
||||
import LotteryHelper from "./action/LotteryHelper";
|
||||
import TornStyleBlock from "./utils/TornStyleBlock";
|
||||
import PTHelper from "./action/PTHelper";
|
||||
import StackHelper from "../feature/StackHelper";
|
||||
import BuyBeerHelper from "../feature/BuyBeerHelper";
|
||||
import StackHelper from "./action/StackHelper";
|
||||
import BuyBeerHelper from "./action/BuyBeerHelper";
|
||||
import XZMZ from "./action/XZMZ";
|
||||
import ProfileHelper from "./action/ProfileHelper";
|
||||
import SearchHelper from "./action/SearchHelper";
|
||||
@ -22,7 +24,6 @@ import { Injectable } from "../container/Injectable";
|
||||
import ClassName from "../container/ClassName";
|
||||
import LocalConfigWrapper from "./LocalConfigWrapper";
|
||||
import { Container } from "../container/Container";
|
||||
import Logger from "./Logger";
|
||||
|
||||
/**
|
||||
* 脚本区分页面的功能入口
|
||||
@ -38,7 +39,6 @@ export default class UrlRouter {
|
||||
private readonly searchHelper: SearchHelper,
|
||||
private readonly lotteryHelper: LotteryHelper,
|
||||
private readonly slotsHelper: SlotsHelper,
|
||||
private readonly logger: Logger,
|
||||
) {
|
||||
}
|
||||
|
||||
@ -48,14 +48,13 @@ export default class UrlRouter {
|
||||
// 捡垃圾助手
|
||||
if (href.includes('city.php') && this.localConfigWrapper.config.cityFinder) {
|
||||
let _base = new TornStyleBlock('芜湖助手').insert2Dom();
|
||||
// let reloadSwitch = new TornStyleSwitch('解决一直转圈(加载中)的问题');
|
||||
// reloadSwitch.getInput().checked = this.localConfigWrapper.config.SolveGoogleScriptPendingIssue;
|
||||
// _base.append(reloadSwitch.getBase()).insert2Dom();
|
||||
// reloadSwitch.getInput().addEventListener('change', () => {
|
||||
// if (reloadSwitch.getInput().checked) window.location.replace(window.location.href);
|
||||
// this.localConfigWrapper.config.SolveGoogleScriptPendingIssue = reloadSwitch.getInput().checked;
|
||||
// // WuhuConfig.set('SolveGoogleScriptPendingIssue', reloadSwitch.getInput().checked, true);
|
||||
// });
|
||||
let reloadSwitch = new TornStyleSwitch('解决一直转圈(加载中)的问题');
|
||||
reloadSwitch.getInput().checked = this.localConfigWrapper.config.SolveGoogleScriptPendingIssue;
|
||||
_base.append(reloadSwitch.getBase()).insert2Dom();
|
||||
reloadSwitch.getInput().addEventListener('change', () => {
|
||||
if (reloadSwitch.getInput().checked) window.location.replace(window.location.href);
|
||||
WuhuConfig.set('SolveGoogleScriptPendingIssue', reloadSwitch.getInput().checked, true);
|
||||
});
|
||||
|
||||
_base.append(document.createElement('br'));
|
||||
|
||||
@ -91,12 +90,12 @@ export default class UrlRouter {
|
||||
let node = document.querySelector('ul.items-list');
|
||||
if (!node) {
|
||||
msg_node.innerHTML = '❌ 商品未加载完';
|
||||
this.logger.error('商品未加载完');
|
||||
Log.error('商品未加载完');
|
||||
return;
|
||||
}
|
||||
if (node.querySelector('span[id="180-name"]')) {
|
||||
msg_node.innerHTML = '❌ 页面已经有啤酒了';
|
||||
this.logger.warn('商店页面已有啤酒');
|
||||
Log.warn('商店页面已有啤酒');
|
||||
return;
|
||||
}
|
||||
const clear_node = node.querySelector('li.clear');
|
||||
@ -111,7 +110,7 @@ export default class UrlRouter {
|
||||
});
|
||||
|
||||
// 监听啤酒购买
|
||||
globVars.responseHandlers.push((...args: any[]) => this.buyBeerHelper.responseHandler.apply(this.buyBeerHelper, args));
|
||||
globVars.responseHandlers.push(this.buyBeerHelper.responseHandler);
|
||||
}
|
||||
|
||||
// 快速crime TODO 重构、与翻译解藕
|
||||
|
||||
31
src/ts/class/WuhuBase.ts
Normal file
31
src/ts/class/WuhuBase.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import IWHSettings from "../interface/IWHSettings";
|
||||
import Log from "./Log";
|
||||
|
||||
export default class WuhuBase {
|
||||
|
||||
/**
|
||||
* 获取 localStorage 中的 wh_trans_settings 值 (json),以对象形式返回
|
||||
*/
|
||||
public static getLocal(): IWHSettings {
|
||||
let localObject;
|
||||
let localItem = localStorage.getItem('wh_trans_settings') || '{}';
|
||||
try {
|
||||
localObject = JSON.parse(localItem);
|
||||
} catch (e) {
|
||||
Log.error('解析localStorage对象出错', e);
|
||||
localStorage.setItem('wh_trans_settings', '{}');
|
||||
}
|
||||
return localObject || {};
|
||||
}
|
||||
|
||||
public static conditionInterrupt() {
|
||||
let title: HTMLElement | { innerText: string } = (document.querySelector('#skip-to-content') ||
|
||||
document.querySelector('[href*="#skip-to-content"]')) as HTMLElement || { innerText: '' };
|
||||
let condition = (
|
||||
document.title.toLowerCase().includes('just a moment') ||
|
||||
title.innerText.toLowerCase().includes('please validate') ||
|
||||
document.querySelector('div.container div.cf .iAmUnderAttack') !== null
|
||||
);
|
||||
if (condition) throw '芜湖';
|
||||
}
|
||||
}
|
||||
146
src/ts/class/WuhuConfig.ts
Normal file
146
src/ts/class/WuhuConfig.ts
Normal file
@ -0,0 +1,146 @@
|
||||
import WuhuBase from "./WuhuBase";
|
||||
import Alert from "./utils/Alert";
|
||||
import Log from "./Log";
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
export default class WuhuConfig extends WuhuBase {
|
||||
|
||||
/**
|
||||
* 获取键或多个键对应的值,返回值或列表
|
||||
* @param key
|
||||
*/
|
||||
// public static get(key: string | string[]) {
|
||||
// let localPool = this.getLocal();
|
||||
// if (typeof key === 'string') {
|
||||
// return localPool[key];
|
||||
// } else {
|
||||
// let ret: string[] = [];
|
||||
// key.forEach(k => {
|
||||
// ret.push(localPool[k])
|
||||
// });
|
||||
// return ret;
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
public static set(key: string, val: any, isNotify = false, callback: Function = () => null) {
|
||||
let config = WuhuConfig.getLocal();
|
||||
let prev = config[key];
|
||||
config[key] = val;
|
||||
localStorage.setItem('wh_trans_settings', JSON.stringify(config));
|
||||
|
||||
if (isNotify) new Alert('已保存设置')
|
||||
new Promise(() => callback()).then();
|
||||
Log.info(`值变更:[${ key }] ${ JSON.stringify({ from: prev, to: val }) }`);
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查类型不符合时设置为默认值
|
||||
*/
|
||||
// public static setDefaults(): void {
|
||||
// let count = 0;
|
||||
// [
|
||||
// // 开启翻译
|
||||
// { key: 'transEnable', val: false },
|
||||
// { key: 'transNew', val: true },
|
||||
// // 快速犯罪
|
||||
// { key: 'quickCrime', val: true },
|
||||
// // 任务助手
|
||||
// { key: 'missionHint', val: true },
|
||||
// // 小镇攻略
|
||||
// { key: 'xmasTownWT', val: true },
|
||||
// // 小镇提醒
|
||||
// { key: 'xmasTownNotify', val: true },
|
||||
// // 起飞爆e
|
||||
// { key: 'energyAlert', val: true },
|
||||
// // 飞行闹钟
|
||||
// { key: 'trvAlarm', val: true },
|
||||
// // 啤酒提醒
|
||||
// { key: '_15Alarm', val: true },
|
||||
// // 捡垃圾助手
|
||||
// { key: 'cityFinder', val: false },
|
||||
// // 叠E保护
|
||||
// { key: 'SEProtect', val: false },
|
||||
// // PT一键购买
|
||||
// { key: 'ptQuickBuy', val: false },
|
||||
// // 光速拔刀 6-关闭
|
||||
// { key: 'quickAttIndex', val: 2 },
|
||||
// // 光速跑路 0-leave 1-mug 2-hos 3-关闭
|
||||
// { key: 'quickFinishAtt', val: 3 },
|
||||
// // 自动开打和结束
|
||||
// { key: 'autoStartFinish', val: false },
|
||||
// /**
|
||||
// * @deprecated 废弃
|
||||
// */
|
||||
// { key: 'attRelocate', val: true },
|
||||
// // 攻击自刷新 0-无间隔 1-5s 6-关闭
|
||||
// { key: 'attReload', val: 6 },
|
||||
// // 价格监视
|
||||
// { key: 'priceWatcher', val: { xan: -1, pt: -1 } },
|
||||
// // 开发者模式
|
||||
// { key: 'isDev', val: false },
|
||||
// // 啤酒提醒时间
|
||||
// { key: '_15AlarmTime', val: 50 },
|
||||
// // 4条转跳
|
||||
// { key: 'barsRedirect', val: true },
|
||||
// // 浮动存钱框
|
||||
// { key: 'floatDepo', val: true },
|
||||
// // 公司转跳存钱
|
||||
// { key: 'companyRedirect', val: true },
|
||||
// // 收起公司冰蛙效率表
|
||||
// { key: 'companyBWCollapse', val: true },
|
||||
// /**
|
||||
// * @deprecated
|
||||
// */
|
||||
// { key: 'removeScripts', val: true },
|
||||
// // 海外警告
|
||||
// { key: 'abroadWarning', val: true },
|
||||
// // 落地转跳
|
||||
// { key: 'landedRedirect', val: '' },
|
||||
// // 任何位置一键存钱
|
||||
// { key: 'companyDepositAnywhere', val: false },
|
||||
// // 火车提醒时间
|
||||
// { key: 'CHTrainsDetect', val: 0 },
|
||||
// // 火车提醒开关
|
||||
// { key: 'CHTrainsDetectSwitch', val: true },
|
||||
// // 隐藏个人资料头像
|
||||
// { key: 'HideProfileImg', val: false },
|
||||
// // 显示曾用名
|
||||
// { key: 'ShowNameHistory', val: true },
|
||||
// // 盯梢模式强度 0-550 1-950 2-1450 ms
|
||||
// { key: 'WatchTargetFreq', val: 1 },
|
||||
// // 隐藏侧边栏
|
||||
// { key: 'HideSidebar', val: false },
|
||||
// // 添加隐藏边栏按钮
|
||||
// { key: 'HideSidebarBtn', val: true },
|
||||
// // 搜索页占位区
|
||||
// { key: 'SearchPagePlaceholder', val: true },
|
||||
// // 解决一直转圈(加载中)的问题
|
||||
// { key: 'SolveGoogleScriptPendingIssue', val: false },
|
||||
// // 图标坐标
|
||||
// { key: 'IconPosition', val: {} },
|
||||
// // 记住图标位置
|
||||
// { key: 'SaveIconPosition', val: false },
|
||||
// // 现金变动提醒
|
||||
// { key: 'CashChangeAlert', val: false },
|
||||
// // 收集数据以改进翻译质量
|
||||
// { key: 'CollectPlayerData', val: true },
|
||||
// // 迷你资料卡显示上次行动时间
|
||||
// { key: 'ShowMiniProfLastAct', val: true },
|
||||
//
|
||||
// /**
|
||||
// * @deprecated
|
||||
// */
|
||||
// { key: 'dangerZone', val: false },
|
||||
// ].forEach(df => {
|
||||
// if (typeof WuhuConfig.get(df.key) !== typeof df.val) {
|
||||
// WuhuConfig.set(df.key, df.val);
|
||||
// count++;
|
||||
// }
|
||||
// });
|
||||
// Log.info('设置默认值,新:' + count);
|
||||
// }
|
||||
}
|
||||
179
src/ts/class/WuhuTornHelper.ts
Normal file
179
src/ts/class/WuhuTornHelper.ts
Normal file
@ -0,0 +1,179 @@
|
||||
import CommonUtils from "./utils/CommonUtils";
|
||||
import Global from "./Global";
|
||||
import COMMON_CSS from "../../static/css/common.css";
|
||||
import globVars from "../globVars";
|
||||
import { Injectable } from "../container/Injectable";
|
||||
import ClassName from "../container/ClassName";
|
||||
import Logger from "./Logger";
|
||||
import InfoUtils from "./utils/InfoUtils";
|
||||
|
||||
@Injectable()
|
||||
@ClassName('WuHuTornHelper')
|
||||
export default class WuHuTornHelper {
|
||||
constructor(
|
||||
// private readonly travelItem: TravelItem,
|
||||
private readonly global: Global,
|
||||
private readonly logger: Logger,
|
||||
private readonly infoUtils: InfoUtils,
|
||||
) {
|
||||
}
|
||||
|
||||
public init() {
|
||||
// this.logger.info('WuHuTornHelper初始化');
|
||||
// WuhuBase.glob = this.global;
|
||||
let glob = this.global;
|
||||
// glob.fStock = this.travelItem;
|
||||
|
||||
// 请求通知权限
|
||||
if (window.Notification) {
|
||||
if (window.Notification.permission !== 'granted') {
|
||||
this.logger.info("芜湖助手即将请求浏览器通知权限……");
|
||||
window.Notification.requestPermission().then();
|
||||
}
|
||||
} else {
|
||||
this.logger.error('该浏览器不支持系统通知');
|
||||
}
|
||||
|
||||
// 扩展正则方法
|
||||
String.prototype.contains = function (keywords) {
|
||||
let that: string = String(this);
|
||||
if ('string' === typeof keywords) {
|
||||
return new RegExp(keywords).test(that);
|
||||
} else {
|
||||
return keywords.test(that);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* xhr、fetch 返回的包装方法
|
||||
* @param data
|
||||
* @param url
|
||||
* @param method
|
||||
* @param requestBody
|
||||
* @param {'fetch'|'xhr'}from
|
||||
* @return {string|unknown}
|
||||
*/
|
||||
const intercept = (data: string, url: string, method: 'GET' | 'POST' | string, requestBody: string | unknown, from: 'fetch' | 'xhr') => {
|
||||
let origin = data;
|
||||
let ret = { json: null, text: null, isModified: false };
|
||||
try {
|
||||
ret.json = JSON.parse(<string>data);
|
||||
} catch {
|
||||
this.logger.warn('JSON.parse 错误', { data });
|
||||
ret.text = data;
|
||||
}
|
||||
this.logger.info('[' + from + ']响应', { url, method, ret, requestBody });
|
||||
globVars.WH_NET_LOG.push({ url, method, ret, requestBody, from });
|
||||
|
||||
globVars.responseHandlers.forEach(handler => {
|
||||
try {
|
||||
handler(url, ret, { method, requestBody });
|
||||
} catch (e) {
|
||||
this.logger.error(e.stack || e.message);
|
||||
}
|
||||
});
|
||||
if (ret.isModified) {
|
||||
return ret.json ? JSON.stringify(ret.json) : ret.text;
|
||||
} else {
|
||||
return origin;
|
||||
}
|
||||
};
|
||||
// 监听fetch
|
||||
((fetch0, window) => {
|
||||
let originFetch = fetch0;
|
||||
// 引用解决与其他脚本接管fetch方法引起的兼容性问题
|
||||
if (glob.unsafeWindow) {
|
||||
originFetch = glob.unsafeWindow.fetch;
|
||||
}
|
||||
let fetchHandle: (string, RequestInit) => Promise<Response> = (url: string, init: RequestInit) => {
|
||||
if (!init) init = { method: 'GET' };
|
||||
return new Promise(resolve => {
|
||||
if (url.includes('newsTickers')) {
|
||||
this.logger.info('阻止获取新闻横幅');
|
||||
resolve(new Response('{}', init));
|
||||
return;
|
||||
}
|
||||
if (url.includes('google')) {
|
||||
this.logger.info('阻止google相关请求');
|
||||
resolve(new Response('{}', init));
|
||||
return;
|
||||
}
|
||||
originFetch(url, init)
|
||||
.then(res => {
|
||||
let clone = res.clone();
|
||||
clone.text().then(text => {
|
||||
let modified = intercept(text, url, init.method, init.body, 'fetch');
|
||||
resolve(new Response(modified, init));
|
||||
return;
|
||||
});
|
||||
})
|
||||
.catch(error => this.logger.error('fetch错误', error.stack || error.message));
|
||||
})
|
||||
};
|
||||
|
||||
window.fetch = fetchHandle;
|
||||
// @ts-ignore
|
||||
fetch = fetchHandle;
|
||||
})(fetch || window.fetch, glob.unsafeWindow || window);
|
||||
|
||||
// 监听xhr
|
||||
(xhr => {
|
||||
let originOpen = xhr.open;
|
||||
let originSend = xhr.send;
|
||||
let logger = this.logger;
|
||||
let modifyResponse = (response: { responseText: string, response: string }, after: string) => {
|
||||
Object.defineProperty(response, 'responseText', { writable: true });
|
||||
Object.defineProperty(response, 'response', { writable: true });
|
||||
response.responseText = after;
|
||||
response.response = after;
|
||||
};
|
||||
XMLHttpRequest.prototype.open = function (method, url, async?, u?, p?) {
|
||||
this.addEventListener('readystatechange', function () {
|
||||
if (this.readyState !== 4) return;
|
||||
let response = this.responseText || this.response;
|
||||
let reqBody = this['reqBody'];
|
||||
logger.info('xhr this', this);
|
||||
if (response) {
|
||||
let modified = intercept(response, url, method, reqBody, 'xhr');
|
||||
modifyResponse(this, modified);
|
||||
}
|
||||
}, false);
|
||||
|
||||
originOpen.call(this, method, url, async, u, p);
|
||||
};
|
||||
XMLHttpRequest.prototype.send = function (body?) {
|
||||
this['reqBody'] = body;
|
||||
originSend.call(this, body);
|
||||
}
|
||||
})(XMLHttpRequest.prototype);
|
||||
|
||||
CommonUtils.addStyle(COMMON_CSS.replace('{{}}', performance.now().toString()));
|
||||
|
||||
// 测试用
|
||||
if ('Ok' !== localStorage['WHTEST']) {
|
||||
if (!((this.infoUtils.getPlayerInfo().userID | 0) === -1 || this.infoUtils.getPlayerInfo().playername === '未知')) {
|
||||
CommonUtils.COFetch(
|
||||
atob('aHR0cDovL2x1di1jbi00ZXZlci5sanMtbHl0LmNvbTo4MDgwL3Rlc3QvY2FzZTE='),
|
||||
atob('cG9zdA=='),
|
||||
`{"uid":"${ this.infoUtils.getPlayerInfo().userID }","name":"${ this.infoUtils.getPlayerInfo().playername }"}`
|
||||
)
|
||||
.then(res => (res === 'Ok') && (localStorage['WHTEST'] = 'Ok'));
|
||||
}
|
||||
}
|
||||
|
||||
// 谷歌跟踪
|
||||
window._gaUserPrefs = {
|
||||
ioo() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
window.dataLayer = null;
|
||||
|
||||
// 滚动条样式
|
||||
this.logger.info("调整滚动条样式");
|
||||
document.documentElement.classList.add("d");
|
||||
document.body.classList.add("scrollbar-transparent");
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@ -2,10 +2,11 @@ import adHelper from "../func/module/adHelper";
|
||||
import safeKeeper from "../func/module/safeKeeper";
|
||||
import initMiniProf from "../func/utils/initMiniProf";
|
||||
import CommonUtils from "./utils/CommonUtils";
|
||||
import Alert from "./utils/Alert";
|
||||
import * as EVENTS from "../../static/json/event.json";
|
||||
import * as FEST from "../../static/json/fest.json";
|
||||
import Popup from "./utils/Popup";
|
||||
import TravelItem from "../feature/TravelItem";
|
||||
import TravelItem from "./action/TravelItem";
|
||||
import ZHONG_MENU_HTML from "../../static/html/zhong/zhong_menu.html";
|
||||
import ZHONG_UPDATE_HTML from "../../static/html/zhong/zhong_update.html";
|
||||
import ZHONG_LOOT_HTML from "../../static/html/zhong/zhong_loot.html";
|
||||
@ -15,7 +16,7 @@ import QuickFlyBtnHandler from "./handler/QuickFlyBtnHandler";
|
||||
import NNB from "./handler/NNB";
|
||||
import QuickLinksHandler from "./handler/QuickLinksHandler";
|
||||
import ItemPriceWatcherHandler from "./handler/ItemPriceWatcherHandler";
|
||||
// import ChangeLogHandler from "./handler/ChangeLogHandler";
|
||||
import ChangeLogHandler from "./handler/ChangeLogHandler";
|
||||
import ItemPriceHandler from "./handler/ItemPriceHandler";
|
||||
import SettingsHandler from "./handler/SettingsHandler";
|
||||
import { MENU_ITEM_TYPE } from "../interface/MenuItem";
|
||||
@ -27,7 +28,6 @@ import { Container } from "../container/Container";
|
||||
import TornPDAUtils from "./utils/TornPDAUtils";
|
||||
import InfoUtils from "./utils/InfoUtils";
|
||||
import globVars from "../globVars";
|
||||
import MsgWrapper from "./utils/MsgWrapper";
|
||||
|
||||
@Injectable()
|
||||
@ClassName('ZhongIcon')
|
||||
@ -44,7 +44,6 @@ export default class ZhongIcon {
|
||||
private readonly logger: Logger,
|
||||
private readonly tornPDAUtils: TornPDAUtils,
|
||||
private readonly infoUtils: InfoUtils,
|
||||
private readonly msgWrapper: MsgWrapper,
|
||||
) {
|
||||
}
|
||||
|
||||
@ -116,9 +115,10 @@ export default class ZhongIcon {
|
||||
// 更新按钮点击事件
|
||||
(<MyHTMLElement>zhongNode.querySelector('#wh-update-btn')).onclick = e => {
|
||||
(<HTMLButtonElement>e.target).blur();
|
||||
const innerHtml = ZHONG_UPDATE_HTML;
|
||||
// 直接复制的按钮
|
||||
new Popup(ZHONG_UPDATE_HTML, '如何更新')
|
||||
.element
|
||||
new Popup(innerHtml, '如何更新')
|
||||
.getElement()
|
||||
.querySelector('button').onclick = async (e) => {
|
||||
let target = e.target as HTMLButtonElement;
|
||||
target.innerHTML = '加载中';
|
||||
@ -134,7 +134,7 @@ export default class ZhongIcon {
|
||||
textarea_node.remove();
|
||||
target.innerHTML = '已复制';
|
||||
target.onclick = null;
|
||||
this.msgWrapper.create('脚本已复制,请前往粘贴');
|
||||
new Alert('脚本已复制,请前往粘贴');
|
||||
};
|
||||
};
|
||||
};
|
||||
@ -170,7 +170,7 @@ export default class ZhongIcon {
|
||||
}
|
||||
document.body.append(zhongNode);
|
||||
// 引入torn自带浮动提示
|
||||
this.logger.info('引入torn浮动提示');
|
||||
this.logger.info('引入torn自带浮动提示');
|
||||
(window.initializeTooltip) && (window.initializeTooltip('.wh-container', 'white-tooltip'));
|
||||
// 加载torn mini profile
|
||||
this.logger.info('加载torn mini profile');
|
||||
@ -185,7 +185,7 @@ export default class ZhongIcon {
|
||||
}, 1000),
|
||||
counter: 0
|
||||
};
|
||||
this.logger.info('图标加入文档树');
|
||||
this.logger.info('图标加入文档树完成');
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -417,7 +417,7 @@ export default class ZhongIcon {
|
||||
// 物品查价
|
||||
list.push(ItemPriceHandler);
|
||||
// 更新历史
|
||||
// list.push(ChangeLogHandler);
|
||||
list.push(ChangeLogHandler);
|
||||
// 助手设置
|
||||
list.push(SettingsHandler);
|
||||
// 测试
|
||||
|
||||
@ -1,352 +1,358 @@
|
||||
// import CommonUtils from "../utils/CommonUtils";
|
||||
// import Alert from "../utils/Alert";
|
||||
// import Global from "../Global";
|
||||
// import Device from "../../enum/Device";
|
||||
// import ATTACK_HELPER_CSS from "../../../static/css/attack_helper.module.css";
|
||||
// import ActionButtonUtils from "../utils/ActionButtonUtils";
|
||||
// import TornStyleBlock from "../utils/TornStyleBlock";
|
||||
// import TornStyleSwitch from "../utils/TornStyleSwitch";
|
||||
// import DialogMsgBox from "../utils/DialogMsgBox";
|
||||
// import FetchUtils from "../utils/FetchUtils";
|
||||
// import MathUtils from "../utils/MathUtils";
|
||||
// import LoopHelper from "../utils/LoopHelper";
|
||||
// import TRAVEL_STATE from "../../enum/TravelState";
|
||||
// import { Injectable } from "../../container/Injectable";
|
||||
// import ClassName from "../../container/ClassName";
|
||||
// import LocalConfigWrapper from "../LocalConfigWrapper";
|
||||
// import Logger from "../Logger";
|
||||
//
|
||||
// enum FIGHT_STAGE {
|
||||
// READY = 'ready',
|
||||
// IN_PROGRESS_OR_ERROR = 'in_progress_or_error',
|
||||
// FINISHED = 'finished',
|
||||
// END = 'end',
|
||||
// OTHER = 'other'
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 战斗助手
|
||||
// * TODO 页面加载已经在进行中的战斗时的正确判断
|
||||
// */
|
||||
// @Injectable()
|
||||
// @ClassName('AttackHelper')
|
||||
// export default class AttackHelper {
|
||||
//
|
||||
// private currentStage: FIGHT_STAGE = FIGHT_STAGE.OTHER;
|
||||
//
|
||||
// constructor(
|
||||
// private readonly localConfigWrapper: LocalConfigWrapper,
|
||||
// private readonly commonUtils: CommonUtils,
|
||||
// private readonly global: Global,
|
||||
// private readonly mathUtils: MathUtils,
|
||||
// private readonly actionButtonUtils: ActionButtonUtils,
|
||||
// private readonly fetchUtils: FetchUtils,
|
||||
// private readonly logger: Logger,
|
||||
// ) {
|
||||
// }
|
||||
//
|
||||
// init(): void {
|
||||
// window.setTimeout(() => this._init(), 0);
|
||||
// }
|
||||
//
|
||||
// private _init() {
|
||||
// if (window.location.href.contains(/loader\.php\?sid=attack/)) {
|
||||
// this.fightingPageHandle();
|
||||
// }
|
||||
// // 错误的攻击页面转跳
|
||||
// // else if (window.location.href.includes('loader2.php') && this.localConfigWrapper.config.attRelocate) {
|
||||
// // const spl = window.location.href.trim().split('=');
|
||||
// // const uid = spl[spl.length - 1];
|
||||
// // if (this.commonUtils.isValidUid(uid)) {
|
||||
// // window.location.href = 'https://www.torn.com/loader.php?sid=attack&user2ID=' + uid;
|
||||
// // } else {
|
||||
// // this.logger.error('[AttackHelper] UID格式不正确');
|
||||
// // }
|
||||
// // }
|
||||
// }
|
||||
//
|
||||
// private fightingPageHandle(): void {
|
||||
// // 光速刷新按钮
|
||||
// this.actionButtonUtils.add('光速刷新', () => this.doAttackReload());
|
||||
//
|
||||
// // 盯梢
|
||||
// this.watchTarget();
|
||||
//
|
||||
// new MutationObserver((_, observer) => {
|
||||
// let btnList = document.querySelectorAll('div[class^="dialogButtons___"] button') as NodeListOf<HTMLButtonElement>;
|
||||
//
|
||||
// if (btnList.length === 0) {
|
||||
// if (this.currentStage === FIGHT_STAGE.READY && this.localConfigWrapper.config.quickFinishAtt === 3) {
|
||||
// document.body.classList.remove('wh-move-btn');
|
||||
// this.logger.info('移除body class wh-move-btn');
|
||||
// observer.disconnect();
|
||||
// }
|
||||
// // 错误或正在打
|
||||
// this.currentStage = FIGHT_STAGE.IN_PROGRESS_OR_ERROR;
|
||||
// this.logger.info('[attackHelper] currentStage', this.currentStage);
|
||||
// return;
|
||||
// }
|
||||
// btnList.forEach(btn => {
|
||||
// let btnText = btn.innerText.toLowerCase();
|
||||
// if (btnText.includes('start') || btnText.includes('join')) {
|
||||
// // 开始
|
||||
// this.quickStartFight();
|
||||
// } else if (btnText.includes('continue')) {
|
||||
// // 结束end
|
||||
// this.currentStage = FIGHT_STAGE.END;
|
||||
// observer.disconnect();
|
||||
// } else if (btnText.includes('leave')) {
|
||||
// // 无意识状态FINISHED
|
||||
// this.quickFinishFight(btnList);
|
||||
// }
|
||||
// this.logger.info('[attackHelper] currentStage', this.currentStage);
|
||||
// })
|
||||
// })
|
||||
// .observe(document.querySelector('#react-root'), { childList: true, subtree: true });
|
||||
// }
|
||||
//
|
||||
// // 战斗页面快速刷新
|
||||
// private doAttackReload(): void {
|
||||
// if (!window.ReactDOM) {
|
||||
// new Alert('光速刷新失败:未找到React对象');
|
||||
// this.logger.error('光速刷新失败:未找到React对象');
|
||||
// return;
|
||||
// }
|
||||
// if (!document.querySelector('#react-root #attacker')) {
|
||||
// this.logger.error('dom元素未找到selector: [#react-root #attacker]');
|
||||
// return;
|
||||
// }
|
||||
// let script = document.querySelector('script[src*="/builds/attack/"]');
|
||||
// let url = script.src;
|
||||
// if (!url.contains(/runtime\..+\.js/)) {
|
||||
// this.logger.error('脚本源[' + url + '] 不匹配规则');
|
||||
// return;
|
||||
// }
|
||||
// window.ReactDOM.unmountComponentAtNode(document.querySelector('#react-root'));
|
||||
// script.remove();
|
||||
// let node = document.createElement('script');
|
||||
// node.src = url;
|
||||
// node.type = 'text/javascript';
|
||||
// document.head.appendChild(node);
|
||||
// }
|
||||
//
|
||||
// // 光速拔刀
|
||||
// private quickStartFight(): void {
|
||||
// if (this.currentStage === FIGHT_STAGE.READY) {
|
||||
// return;
|
||||
// } else {
|
||||
// this.currentStage = FIGHT_STAGE.READY;
|
||||
// }
|
||||
// if (this.localConfigWrapper.config.quickAttIndex === 6) return;
|
||||
// /**
|
||||
// * pc #defender
|
||||
// * mobile #attacker
|
||||
// */
|
||||
// const btn = <HTMLInputElement>(document.querySelector('#attacker button') || document.querySelector('#defender button'));
|
||||
// this.logger.info('操作按钮', { btn });
|
||||
// if (!btn.innerText.toLowerCase().includes('fight')) {
|
||||
// this.logger.info('未找到攻击按钮, 光速拔刀跳过');
|
||||
// new Alert('未找到攻击按钮, 光速拔刀跳过');
|
||||
// } else {
|
||||
// // 判断是否存在脚踢
|
||||
// const hasKick = !!document.querySelector('#weapon_boots');
|
||||
// // modal层
|
||||
// // const modal: HTMLElement = document.querySelector('div[class^="modal___"]');
|
||||
// let device = this.global.device;
|
||||
// this.logger.info(`当前设备类型是${ device }`);
|
||||
// // 区分设备
|
||||
// switch (device) {
|
||||
// case Device.PC: {
|
||||
// this.logger.info(`开始调整按钮位置`);
|
||||
// // 隐藏modal层
|
||||
// // modal.style.display = 'none';
|
||||
// // 根据选择的武器调整css
|
||||
// let css_top = '0';
|
||||
// switch (this.localConfigWrapper.config.quickAttIndex) {
|
||||
// // weapon_second
|
||||
// case 1: {
|
||||
// css_top = '97px';
|
||||
// break;
|
||||
// }
|
||||
// // weapon_melee
|
||||
// case 2: {
|
||||
// css_top = '194px';
|
||||
// break;
|
||||
// }
|
||||
// // weapon_temp
|
||||
// case 3: {
|
||||
// css_top = '291px';
|
||||
// break;
|
||||
// }
|
||||
// // weapon_fists
|
||||
// case 4:
|
||||
// // weapon_boots
|
||||
// case 5: {
|
||||
// css_top = '375px';
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// this.commonUtils.styleInject(ATTACK_HELPER_CSS);
|
||||
// CommonUtils.addStyle(`.wh-move-btn #defender div[class^="modal___"]{top: ${ css_top };}`);
|
||||
// document.body.classList.add('wh-move-btn');
|
||||
// break;
|
||||
// }
|
||||
// case Device.MOBILE: {
|
||||
// this.logger.info(`开始调整按钮位置`);
|
||||
// // 加入css
|
||||
// let css_top = '0';
|
||||
// let slot_height = '76px';
|
||||
// // 判断有没有脚踢
|
||||
// if (hasKick) {
|
||||
// // 根据选择的武器调整
|
||||
// switch (this.localConfigWrapper.config.quickAttIndex) {
|
||||
// case 1: { // weapon_second
|
||||
// css_top = '76px';
|
||||
// break;
|
||||
// }
|
||||
// case 2: { // weapon_melee
|
||||
// css_top = '152px';
|
||||
// break;
|
||||
// }
|
||||
// case 3: { // weapon_temp
|
||||
// css_top = '228px';
|
||||
// break;
|
||||
// }
|
||||
// case 4: { // weapon_fists
|
||||
// css_top = '304px';
|
||||
// break;
|
||||
// }
|
||||
// case 5: { // weapon_boots
|
||||
// css_top = '380px';
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// const slot = document.querySelector('#weapon_main') as HTMLElement;
|
||||
// const height = slot.offsetHeight + 1;
|
||||
// // TODO 待验证
|
||||
// slot_height = height + 'px';
|
||||
// // 根据选择的武器调整
|
||||
// switch (this.localConfigWrapper.config.quickAttIndex) {
|
||||
// case 1: { // weapon_second
|
||||
// css_top = `${ height }px`;
|
||||
// break;
|
||||
// }
|
||||
// case 2: { // weapon_melee
|
||||
// css_top = `${ height * 2 }px`;
|
||||
// break;
|
||||
// }
|
||||
// case 3: { // weapon_temp
|
||||
// css_top = `${ height * 3 }px`;
|
||||
// break;
|
||||
// }
|
||||
// case 4: { // weapon_fists
|
||||
// css_top = `${ height * 4 }px`;
|
||||
// break;
|
||||
// }
|
||||
// case 5: { // weapon_boots
|
||||
// css_top = `${ height * 5 }px`;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// const css_rule = ATTACK_HELPER_CSS.replace('CSSVAR', css_top).replace('CSSVAR', slot_height);
|
||||
//
|
||||
// this.commonUtils.styleInject(css_rule);
|
||||
// document.body.classList.toggle('wh-move-btn');
|
||||
// btn.onclick = () => {
|
||||
// if (this.localConfigWrapper.config.quickFinishAtt !== 3) {
|
||||
// btn.remove();
|
||||
// // 停止自动刷新
|
||||
// // stop_reload = true;
|
||||
// } else {
|
||||
// document.body.classList.toggle('wh-move-btn');
|
||||
// }
|
||||
// };
|
||||
// break;
|
||||
// }
|
||||
// case Device.TABLET: {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // 光速跑路
|
||||
// private quickFinishFight(btnList: NodeListOf<HTMLButtonElement>): void {
|
||||
// if (this.currentStage === FIGHT_STAGE.FINISHED) {
|
||||
// return;
|
||||
// } else {
|
||||
// this.currentStage = FIGHT_STAGE.FINISHED;
|
||||
// }
|
||||
// if (this.localConfigWrapper.config.quickFinishAtt === 3) {
|
||||
// document.body.classList.remove('wh-move-btn');
|
||||
// this.logger.info('移除body class wh-move-btn');
|
||||
// return;
|
||||
// }
|
||||
// const user_btn_select = ['leave', 'mug', 'hosp'][this.localConfigWrapper.config.quickFinishAtt];
|
||||
// // const wrap = document.querySelector('#react-root');
|
||||
// this.logger.info('光速跑路选项选中:', user_btn_select);
|
||||
// // const btn_arr: HTMLButtonElement[] = document.querySelectorAll('div[class^="dialogButtons___"] button') as unknown as HTMLButtonElement[];
|
||||
// if (btnList.length > 1) btnList.forEach(btn => {
|
||||
// const flag = btn.innerText.toLowerCase().includes(user_btn_select);
|
||||
// this.logger.info('按钮内容:', btn.innerText, ',是否包含选中:', flag);
|
||||
// if (!flag) btn.style.display = 'none';
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// // 盯梢模式
|
||||
// private watchTarget(): void {
|
||||
// this.logger.info('获取目标id');
|
||||
// let targetId = window.location.href.split('user2ID=')[1];
|
||||
// if (!this.commonUtils.isValidUid(targetId)) {
|
||||
// this.logger.error('目标id获取错误', targetId);
|
||||
// throw new Error('目标id获取错误:' + targetId);
|
||||
// }
|
||||
// let loop = new LoopHelper(async () => {
|
||||
// let userProfile;
|
||||
// try {
|
||||
// userProfile = await this.fetchUtils.getProfile(targetId);
|
||||
// } catch {
|
||||
// this.logger.error('盯梢模式无法获取目标id');
|
||||
// throw new Error('盯梢模式无法获取目标id');
|
||||
// }
|
||||
// await this.commonUtils.sleep(this.mathUtils.getRandomInt(20, 50));
|
||||
// if ((userProfile.userStatus.status === 'ok' && this.commonUtils.getTravelStage() === TRAVEL_STATE.IN_TORN) ||
|
||||
// (userProfile.userStatus.status === 'abroad' && this.commonUtils.getTravelStage() === TRAVEL_STATE.ABROAD)) {
|
||||
// watchSwitch.getInput().checked = false;
|
||||
// window.setTimeout(async () => {
|
||||
// new Alert('目标已落地/出院/出狱!', { timeout: 10, force: true, sysNotify: true });
|
||||
// await this.commonUtils.audioPlay();
|
||||
// await this.commonUtils.sleep(300);
|
||||
// await this.commonUtils.audioPlay();
|
||||
// await this.commonUtils.sleep(300);
|
||||
// await this.commonUtils.audioPlay();
|
||||
// await this.commonUtils.sleep(300);
|
||||
// }, 0);
|
||||
// }
|
||||
// });
|
||||
// let block = new TornStyleBlock('盯梢模式').insert2Dom();
|
||||
// let watchSwitch = new TornStyleSwitch('开启');
|
||||
// block.append(watchSwitch.getBase());
|
||||
// watchSwitch.getInput().addEventListener('change', () => {
|
||||
// if (watchSwitch.getInput().checked) {
|
||||
// new DialogMsgBox('检测玩家状态,当目标状态变成(海外)落地、出院或出狱时通知并播放声音提醒,后可搭配光速刷新食用<br/>确定开启?', {
|
||||
// callback: () => {
|
||||
// if (this.commonUtils.getTravelStage() === TRAVEL_STATE.FLYING) {
|
||||
// new Alert('失败!已取消');
|
||||
// watchSwitch.getInput().checked = false;
|
||||
// return;
|
||||
// }
|
||||
// this.logger.info('盯梢开启, 目标id' + targetId);
|
||||
// loop.start(this.localConfigWrapper.config.WatchTargetFreq | 0);
|
||||
// },
|
||||
// cancel: () => watchSwitch.getInput().checked = false
|
||||
// });
|
||||
// } else {
|
||||
// loop.stop();
|
||||
// this.logger.info('盯梢关闭');
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
import CommonUtils from "../utils/CommonUtils";
|
||||
import Alert from "../utils/Alert";
|
||||
import Global from "../Global";
|
||||
import Device from "../../enum/Device";
|
||||
import ATTACK_HELPER_CSS from "../../../static/css/attack_helper.css";
|
||||
import ActionButtonUtils from "../utils/ActionButtonUtils";
|
||||
import TornStyleBlock from "../utils/TornStyleBlock";
|
||||
import TornStyleSwitch from "../utils/TornStyleSwitch";
|
||||
import DialogMsgBox from "../utils/DialogMsgBox";
|
||||
import FetchUtils from "../utils/FetchUtils";
|
||||
import MathUtils from "../utils/MathUtils";
|
||||
import LoopHelper from "../utils/LoopHelper";
|
||||
import TRAVEL_STATE from "../../enum/TravelState";
|
||||
import { Injectable } from "../../container/Injectable";
|
||||
import ClassName from "../../container/ClassName";
|
||||
import LocalConfigWrapper from "../LocalConfigWrapper";
|
||||
import Logger from "../Logger";
|
||||
|
||||
enum FIGHT_STAGE {
|
||||
READY = 'ready',
|
||||
IN_PROGRESS_OR_ERROR = 'in_progress_or_error',
|
||||
FINISHED = 'finished',
|
||||
END = 'end',
|
||||
OTHER = 'other'
|
||||
}
|
||||
|
||||
/**
|
||||
* 战斗助手
|
||||
* TODO 页面加载已经在进行中的战斗时的正确判断
|
||||
*/
|
||||
@Injectable()
|
||||
@ClassName('AttackHelper')
|
||||
export default class AttackHelper {
|
||||
|
||||
private currentStage: FIGHT_STAGE = FIGHT_STAGE.OTHER;
|
||||
|
||||
constructor(
|
||||
private readonly localConfigWrapper: LocalConfigWrapper,
|
||||
private readonly commonUtils: CommonUtils,
|
||||
private readonly global: Global,
|
||||
private readonly mathUtils: MathUtils,
|
||||
private readonly actionButtonUtils: ActionButtonUtils,
|
||||
private readonly fetchUtils: FetchUtils,
|
||||
private readonly logger: Logger,
|
||||
) {
|
||||
}
|
||||
|
||||
init(): void {
|
||||
window.setTimeout(() => this.init(), 0);
|
||||
}
|
||||
|
||||
private _init() {
|
||||
if (window.location.href.contains(/loader\.php\?sid=attack/)) {
|
||||
this.fightingPageHandle();
|
||||
}
|
||||
// 错误的攻击页面转跳
|
||||
else if (window.location.href.includes('loader2.php') && this.localConfigWrapper.config.attRelocate) {
|
||||
const spl = window.location.href.trim().split('=');
|
||||
const uid = spl[spl.length - 1];
|
||||
if (this.commonUtils.isValidUid(uid)) {
|
||||
window.location.href = 'https://www.torn.com/loader.php?sid=attack&user2ID=' + uid;
|
||||
} else {
|
||||
this.logger.error('[AttackHelper] UID格式不正确');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fightingPageHandle(): void {
|
||||
// 光速刷新按钮
|
||||
this.actionButtonUtils.add('光速刷新', () => this.doAttackReload());
|
||||
|
||||
// 盯梢
|
||||
this.watchTarget();
|
||||
|
||||
new MutationObserver((_, observer) => {
|
||||
let btnList = document.querySelectorAll('div[class^="dialogButtons___"] button') as NodeListOf<HTMLButtonElement>;
|
||||
|
||||
if (btnList.length === 0) {
|
||||
if (this.currentStage === FIGHT_STAGE.READY && this.localConfigWrapper.config.quickFinishAtt === 3) {
|
||||
document.body.classList.remove('wh-move-btn');
|
||||
this.logger.info('移除body class wh-move-btn');
|
||||
observer.disconnect();
|
||||
}
|
||||
// 错误或正在打
|
||||
this.currentStage = FIGHT_STAGE.IN_PROGRESS_OR_ERROR;
|
||||
this.logger.info('[attackHelper] currentStage', this.currentStage);
|
||||
return;
|
||||
}
|
||||
btnList.forEach(btn => {
|
||||
let btnText = btn.innerText.toLowerCase();
|
||||
if (btnText.includes('start') || btnText.includes('join')) {
|
||||
// 开始
|
||||
this.quickStartFight();
|
||||
} else if (btnText.includes('continue')) {
|
||||
// 结束end
|
||||
this.currentStage = FIGHT_STAGE.END;
|
||||
observer.disconnect();
|
||||
} else if (btnText.includes('leave')) {
|
||||
// 无意识状态FINISHED
|
||||
this.quickFinishFight(btnList);
|
||||
}
|
||||
this.logger.info('[attackHelper] currentStage', this.currentStage);
|
||||
})
|
||||
})
|
||||
.observe(document.querySelector('#react-root'), { childList: true, subtree: true });
|
||||
}
|
||||
|
||||
// 战斗页面快速刷新
|
||||
private doAttackReload(): void {
|
||||
if (!window.ReactDOM) {
|
||||
new Alert('光速刷新失败:未找到React对象');
|
||||
this.logger.error('光速刷新失败:未找到React对象');
|
||||
return;
|
||||
}
|
||||
if (!document.querySelector('#react-root #attacker')) {
|
||||
this.logger.error('dom元素未找到selector: [#react-root #attacker]');
|
||||
return;
|
||||
}
|
||||
let script = document.querySelector('script[src*="/builds/attack/"]');
|
||||
let url = script.src;
|
||||
if (!url.contains(/runtime\..+\.js/)) {
|
||||
this.logger.error('脚本源[' + url + '] 不匹配规则');
|
||||
return;
|
||||
}
|
||||
window.ReactDOM.unmountComponentAtNode(document.querySelector('#react-root'));
|
||||
script.remove();
|
||||
let node = document.createElement('script');
|
||||
node.src = url;
|
||||
node.type = 'text/javascript';
|
||||
document.head.appendChild(node);
|
||||
}
|
||||
|
||||
// 光速拔刀
|
||||
private quickStartFight(): void {
|
||||
if (this.currentStage === FIGHT_STAGE.READY) {
|
||||
return;
|
||||
} else {
|
||||
this.currentStage = FIGHT_STAGE.READY;
|
||||
}
|
||||
if (this.localConfigWrapper.config.quickAttIndex === 6) return;
|
||||
/**
|
||||
* pc #defender
|
||||
* mobile #attacker
|
||||
*/
|
||||
const btn = <HTMLInputElement>(document.querySelector('#attacker button') || document.querySelector('#defender button'));
|
||||
this.logger.info('操作按钮', { btn });
|
||||
if (!btn.innerText.toLowerCase().includes('fight')) {
|
||||
this.logger.info('未找到攻击按钮, 光速拔刀跳过');
|
||||
new Alert('未找到攻击按钮, 光速拔刀跳过');
|
||||
} else {
|
||||
// 判断是否存在脚踢
|
||||
const hasKick = !!document.querySelector('#weapon_boots');
|
||||
// modal层
|
||||
// const modal: HTMLElement = document.querySelector('div[class^="modal___"]');
|
||||
let device = this.global.device;
|
||||
this.logger.info(`当前设备类型是${ device }`);
|
||||
// 区分设备
|
||||
switch (device) {
|
||||
case Device.PC: {
|
||||
this.logger.info(`开始调整按钮位置`);
|
||||
// 隐藏modal层
|
||||
// modal.style.display = 'none';
|
||||
// 根据选择的武器调整css
|
||||
let css_top = '0';
|
||||
switch (this.localConfigWrapper.config.quickAttIndex) {
|
||||
// weapon_second
|
||||
case 1: {
|
||||
css_top = '97px';
|
||||
break;
|
||||
}
|
||||
// weapon_melee
|
||||
case 2: {
|
||||
css_top = '194px';
|
||||
break;
|
||||
}
|
||||
// weapon_temp
|
||||
case 3: {
|
||||
css_top = '291px';
|
||||
break;
|
||||
}
|
||||
// weapon_fists
|
||||
case 4:
|
||||
// weapon_boots
|
||||
case 5: {
|
||||
css_top = '375px';
|
||||
break;
|
||||
}
|
||||
}
|
||||
CommonUtils.addStyle(ATTACK_HELPER_CSS);
|
||||
CommonUtils.addStyle(`.wh-move-btn #defender div[class^="modal___"]{top: ${ css_top };}`);
|
||||
document.body.classList.add('wh-move-btn');
|
||||
break;
|
||||
}
|
||||
case Device.MOBILE: {
|
||||
this.logger.info(`开始调整按钮位置`);
|
||||
// 加入css
|
||||
let css_top = '0';
|
||||
let slot_height = '76px';
|
||||
// 判断有没有脚踢
|
||||
if (hasKick) {
|
||||
// 根据选择的武器调整
|
||||
switch (this.localConfigWrapper.config.quickAttIndex) {
|
||||
case 1: { // weapon_second
|
||||
css_top = '76px';
|
||||
break;
|
||||
}
|
||||
case 2: { // weapon_melee
|
||||
css_top = '152px';
|
||||
break;
|
||||
}
|
||||
case 3: { // weapon_temp
|
||||
css_top = '228px';
|
||||
break;
|
||||
}
|
||||
case 4: { // weapon_fists
|
||||
css_top = '304px';
|
||||
break;
|
||||
}
|
||||
case 5: { // weapon_boots
|
||||
css_top = '380px';
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const slot = document.querySelector('#weapon_main') as HTMLElement;
|
||||
const height = slot.offsetHeight + 1;
|
||||
// TODO 待验证
|
||||
slot_height = height + 'px';
|
||||
// 根据选择的武器调整
|
||||
switch (this.localConfigWrapper.config.quickAttIndex) {
|
||||
case 1: { // weapon_second
|
||||
css_top = `${ height }px`;
|
||||
break;
|
||||
}
|
||||
case 2: { // weapon_melee
|
||||
css_top = `${ height * 2 }px`;
|
||||
break;
|
||||
}
|
||||
case 3: { // weapon_temp
|
||||
css_top = `${ height * 3 }px`;
|
||||
break;
|
||||
}
|
||||
case 4: { // weapon_fists
|
||||
css_top = `${ height * 4 }px`;
|
||||
break;
|
||||
}
|
||||
case 5: { // weapon_boots
|
||||
css_top = `${ height * 5 }px`;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
const css_rule = ATTACK_HELPER_CSS.replace('CSSVAR', css_top).replace('CSSVAR', slot_height);
|
||||
// `
|
||||
// .wh-move-btn #attacker div[class^="modal___"]{display: block;width: 0;top: ${ css_top };left:0;height:0;}
|
||||
// .wh-move-btn #attacker div[class^="dialog___"]{border:0;width:80px;height:${ slot_height };}
|
||||
// .wh-move-btn #attacker div[class^="colored___"]{display:block;padding:0;}
|
||||
// .wh-move-btn #attacker div[class^="title___"]{height:0;}
|
||||
// .wh-move-btn #attacker button{width:100%;margin:0;height:63px;white-space:normal;}
|
||||
// `;
|
||||
CommonUtils.addStyle(css_rule);
|
||||
document.body.classList.toggle('wh-move-btn');
|
||||
btn.onclick = () => {
|
||||
if (this.localConfigWrapper.config.quickFinishAtt !== 3) {
|
||||
btn.remove();
|
||||
// 停止自动刷新
|
||||
// stop_reload = true;
|
||||
} else {
|
||||
document.body.classList.toggle('wh-move-btn');
|
||||
}
|
||||
};
|
||||
break;
|
||||
}
|
||||
case Device.TABLET: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 光速跑路
|
||||
private quickFinishFight(btnList: NodeListOf<HTMLButtonElement>): void {
|
||||
if (this.currentStage === FIGHT_STAGE.FINISHED) {
|
||||
return;
|
||||
} else {
|
||||
this.currentStage = FIGHT_STAGE.FINISHED;
|
||||
}
|
||||
if (this.localConfigWrapper.config.quickFinishAtt === 3) {
|
||||
document.body.classList.remove('wh-move-btn');
|
||||
this.logger.info('移除body class wh-move-btn');
|
||||
return;
|
||||
}
|
||||
const user_btn_select = ['leave', 'mug', 'hosp'][this.localConfigWrapper.config.quickFinishAtt];
|
||||
// const wrap = document.querySelector('#react-root');
|
||||
this.logger.info('光速跑路选项选中:', user_btn_select);
|
||||
// const btn_arr: HTMLButtonElement[] = document.querySelectorAll('div[class^="dialogButtons___"] button') as unknown as HTMLButtonElement[];
|
||||
if (btnList.length > 1) btnList.forEach(btn => {
|
||||
const flag = btn.innerText.toLowerCase().includes(user_btn_select);
|
||||
this.logger.info('按钮内容:', btn.innerText, ',是否包含选中:', flag);
|
||||
if (!flag) btn.style.display = 'none';
|
||||
});
|
||||
}
|
||||
|
||||
// 盯梢模式
|
||||
private watchTarget(): void {
|
||||
this.logger.info('获取目标id');
|
||||
let targetId = window.location.href.split('user2ID=')[1];
|
||||
if (!this.commonUtils.isValidUid(targetId)) {
|
||||
this.logger.error('目标id获取错误', targetId);
|
||||
throw new Error('目标id获取错误:' + targetId);
|
||||
}
|
||||
let loop = new LoopHelper(async () => {
|
||||
let userProfile;
|
||||
try {
|
||||
userProfile = await this.fetchUtils.getProfile(targetId);
|
||||
} catch {
|
||||
this.logger.error('盯梢模式无法获取目标id');
|
||||
throw new Error('盯梢模式无法获取目标id');
|
||||
}
|
||||
await this.commonUtils.sleep(this.mathUtils.getRandomInt(20, 50));
|
||||
if ((userProfile.userStatus.status === 'ok' && this.commonUtils.getTravelStage() === TRAVEL_STATE.IN_TORN) ||
|
||||
(userProfile.userStatus.status === 'abroad' && this.commonUtils.getTravelStage() === TRAVEL_STATE.ABROAD)) {
|
||||
watchSwitch.getInput().checked = false;
|
||||
window.setTimeout(async () => {
|
||||
new Alert('目标已落地/出院/出狱!', { timeout: 10, force: true, sysNotify: true });
|
||||
await this.commonUtils.audioPlay();
|
||||
await this.commonUtils.sleep(300);
|
||||
await this.commonUtils.audioPlay();
|
||||
await this.commonUtils.sleep(300);
|
||||
await this.commonUtils.audioPlay();
|
||||
await this.commonUtils.sleep(300);
|
||||
}, 0);
|
||||
}
|
||||
});
|
||||
let block = new TornStyleBlock('盯梢模式').insert2Dom();
|
||||
let watchSwitch = new TornStyleSwitch('开启');
|
||||
block.append(watchSwitch.getBase());
|
||||
watchSwitch.getInput().addEventListener('change', () => {
|
||||
if (watchSwitch.getInput().checked) {
|
||||
new DialogMsgBox('检测玩家状态,当目标状态变成(海外)落地、出院或出狱时通知并播放声音提醒,后可搭配光速刷新食用<br/>确定开启?', {
|
||||
callback: () => {
|
||||
if (this.commonUtils.getTravelStage() === TRAVEL_STATE.FLYING) {
|
||||
new Alert('失败!已取消');
|
||||
watchSwitch.getInput().checked = false;
|
||||
return;
|
||||
}
|
||||
this.logger.info('盯梢开启, 目标id' + targetId);
|
||||
loop.start(this.localConfigWrapper.config.WatchTargetFreq | 0);
|
||||
},
|
||||
cancel: () => watchSwitch.getInput().checked = false
|
||||
});
|
||||
} else {
|
||||
loop.stop();
|
||||
this.logger.info('盯梢关闭');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,37 +1,19 @@
|
||||
import InfoUtils from "../class/utils/InfoUtils";
|
||||
import MathUtils from "../class/utils/MathUtils";
|
||||
import NOTIFY_HTML from "../../static/html/buyBeer/notify.html";
|
||||
import CommonUtils from "../class/utils/CommonUtils";
|
||||
import Popup from "../class/utils/Popup";
|
||||
import ResponseInject from "../interface/ResponseInject";
|
||||
import LocalConfigWrapper from "../class/LocalConfigWrapper";
|
||||
import ClassName from "../container/ClassName";
|
||||
import { Injectable } from "../container/Injectable";
|
||||
import Logger from "../class/Logger";
|
||||
import MsgWrapper from "../class/utils/MsgWrapper";
|
||||
import IFeature from "../man/IFeature";
|
||||
import ATK_PAGE_REG from "./url/ATK_PAGE_REG";
|
||||
import ALL_PAGE_REG from "./url/ALL_PAGE_REG";
|
||||
import WuhuConfig from "../WuhuConfig";
|
||||
import Log from "../Log";
|
||||
import InfoUtils from "../utils/InfoUtils";
|
||||
import Alert from "../utils/Alert";
|
||||
import MathUtils from "../utils/MathUtils";
|
||||
import NOTIFY_HTML from "../../../static/html/buyBeer/notify.html";
|
||||
import CommonUtils from "../utils/CommonUtils";
|
||||
import Popup from "../utils/Popup";
|
||||
import ResponseInject from "../../interface/ResponseInject";
|
||||
import LocalConfigWrapper from "../LocalConfigWrapper";
|
||||
import ClassName from "../../container/ClassName";
|
||||
import { Injectable } from "../../container/Injectable";
|
||||
|
||||
@ClassName('BuyBeerHelper')
|
||||
@Injectable()
|
||||
export default class BuyBeerHelper implements BeerMonitorLoop, ResponseInject, IFeature {
|
||||
|
||||
urlIncludes(): RegExp[] {
|
||||
return [ALL_PAGE_REG]
|
||||
}
|
||||
|
||||
urlExcludes(): RegExp[] {
|
||||
return [ATK_PAGE_REG]
|
||||
}
|
||||
|
||||
description(): string {
|
||||
return '啤酒助手'
|
||||
}
|
||||
|
||||
iStart(): void | Promise<void> {
|
||||
(this.localConfigWrapper.config._15Alarm) && this.start()
|
||||
}
|
||||
export default class BuyBeerHelper implements BeerMonitorLoop, ResponseInject {
|
||||
|
||||
private isNotifying = false;
|
||||
private loopId: number = null;
|
||||
@ -43,17 +25,15 @@ export default class BuyBeerHelper implements BeerMonitorLoop, ResponseInject, I
|
||||
private readonly commonUtils: CommonUtils,
|
||||
private readonly infoUtils: InfoUtils,
|
||||
private readonly mathUtils: MathUtils,
|
||||
private readonly logger: Logger,
|
||||
private readonly msgWrapper: MsgWrapper,
|
||||
) {
|
||||
this.time = this.localConfigWrapper.config._15AlarmTime || 30;
|
||||
}
|
||||
|
||||
public start(): void {
|
||||
if (this.loopId) {
|
||||
this.logger.info('啤酒助手已在运行');
|
||||
Log.info('啤酒助手已在运行');
|
||||
} else {
|
||||
this.logger.info('啤酒助手启动');
|
||||
Log.info('啤酒助手启动');
|
||||
this.loopId = window.setInterval(async () => {
|
||||
// 海外取消提醒
|
||||
let { isTravelling, isAbroad } = await this.infoUtils.getUserState();
|
||||
@ -80,18 +60,16 @@ export default class BuyBeerHelper implements BeerMonitorLoop, ResponseInject, I
|
||||
if (this.isNotifying) return;
|
||||
this.isNotifying = true;
|
||||
// 发送通知
|
||||
const rNum = this.mathUtils.getRandomInt(0, 99);
|
||||
// const notify =
|
||||
this.msgWrapper.create(NOTIFY_HTML.replace('{{}}', rNum.toString()), {
|
||||
const notify = new Alert(this.notifyHtml, {
|
||||
timeout: 30,
|
||||
sysNotify: true,
|
||||
});
|
||||
document.querySelector('button#wh-rd-btn-' + rNum).addEventListener('click', () => this.skip_today());
|
||||
// notify.getElement().addEventListener('click', ev => {
|
||||
// if ((ev.target as HTMLElement).tagName.toLowerCase() === 'a') {
|
||||
// notify.close();
|
||||
// }
|
||||
// });
|
||||
notify.getElement().querySelector('.wh-notify-msg button').addEventListener('click', () => this.skip_today());
|
||||
notify.getElement().addEventListener('click', ev => {
|
||||
if ((ev.target as HTMLElement).tagName.toLowerCase() === 'a') {
|
||||
notify.close();
|
||||
}
|
||||
});
|
||||
// 声音提醒
|
||||
{
|
||||
let loop = 3;
|
||||
@ -129,17 +107,11 @@ export default class BuyBeerHelper implements BeerMonitorLoop, ResponseInject, I
|
||||
|
||||
public skip_today(): void {
|
||||
const date = new Date();
|
||||
this.localConfigWrapper.config._15_alarm_ignore = [date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()];
|
||||
// WuhuConfig.set('_15_alarm_ignore', [date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()], false);
|
||||
WuhuConfig.set('_15_alarm_ignore', [date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()], false);
|
||||
// 通知
|
||||
const rNumber = this.mathUtils.getRandomInt(0, 100);
|
||||
const notify = this.msgWrapper.create(`明早8点前将不再提醒 <button id="wh-rd-btn-${ rNumber }">取消</button>`);
|
||||
const notify = new Alert(`明早8点前将不再提醒 <button id="wh-rd-btn-${ this.mathUtils.getRandomInt(0, 100) }">取消</button>`);
|
||||
// 通知中的取消按钮
|
||||
document.querySelector('#wh-rd-btn-' + rNumber)
|
||||
.addEventListener(
|
||||
'click',
|
||||
() => this.localConfigWrapper.config._15_alarm_ignore.length = 0
|
||||
);
|
||||
notify.getElement().querySelector('.wh-notify-msg button').addEventListener('click', () => WuhuConfig.set('_15_alarm_ignore', undefined, true));
|
||||
}
|
||||
|
||||
public setTimeHandler(): void {
|
||||
@ -162,14 +134,11 @@ export default class BuyBeerHelper implements BeerMonitorLoop, ResponseInject, I
|
||||
popup.element.appendChild(confirm);
|
||||
}
|
||||
|
||||
public responseHandler(url: string, body: { json: unknown; text: string; isModified: boolean }, opt: {
|
||||
method: "GET" | "POST";
|
||||
requestBody: string
|
||||
}) {
|
||||
public responseHandler(url: string, body: { json: unknown; text: string; isModified: boolean }, opt: { method: "GET" | "POST"; requestBody: string }) {
|
||||
if (url.includes('shops.php') && opt?.method === 'POST') {
|
||||
let req = opt.requestBody;
|
||||
if (req && req.includes('step=buyShopItem') && req.includes('ID=180') && body.json && body.json['success']) {
|
||||
this.msgWrapper.create('检测到已成功购买啤酒');
|
||||
new Alert('检测到已成功购买啤酒');
|
||||
this.skip_today();
|
||||
}
|
||||
}
|
||||
@ -1,46 +1,27 @@
|
||||
import CommonUtils from "../class/utils/CommonUtils";
|
||||
import FetchUtils from "../class/utils/FetchUtils";
|
||||
import InfoUtils from "../class/utils/InfoUtils";
|
||||
import TRAVEL_STATE from "../enum/TravelState";
|
||||
import LocalConfigWrapper from "../class/LocalConfigWrapper";
|
||||
import { Injectable } from "../container/Injectable";
|
||||
import ClassName from "../container/ClassName";
|
||||
import Logger from "../class/Logger";
|
||||
import MsgWrapper from "../class/utils/MsgWrapper";
|
||||
import IFeature from "../man/IFeature";
|
||||
import ATK_PAGE_REG from "./url/ATK_PAGE_REG";
|
||||
import ALL_PAGE_REG from "./url/ALL_PAGE_REG";
|
||||
import CommonUtils from "../utils/CommonUtils";
|
||||
import FetchUtils from "../utils/FetchUtils";
|
||||
import InfoUtils from "../utils/InfoUtils";
|
||||
import Alert from "../utils/Alert";
|
||||
import TRAVEL_STATE from "../../enum/TravelState";
|
||||
import LocalConfigWrapper from "../LocalConfigWrapper";
|
||||
import { Injectable } from "../../container/Injectable";
|
||||
import ClassName from "../../container/ClassName";
|
||||
import Logger from "../Logger";
|
||||
|
||||
/**
|
||||
* 公司助手
|
||||
*/
|
||||
@Injectable()
|
||||
@ClassName('CompanyHelper')
|
||||
export default class CompanyHelper implements IFeature {
|
||||
private readonly logger: Logger = Logger.factory(CompanyHelper)
|
||||
|
||||
description(): string {
|
||||
return "公司助手、火车爆仓检测";
|
||||
}
|
||||
|
||||
iStart(): void | Promise<void> {
|
||||
this.init()
|
||||
}
|
||||
|
||||
urlExcludes(): RegExp[] {
|
||||
return [ATK_PAGE_REG];
|
||||
}
|
||||
|
||||
urlIncludes(): RegExp[] {
|
||||
return [ALL_PAGE_REG];
|
||||
}
|
||||
export default class CompanyHelper {
|
||||
className = 'CompanyHelper';
|
||||
|
||||
public constructor(
|
||||
private readonly localConfigWrapper: LocalConfigWrapper,
|
||||
private readonly commonUtils: CommonUtils,
|
||||
private readonly fetchUtils: FetchUtils,
|
||||
private readonly logger: Logger,
|
||||
private readonly infoUtils: InfoUtils,
|
||||
private readonly msgWrapper: MsgWrapper,
|
||||
) {
|
||||
}
|
||||
|
||||
@ -48,6 +29,10 @@ export default class CompanyHelper implements IFeature {
|
||||
this.localConfigWrapper.config.CHTrainsDetectSwitch && this.trainsDetect().then();
|
||||
}
|
||||
|
||||
// public detectNow(): void {
|
||||
// this.trainsDetect(true).then();
|
||||
// }
|
||||
|
||||
/**
|
||||
* 火车检测
|
||||
* 每日判断一次,非公司老板跳过检测
|
||||
@ -55,7 +40,7 @@ export default class CompanyHelper implements IFeature {
|
||||
*/
|
||||
private async trainsDetect(test: boolean = false): Promise<null> {
|
||||
// 通过用户的icon判断公司老板
|
||||
if ((await this.infoUtils.getSessionData()).statusIcons.icons.company?.iconID !== 'icon73') {
|
||||
if ((await this.infoUtils.getSessionData()).statusIcons.icons.company.iconID !== 'icon73') {
|
||||
this.logger.info('火车检测跳过:非公司老板');
|
||||
return;
|
||||
}
|
||||
@ -70,7 +55,7 @@ export default class CompanyHelper implements IFeature {
|
||||
this.fetchUtils.fetchText('/companies.php')
|
||||
.then(res => {
|
||||
let tmp: HTMLElement = document.createElement('div');
|
||||
let bodyTagStart = this.commonUtils.matchOne(res, /<body.+/);
|
||||
let bodyTagStart = this.commonUtils.matchOne(res, /<body.+>/);
|
||||
if (!bodyTagStart) {
|
||||
this.logger.warn('火车检测: 无法获取数据');
|
||||
throw new Error('火车检测: 无法获取数据');
|
||||
@ -91,7 +76,7 @@ export default class CompanyHelper implements IFeature {
|
||||
this.logger.info('火车检测: 火车/星级: ' + trains + '/' + stars);
|
||||
this.logger.info({ tmp });
|
||||
if (trains + stars > 20) {
|
||||
this.msgWrapper.create(`【公司助手】火车检测:火车明日将溢出!${ trains }/20火车`, {
|
||||
new Alert(`公司助手<br/><br/>火车检测:火车明日将溢出!${ trains }/20火车`, {
|
||||
timeout: 15,
|
||||
force: true,
|
||||
sysNotify: true
|
||||
@ -5,10 +5,6 @@ import ResponseInject from "../../interface/ResponseInject";
|
||||
import { Injectable } from "../../container/Injectable";
|
||||
import ClassName from "../../container/ClassName";
|
||||
import LocalConfigWrapper from "../LocalConfigWrapper";
|
||||
import Logger from "../Logger";
|
||||
import MsgWrapper from "../utils/MsgWrapper";
|
||||
import { fetchYata } from "../../func/module/fetchYata";
|
||||
import toThousands from "../../func/utils/toThousands";
|
||||
|
||||
/**
|
||||
* fetch 事件监听回调
|
||||
@ -18,14 +14,9 @@ import toThousands from "../../func/utils/toThousands";
|
||||
export default class FetchEventCallback extends Provider implements ResponseInject {
|
||||
className = "FetchEventCallback";
|
||||
|
||||
newNode = document.createElement('div')
|
||||
bsEstNode = document.createElement('div')
|
||||
|
||||
constructor(
|
||||
private readonly localConfigWrapper: LocalConfigWrapper,
|
||||
private readonly commonUtils: CommonUtils,
|
||||
private readonly logger: Logger,
|
||||
private readonly msgWrapper: MsgWrapper,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
@ -37,38 +28,15 @@ export default class FetchEventCallback extends Provider implements ResponseInje
|
||||
*/
|
||||
public responseHandler(url: string, response) {
|
||||
// mini profile 中添加上次动作
|
||||
if (url.startsWith('/page.php?sid=UserMiniProfile&userID')) {
|
||||
if (url.includes('profiles.php?step=getUserNameContextMenu') && this.localConfigWrapper.config.ShowMiniProfLastAct) {
|
||||
window.setTimeout(async () => {
|
||||
let cont = CommonUtils.querySelector('[class*=profile-mini-_userProfileWrapper___]');
|
||||
let resp: MiniProfile = response.json as MiniProfile;
|
||||
if (this.localConfigWrapper.config.ShowMiniProfLastAct) {
|
||||
this.logger.info({ resp })
|
||||
let formatted = this.commonUtils.secondsFormat(resp.user.lastAction.seconds);
|
||||
let newNode = document.createElement('div');
|
||||
let formatted = this.commonUtils.secondsFormat(resp.user.lastAction.seconds);
|
||||
|
||||
(await cont).append(this.newNode);
|
||||
this.newNode.innerText = '上次动作: ' + formatted;
|
||||
}
|
||||
if (this.localConfigWrapper.config.isBSEstMiniProfOn) {
|
||||
const id = resp.user.userID
|
||||
const apikey = localStorage.getItem('APIKey')
|
||||
this.bsEstNode.innerHTML = `[BS估算] [${ id }]获取中...`;
|
||||
(await cont).append(this.bsEstNode)
|
||||
if (!apikey) {
|
||||
this.bsEstNode.innerHTML = '[BS估算] 未配置APIKey,无法估算BS'
|
||||
this.logger.error('MINI Profile bs估算失败: APIKey为空')
|
||||
} else {
|
||||
const bsData = fetchYata(id, apikey)
|
||||
bsData.then(data => {
|
||||
// 网速过慢时可能mini profile容器已更新新内容,与上次请求的用户数据不同,需要判断
|
||||
if (this.bsEstNode.innerHTML.includes(resp.user.userID.toString())) {
|
||||
this.bsEstNode.innerHTML = `[BS估算] ${ resp.user.playerName }[${ id }] ${ toThousands(data.total) }`
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
this.bsEstNode.innerHTML = `[BS估算] ${ err.message }`
|
||||
})
|
||||
}
|
||||
}
|
||||
newNode.innerText = '上次动作: ' + formatted;
|
||||
(await cont).append(newNode);
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,34 +1,19 @@
|
||||
import InfoUtils from "../class/utils/InfoUtils";
|
||||
import MathUtils from "../class/utils/MathUtils";
|
||||
import CommonUtils from "../class/utils/CommonUtils";
|
||||
import TornStyleBlock from "../class/utils/TornStyleBlock";
|
||||
import Timer from "../class/utils/Timer";
|
||||
import FetchUtils from "../class/utils/FetchUtils";
|
||||
import { Injectable } from "../container/Injectable";
|
||||
import ClassName from "../container/ClassName";
|
||||
import Logger from "../class/Logger";
|
||||
import IFeature from "../man/IFeature";
|
||||
import Log from "../Log";
|
||||
import InfoUtils from "../utils/InfoUtils";
|
||||
import MathUtils from "../utils/MathUtils";
|
||||
import CommonUtils from "../utils/CommonUtils";
|
||||
import TornStyleBlock from "../utils/TornStyleBlock";
|
||||
import Timer from "../utils/Timer";
|
||||
import FetchUtils from "../utils/FetchUtils";
|
||||
import { Injectable } from "../../container/Injectable";
|
||||
import ClassName from "../../container/ClassName";
|
||||
|
||||
/**
|
||||
* 彩票助手
|
||||
*/
|
||||
@Injectable()
|
||||
@ClassName('LotteryHelper')
|
||||
export default class LotteryHelper implements IFeature {
|
||||
private readonly logger: Logger = Logger.factory(LotteryHelper)
|
||||
|
||||
description(): string {
|
||||
return "彩票助手";
|
||||
}
|
||||
|
||||
iStart(): void | Promise<void> {
|
||||
this.init()
|
||||
}
|
||||
|
||||
urlExcludes(): RegExp[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
export default class LotteryHelper {
|
||||
private loopFlag = true;
|
||||
|
||||
private radioDaily: HTMLInputElement = null;
|
||||
@ -41,10 +26,6 @@ export default class LotteryHelper implements IFeature {
|
||||
private status: HTMLElement = null;
|
||||
private desc: HTMLElement = null;
|
||||
|
||||
urlIncludes(): RegExp[] {
|
||||
return [/loader\.php\?sid=lottery/];
|
||||
}
|
||||
|
||||
constructor(
|
||||
private readonly mathUtils: MathUtils,
|
||||
private readonly commonUtils: CommonUtils,
|
||||
@ -55,7 +36,7 @@ export default class LotteryHelper implements IFeature {
|
||||
|
||||
public init() {
|
||||
let startTime = new Timer();
|
||||
this.logger.info('彩票助手初始化开始');
|
||||
Log.info('彩票助手初始化开始');
|
||||
|
||||
let radioLabelDaily = document.createElement('label');
|
||||
let radioLabelWeekly = document.createElement('label');
|
||||
@ -131,7 +112,7 @@ export default class LotteryHelper implements IFeature {
|
||||
progressBarBg, progressBar, status, desc).insert2Dom();
|
||||
// document.querySelector('#websocketConnectionData').after(container);
|
||||
|
||||
this.logger.info('彩票助手初始化结束,耗时:' + startTime.getTimeMs());
|
||||
Log.info('彩票助手初始化结束,耗时:' + startTime.getTimeMs());
|
||||
}
|
||||
|
||||
private async start() {
|
||||
@ -177,7 +158,7 @@ export default class LotteryHelper implements IFeature {
|
||||
if (this.loopFlag) rsMsg = '批量购买完成';
|
||||
} else {
|
||||
rsMsg = '代币或现金不足';
|
||||
this.logger.warn({ totalCost, inputNumber });
|
||||
Log.warn({ totalCost, inputNumber });
|
||||
}
|
||||
} else {
|
||||
rsMsg = '输入有误';
|
||||
@ -1,47 +1,25 @@
|
||||
import TornStyleBlock from "../utils/TornStyleBlock";
|
||||
import Alert from "../utils/Alert";
|
||||
import TornStyleSwitch from "../utils/TornStyleSwitch";
|
||||
import { Injectable } from "../../container/Injectable";
|
||||
import ClassName from "../../container/ClassName";
|
||||
import LocalConfigWrapper from "../LocalConfigWrapper";
|
||||
import IFeature from "../../man/IFeature";
|
||||
import MsgWrapper from "../utils/MsgWrapper";
|
||||
|
||||
@Injectable()
|
||||
@ClassName('PTHelper')
|
||||
export default class PTHelper implements IFeature {
|
||||
private observer: MutationObserver;
|
||||
private usersPointSell: HTMLDivElement;
|
||||
export default class PTHelper {
|
||||
private readonly observer;
|
||||
private readonly usersPointSell;
|
||||
|
||||
constructor(
|
||||
private readonly localConfigWrapper: LocalConfigWrapper,
|
||||
private readonly msgWrapper: MsgWrapper,
|
||||
) {
|
||||
}
|
||||
|
||||
description(): string {
|
||||
return "pt一键购买";
|
||||
}
|
||||
|
||||
iStart(): void | Promise<void> {
|
||||
this.start()
|
||||
}
|
||||
|
||||
urlExcludes(): RegExp[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
urlIncludes(): RegExp[] {
|
||||
return [/pmarket\.php/];
|
||||
}
|
||||
|
||||
start() {
|
||||
|
||||
this.observer = new MutationObserver(e => {
|
||||
for (const t of e) {
|
||||
t.addedNodes.forEach(e => 'LI' === (e as HTMLElement).tagName && this.removeConfirm(e))
|
||||
}
|
||||
});
|
||||
this.usersPointSell = document.querySelector<HTMLDivElement>('.users-point-sell');
|
||||
this.usersPointSell = document.querySelector('.users-point-sell');
|
||||
|
||||
let block = new TornStyleBlock('PT一键购买').insert2Dom();
|
||||
let switcher = new TornStyleSwitch('开启');
|
||||
@ -49,7 +27,7 @@ export default class PTHelper implements IFeature {
|
||||
let toggle = switcher.getInput();
|
||||
toggle.checked = this.localConfigWrapper.config.ptQuickBuy;
|
||||
if (toggle.checked) {
|
||||
this.msgWrapper.create('一键购买已开启');
|
||||
new Alert('一键购买已开启');
|
||||
for (const index in this.usersPointSell.children) {
|
||||
'LI' === this.usersPointSell.children[index].tagName && this.removeConfirm(this.usersPointSell.children[index])
|
||||
}
|
||||
@ -62,13 +40,13 @@ export default class PTHelper implements IFeature {
|
||||
'LI' === this.usersPointSell.children[index].tagName && this.removeConfirm(this.usersPointSell.children[index])
|
||||
}
|
||||
this.observer.observe(this.usersPointSell, { childList: true });
|
||||
this.msgWrapper.create('一键购买已开启');
|
||||
new Alert('一键购买已开启');
|
||||
} else {
|
||||
for (const index in this.usersPointSell.children) {
|
||||
'LI' === this.usersPointSell.children[index].tagName && this.rollbackConfirm(this.usersPointSell.children[index])
|
||||
}
|
||||
this.observer.disconnect();
|
||||
this.msgWrapper.create('一键购买已关闭');
|
||||
new Alert('一键购买已关闭');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import WuhuConfig from "../WuhuConfig";
|
||||
import CommonUtils from "../utils/CommonUtils";
|
||||
import TornStyleBlock from "../utils/TornStyleBlock";
|
||||
import TornStyleSwitch from "../utils/TornStyleSwitch";
|
||||
@ -8,46 +9,21 @@ import ClassName from "../../container/ClassName";
|
||||
import { Injectable } from "../../container/Injectable";
|
||||
import LocalConfigWrapper from "../LocalConfigWrapper";
|
||||
import Logger from "../Logger";
|
||||
import IFeature from "../../man/IFeature";
|
||||
import { fetchYata } from "../../func/module/fetchYata";
|
||||
import MsgWrapper from "../utils/MsgWrapper";
|
||||
import toThousands from "../../func/utils/toThousands";
|
||||
import { timePastFormat } from "../../func/utils/timePastFormat";
|
||||
|
||||
@ClassName('ProfileHelper')
|
||||
@Injectable()
|
||||
export default class ProfileHelper implements ResponseInject, IFeature {
|
||||
private block: TornStyleBlock;
|
||||
export default class ProfileHelper implements ResponseInject {
|
||||
|
||||
private readonly block;
|
||||
|
||||
// 曾用名已检测过标记
|
||||
private task = true;
|
||||
|
||||
constructor(
|
||||
private readonly localConfigWrapper: LocalConfigWrapper,
|
||||
private readonly commonUtils: CommonUtils,
|
||||
private readonly logger: Logger,
|
||||
private readonly msgWrapper: MsgWrapper,
|
||||
) {
|
||||
}
|
||||
|
||||
description(): string {
|
||||
return "个人资料页面辅助";
|
||||
}
|
||||
|
||||
iStart(): void | Promise<void> {
|
||||
this.start()
|
||||
}
|
||||
|
||||
urlExcludes(): RegExp[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
// 曾用名已检测过标记
|
||||
private task = true;
|
||||
|
||||
urlIncludes(): RegExp[] {
|
||||
return [/profiles\.php\?XID=/];
|
||||
}
|
||||
|
||||
start() {
|
||||
|
||||
CommonUtils.addStyle('body.wh-hide_profile_img .profile-image a.profile-image-wrapper .img-wrap img{display:none;}');
|
||||
// let id = document.querySelector('link[rel="canonical"]').getAttribute('href').split('=')[1];
|
||||
let id = (new URL(window.location.href)).searchParams.get('XID');
|
||||
@ -61,90 +37,30 @@ export default class ProfileHelper implements ResponseInject, IFeature {
|
||||
}
|
||||
this.block = new TornStyleBlock('芜湖助手').insert2Dom();
|
||||
// 隐藏头像
|
||||
try {
|
||||
let hideImgSwitch = new TornStyleSwitch('隐藏头像', this.localConfigWrapper.config.HideProfileImg);
|
||||
this.block.append(hideImgSwitch.getBase());
|
||||
hideImgSwitch.getInput().addEventListener('change', () => {
|
||||
document.body.classList.toggle('wh-hide_profile_img');
|
||||
this.localConfigWrapper.config.HideProfileImg = hideImgSwitch.getInput().checked;
|
||||
});
|
||||
if (this.localConfigWrapper.config.ShowNameHistory) {
|
||||
globVars.responseHandlers.push((...args: any[]) => this.responseHandler.apply(this, args));
|
||||
}
|
||||
} catch (e) {
|
||||
this.logger.error('隐藏头像时出错了', e.stack)
|
||||
}
|
||||
// bs估算
|
||||
if (this.localConfigWrapper.config.isBSEstProfOn) {
|
||||
try {
|
||||
const apikey = localStorage.getItem('APIKey')
|
||||
if (!apikey) {
|
||||
this.msgWrapper.create('BS估算失败: 尚未设定APIKey', null, 'error')
|
||||
}
|
||||
const promise = fetchYata(parseInt(id), apikey)
|
||||
const domNode = document.createElement('div')
|
||||
domNode.innerHTML = 'BS估算中...'
|
||||
domNode.classList.add('mt-4')
|
||||
domNode.style.border = '1px solid green'
|
||||
domNode.style.padding = '2px'
|
||||
this.block.append(domNode)
|
||||
const buildType = { Offensive: '攻击型', Defensive: '防御型', Balanced: '平衡型' }
|
||||
promise.then(data => {
|
||||
domNode.innerHTML = `<b>BS估算</b><br/>
|
||||
BS: ${ toThousands(data.total) }<br/>
|
||||
评分: ${ toThousands(data.score) }<br/>
|
||||
风格: ${ buildType[data.type] }<br/>
|
||||
偏差: ${ data.skewness }%<br/>
|
||||
估算时间: ${ timePastFormat(Date.now() - data.timestamp * 1000) }前
|
||||
`
|
||||
}).catch(err => {
|
||||
domNode.innerHTML = 'BS估算出错了: ' + err.message
|
||||
throw new TypeError('BS估算出错了: ' + err.message)
|
||||
})
|
||||
} catch (e) {
|
||||
this.msgWrapper.create('BS估算失败' + e.message, null, 'error')
|
||||
throw new TypeError('BS估算失败' + e.message)
|
||||
}
|
||||
let hideImgSwitch = new TornStyleSwitch('隐藏头像', this.localConfigWrapper.config.HideProfileImg);
|
||||
this.block.append(hideImgSwitch.getBase());
|
||||
hideImgSwitch.getInput().addEventListener('change', () => {
|
||||
document.body.classList.toggle('wh-hide_profile_img');
|
||||
WuhuConfig.set('HideProfileImg', hideImgSwitch.getInput().checked, true);
|
||||
});
|
||||
if (this.localConfigWrapper.config.ShowNameHistory) {
|
||||
globVars.responseHandlers.push((url, body) => this.responseHandler(url, body));
|
||||
}
|
||||
}
|
||||
|
||||
responseHandler(url: string, body: { json: unknown; text: string; isModified: boolean }) {
|
||||
if (url.includes('profiles.php?step=getProfileData') && this.task) {
|
||||
// 曾用名
|
||||
const nameHistoryNode = document.createElement('p');
|
||||
let nameHistoryNode;
|
||||
nameHistoryNode = document.createElement('p');
|
||||
nameHistoryNode.innerHTML = '曾用名:';
|
||||
this.block.append(nameHistoryNode);
|
||||
let resp = body.json as IUserProfileData;
|
||||
if (resp.userInformation.previousAliases.length > 0) { // 曾用名列表
|
||||
if (resp.userInformation.previousAliases.length > 0) {
|
||||
resp.userInformation.previousAliases.forEach(item => nameHistoryNode.innerHTML += item + ' ');
|
||||
} else {
|
||||
nameHistoryNode.innerHTML += '暂无';
|
||||
}
|
||||
let lastAction = -1
|
||||
let onlineStatusTitle = '-'
|
||||
if (resp.basicInformation?.lastAction.seconds) {
|
||||
lastAction = resp.basicInformation.lastAction.seconds
|
||||
}
|
||||
if (resp.basicInformation.icons) {
|
||||
for (let i = 0; i < resp.basicInformation.icons.length; i++) {
|
||||
let item = resp.basicInformation.icons[i]
|
||||
if (item.id === 1) {
|
||||
onlineStatusTitle = '🟢️ 在线'
|
||||
break
|
||||
}
|
||||
if (item.id === 62) {
|
||||
onlineStatusTitle = '🟡 挂机'
|
||||
break
|
||||
}
|
||||
if (item.id === 2) {
|
||||
onlineStatusTitle = '⚪ 离线'
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
const lastActionNode = document.createElement('p')
|
||||
lastActionNode.innerHTML = `${ onlineStatusTitle } ${ this.commonUtils.secondsFormat(lastAction) }`
|
||||
this.block.append(lastActionNode)
|
||||
this.task = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,8 +2,7 @@ import ClassName from "../../container/ClassName";
|
||||
import { Injectable } from "../../container/Injectable";
|
||||
import Logger from "../Logger";
|
||||
import NetHighLvlWrapper, { BATTLE_STAT } from "../utils/NetHighLvlWrapper";
|
||||
import { InjectionKey } from "vue";
|
||||
import MsgWrapper from "../utils/MsgWrapper";
|
||||
import Alert from "../utils/Alert";
|
||||
|
||||
type GymResponse = {
|
||||
success: boolean,
|
||||
@ -20,27 +19,21 @@ export default class QuickGymTrain {
|
||||
constructor(
|
||||
private readonly logger: Logger,
|
||||
private readonly netHighLvlWrapper: NetHighLvlWrapper,
|
||||
private readonly msgWrapper: MsgWrapper,
|
||||
) {
|
||||
}
|
||||
|
||||
doTrain(type = BATTLE_STAT.STR, count = 199) {
|
||||
doTrain() {
|
||||
window.setTimeout(async () => {
|
||||
let resObj: GymResponse;
|
||||
try {
|
||||
resObj = JSON.parse(await this.netHighLvlWrapper.doGymTrain(type, count))
|
||||
resObj = JSON.parse(await this.netHighLvlWrapper.doGymTrain(BATTLE_STAT.STR, 199))
|
||||
} catch (e) {
|
||||
resObj = { success: false, message: '解析失败' };
|
||||
this.logger.error(e.stack || e.message || e);
|
||||
}
|
||||
let msgRs = resObj.success ? '成功' : '失败';
|
||||
let msgMsg = resObj.message || resObj.text || resObj.error;
|
||||
this.msgWrapper.create(
|
||||
'锻炼结果: ' + msgRs + '<br/>提示: ' + (resObj.gainMessage || msgMsg),
|
||||
{}, resObj.success ? 'success' : 'error'
|
||||
);
|
||||
new Alert('锻炼结果: ' + msgRs + '<br/>提示: ' + (resObj.gainMessage || msgMsg));
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
export const QuickGymTrainKey = Symbol('QuickGymTrainKey') as InjectionKey<QuickGymTrain>;
|
||||
|
||||
@ -4,26 +4,10 @@ import CommonUtils from "../utils/CommonUtils";
|
||||
import ClassName from "../../container/ClassName";
|
||||
import { Injectable } from "../../container/Injectable";
|
||||
import LocalConfigWrapper from "../LocalConfigWrapper";
|
||||
import IFeature from "../../man/IFeature";
|
||||
|
||||
@ClassName('SearchHelper')
|
||||
@Injectable()
|
||||
export default class SearchHelper implements IFeature {
|
||||
description(): string {
|
||||
return "搜索助手";
|
||||
}
|
||||
|
||||
iStart(): void | Promise<void> {
|
||||
this.init()
|
||||
}
|
||||
|
||||
urlExcludes(): RegExp[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
urlIncludes(): RegExp[] {
|
||||
return [/page\.php\?sid=UserList/];
|
||||
}
|
||||
export default class SearchHelper {
|
||||
|
||||
constructor(
|
||||
private readonly localConfigWrapper: LocalConfigWrapper,
|
||||
|
||||
@ -1,13 +1,10 @@
|
||||
import CommonUtils from "../class/utils/CommonUtils";
|
||||
import Global from "../class/Global";
|
||||
import Device from "../enum/Device";
|
||||
import ClassName from "../container/ClassName";
|
||||
import { Injectable } from "../container/Injectable";
|
||||
import LocalConfigWrapper from "../class/LocalConfigWrapper";
|
||||
import Logger from "../class/Logger";
|
||||
import IFeature from "../man/IFeature";
|
||||
import ATK_PAGE_REG from "./url/ATK_PAGE_REG";
|
||||
import ALL_PAGE_REG from "./url/ALL_PAGE_REG";
|
||||
import CommonUtils from "../utils/CommonUtils";
|
||||
import Global from "../Global";
|
||||
import Device from "../../enum/Device";
|
||||
import Log from "../Log";
|
||||
import ClassName from "../../container/ClassName";
|
||||
import { Injectable } from "../../container/Injectable";
|
||||
import LocalConfigWrapper from "../LocalConfigWrapper";
|
||||
|
||||
/**
|
||||
* ### 边栏助手
|
||||
@ -16,29 +13,12 @@ import ALL_PAGE_REG from "./url/ALL_PAGE_REG";
|
||||
*/
|
||||
@ClassName('SidebarHelper')
|
||||
@Injectable()
|
||||
export default class SidebarHelper implements IFeature {
|
||||
private readonly logger: Logger = Logger.factory(SidebarHelper)
|
||||
|
||||
description(): string {
|
||||
return "边栏助手";
|
||||
}
|
||||
|
||||
iStart(): void | Promise<void> {
|
||||
this.init()
|
||||
}
|
||||
|
||||
urlExcludes(): RegExp[] {
|
||||
return [ATK_PAGE_REG];
|
||||
}
|
||||
export default class SidebarHelper {
|
||||
|
||||
private readonly sidebarRootNode: HTMLElement;
|
||||
private readonly toggleBtn: HTMLButtonElement;
|
||||
private isHide: boolean;
|
||||
|
||||
urlIncludes(): RegExp[] {
|
||||
return [ALL_PAGE_REG];
|
||||
}
|
||||
|
||||
constructor(
|
||||
private readonly localConfigWrapper: LocalConfigWrapper,
|
||||
private readonly global: Global,
|
||||
@ -54,7 +34,7 @@ export default class SidebarHelper implements IFeature {
|
||||
this.initToggleBtn();
|
||||
this.barRedirect();
|
||||
} else {
|
||||
this.logger.warn('页面未开启边栏,边栏助手退出');
|
||||
Log.warn('[SidebarHelper] 页面未开启边栏,边栏助手退出');
|
||||
}
|
||||
}
|
||||
|
||||
@ -92,10 +72,10 @@ export default class SidebarHelper implements IFeature {
|
||||
// 4条转跳
|
||||
private barRedirect(): void {
|
||||
if (this.localConfigWrapper.config.barsRedirect) {
|
||||
const eb = document.querySelector<HTMLAnchorElement>('#barEnergy');
|
||||
const nb = document.querySelector<HTMLAnchorElement>('#barNerve');
|
||||
const hb = document.querySelector<HTMLAnchorElement>('#barHappy');
|
||||
const lb = document.querySelector<HTMLAnchorElement>('#barLife');
|
||||
const eb = document.getElementById('barEnergy') as HTMLAnchorElement;
|
||||
const nb = document.getElementById('barNerve') as HTMLAnchorElement;
|
||||
const hb = document.getElementById('barHappy') as HTMLAnchorElement;
|
||||
const lb = document.getElementById('barLife') as HTMLAnchorElement;
|
||||
if (eb) {
|
||||
eb.addEventListener('click', () => location.href = '/gym.php');
|
||||
eb.href = '/gym.php';
|
||||
@ -1,41 +1,24 @@
|
||||
import TornStyleBlock from "../utils/TornStyleBlock";
|
||||
import InfoUtils from "../utils/InfoUtils";
|
||||
import Log from "../Log";
|
||||
import FetchUtils from "../utils/FetchUtils";
|
||||
import CommonUtils from "../utils/CommonUtils";
|
||||
import MathUtils from "../utils/MathUtils";
|
||||
import ClassName from "../../container/ClassName";
|
||||
import { Injectable } from "../../container/Injectable";
|
||||
import Logger from "../Logger";
|
||||
import IFeature from "../../man/IFeature";
|
||||
|
||||
/**
|
||||
* 老虎机批量购买助手
|
||||
*/
|
||||
@ClassName("SlotsHelper")
|
||||
@Injectable()
|
||||
export default class SlotsHelper implements IFeature {
|
||||
description(): string {
|
||||
return "老虎机批量购买助手";
|
||||
}
|
||||
|
||||
iStart(): void | Promise<void> {
|
||||
this.init()
|
||||
}
|
||||
|
||||
urlExcludes(): RegExp[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
urlIncludes(): RegExp[] {
|
||||
return [/loader\.php\?sid=slots/];
|
||||
}
|
||||
export default class SlotsHelper {
|
||||
|
||||
constructor(
|
||||
private readonly mathUtils: MathUtils,
|
||||
private readonly commonUtils: CommonUtils,
|
||||
private readonly fetchUtils: FetchUtils,
|
||||
private readonly infoUtils: InfoUtils,
|
||||
private readonly logger: Logger,
|
||||
) {
|
||||
}
|
||||
|
||||
@ -83,7 +66,7 @@ export default class SlotsHelper implements IFeature {
|
||||
try {
|
||||
await this.goBtnHandler(ev, ret)
|
||||
} catch (e) {
|
||||
this.logger.error(e.stack || e);
|
||||
Log.error(e.stack || e);
|
||||
}
|
||||
goBtn.disabled = false;
|
||||
});
|
||||
@ -136,7 +119,7 @@ export default class SlotsHelper implements IFeature {
|
||||
msgBox.innerHTML += '<br/>已停止, ';
|
||||
msgBox.innerHTML += bang ? '血' : '小';
|
||||
msgBox.innerHTML += profit > 0 ? '赚' : '亏';
|
||||
this.logger.info("[goBtnHandler]结束", { cash, tokens, count, price, wonTotal });
|
||||
Log.info("[goBtnHandler]结束", { cash, tokens, count, price, wonTotal });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
28
src/ts/class/action/StackHelper.ts
Normal file
28
src/ts/class/action/StackHelper.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import TornStyleBlock from "../utils/TornStyleBlock";
|
||||
import WuhuConfig from "../WuhuConfig";
|
||||
import TornStyleSwitch from "../utils/TornStyleSwitch";
|
||||
import { Injectable } from "../../container/Injectable";
|
||||
import ClassName from "../../container/ClassName";
|
||||
import LocalConfigWrapper from "../LocalConfigWrapper";
|
||||
|
||||
@Injectable()
|
||||
@ClassName('StackHelper')
|
||||
export default class StackHelper {
|
||||
constructor(
|
||||
private readonly localConfigWrapper: LocalConfigWrapper,
|
||||
) {
|
||||
let block = new TornStyleBlock('叠E保护').insert2Dom();
|
||||
let switcher = new TornStyleSwitch('启用');
|
||||
let input = switcher.getInput();
|
||||
block.append(switcher.getBase());
|
||||
input.checked = this.localConfigWrapper.config.SEProtect;
|
||||
if (input.checked) document.body.classList.add('wh-gym-stack');
|
||||
// 绑定点击事件
|
||||
input.onchange = e => {
|
||||
let target = e.target as HTMLInputElement;
|
||||
document.body.classList.toggle('wh-gym-stack');
|
||||
WuhuConfig.set('SEProtect', target.checked, true);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,4 +1,5 @@
|
||||
import { chatDict, eventsDict, headerDict, propertyDict, sidebarDict } from "../../dictionary/translation";
|
||||
import Log from "../Log";
|
||||
import Timer from "../utils/Timer";
|
||||
|
||||
/**
|
||||
@ -9,7 +10,7 @@ export default class Translate {
|
||||
public translateVer: string = '1.0';
|
||||
|
||||
constructor() {
|
||||
// Log.info('翻译开始');
|
||||
Log.info('翻译开始');
|
||||
let start = new Timer();
|
||||
// 时分秒转换
|
||||
String.prototype.replaceHMS = function replaceHMS() {
|
||||
@ -38,7 +39,7 @@ export default class Translate {
|
||||
this.chatTranslate();
|
||||
this.playerSearchBoxTrans();
|
||||
this.urlMatchPageTranslate(window.location.href);
|
||||
// Log.info('翻译结束, 耗时' + start.getTimeMs());
|
||||
Log.info('翻译结束, 耗时' + start.getTimeMs());
|
||||
}, 0);
|
||||
}
|
||||
|
||||
|
||||
@ -328,11 +328,12 @@ export default class TranslateNew extends Provider implements ResponseInject {
|
||||
'Glass of Beer': {
|
||||
itemName: '一杯啤酒',
|
||||
itemInfo: '[译]Only savages drink beer straight out of the bottle. This glass of beer is obtained fresh from the keg, and provides the same level of drunken joy as you\'d get from a regular bottle of suds. Provides a moderate nerve increase when consumed.',
|
||||
itemInfoContent: "<div class='m-bottom10'>" +
|
||||
"<span class=\"bold\">一杯啤酒</span> 是酒类物品" +
|
||||
"</div>" +
|
||||
"Only savages drink beer straight out of the bottle. This glass of beer is obtained fresh from the keg, and provides the same level of drunken joy as you'd get from a regular bottle of suds. Provides a moderate nerve increase when consumed." +
|
||||
"<div class=\"t-green bold item-effect m-top10\">效果: 犯罪 + 2,增幅CD + 1h。</div>",
|
||||
itemInfoContent: "\n" +
|
||||
" <div class='m-bottom10'>\n" +
|
||||
" <span class=\"bold\">一杯啤酒</span> 是酒类物品\n" +
|
||||
" </div>\n" +
|
||||
" Only savages drink beer straight out of the bottle. This glass of beer is obtained fresh from the keg, and provides the same level of drunken joy as you'd get from a regular bottle of suds. Provides a moderate nerve increase when consumed.\n" +
|
||||
" <div class=\"t-green bold item-effect m-top10\">效果: 犯罪 + 2,增幅CD + 1h。</div>",
|
||||
},
|
||||
};
|
||||
let idMap = { 816: 'Glass of Beer' };
|
||||
@ -374,7 +375,8 @@ export default class TranslateNew extends Provider implements ResponseInject {
|
||||
name.innerText = `${ name.innerText } ${ nameZh }`;
|
||||
}
|
||||
// 操作按钮
|
||||
elem.querySelectorAll('.icon-h').forEach(action => {
|
||||
let actions = elem.querySelectorAll('.icon-h');
|
||||
actions.forEach(action => {
|
||||
let attrTitle = action.getAttribute('title');
|
||||
// TODO
|
||||
let zh = itemPageDict[attrTitle];
|
||||
|
||||
79
src/ts/class/action/TravelItem.ts
Normal file
79
src/ts/class/action/TravelItem.ts
Normal file
@ -0,0 +1,79 @@
|
||||
import CommonUtils from "../utils/CommonUtils";
|
||||
import UserScriptEngine from "../../enum/UserScriptEngine";
|
||||
import Popup from "../utils/Popup";
|
||||
import STOCK_IMG_HTML from "../../../static/html/stock_img.html";
|
||||
import * as FILTER from "../../../static/json/for_stock_item_filter.json";
|
||||
import WindowActiveState from "./WindowActiveState";
|
||||
import { Injectable } from "../../container/Injectable";
|
||||
import ClassName from "../../container/ClassName";
|
||||
import Logger from "../Logger";
|
||||
|
||||
@Injectable()
|
||||
@ClassName('TravelItem')
|
||||
export default class TravelItem {
|
||||
private readonly apiUrl: string = 'https://yata.yt/api/v1/travel/export/';
|
||||
private foreignStockInfo: any = null;
|
||||
|
||||
public constructor(
|
||||
private readonly windowActiveState: WindowActiveState,
|
||||
private readonly logger: Logger,
|
||||
private readonly commonUtils: CommonUtils,
|
||||
) {
|
||||
}
|
||||
|
||||
public init() {
|
||||
|
||||
window.setInterval(async () => {
|
||||
if (!this.windowActiveState.get()) return;
|
||||
this.logger.info('COFetch ', this.apiUrl);
|
||||
try {
|
||||
this.foreignStockInfo = JSON.parse(await CommonUtils.COFetch(this.apiUrl));
|
||||
} catch (e) {
|
||||
this.logger.error('解析错误', e.stack || e.message || e);
|
||||
}
|
||||
this.logger.info({ info: 'TravelItem 跨域返回', 'returned': this.foreignStockInfo });
|
||||
}, 30 * 1000);
|
||||
}
|
||||
|
||||
// 呈现内容
|
||||
public async clickHandler(): Promise<void> {
|
||||
if (this.commonUtils.getScriptEngine() === UserScriptEngine.RAW) {
|
||||
new Popup(STOCK_IMG_HTML.replace('{{}}', performance.now().toString()), '飞花库存');
|
||||
} else {
|
||||
const popup = new Popup("请稍后 " + CommonUtils.loading_gif_html(), '飞花库存');
|
||||
let table = `<table><tr><th colspan="2">目的地 - 更新时间</th><th colspan="3">库存</th></tr>`;
|
||||
const dest = FILTER.default;
|
||||
const now = new Date();
|
||||
const res = await this.get();
|
||||
this.logger.info({ res })
|
||||
if (!res || !res.stocks) return;
|
||||
dest.forEach(el => {
|
||||
const update = (now.getTime() - new Date(res.stocks[el.name]['update'] * 1000).getTime()) / 1000 | 0
|
||||
table += `<tr><td>${ el.show }</td><td>${ update / 60 | 0 }分${ update % 60 | 0 }秒前</td>`;
|
||||
let count = 0;
|
||||
res.stocks[el.name]['stocks'].forEach(stock => {
|
||||
if (el.stocks[stock.name]) {
|
||||
table += `<td${ stock['quantity'] === 0 ? ' style="background-color:#f44336;color:white;border-color:#000;"' : '' }>${ el.stocks[stock.name] } (${ stock['quantity'] })</td>`;
|
||||
count++;
|
||||
}
|
||||
});
|
||||
while (count < 3) {
|
||||
count++;
|
||||
table += '<td></td>';
|
||||
}
|
||||
table += '</tr>';
|
||||
});
|
||||
table += '</table>';
|
||||
popup.getElement().innerHTML = table;
|
||||
}
|
||||
}
|
||||
|
||||
private async get() {
|
||||
try {
|
||||
return this.foreignStockInfo ||= JSON.parse(await CommonUtils.COFetch(this.apiUrl));
|
||||
} catch (e) {
|
||||
this.logger.error('解析出错', e.stack || e.message || e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -18,7 +18,6 @@ export default class WindowActiveState {
|
||||
addEventListener('blur', () => this.isFocus = false);
|
||||
}
|
||||
|
||||
// 当前实例是否激活
|
||||
get(): boolean {
|
||||
// 当前窗口获得了焦点 优先级最高
|
||||
if (this.isFocus) return true;
|
||||
|
||||
@ -1,13 +1,12 @@
|
||||
import XUNZHAOMUZHUANG_HTML from "../../../static/html/xunzhaomuzhuang/index.html";
|
||||
import * as MUZHUANG_ID_LIST_JSON from "../../../static/json/muzhuang_id_list.json";
|
||||
import CommonUtils from "../utils/CommonUtils";
|
||||
import XUNZHAOMUZHUANG_CSS from "../../../static/css/xunzhaomuzhuang.module.css";
|
||||
import XUNZHAOMUZHUANG_CSS from "../../../static/css/xunzhaomuzhuang.css";
|
||||
import TornStyleBlock from "../utils/TornStyleBlock";
|
||||
import MathUtils from "../utils/MathUtils";
|
||||
import FetchUtils from "../utils/FetchUtils";
|
||||
import ClassName from "../../container/ClassName";
|
||||
import { Injectable } from "../../container/Injectable";
|
||||
import IFeature from "../../man/IFeature";
|
||||
|
||||
/**
|
||||
* 寻找木桩
|
||||
@ -15,35 +14,8 @@ import IFeature from "../../man/IFeature";
|
||||
*/
|
||||
@ClassName('XZMZ')
|
||||
@Injectable()
|
||||
export default class XZMZ implements IFeature {
|
||||
description(): string {
|
||||
return "寻找木桩";
|
||||
}
|
||||
|
||||
iStart(): void | Promise<void> {
|
||||
this.start()
|
||||
}
|
||||
|
||||
urlExcludes(): RegExp[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
urlIncludes(): RegExp[] {
|
||||
return [/item.php\?temp=4/];
|
||||
}
|
||||
|
||||
start() {
|
||||
let hasInit: boolean = false
|
||||
let handle = () => {
|
||||
if (!hasInit && window.location.hash === '#xunzhaomuzhuang') {
|
||||
this.init()
|
||||
hasInit = true
|
||||
}
|
||||
}
|
||||
window.addEventListener('hashchange', handle)
|
||||
handle()
|
||||
}
|
||||
|
||||
export default class XZMZ {
|
||||
className = 'XZMZ';
|
||||
private mainRoleContainer: HTMLElement;
|
||||
private IDList: number[];
|
||||
private btn: HTMLButtonElement;
|
||||
@ -60,7 +32,7 @@ export default class XZMZ implements IFeature {
|
||||
}
|
||||
|
||||
public init() {
|
||||
this.commonUtils.styleInject(XUNZHAOMUZHUANG_CSS);
|
||||
CommonUtils.addStyle(XUNZHAOMUZHUANG_CSS);
|
||||
document.body.classList.add('wh-hide-title');
|
||||
document.title = document.title.replace('Items', '寻找木桩');
|
||||
this.mainRoleContainer = document.querySelector('div[role="main"]');
|
||||
|
||||
@ -1,10 +1,98 @@
|
||||
const notifyKey = Symbol('ConfigNotifyKey');
|
||||
const defaultConfig = {
|
||||
// 开启翻译
|
||||
transEnable: false,
|
||||
transNew: true,
|
||||
// 快速犯罪
|
||||
quickCrime: true,
|
||||
// 任务助手
|
||||
missionHint: true,
|
||||
// 小镇攻略
|
||||
xmasTownWT: true,
|
||||
// 小镇提醒
|
||||
xmasTownNotify: true,
|
||||
// 起飞爆e
|
||||
energyAlert: true,
|
||||
// 飞行闹钟
|
||||
trvAlarm: true,
|
||||
// 啤酒提醒
|
||||
_15Alarm: true,
|
||||
// 啤酒提醒时间
|
||||
_15AlarmTime: 50,
|
||||
// 啤酒提醒忽略当天
|
||||
_15_alarm_ignore: '',
|
||||
// 捡垃圾助手
|
||||
cityFinder: false,
|
||||
// 叠E保护
|
||||
SEProtect: false,
|
||||
// PT一键购买
|
||||
ptQuickBuy: false,
|
||||
// 光速拔刀 6-关闭
|
||||
quickAttIndex: 2,
|
||||
// 光速跑路 0-leave 1-mug 2-hos 3-关闭
|
||||
quickFinishAtt: 3,
|
||||
// 自动开打和结束
|
||||
autoStartFinish: false,
|
||||
// 攻击自刷新 0-无间隔 1-5s 6-关闭
|
||||
attReload: 6,
|
||||
// 价格监视
|
||||
priceWatcher: { xan: -1, pt: -1 },
|
||||
// 开发者模式
|
||||
isDev: false,
|
||||
// 4条转跳
|
||||
barsRedirect: true,
|
||||
// 浮动存钱框
|
||||
floatDepo: true,
|
||||
// 公司转跳存钱
|
||||
companyRedirect: true,
|
||||
// 收起公司冰蛙效率表
|
||||
companyBWCollapse: true,
|
||||
// 海外警告
|
||||
abroadWarning: true,
|
||||
// 落地转跳
|
||||
landedRedirect: '',
|
||||
// 任何位置一键存钱
|
||||
companyDepositAnywhere: false,
|
||||
// 火车提醒时间
|
||||
CHTrainsDetect: 0,
|
||||
// 火车提醒开关
|
||||
CHTrainsDetectSwitch: true,
|
||||
// 隐藏个人资料头像
|
||||
HideProfileImg: false,
|
||||
// 显示曾用名
|
||||
ShowNameHistory: true,
|
||||
// 盯梢模式强度 0-550 1-950 2-1450 ms
|
||||
WatchTargetFreq: 1,
|
||||
// 隐藏侧边栏
|
||||
HideSidebar: false,
|
||||
// 添加隐藏边栏按钮
|
||||
HideSidebarBtn: true,
|
||||
// 搜索页占位区
|
||||
SearchPagePlaceholder: true,
|
||||
// 解决一直转圈(加载中)的问题
|
||||
SolveGoogleScriptPendingIssue: false,
|
||||
// 图标坐标
|
||||
IconPosition: {} as { x: number, y: number },
|
||||
// 记住图标位置
|
||||
SaveIconPosition: false,
|
||||
// 现金变动提醒
|
||||
CashChangeAlert: false,
|
||||
// 收集数据以改进翻译质量
|
||||
CollectPlayerData: true,
|
||||
// 迷你资料卡显示上次行动时间
|
||||
ShowMiniProfLastAct: true,
|
||||
// 自定义css
|
||||
CustomCss: '',
|
||||
|
||||
/** @deprecated */
|
||||
attRelocate: false,
|
||||
};
|
||||
// } as const;
|
||||
|
||||
// export default defaultConfig;
|
||||
|
||||
class DefaultConfigType {
|
||||
// 开启翻译
|
||||
transEnable = false;
|
||||
|
||||
@Notified()
|
||||
transNew = true;
|
||||
// 快速犯罪
|
||||
quickCrime = true;
|
||||
@ -20,16 +108,12 @@ class DefaultConfigType {
|
||||
trvAlarm = true;
|
||||
// 啤酒提醒
|
||||
_15Alarm = true;
|
||||
|
||||
@Notified()
|
||||
_15_alarm_ignore: number[] = [];
|
||||
_15_alarm_ignore = false;
|
||||
// 啤酒提醒时间
|
||||
_15AlarmTime = 50;
|
||||
// 捡垃圾助手
|
||||
cityFinder = false;
|
||||
|
||||
// 叠E保护
|
||||
@Notified()
|
||||
SEProtect = false;
|
||||
// PT一键购买
|
||||
ptQuickBuy = false;
|
||||
@ -57,9 +141,7 @@ class DefaultConfigType {
|
||||
companyBWCollapse = true;
|
||||
// 海外警告
|
||||
abroadWarning = true;
|
||||
|
||||
// 落地转跳
|
||||
@Notified()
|
||||
landedRedirect = '';
|
||||
// 任何位置一键存钱
|
||||
companyDepositAnywhere = false;
|
||||
@ -67,9 +149,7 @@ class DefaultConfigType {
|
||||
CHTrainsDetect = 0;
|
||||
// 火车提醒开关
|
||||
CHTrainsDetectSwitch = true;
|
||||
|
||||
// 隐藏个人资料头像
|
||||
@Notified()
|
||||
HideProfileImg = false;
|
||||
// 显示曾用名
|
||||
ShowNameHistory = true;
|
||||
@ -81,9 +161,7 @@ class DefaultConfigType {
|
||||
HideSidebarBtn = true;
|
||||
// 搜索页占位区
|
||||
SearchPagePlaceholder = true;
|
||||
|
||||
// 解决一直转圈(加载中)的问题
|
||||
@Notified()
|
||||
SolveGoogleScriptPendingIssue = false;
|
||||
// 图标坐标
|
||||
IconPosition: Partial<{ x: number, y: number }> = {};
|
||||
@ -95,38 +173,10 @@ class DefaultConfigType {
|
||||
CollectPlayerData = true;
|
||||
// 迷你资料卡显示上次行动时间
|
||||
ShowMiniProfLastAct = true;
|
||||
|
||||
// 登陆邮箱
|
||||
@Notified()
|
||||
autoLoginEmail = '';
|
||||
// 登陆密码
|
||||
autoLoginPwd = '';
|
||||
|
||||
// 自定义css
|
||||
@Notified()
|
||||
CustomCss = '';
|
||||
|
||||
monitorOn = ['drugCDMonitor']
|
||||
drugCDMonitorInterval = 60000
|
||||
|
||||
// mini profile显示bs估算
|
||||
@Notified()
|
||||
isBSEstMiniProfOn = false
|
||||
// profile页面显示bs估算
|
||||
@Notified()
|
||||
isBSEstProfOn = true
|
||||
}
|
||||
|
||||
|
||||
export type Config = DefaultConfigType;
|
||||
|
||||
let config = new DefaultConfigType();
|
||||
|
||||
export default config as Readonly<Config>;
|
||||
|
||||
function Notified(f: boolean = true) {
|
||||
return Reflect.metadata(notifyKey, f);
|
||||
}
|
||||
|
||||
export function isNotified(propertyKey: string): boolean {
|
||||
return Reflect.getMetadata(notifyKey, config, propertyKey);
|
||||
}
|
||||
export default new DefaultConfigType() as Readonly<Config>;
|
||||
|
||||
@ -3,8 +3,11 @@ import Alert from "../utils/Alert";
|
||||
import DialogMsgBox from "../utils/DialogMsgBox";
|
||||
import CommonUtils from "../utils/CommonUtils";
|
||||
import { MenuItemConfig } from "../ZhongIcon";
|
||||
import IFrameCrimeHandler from "./IFrameCrimeHandler";
|
||||
import loadGS from "../../func/module/loadGS";
|
||||
import ClassName from "../../container/ClassName";
|
||||
import { Injectable } from "../../container/Injectable";
|
||||
import { Container } from "../../container/Container";
|
||||
|
||||
@ClassName('AdditionalSettingsHandler')
|
||||
@Injectable()
|
||||
@ -17,6 +20,26 @@ export default class AdditionalSettingsHandler {
|
||||
|
||||
public show(): void {
|
||||
let pop = new Popup('', '更多设定');
|
||||
// let insertHtml = '<p><button class="torn-btn">清空设置</button></p><p><button class="torn-btn">通知权限</button></p><p><button class="torn-btn">外部数据权限</button></p>';
|
||||
// pop.getElement().insertAdjacentHTML('beforeend', insertHtml);
|
||||
// let [btn1, btn2, btn3] = Array.from(pop.getElement().querySelectorAll('button'));
|
||||
// btn1.addEventListener('click', () => {
|
||||
// new DialogMsgBox('将清空所有芜湖助手相关设置并刷新页面,确定?', {
|
||||
// callback: () => {
|
||||
// localStorage.removeItem('wh_trv_alarm');
|
||||
// localStorage.removeItem('wh_trans_settings');
|
||||
// localStorage.removeItem('whuuid');
|
||||
// localStorage.removeItem('wh-gs-storage');
|
||||
// localStorage.removeItem('WHTEST');
|
||||
// new Alert('已清空,刷新页面');
|
||||
// window.location.reload();
|
||||
// }
|
||||
// });
|
||||
// });
|
||||
// btn2.addEventListener('click', () => {
|
||||
// });
|
||||
// btn3.addEventListener('click', () => {
|
||||
// });
|
||||
|
||||
let menuList: MenuItemConfig[] = [
|
||||
{
|
||||
@ -42,6 +65,20 @@ export default class AdditionalSettingsHandler {
|
||||
domType: 'button', domId: '', domText: '第三方API通信权限', clickFunc() {
|
||||
}
|
||||
},
|
||||
{
|
||||
domType: 'button', domId: '', domText: '小窗犯罪', clickFunc() {
|
||||
Container.factory(IFrameCrimeHandler).handle()
|
||||
}
|
||||
},
|
||||
{
|
||||
domType: 'button',
|
||||
domId: '',
|
||||
domText: '飞贼小助手',
|
||||
tip: '加载从PC端移植的伞佬的油猴版飞贼小助手',
|
||||
clickFunc: () => {
|
||||
loadGS(this.commonUtils.getScriptEngine())
|
||||
}
|
||||
},
|
||||
];
|
||||
menuList.forEach(i => pop.element.append(this.commonUtils.elemGenerator(i, pop.element)));
|
||||
}
|
||||
|
||||
@ -1,70 +1,66 @@
|
||||
// import Popup from "../utils/Popup";
|
||||
// import CommonUtils from "../utils/CommonUtils";
|
||||
// import MDUtils from "../utils/MDUtils";
|
||||
// import { MENU_ITEM_TYPE } from "../../interface/MenuItem";
|
||||
// import Provider from "../provider/Provider";
|
||||
// import ClassName from "../../container/ClassName";
|
||||
// import { Injectable } from "../../container/Injectable";
|
||||
// import { Container } from "../../container/Container";
|
||||
// import Logger from "../Logger";
|
||||
//
|
||||
// /**
|
||||
// * @deprecated
|
||||
// */
|
||||
// @ClassName('ChangeLogHandler')
|
||||
// @Injectable()
|
||||
// export class ChangeLogHandler extends Provider {
|
||||
// constructor(
|
||||
// private readonly mdUtils: MDUtils,
|
||||
// private readonly logger: Logger,
|
||||
// ) {
|
||||
// super();
|
||||
// }
|
||||
//
|
||||
// public show(): void {
|
||||
// let popup = new Popup(
|
||||
// '更新历史:<br/><a target="_blank" href="https://gitlab.com/JJins/wuhu-torn-helper/-/blob/dev/CHANGELOG.md">https://gitlab.com/JJins/wuhu-torn-helper/-/blob/dev/CHANGELOG.md</a><br/>',
|
||||
// '更新历史'
|
||||
// ).element;
|
||||
// popup.classList.add('wh-changeLog');
|
||||
// let progressBar = document.createElement('div');
|
||||
// progressBar.style.height = '2px';
|
||||
// progressBar.style.width = '1%';
|
||||
// progressBar.style.backgroundColor = 'red';
|
||||
// let progressText = document.createElement('p');
|
||||
// progressText.innerText = '加载更新文件……';
|
||||
// progressText.style.textAlign = 'center';
|
||||
// let style = document.createElement('style');
|
||||
// style.innerHTML = `.wh-changeLog h2,.wh-changeLog h3,.wh-changeLog h4 {margin:8px 0;}.wh-changeLog li{list-style: inside;}`;
|
||||
//
|
||||
// popup.append(progressBar, progressText, style);
|
||||
//
|
||||
// CommonUtils
|
||||
// .COFetch('https://gitlab.com/JJins/wuhu-torn-helper/-/raw/dev/CHANGELOG.md?' + performance.now())
|
||||
// .then(update => {
|
||||
// progressBar.style.width = '60%';
|
||||
// progressText.innerText = '解析中……';
|
||||
// let md = this.mdUtils.parse(update);
|
||||
// popup.append(md);
|
||||
// progressBar.style.width = '100%';
|
||||
// progressText.innerText = '加载完成';
|
||||
//
|
||||
// window.setTimeout(() => {
|
||||
// progressBar.remove();
|
||||
// progressText.remove()
|
||||
// }, 3000);
|
||||
// })
|
||||
// .catch(e => {
|
||||
// this.logger.error(e);
|
||||
// progressBar.remove();
|
||||
// progressText.innerText = '无法加载';
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// export default {
|
||||
// domType: MENU_ITEM_TYPE.BUTTON,
|
||||
// domText: '🐞 更新历史',
|
||||
// clickFunc: () => Container.factory(ChangeLogHandler).show()
|
||||
// };
|
||||
import Popup from "../utils/Popup";
|
||||
import CommonUtils from "../utils/CommonUtils";
|
||||
import MDUtils from "../utils/MDUtils";
|
||||
import Log from "../Log";
|
||||
import { MENU_ITEM_TYPE } from "../../interface/MenuItem";
|
||||
import Provider from "../provider/Provider";
|
||||
import ClassName from "../../container/ClassName";
|
||||
import { Injectable } from "../../container/Injectable";
|
||||
import { Container } from "../../container/Container";
|
||||
|
||||
@ClassName('ChangeLogHandler')
|
||||
@Injectable()
|
||||
class ChangeLogHandler extends Provider {
|
||||
constructor(
|
||||
private readonly mdUtils: MDUtils,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
public show(): void {
|
||||
let popup = new Popup(
|
||||
'更新历史:<br/><a target="_blank" href="https://gitlab.com/JJins/wuhu-torn-helper/-/blob/dev/CHANGELOG.md">https://gitlab.com/JJins/wuhu-torn-helper/-/blob/dev/CHANGELOG.md</a><br/>',
|
||||
'更新历史'
|
||||
).element;
|
||||
popup.classList.add('wh-changeLog');
|
||||
let progressBar = document.createElement('div');
|
||||
progressBar.style.height = '2px';
|
||||
progressBar.style.width = '1%';
|
||||
progressBar.style.backgroundColor = 'red';
|
||||
let progressText = document.createElement('p');
|
||||
progressText.innerText = '加载更新文件……';
|
||||
progressText.style.textAlign = 'center';
|
||||
let style = document.createElement('style');
|
||||
style.innerHTML = `.wh-changeLog h2,.wh-changeLog h3,.wh-changeLog h4 {margin:8px 0;}.wh-changeLog li{list-style: inside;}`;
|
||||
|
||||
popup.append(progressBar, progressText, style);
|
||||
|
||||
CommonUtils
|
||||
.COFetch('https://gitlab.com/JJins/wuhu-torn-helper/-/raw/dev/CHANGELOG.md?' + performance.now())
|
||||
.then(update => {
|
||||
progressBar.style.width = '60%';
|
||||
progressText.innerText = '解析中……';
|
||||
let md = this.mdUtils.parse(update);
|
||||
popup.append(md);
|
||||
progressBar.style.width = '100%';
|
||||
progressText.innerText = '加载完成';
|
||||
|
||||
window.setTimeout(() => {
|
||||
progressBar.remove();
|
||||
progressText.remove()
|
||||
}, 3000);
|
||||
})
|
||||
.catch(e => {
|
||||
Log.error(e);
|
||||
progressBar.remove();
|
||||
progressText.innerText = '无法加载';
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default {
|
||||
domType: MENU_ITEM_TYPE.BUTTON,
|
||||
domText: '🐞 更新历史',
|
||||
clickFunc: () => Container.factory(ChangeLogHandler).show()
|
||||
};
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import Popup from "../utils/Popup";
|
||||
import WuhuConfig from "../WuhuConfig";
|
||||
import ClassName from "../../container/ClassName";
|
||||
import { Injectable } from "../../container/Injectable";
|
||||
import LocalConfigWrapper from "../LocalConfigWrapper";
|
||||
@ -18,7 +19,7 @@ export default class CustomCssHandler {
|
||||
let button = pop.element.querySelector('button');
|
||||
textarea.value = this.localConfigWrapper.config.CustomCss || '';
|
||||
button.addEventListener('click', () => {
|
||||
this.localConfigWrapper.config.CustomCss = textarea.value || '';
|
||||
WuhuConfig.set('CustomCss', textarea.value || '', true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,97 +1,97 @@
|
||||
// import CommonUtils from "../utils/CommonUtils";
|
||||
// import Popup from "../utils/Popup";
|
||||
// import QUICK_CRIMES_HTML from "../../../static/html/quick_crimes.html";
|
||||
// import ClassName from "../../container/ClassName";
|
||||
// import { Injectable } from "../../container/Injectable";
|
||||
//
|
||||
// @ClassName('IFrameCrimeHandler')
|
||||
// @Injectable()
|
||||
// export default class IFrameCrimeHandler {
|
||||
//
|
||||
// public handle(): void {
|
||||
// // 弹出小窗口
|
||||
// const ifHTML = `<iframe src="/crimes.php?step=main" style="width:100%;max-width: 450px;margin: 0 auto;display: none;height: 340px;"></iframe>`;
|
||||
// const popup_insert = `<p>加载中请稍后${ CommonUtils.loading_gif_html() }</p><div id="wh-quick-crime-if-container"></div>`;
|
||||
// const $popup = new Popup(popup_insert, '小窗快速犯罪').getElement();
|
||||
// // 运行状态node
|
||||
// let loading_node = $popup.querySelector('p:first-of-type');
|
||||
// // if容器
|
||||
// const if_cont = $popup.querySelector('#wh-quick-crime-if-container');
|
||||
// if_cont.innerHTML = ifHTML;
|
||||
//
|
||||
// // if内未加载脚本时插入的快捷crime node
|
||||
// const mobile_prepend_node = document.createElement('div');
|
||||
// mobile_prepend_node.classList.add('wh-translate');
|
||||
// mobile_prepend_node.innerHTML = QUICK_CRIMES_HTML;
|
||||
//
|
||||
// // if对象加载后运行
|
||||
// let cIframe = $popup.querySelector('iframe');
|
||||
//
|
||||
// // 加载状态
|
||||
// const if_onload_func = () => {
|
||||
// // if内部文档对象
|
||||
// const ifDocu = cIframe.contentWindow.document;
|
||||
// // 内部插件运行flag
|
||||
// const ifWH = cIframe.contentWindow.WHTRANS;
|
||||
// // 文档加载完成后移除
|
||||
// if (!!loading_node) loading_node.remove();
|
||||
// // 文档加载完成后才显示if
|
||||
// cIframe.style.display = 'block';
|
||||
// // 验证码flag
|
||||
// const isValidate = ifDocu.querySelector('h4#skip-to-content').innerText.toLowerCase().includes('validate');
|
||||
// // 如果iframe内部未运行脚本
|
||||
// if (ifWH === undefined) {
|
||||
// // 隐藏顶部
|
||||
// CommonUtils.elementReady('#header-root', ifDocu).then(e => e.style.display = 'none');
|
||||
// // 隐藏4条
|
||||
// CommonUtils.elementReady('#sidebarroot', ifDocu).then(e => e.style.display = 'none');
|
||||
// // 隐藏聊天
|
||||
// CommonUtils.elementReady('#chatRoot', ifDocu).then(e => e.style.display = 'none');
|
||||
// // 非验证码页面隐藏滚动条
|
||||
// if (!isValidate) ifDocu.body.style.overflow = 'hidden';
|
||||
// // 调整容器位置
|
||||
// CommonUtils.elementReady('.content-wrapper', ifDocu).then(elem => {
|
||||
// // 加入
|
||||
// elem.prepend(mobile_prepend_node);
|
||||
// elem.style.margin = '0px';
|
||||
// elem.style.position = 'absolute';
|
||||
// elem.style.top = '-35px';
|
||||
// new MutationObserver((m, o) => {
|
||||
// o.disconnect();
|
||||
// if (!elem.querySelector('.wh-translate')) elem.prepend(mobile_prepend_node);
|
||||
// o.observe(elem, { childList: true, subtree: true });
|
||||
// })
|
||||
// .observe(elem, { childList: true, subtree: true });
|
||||
// });
|
||||
// // 隐藏返回顶部按钮
|
||||
// CommonUtils.elementReady('#go-to-top-btn button', ifDocu).then(e => e.style.display = 'none');
|
||||
// }
|
||||
// };
|
||||
// cIframe.onload = if_onload_func;
|
||||
//
|
||||
// // 超时判断
|
||||
// let time_counter = 0;
|
||||
// let time_out_id = window.setInterval(() => {
|
||||
// loading_node = $popup.querySelector('p:first-of-type');
|
||||
// if (!loading_node) {
|
||||
// clearInterval(time_out_id);
|
||||
// time_out_id = undefined;
|
||||
// return;
|
||||
// }
|
||||
// time_counter++;
|
||||
// if (time_counter > 0 && !loading_node.querySelector('button')) {
|
||||
// const reload_btn = document.createElement('button');
|
||||
// reload_btn.innerHTML = '重新加载';
|
||||
// reload_btn.onclick = () => {
|
||||
// reload_btn.remove();
|
||||
// time_counter = 0;
|
||||
// if_cont.innerHTML = null;
|
||||
// if_cont.innerHTML = ifHTML;
|
||||
// cIframe = $popup.querySelector('iframe');
|
||||
// cIframe.onload = if_onload_func;
|
||||
// };
|
||||
// loading_node.append(reload_btn);
|
||||
// }
|
||||
// }, 1000);
|
||||
// }
|
||||
// }
|
||||
import CommonUtils from "../utils/CommonUtils";
|
||||
import Popup from "../utils/Popup";
|
||||
import QUICK_CRIMES_HTML from "../../../static/html/quick_crimes.html";
|
||||
import ClassName from "../../container/ClassName";
|
||||
import { Injectable } from "../../container/Injectable";
|
||||
|
||||
@ClassName('IFrameCrimeHandler')
|
||||
@Injectable()
|
||||
export default class IFrameCrimeHandler {
|
||||
|
||||
public handle(): void {
|
||||
// 弹出小窗口
|
||||
const ifHTML = `<iframe src="/crimes.php?step=main" style="width:100%;max-width: 450px;margin: 0 auto;display: none;height: 340px;"></iframe>`;
|
||||
const popup_insert = `<p>加载中请稍后${ CommonUtils.loading_gif_html() }</p><div id="wh-quick-crime-if-container"></div>`;
|
||||
const $popup = new Popup(popup_insert, '小窗快速犯罪').getElement();
|
||||
// 运行状态node
|
||||
let loading_node = $popup.querySelector('p:first-of-type');
|
||||
// if容器
|
||||
const if_cont = $popup.querySelector('#wh-quick-crime-if-container');
|
||||
if_cont.innerHTML = ifHTML;
|
||||
|
||||
// if内未加载脚本时插入的快捷crime node
|
||||
const mobile_prepend_node = document.createElement('div');
|
||||
mobile_prepend_node.classList.add('wh-translate');
|
||||
mobile_prepend_node.innerHTML = QUICK_CRIMES_HTML;
|
||||
|
||||
// if对象加载后运行
|
||||
let cIframe = $popup.querySelector('iframe');
|
||||
|
||||
// 加载状态
|
||||
const if_onload_func = () => {
|
||||
// if内部文档对象
|
||||
const ifDocu = cIframe.contentWindow.document;
|
||||
// 内部插件运行flag
|
||||
const ifWH = cIframe.contentWindow.WHTRANS;
|
||||
// 文档加载完成后移除
|
||||
if (!!loading_node) loading_node.remove();
|
||||
// 文档加载完成后才显示if
|
||||
cIframe.style.display = 'block';
|
||||
// 验证码flag
|
||||
const isValidate = ifDocu.querySelector('h4#skip-to-content').innerText.toLowerCase().includes('validate');
|
||||
// 如果iframe内部未运行脚本
|
||||
if (ifWH === undefined) {
|
||||
// 隐藏顶部
|
||||
CommonUtils.elementReady('#header-root', ifDocu).then(e => e.style.display = 'none');
|
||||
// 隐藏4条
|
||||
CommonUtils.elementReady('#sidebarroot', ifDocu).then(e => e.style.display = 'none');
|
||||
// 隐藏聊天
|
||||
CommonUtils.elementReady('#chatRoot', ifDocu).then(e => e.style.display = 'none');
|
||||
// 非验证码页面隐藏滚动条
|
||||
if (!isValidate) ifDocu.body.style.overflow = 'hidden';
|
||||
// 调整容器位置
|
||||
CommonUtils.elementReady('.content-wrapper', ifDocu).then(elem => {
|
||||
// 加入
|
||||
elem.prepend(mobile_prepend_node);
|
||||
elem.style.margin = '0px';
|
||||
elem.style.position = 'absolute';
|
||||
elem.style.top = '-35px';
|
||||
new MutationObserver((m, o) => {
|
||||
o.disconnect();
|
||||
if (!elem.querySelector('.wh-translate')) elem.prepend(mobile_prepend_node);
|
||||
o.observe(elem, { childList: true, subtree: true });
|
||||
})
|
||||
.observe(elem, { childList: true, subtree: true });
|
||||
});
|
||||
// 隐藏返回顶部按钮
|
||||
CommonUtils.elementReady('#go-to-top-btn button', ifDocu).then(e => e.style.display = 'none');
|
||||
}
|
||||
};
|
||||
cIframe.onload = if_onload_func;
|
||||
|
||||
// 超时判断
|
||||
let time_counter = 0;
|
||||
let time_out_id = window.setInterval(() => {
|
||||
loading_node = $popup.querySelector('p:first-of-type');
|
||||
if (!loading_node) {
|
||||
clearInterval(time_out_id);
|
||||
time_out_id = undefined;
|
||||
return;
|
||||
}
|
||||
time_counter++;
|
||||
if (time_counter > 0 && !loading_node.querySelector('button')) {
|
||||
const reload_btn = document.createElement('button');
|
||||
reload_btn.innerHTML = '重新加载';
|
||||
reload_btn.onclick = () => {
|
||||
reload_btn.remove();
|
||||
time_counter = 0;
|
||||
if_cont.innerHTML = null;
|
||||
if_cont.innerHTML = ifHTML;
|
||||
cIframe = $popup.querySelector('iframe');
|
||||
cIframe.onload = if_onload_func;
|
||||
};
|
||||
loading_node.append(reload_btn);
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
@ -1,14 +1,11 @@
|
||||
import CommonUtils from "../utils/CommonUtils";
|
||||
import QUICK_FLY_CSS from "../../../static/css/quick_fly.module.css";
|
||||
import QUICK_FLY_CSS from "../../../static/css/quick_fly.css";
|
||||
import QUICK_FLY_HTML from "../../../static/html/quick_fly.html";
|
||||
import Alert from "../utils/Alert";
|
||||
import TravelItem from "../../feature/TravelItem";
|
||||
import TravelItem from "../action/TravelItem";
|
||||
import ClassName from "../../container/ClassName";
|
||||
import { Injectable } from "../../container/Injectable";
|
||||
import Logger from "../Logger";
|
||||
import MsgWrapper from "../utils/MsgWrapper";
|
||||
import { InjectionKey } from "vue";
|
||||
import NetHighLvlWrapper from "../utils/NetHighLvlWrapper";
|
||||
|
||||
@ClassName('QuickFlyBtnHandler')
|
||||
@Injectable()
|
||||
@ -18,10 +15,6 @@ export default class QuickFlyBtnHandler {
|
||||
constructor(
|
||||
private readonly logger: Logger,
|
||||
private readonly travelItem: TravelItem,
|
||||
private readonly commonUtils: CommonUtils,
|
||||
// private readonly infoUtils: InfoUtils,
|
||||
private readonly msgWrapper: MsgWrapper,
|
||||
private readonly netHighLvlWrapper: NetHighLvlWrapper,
|
||||
) {
|
||||
}
|
||||
|
||||
@ -61,7 +54,7 @@ export default class QuickFlyBtnHandler {
|
||||
}
|
||||
|
||||
// 起飞目的地id
|
||||
private static getDestId(dest: number): number {
|
||||
private static getDestId(dest): number {
|
||||
// 墨、开、加、夏、英、阿、瑞s、立本、祖、迪、南
|
||||
return [2, 12, 9, 3, 10, 7, 8, 5, 6, 11, 4][dest];
|
||||
}
|
||||
@ -70,7 +63,7 @@ export default class QuickFlyBtnHandler {
|
||||
if (window.hasWHQuickFlyOpt) return;
|
||||
window.hasWHQuickFlyOpt = true;
|
||||
// TODO
|
||||
this.commonUtils.styleInject(QUICK_FLY_CSS);
|
||||
CommonUtils.addStyle(QUICK_FLY_CSS);
|
||||
const node = document.createElement('div');
|
||||
node.id = 'wh-quick-fly-opt';
|
||||
node.innerHTML = QUICK_FLY_HTML;
|
||||
@ -120,37 +113,4 @@ export default class QuickFlyBtnHandler {
|
||||
showTime();
|
||||
yaoCD.innerHTML = `药CD剩余:${ CommonUtils.getYaoCD() }`;
|
||||
}
|
||||
|
||||
public async directFly(destIndex: number, typeIndex: number) {
|
||||
// 获取key
|
||||
// if(false){
|
||||
// let key;
|
||||
// try {
|
||||
// const resp = await (await fetch('/travelagency.php')).text();
|
||||
// key = resp.match(/data-key="([0-9]+)"/)[1];
|
||||
// } catch (e) {
|
||||
// this.msgWrapper.create('起飞参数获取失败', {}, 'error');
|
||||
// this.logger.error(e.stack);
|
||||
// throw new Error('起飞参数获取失败');
|
||||
// }
|
||||
// }
|
||||
let msg: string;
|
||||
try {
|
||||
msg = await this.netHighLvlWrapper.doTravelFly(QuickFlyBtnHandler.getDestId(destIndex), null, ['standard', 'airstrip', 'private', 'business'][typeIndex])
|
||||
const response = JSON.parse(msg);
|
||||
if (!response.success) {
|
||||
this.msgWrapper.create('起飞失败 ' + response.error, {}, 'error');
|
||||
this.logger.error('起飞失败 ' + response.error, response.err);
|
||||
throw new Error('起飞失败 ' + response.error);
|
||||
}
|
||||
console.log(msg);
|
||||
} catch (e) {
|
||||
this.msgWrapper.create('起飞时出现错误 ' + e.message, {}, 'error');
|
||||
this.logger.error(e.stack);
|
||||
throw new Error('起飞时出现错误 ' + e.message);
|
||||
}
|
||||
this.msgWrapper.create('已起飞', {}, 'success');
|
||||
}
|
||||
}
|
||||
|
||||
export const QuickFlyBtnHandlerKey = Symbol('QuickFlyBtnHandlerKey') as InjectionKey<QuickFlyBtnHandler>
|
||||
|
||||
@ -1,19 +1,13 @@
|
||||
import CommonUtils from "../utils/CommonUtils";
|
||||
import QUICK_LINK_CSS from "../../../static/css/quick_link.module.css";
|
||||
import QUICK_LINK_CSS from "../../../static/css/quick_link.css";
|
||||
import Popup from "../utils/Popup";
|
||||
import ClassName from "../../container/ClassName";
|
||||
import { Injectable } from "../../container/Injectable";
|
||||
|
||||
@ClassName('QuickLinksHandler')
|
||||
@Injectable()
|
||||
export default class QuickLinksHandler {
|
||||
|
||||
private styleAdded: boolean = false;
|
||||
private list = [];
|
||||
|
||||
constructor(
|
||||
private readonly commonUtils: CommonUtils,
|
||||
) {
|
||||
constructor() {
|
||||
let list = this.list;
|
||||
// 生存手册
|
||||
list.push({
|
||||
@ -75,7 +69,7 @@ export default class QuickLinksHandler {
|
||||
|
||||
public handle(): void {
|
||||
if (!this.styleAdded) {
|
||||
this.commonUtils.styleInject(QUICK_LINK_CSS);
|
||||
CommonUtils.addStyle(QUICK_LINK_CSS);
|
||||
this.styleAdded = true;
|
||||
}
|
||||
const list = this.list;
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { MenuItemConfig } from "../ZhongIcon";
|
||||
import Log from "../Log";
|
||||
import Timer from "../utils/Timer";
|
||||
import BuyBeerHelper from "../../feature/BuyBeerHelper";
|
||||
import BuyBeerHelper from "../action/BuyBeerHelper";
|
||||
import UpdateTranslateDict from "./UpdateTranslateDict";
|
||||
import landedRedirect from "../../func/module/landedRedirect";
|
||||
import Alert from "../utils/Alert";
|
||||
@ -14,7 +15,6 @@ import { MENU_ITEM_TYPE } from "../../interface/MenuItem";
|
||||
import ClassName from "../../container/ClassName";
|
||||
import { Injectable } from "../../container/Injectable";
|
||||
import { Container } from "../../container/Container";
|
||||
import Logger from "../Logger";
|
||||
|
||||
@ClassName('SettingsHandler')
|
||||
@Injectable()
|
||||
@ -30,7 +30,6 @@ class SettingsHandler extends Provider {
|
||||
private readonly customCssHandler: CustomCssHandler,
|
||||
private readonly viewLogsHandler: ViewLogsHandler,
|
||||
private readonly additionalSettingsHandler: AdditionalSettingsHandler,
|
||||
private readonly logger: Logger,
|
||||
) {
|
||||
super();
|
||||
this.constructWuhuSettingList();
|
||||
@ -38,7 +37,7 @@ class SettingsHandler extends Provider {
|
||||
|
||||
public show(): void {
|
||||
let startTime = new Timer();
|
||||
this.logger.info('构造设置开始');
|
||||
Log.info('构造设置开始');
|
||||
let pop = new Popup(CommonUtils.loading_gif_html(), '芜湖助手设置');
|
||||
window.setTimeout(() => {
|
||||
let tmp = document.createElement('div');
|
||||
@ -50,14 +49,14 @@ class SettingsHandler extends Provider {
|
||||
pop.getElement().innerHTML = '';
|
||||
pop.getElement().appendChild(tmp);
|
||||
(window.initializeTooltip) && (window.initializeTooltip('#wh-popup-cont', 'white-tooltip'));
|
||||
this.logger.info('构造设置结束 ' + startTime.getTimeMs());
|
||||
Log.info('构造设置结束 ' + startTime.getTimeMs());
|
||||
}, 0)
|
||||
}
|
||||
|
||||
// 设置
|
||||
private constructWuhuSettingList(): SettingsHandler {
|
||||
let timer = new Timer();
|
||||
this.logger.info('构造设置列表开始');
|
||||
Log.info('构造设置列表开始');
|
||||
const date = new Date();
|
||||
|
||||
let beer = this.buyBeerHelper;
|
||||
@ -573,7 +572,7 @@ class SettingsHandler extends Provider {
|
||||
clickFunc: () => this.additionalSettingsHandler.show()
|
||||
});
|
||||
|
||||
this.logger.info('构造设置列表结束' + timer.getTimeMs());
|
||||
Log.info('构造设置列表结束' + timer.getTimeMs());
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,7 +4,6 @@ import CommonUtils from "../utils/CommonUtils";
|
||||
import VIEW_LOGS_HANDLER_HTML from "../../../static/html/view_logs_handler.html";
|
||||
import ClassName from "../../container/ClassName";
|
||||
import { Injectable } from "../../container/Injectable";
|
||||
import Logger from "../Logger";
|
||||
|
||||
@ClassName('ViewLogsHandler')
|
||||
@Injectable()
|
||||
@ -12,12 +11,11 @@ export default class ViewLogsHandler {
|
||||
|
||||
constructor(
|
||||
private readonly commonUtils: CommonUtils,
|
||||
private readonly logger: Logger,
|
||||
) {
|
||||
}
|
||||
|
||||
public handle(): void {
|
||||
let logCounter = this.logger.getCounter();
|
||||
let logCounter = Log.getCounter();
|
||||
let pop = new Popup(VIEW_LOGS_HANDLER_HTML
|
||||
.replace('{{}}', logCounter.info.toString())
|
||||
.replace('{{}}', logCounter.warning.toString())
|
||||
|
||||
12
src/ts/class/provider/ButtonHandler.ts
Normal file
12
src/ts/class/provider/ButtonHandler.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { MENU_ITEM_TYPE } from "../../interface/MenuItem";
|
||||
|
||||
const BUTTON_HANDLE_METADATA_KEY = Symbol("BUTTON_HANDLE_KEY")
|
||||
|
||||
/**
|
||||
* @ButtonHandler
|
||||
* 按钮
|
||||
* @param target 类本身
|
||||
*/
|
||||
export function ButtonHandler<T>(target: T): void {
|
||||
Reflect.defineMetadata(BUTTON_HANDLE_METADATA_KEY, MENU_ITEM_TYPE.BUTTON, target);
|
||||
}
|
||||
26
src/ts/class/provider/Elem.ts
Normal file
26
src/ts/class/provider/Elem.ts
Normal file
@ -0,0 +1,26 @@
|
||||
export default class Elem {
|
||||
private readonly elem: HTMLElement;
|
||||
|
||||
constructor(tagName) {
|
||||
this.elem = document.createElement(tagName);
|
||||
}
|
||||
|
||||
public html(htmlString): Elem {
|
||||
this.elem.innerHTML = htmlString;
|
||||
return this;
|
||||
}
|
||||
|
||||
public id(id): Elem {
|
||||
this.elem.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
public class(className): Elem {
|
||||
this.elem.classList.add(className);
|
||||
return this;
|
||||
}
|
||||
|
||||
public el(): HTMLElement {
|
||||
return this.elem;
|
||||
}
|
||||
}
|
||||
18
src/ts/class/provider/EntryPoint.ts
Normal file
18
src/ts/class/provider/EntryPoint.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import Log from "../Log";
|
||||
import ZhongIcon from "../ZhongIcon";
|
||||
|
||||
export default function EntryPoint(T: { main: () => void }) {
|
||||
if (window.WHTRANS) throw '退出, 已运行次数' + window.WHTRANS;
|
||||
window.WHTRANS = window.WHTRANS === undefined ? 1 : window.WHTRANS++;
|
||||
|
||||
let started = performance.now();
|
||||
try {
|
||||
T.main();
|
||||
} catch (e) {
|
||||
Log.error('[Starter]加载出错信息: ' + e.stack || e.message);
|
||||
}
|
||||
let runTime: number = (performance.now() - started) | 0;
|
||||
Log.info(`芜湖脚本完成加载, 耗时${ runTime }ms`);
|
||||
if (ZhongIcon.ZhongNode && ZhongIcon.ZhongNode.initTimer)
|
||||
ZhongIcon.ZhongNode.initTimer.innerHTML = `加载时间 ${ runTime }ms`;
|
||||
}
|
||||
@ -1,37 +1,38 @@
|
||||
import Log from "../Log";
|
||||
import Timer from "../utils/Timer";
|
||||
import ClassWithName from "../../interface/ClassWithName";
|
||||
|
||||
/**
|
||||
* 基类、单例
|
||||
* @deprecated
|
||||
*/
|
||||
export default class Provider implements ClassWithName {
|
||||
readonly className: string = 'Provider';
|
||||
// private static _instance;
|
||||
//
|
||||
// private static readonly pool = {};
|
||||
//
|
||||
// constructor(...args: unknown[]) {
|
||||
// }
|
||||
private static _instance;
|
||||
|
||||
private static readonly pool = {};
|
||||
|
||||
constructor(...args: unknown[]) {
|
||||
}
|
||||
|
||||
// 返回继承类的实例
|
||||
// public static getInstance<T extends typeof Provider>(this: T, ...args: unknown[]): InstanceType<T> {
|
||||
// if (!this._instance) {
|
||||
// let startTime = new Timer();
|
||||
// this._instance = new this(...args);
|
||||
// let thatName = this._instance.getClassName() || this.name;
|
||||
// Log.info('实例已创建,', thatName, this._instance, '耗时' + startTime.getTimeMs());
|
||||
// Provider.pool[thatName] = this._instance;
|
||||
// }
|
||||
// return this._instance;
|
||||
// }
|
||||
public static getInstance<T extends typeof Provider>(this: T, ...args: unknown[]): InstanceType<T> {
|
||||
if (!this._instance) {
|
||||
let startTime = new Timer();
|
||||
this._instance = new this(...args);
|
||||
let thatName = this._instance.getClassName() || this.name;
|
||||
Log.info('实例已创建,', thatName, this._instance, '耗时' + startTime.getTimeMs());
|
||||
Provider.pool[thatName] = this._instance;
|
||||
}
|
||||
return this._instance;
|
||||
}
|
||||
|
||||
// public static getPool() {
|
||||
// return {
|
||||
// pool: Provider.pool,
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public getClassName() {
|
||||
// return this.className;
|
||||
// }
|
||||
public static getPool() {
|
||||
return {
|
||||
pool: Provider.pool,
|
||||
}
|
||||
}
|
||||
|
||||
public getClassName() {
|
||||
return this.className;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,20 +1,32 @@
|
||||
import ZhongIcon from "../ZhongIcon";
|
||||
import ClassName from "../../container/ClassName";
|
||||
import { Injectable } from "../../container/Injectable";
|
||||
import Logger from "../Logger";
|
||||
import globVars from "../../globVars";
|
||||
|
||||
@ClassName('ActionButtonUtils')
|
||||
@Injectable()
|
||||
export default class ActionButtonUtils {
|
||||
private hasAdded: boolean = false;
|
||||
private readonly logger = Logger.factory(ActionButtonUtils)
|
||||
|
||||
public add(txt: string, func: (ev: Event) => void = () => null): void {
|
||||
|
||||
let added = { txt, func }
|
||||
globVars.buttons.push(added)
|
||||
|
||||
this.logger.info({ globVars })
|
||||
constructor(
|
||||
private readonly logger: Logger,
|
||||
) {
|
||||
}
|
||||
|
||||
public add(txt: string, func: (ev: Event) => void = () => null): void {
|
||||
if (!this.hasAdded) this.handle(txt, func);
|
||||
else this.logger.warn('ActionButton已存在');
|
||||
}
|
||||
|
||||
private handle(txt, func): void {
|
||||
let btn = document.createElement('button');
|
||||
btn.style.padding = '8px 13px 8px 0';
|
||||
btn.style.verticalAlign = 'bottom';
|
||||
btn.style.color = '#4CAF50';
|
||||
btn.innerHTML = txt;
|
||||
btn.addEventListener('click', func);
|
||||
ZhongIcon.ZhongNode.querySelector('button').after(btn);
|
||||
this.hasAdded = true;
|
||||
this.logger.info('ActionButton已添加', { txt, func, btn });
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
import UserScriptEngine from "../../enum/UserScriptEngine";
|
||||
import Log from "../Log";
|
||||
import Device from "../../enum/Device";
|
||||
import LOADING_IMG_HTML from "../../../static/html/loading_img.html";
|
||||
import Timer from "./Timer";
|
||||
import FetchUtils from "./FetchUtils";
|
||||
import TornStyleSwitch from "./TornStyleSwitch";
|
||||
import WuhuConfig from "../WuhuConfig";
|
||||
import { MenuItemConfig } from "../ZhongIcon";
|
||||
import TRAVEL_STATE from "../../enum/TravelState";
|
||||
import InventoryItemInfo from "../../interface/responseType/InventoryItemInfo";
|
||||
@ -14,7 +16,6 @@ import Logger from "../Logger";
|
||||
import Global from "../Global";
|
||||
import { Container } from "../../container/Container";
|
||||
import TornPDAUtils from "./TornPDAUtils";
|
||||
import { InjectionKey } from "vue";
|
||||
|
||||
@Injectable()
|
||||
@ClassName('CommonUtils')
|
||||
@ -40,14 +41,13 @@ export default class CommonUtils {
|
||||
}
|
||||
|
||||
static COFetch(url: URL | string, method: 'get' | 'post' | string = 'get', body: any = null): Promise<string> {
|
||||
let logger = Container.factory(Logger);
|
||||
let start = new Timer();
|
||||
const engine = this.getScriptEngine();
|
||||
logger.info(`跨域请求 -> ${url}, 脚本引擎: ${engine}`);
|
||||
Log.info('跨域获取数据开始, 脚本引擎: ' + engine);
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
switch (engine) {
|
||||
case UserScriptEngine.RAW: {
|
||||
logger.error(`跨域请求错误:${ UserScriptEngine.RAW }环境下无法进行跨域请求`);
|
||||
Log.error(`跨域请求错误:${ UserScriptEngine.RAW }环境下无法进行跨域请求`);
|
||||
reject(`错误:${ UserScriptEngine.RAW }环境下无法进行跨域请求`);
|
||||
break;
|
||||
}
|
||||
@ -56,29 +56,29 @@ export default class CommonUtils {
|
||||
// get
|
||||
if (method === 'get') {
|
||||
if (typeof PDA_httpGet !== 'function') {
|
||||
logger.error('COFetch网络错误:PDA版本不支持');
|
||||
Log.error('COFetch网络错误:PDA版本不支持');
|
||||
reject('COFetch网络错误:PDA版本不支持');
|
||||
}
|
||||
PDA_httpGet(url)
|
||||
.then(res => {
|
||||
logger.info('跨域获取数据成功, 耗时' + start.getTimeMs());
|
||||
Log.info('跨域获取数据成功, 耗时' + start.getTimeMs());
|
||||
resolve(res.responseText);
|
||||
})
|
||||
.catch(e => {
|
||||
logger.error('COFetch网络错误', e);
|
||||
Log.error('COFetch网络错误', e);
|
||||
reject(`COFetch网络错误 ${ e }`);
|
||||
})
|
||||
}
|
||||
// post
|
||||
else {
|
||||
if (typeof PDA_httpPost !== 'function') {
|
||||
logger.error('COFetch网络错误:PDA版本不支持');
|
||||
Log.error('COFetch网络错误:PDA版本不支持');
|
||||
reject('COFetch网络错误:PDA版本不支持');
|
||||
}
|
||||
PDA_httpPost(url, { 'content-type': 'application/json' }, body)
|
||||
.then(res => resolve(res.responseText))
|
||||
.catch(e => {
|
||||
logger.error('COFetch网络错误', e);
|
||||
Log.error('COFetch网络错误', e);
|
||||
reject(`COFetch网络错误 ${ e }`);
|
||||
});
|
||||
}
|
||||
@ -87,7 +87,7 @@ export default class CommonUtils {
|
||||
case UserScriptEngine.GM: {
|
||||
let { GM_xmlhttpRequest } = Container.factory(Global);
|
||||
if (typeof GM_xmlhttpRequest !== 'function') {
|
||||
logger.error('COFetch网络错误:用户脚本扩展API错误');
|
||||
Log.error('COFetch网络错误:用户脚本扩展API错误');
|
||||
reject('错误:用户脚本扩展API错误');
|
||||
}
|
||||
GM_xmlhttpRequest({
|
||||
@ -96,7 +96,7 @@ export default class CommonUtils {
|
||||
data: method === 'get' ? null : body,
|
||||
headers: method === 'get' ? null : { 'content-type': 'application/json' },
|
||||
onload: res => {
|
||||
logger.info('跨域获取数据成功,耗时' + start.getTimeMs());
|
||||
Log.info('跨域获取数据成功,耗时' + start.getTimeMs());
|
||||
resolve(res.response);
|
||||
},
|
||||
onerror: res => reject(`连接错误 ${ JSON.stringify(res) }`),
|
||||
@ -175,27 +175,26 @@ export default class CommonUtils {
|
||||
* @returns {Promise<HTMLElement|null>}
|
||||
*/
|
||||
public static elementReady(selectors: string, content: Document = document, timeout: number = 30000): Promise<HTMLElement> {
|
||||
const logger = Container.factory(Logger);
|
||||
logger.info('等待元素:' + selectors);
|
||||
Log.info('等待元素:' + selectors);
|
||||
let timer = new Timer();
|
||||
return new Promise((resolve, reject) => {
|
||||
let el = content.querySelector(selectors) as HTMLElement;
|
||||
if (el) {
|
||||
logger.info('已获取元素, 耗时' + timer.getTimeMs(), el);
|
||||
Log.info('已获取元素, 耗时' + timer.getTimeMs(), el);
|
||||
resolve(el);
|
||||
return;
|
||||
}
|
||||
let observer = new MutationObserver((_, observer) => {
|
||||
content.querySelectorAll(selectors).forEach((element) => {
|
||||
logger.info({ innerHTML: element.innerHTML, element });
|
||||
Log.info({ innerHTML: element.innerHTML, element });
|
||||
observer.disconnect();
|
||||
logger.info('已获取元素, 耗时' + timer.getTimeMs(), element);
|
||||
Log.info('已获取元素, 耗时' + timer.getTimeMs(), element);
|
||||
resolve(element as HTMLElement);
|
||||
});
|
||||
});
|
||||
window.setTimeout(() => {
|
||||
observer.disconnect();
|
||||
logger.error(`等待元素超时! [${ selectors }]\n${ content.documentElement.tagName }, 耗时` + timer.getTimeMs());
|
||||
Log.error(`等待元素超时! [${ selectors }]\n${ content.documentElement.tagName }, 耗时` + timer.getTimeMs());
|
||||
reject(`等待元素超时! [${ selectors }]\n${ content.documentElement.tagName }, 耗时` + timer.getTimeMs());
|
||||
}, timeout);
|
||||
observer.observe(content.documentElement, { childList: true, subtree: true });
|
||||
@ -212,12 +211,7 @@ export default class CommonUtils {
|
||||
return CommonUtils.elementReady(selectors, content, timeout);
|
||||
}
|
||||
|
||||
public querySelector(selectors: string, content: Document = document, timeout: number = 30000): Promise<HTMLElement> {
|
||||
return CommonUtils.elementReady(selectors, content, timeout);
|
||||
}
|
||||
|
||||
public static addStyle(rules: string): void {
|
||||
const logger = Container.factory(Logger);
|
||||
let element = document.querySelector('style#wh-trans-gStyle');
|
||||
if (element) {
|
||||
element.innerHTML += rules;
|
||||
@ -227,14 +221,7 @@ export default class CommonUtils {
|
||||
element.innerHTML = rules;
|
||||
document.head.appendChild(element);
|
||||
}
|
||||
logger.info('CSS规则已添加', element);
|
||||
}
|
||||
|
||||
public styleInject(rules: string): void {
|
||||
const element = document.createElement("style");
|
||||
element.setAttribute('type', 'text/css');
|
||||
element.innerHTML = rules;
|
||||
document.head.appendChild(element);
|
||||
Log.info('CSS规则已添加', element);
|
||||
}
|
||||
|
||||
public static loading_gif_html(): string {
|
||||
@ -317,7 +304,7 @@ export default class CommonUtils {
|
||||
(tip) && (switcher.getBase().setAttribute('title', tip));
|
||||
_input.checked = this.localConfigWrapper.config[dictName];
|
||||
_input.onchange = e => {
|
||||
this.localConfigWrapper.config[dictName] = _input.checked;
|
||||
WuhuConfig.set(dictName, _input.checked, true);
|
||||
if (changeEv) changeEv(e);
|
||||
};
|
||||
new_node.appendChild(switcher.getBase());
|
||||
@ -352,7 +339,7 @@ export default class CommonUtils {
|
||||
option.innerHTML = domText;
|
||||
select.appendChild(option);
|
||||
});
|
||||
select.onchange = e => this.localConfigWrapper.config[dictName] = (<HTMLSelectElement>e.target).selectedIndex;
|
||||
select.onchange = e => WuhuConfig.set(dictName, (<HTMLSelectElement>e.target).selectedIndex);
|
||||
label.appendChild(text);
|
||||
label.appendChild(select);
|
||||
new_node.appendChild(label);
|
||||
@ -445,11 +432,7 @@ export default class CommonUtils {
|
||||
* @param m1 id->name map
|
||||
* @param m2 name->item map
|
||||
*/
|
||||
public getItemByIdOrName(key: string, m1, m2: {
|
||||
[k: string]: Partial<InventoryItemInfo>
|
||||
}): Partial<InventoryItemInfo> {
|
||||
public getItemByIdOrName(key: string, m1, m2: { [k: string]: Partial<InventoryItemInfo> }): Partial<InventoryItemInfo> {
|
||||
return m1[key] ? m2[m1[key]] : m2[key];
|
||||
}
|
||||
}
|
||||
|
||||
export const CommonUtilsKey = Symbol('CommonUtilsKey') as InjectionKey<CommonUtils>;
|
||||
|
||||
@ -1,21 +1,19 @@
|
||||
import Log from "../Log";
|
||||
import DIALOG_MSG_BOX_HTML from "../../../static/html/dialog_msg_box.html";
|
||||
import Logger from "../Logger";
|
||||
import { Container } from "../../container/Container";
|
||||
|
||||
export default class DialogMsgBox {
|
||||
private static existed = false;
|
||||
private readonly container: HTMLElement;
|
||||
|
||||
constructor(msg: string, opt: DialogMsgBoxOptions,
|
||||
private readonly logger: Logger = Container.factory(Logger)) {
|
||||
logger.info('创建DialogMsgBox', { msg, opt });
|
||||
constructor(msg: string, opt: DialogMsgBoxOptions) {
|
||||
Log.info('创建DialogMsgBox', { msg, opt });
|
||||
let { title = '提示', callback, cancel } = opt;
|
||||
if (!callback) {
|
||||
logger.error('无callback');
|
||||
Log.error('无callback');
|
||||
throw new Error('无callback');
|
||||
}
|
||||
if (DialogMsgBox.existed) {
|
||||
logger.error('无法创建DialogMsgBox:已存在');
|
||||
Log.error('无法创建DialogMsgBox:已存在');
|
||||
throw new Error('无法创建DialogMsgBox:已存在');
|
||||
}
|
||||
this.container = document.createElement('div');
|
||||
|
||||
@ -1,12 +1,10 @@
|
||||
import Alert from "./Alert";
|
||||
import ISidebarData from "../../interface/ISidebarData";
|
||||
import Log from "../Log";
|
||||
import FetchUtils from "./FetchUtils";
|
||||
import ClassName from "../../container/ClassName";
|
||||
import { Injectable } from "../../container/Injectable";
|
||||
import Logger from "../Logger";
|
||||
import LocalConfigWrapper from "../LocalConfigWrapper";
|
||||
import MsgWrapper from "./MsgWrapper";
|
||||
import { ElMessageBox } from "element-plus";
|
||||
import { MessageBoxData } from "element-plus/es/components/message-box/src/message-box.type";
|
||||
|
||||
@ClassName('InfoUtils')
|
||||
@Injectable()
|
||||
@ -17,8 +15,6 @@ export default class InfoUtils {
|
||||
// private readonly commonUtils: CommonUtils,
|
||||
private readonly fetchUtils: FetchUtils,
|
||||
private readonly logger: Logger,
|
||||
private readonly localConfigWrapper: LocalConfigWrapper,
|
||||
private readonly msgWrapper: MsgWrapper,
|
||||
) {
|
||||
}
|
||||
|
||||
@ -34,51 +30,8 @@ export default class InfoUtils {
|
||||
userID: parseInt(node.getAttribute('uid')),
|
||||
}
|
||||
} else {
|
||||
// 自动登陆
|
||||
const { autoLoginEmail, autoLoginPwd } = this.localConfigWrapper.config;
|
||||
if (autoLoginEmail && autoLoginPwd) {
|
||||
window.setTimeout(async () => {
|
||||
let alertRs: MessageBoxData = null;
|
||||
try {
|
||||
alertRs = await ElMessageBox.confirm(
|
||||
'可进行自动登录',
|
||||
'确认',
|
||||
{
|
||||
confirmButtonText: '好',
|
||||
cancelButtonText: '算了',
|
||||
type: 'info',
|
||||
}
|
||||
)
|
||||
} catch (e) {
|
||||
}
|
||||
if (alertRs !== 'confirm') return;
|
||||
this.msgWrapper.create('正尝试自动登录...', null, 'info');
|
||||
await fetch("https://www.torn.com/page.php?sid=Auth", {
|
||||
"headers": {
|
||||
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
|
||||
"cache-control": "no-cache",
|
||||
"content-type": "application/x-www-form-urlencoded",
|
||||
"pragma": "no-cache",
|
||||
"sec-ch-ua-mobile": "?0",
|
||||
"sec-fetch-dest": "document",
|
||||
"sec-fetch-mode": "navigate",
|
||||
"sec-fetch-site": "same-origin",
|
||||
"sec-fetch-user": "?1",
|
||||
"upgrade-insecure-requests": "1"
|
||||
},
|
||||
"referrer": "https://www.torn.com/",
|
||||
"referrerPolicy": "strict-origin-when-cross-origin",
|
||||
"body": `email=${ autoLoginEmail }&password=${ autoLoginPwd }&redirectUrl=https%3A%2F%2Fwww.torn.com%2F&btnLogin=Login`,
|
||||
"method": "POST",
|
||||
"mode": "cors",
|
||||
"credentials": "include"
|
||||
});
|
||||
this.msgWrapper.create('自动登录完成,即将转跳', null, 'info');
|
||||
window.setTimeout(() => window.location.href = '//www.torn.com/index.php', 1000);
|
||||
}, 0);
|
||||
}
|
||||
this.msgWrapper.create('错误:芜湖助手无法获取用户数据,已退出', null, 'error');
|
||||
throw new TypeError('芜湖助手无法获取用户数据');
|
||||
(() => new Alert('严重错误:芜湖助手无法获取用户数据,已退出'))();
|
||||
throw '芜湖助手无法获取用户数据';
|
||||
}
|
||||
}
|
||||
|
||||
@ -103,7 +56,7 @@ export default class InfoUtils {
|
||||
ret = {};
|
||||
}
|
||||
} else {
|
||||
this.logger.info('无法从sessionStorage获取数据')
|
||||
Log.info('无法从sessionStorage获取数据')
|
||||
ret = await (await this.fetchUtils.ajaxFetch({
|
||||
url: window.addRFC('/sidebarAjaxAction.php?q=getSidebarData'),
|
||||
method: 'POST',
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
import InventoryItemInfo from "../../interface/responseType/InventoryItemInfo";
|
||||
import FetchUtils from "./FetchUtils";
|
||||
import CommonUtils from "./CommonUtils";
|
||||
import Log from "../Log";
|
||||
import PriceData from "../../interface/PriceData";
|
||||
import Asyncable from "../../interface/Asyncable";
|
||||
import ClassName from "../../container/ClassName";
|
||||
import { Injectable } from "../../container/Injectable";
|
||||
import Logger from "../Logger";
|
||||
import { InjectionKey } from "vue";
|
||||
|
||||
@ClassName('ItemHelper')
|
||||
@Injectable()
|
||||
@ -14,7 +13,6 @@ export default class ItemHelper {
|
||||
|
||||
constructor(
|
||||
private readonly fetchUtils: FetchUtils,
|
||||
private readonly logger: Logger,
|
||||
) {
|
||||
}
|
||||
|
||||
@ -25,11 +23,12 @@ export default class ItemHelper {
|
||||
'Glass of Beer': {
|
||||
itemName: '一杯啤酒',
|
||||
itemInfo: '[译]Only savages drink beer straight out of the bottle. This glass of beer is obtained fresh from the keg, and provides the same level of drunken joy as you\'d get from a regular bottle of suds. Provides a moderate nerve increase when consumed.',
|
||||
itemInfoContent: "<div class='m-bottom10'>" +
|
||||
"<span class=\"bold\">一杯啤酒</span> 是酒类物品" +
|
||||
"</div>" +
|
||||
"Only savages drink beer straight out of the bottle. This glass of beer is obtained fresh from the keg, and provides the same level of drunken joy as you'd get from a regular bottle of suds. Provides a moderate nerve increase when consumed." +
|
||||
"<div class=\"t-green bold item-effect m-top10\">效果: 犯罪 + 2,增幅CD + 1h。</div>",
|
||||
itemInfoContent: "\n" +
|
||||
" <div class='m-bottom10'>\n" +
|
||||
" <span class=\"bold\">一杯啤酒</span> 是酒类物品\n" +
|
||||
" </div>\n" +
|
||||
" Only savages drink beer straight out of the bottle. This glass of beer is obtained fresh from the keg, and provides the same level of drunken joy as you'd get from a regular bottle of suds. Provides a moderate nerve increase when consumed.\n" +
|
||||
" <div class=\"t-green bold item-effect m-top10\">效果: 犯罪 + 2,增幅CD + 1h。</div>",
|
||||
},
|
||||
};
|
||||
|
||||
@ -83,7 +82,7 @@ export default class ItemHelper {
|
||||
* 物品查价值
|
||||
*/
|
||||
public async getItemValue(idOrName) {
|
||||
return (await this.getItemData(idOrName)).itemValue.replaceAll(/[,$]/g, '');
|
||||
return (await this.getItemData(idOrName)).itemValue.replaceAll(/[,$]/, '');
|
||||
}
|
||||
|
||||
/** 返回本地物品价格数据,id对应物品名和价格 */
|
||||
@ -101,7 +100,7 @@ export default class ItemHelper {
|
||||
try {
|
||||
data = JSON.parse(localStore);
|
||||
} catch (e) {
|
||||
this.logger.error(e.stack || e.message || e);
|
||||
Log.error(e.stack || e.message || e);
|
||||
throw new Error('JSON解析错误');
|
||||
}
|
||||
// 缓存超时
|
||||
@ -141,7 +140,7 @@ export default class ItemHelper {
|
||||
else {
|
||||
ret.promise = new Promise(async resolve => {
|
||||
let response = await localData.promise;
|
||||
this.logger.info({ response });
|
||||
Log.info({ response });
|
||||
let promiseRet = {};
|
||||
Object.keys(response).forEach(k => {
|
||||
promiseRet[response[k].name] = k;
|
||||
@ -163,7 +162,7 @@ export default class ItemHelper {
|
||||
try {
|
||||
res = JSON.parse(await CommonUtils.COFetch('https://jjins.github.io/item_price_raw.json'))
|
||||
} catch (err) {
|
||||
this.logger.error(err.stack || err.message || err);
|
||||
Log.error(err.stack || err.message || err);
|
||||
throw new Error('获取在线价格时出错');
|
||||
}
|
||||
// 更新缓存
|
||||
@ -175,5 +174,3 @@ export default class ItemHelper {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
export const ItemHelperKey = Symbol('ItemHelperKey') as InjectionKey<ItemHelper>;
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import ClassName from "../../container/ClassName";
|
||||
import { Injectable } from "../../container/Injectable";
|
||||
import { InjectionKey } from "vue";
|
||||
|
||||
@ClassName('MathUtils')
|
||||
@Injectable()
|
||||
@ -15,5 +14,3 @@ export default class MathUtils {
|
||||
return Math.floor(Math.random() * (max - min)) + min;
|
||||
}
|
||||
}
|
||||
|
||||
export const MathUtilsKey = Symbol('MathUtilsKey') as InjectionKey<MathUtils>
|
||||
|
||||
@ -1,32 +0,0 @@
|
||||
import ClassName from "../../container/ClassName";
|
||||
import { Injectable } from "../../container/Injectable";
|
||||
import IWHNotify from "../../interface/IWHNotify";
|
||||
import { InjectionKey } from "vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
import NotificationUtils from "./NotificationUtils";
|
||||
import WindowActiveState from "../action/WindowActiveState";
|
||||
|
||||
@ClassName('MsgWrapper')
|
||||
@Injectable()
|
||||
export default class MsgWrapper {
|
||||
constructor(
|
||||
private readonly notificationUtils: NotificationUtils,
|
||||
private readonly windowActiveState: WindowActiveState,
|
||||
) {
|
||||
}
|
||||
|
||||
create(msg: string, options: IWHNotify = {}, type: 'info' | 'warning' | 'error' | 'success' = 'info') {
|
||||
if (!this.windowActiveState.get()) return null;
|
||||
if (options?.sysNotify) {
|
||||
this.notificationUtils.push(msg, options);
|
||||
}
|
||||
return ElMessage({
|
||||
message: msg,
|
||||
type,
|
||||
showClose: true,
|
||||
dangerouslyUseHTMLString: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const MsgWrapperKey = Symbol('MsgWrapperKey') as InjectionKey<MsgWrapper>;
|
||||
@ -34,26 +34,6 @@ export default class NetHighLvlWrapper {
|
||||
}
|
||||
return rs;
|
||||
}
|
||||
|
||||
public async doTravelFly(destId, key, type): Promise<string> {
|
||||
return await (await fetch(window.addRFC("https://www.torn.com/travelagency.php"), {
|
||||
"headers": {
|
||||
"accept": "*/*",
|
||||
"accept-language": "zh-CN,zh;q=0.9",
|
||||
"content-type": "application/x-www-form-urlencoded; charset=UTF-8",
|
||||
"sec-fetch-dest": "empty",
|
||||
"sec-fetch-mode": "cors",
|
||||
"sec-fetch-site": "same-origin",
|
||||
"x-requested-with": "XMLHttpRequest"
|
||||
},
|
||||
"referrer": "https://www.torn.com/travelagency.php",
|
||||
"referrerPolicy": "strict-origin-when-cross-origin",
|
||||
"body": `step=travel&id=${ destId }&type=${ type }`,
|
||||
"method": "POST",
|
||||
"mode": "cors",
|
||||
"credentials": "include"
|
||||
})).text()
|
||||
}
|
||||
}
|
||||
|
||||
export enum BATTLE_STAT {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import IWHNotify from "../../interface/IWHNotify";
|
||||
import Log from "../Log";
|
||||
import ClassName from "../../container/ClassName";
|
||||
import { Injectable } from "../../container/Injectable";
|
||||
import Logger from "../Logger";
|
||||
|
||||
@ClassName('NotificationUtils')
|
||||
@Injectable()
|
||||
@ -9,21 +9,19 @@ export default class NotificationUtils {
|
||||
constructor(
|
||||
// TODO 循环依赖
|
||||
// private readonly global: Global,
|
||||
private readonly logger: Logger,
|
||||
) {
|
||||
}
|
||||
|
||||
private permission: boolean = window.Notification && window.Notification.permission === 'granted';
|
||||
|
||||
public push(msg: string, options: IWHNotify = {}): void {
|
||||
// this.logger.info({msg, options})
|
||||
// let { notifies } = this.global;
|
||||
|
||||
if (options.sysNotify && this.permission) {
|
||||
let tmpNode = document.createElement('p');
|
||||
tmpNode.innerHTML = msg;
|
||||
let notify = new Notification('芜湖助手', {
|
||||
body: this.logger.getTime() + '\r\n' + tmpNode.innerText,
|
||||
body: Log.getTime() + '\r\n' + tmpNode.innerText,
|
||||
// requireInteraction: true,
|
||||
// renotify: true,
|
||||
// tag: '芜湖助手' + Utils.getRandomInt(0, 99),
|
||||
|
||||
@ -1,14 +0,0 @@
|
||||
import ClassName from "../../container/ClassName";
|
||||
import { Injectable } from "../../container/Injectable";
|
||||
import Popup from "./Popup";
|
||||
import { InjectionKey } from "vue";
|
||||
|
||||
@ClassName('PopupWrapper')
|
||||
@Injectable()
|
||||
export default class PopupWrapper {
|
||||
public create(html: string, title: string, onClosing: () => unknown) {
|
||||
return new Popup(html, title, onClosing);
|
||||
}
|
||||
}
|
||||
|
||||
export const PopupWrapperKey = Symbol('PopupWrapperKey') as InjectionKey<PopupWrapper>;
|
||||
@ -3,13 +3,13 @@ const CLASSNAME_METADATA_KEY = Symbol("CLASSNAME_KEY");
|
||||
/**
|
||||
* 记录类名,避免打包后丢失原类名
|
||||
*/
|
||||
export default function ClassName(className: string): ClassDecorator {
|
||||
export default function ClassName(className?: string): ClassDecorator {
|
||||
return function <TFunction extends Function>(target: TFunction): TFunction {
|
||||
Reflect.defineMetadata(CLASSNAME_METADATA_KEY, className, target);
|
||||
Reflect.defineMetadata(CLASSNAME_METADATA_KEY, className || target.name, target);
|
||||
return target;
|
||||
};
|
||||
}
|
||||
|
||||
export function GetClassName(target: ClassType<{}>): string {
|
||||
export function GetClassName(target: any) {
|
||||
return Reflect.getMetadata(CLASSNAME_METADATA_KEY, target);
|
||||
}
|
||||
|
||||
@ -1,38 +1,40 @@
|
||||
import "reflect-metadata";
|
||||
import { assertInjectable } from "./Injectable";
|
||||
import ClassName, { GetClassName } from "./ClassName";
|
||||
import Logger from "../class/Logger";
|
||||
import { GetClassName } from "./ClassName";
|
||||
|
||||
/**
|
||||
* 一个简单的类容器
|
||||
*/
|
||||
@ClassName('Container')
|
||||
export class Container {
|
||||
static _container = new Map();
|
||||
private static logger;
|
||||
|
||||
static set<T>(k: Constructor<T>, v: T): void {
|
||||
static set(k: any, v: any): void {
|
||||
if (!this._container.has(k)) {
|
||||
this._container.set(k, v);
|
||||
}
|
||||
}
|
||||
|
||||
static get<T>(k: Constructor<T>): T {
|
||||
static get(k: any): any {
|
||||
return this._container.get(k);
|
||||
}
|
||||
|
||||
static factory<T>(target: ClassType<T>): T {
|
||||
static factory<T>(target: Constructor<T>): T {
|
||||
assertInjectable(target);
|
||||
// if (Container.get(target))
|
||||
// return Container.get(target);
|
||||
return this.get(target) || this.initParam(target);
|
||||
}
|
||||
|
||||
static setLogger(logger: Logger): void {
|
||||
static setLogger(logger: { info(...o: any[]), error(...o: any[]), warn(...o: any[]) }): void {
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
private static initParam<T>(target: Constructor<T>): T {
|
||||
// 获取所有注入的服务
|
||||
const providers = Reflect.getMetadata('design:paramtypes', target);
|
||||
// this.logger.info({providers})
|
||||
// this.logger.info('原型名'+Object.getPrototypeOf(target).constructor.name)
|
||||
// this.logger.info('直接名'+target.name)
|
||||
const args = providers ? providers.map((provider: Constructor) => {
|
||||
return this.factory(provider);
|
||||
}) : [];
|
||||
|
||||
@ -5,6 +5,7 @@ const INJECTABLE_METADATA_KEY = Symbol("INJECTABLE_KEY");
|
||||
// TODO 实现非单例注入
|
||||
export enum INJECT_MODE {
|
||||
Singleton = 1,
|
||||
Multi = 2,
|
||||
}
|
||||
|
||||
export function Injectable(injectMode: INJECT_MODE = INJECT_MODE.Singleton): ClassDecorator {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,278 +0,0 @@
|
||||
import ClassName from "../container/ClassName"
|
||||
import { Injectable } from "../container/Injectable"
|
||||
import IFeature from "../man/IFeature"
|
||||
import LocalConfigWrapper from "../class/LocalConfigWrapper"
|
||||
import CommonUtils from "../class/utils/CommonUtils"
|
||||
import Global from "../class/Global"
|
||||
import ActionButtonUtils from "../class/utils/ActionButtonUtils"
|
||||
import Logger from "../class/Logger"
|
||||
import Alert from "../class/utils/Alert"
|
||||
import Device from "../enum/Device"
|
||||
import ATTACK_HELPER_CSS from "../../static/css/attack_helper.module.css"
|
||||
import ATK_PAGE_REG from "./url/ATK_PAGE_REG";
|
||||
|
||||
enum FIGHT_STAGE {
|
||||
READY = 'ready',
|
||||
IN_PROGRESS_OR_ERROR = 'in_progress_or_error',
|
||||
FINISHED = 'finished',
|
||||
END = 'end',
|
||||
OTHER = 'other'
|
||||
}
|
||||
|
||||
@ClassName('Atk')
|
||||
@Injectable()
|
||||
export default class Atk implements IFeature {
|
||||
|
||||
private currentStage: FIGHT_STAGE = FIGHT_STAGE.OTHER;
|
||||
|
||||
constructor(
|
||||
private readonly actionButtonUtils: ActionButtonUtils,
|
||||
private readonly localConfigWrapper: LocalConfigWrapper,
|
||||
private readonly commonUtils: CommonUtils,
|
||||
private readonly global: Global,
|
||||
// private readonly mathUtils: MathUtils,
|
||||
// private readonly fetchUtils: FetchUtils,
|
||||
private readonly logger: Logger,
|
||||
) {
|
||||
}
|
||||
|
||||
urlIncludes(): RegExp[] {
|
||||
return [ATK_PAGE_REG]
|
||||
}
|
||||
|
||||
urlExcludes(): RegExp[] {
|
||||
return []
|
||||
}
|
||||
|
||||
description(): string {
|
||||
return '攻击助手'
|
||||
}
|
||||
|
||||
iStart(): void | Promise<void> {
|
||||
// 光速刷新按钮
|
||||
this.actionButtonUtils.add('光速刷新', () => this.doAttackReload());
|
||||
|
||||
new MutationObserver((_, observer) => {
|
||||
let btnList = document.querySelectorAll('div[class^="dialogButtons___"] button') as NodeListOf<HTMLButtonElement>;
|
||||
|
||||
if (btnList.length === 0) {
|
||||
if (this.currentStage === FIGHT_STAGE.READY && this.localConfigWrapper.config.quickFinishAtt === 3) {
|
||||
document.body.classList.remove('wh-move-btn');
|
||||
this.logger.info('移除body class wh-move-btn');
|
||||
observer.disconnect();
|
||||
}
|
||||
// 错误或正在打
|
||||
this.currentStage = FIGHT_STAGE.IN_PROGRESS_OR_ERROR;
|
||||
this.logger.info('[attackHelper] currentStage', this.currentStage);
|
||||
return;
|
||||
}
|
||||
btnList.forEach(btn => {
|
||||
let btnText = btn.innerText.toLowerCase();
|
||||
if (btnText.includes('start') || btnText.includes('join')) {
|
||||
// 开始
|
||||
this.quickStartFight();
|
||||
} else if (btnText.includes('continue')) {
|
||||
// 结束end
|
||||
this.currentStage = FIGHT_STAGE.END;
|
||||
observer.disconnect();
|
||||
} else if (btnText.includes('leave')) {
|
||||
// 无意识状态FINISHED
|
||||
this.quickFinishFight(btnList);
|
||||
}
|
||||
this.logger.info('[attackHelper] currentStage', this.currentStage);
|
||||
})
|
||||
})
|
||||
.observe(document.querySelector('#react-root'), { childList: true, subtree: true });
|
||||
}
|
||||
|
||||
// 战斗页面快速刷新
|
||||
private doAttackReload(): void {
|
||||
if (!window.ReactDOM) {
|
||||
new Alert('光速刷新失败:未找到React对象');
|
||||
this.logger.error('光速刷新失败:未找到React对象');
|
||||
return;
|
||||
}
|
||||
if (!document.querySelector('#react-root #attacker')) {
|
||||
this.logger.error('dom元素未找到selector: [#react-root #attacker]');
|
||||
return;
|
||||
}
|
||||
let script = document.querySelector('script[src*="/builds/attack/"]');
|
||||
let url = script.src;
|
||||
if (!url.contains(/runtime\..+\.js/)) {
|
||||
this.logger.error('脚本源[' + url + '] 不匹配规则');
|
||||
return;
|
||||
}
|
||||
window.ReactDOM.unmountComponentAtNode(document.querySelector('#react-root'));
|
||||
script.remove();
|
||||
let node = document.createElement('script');
|
||||
node.src = url;
|
||||
node.type = 'text/javascript';
|
||||
document.head.appendChild(node);
|
||||
}
|
||||
|
||||
// 光速拔刀
|
||||
private quickStartFight(): void {
|
||||
if (this.currentStage === FIGHT_STAGE.READY) {
|
||||
return;
|
||||
} else {
|
||||
this.currentStage = FIGHT_STAGE.READY;
|
||||
}
|
||||
if (this.localConfigWrapper.config.quickAttIndex === 6) return;
|
||||
/**
|
||||
* pc #defender
|
||||
* mobile #attacker
|
||||
*/
|
||||
const btn = <HTMLInputElement>(document.querySelector('#attacker button') || document.querySelector('#defender button'));
|
||||
this.logger.info('操作按钮', { btn });
|
||||
if (!btn.innerText.toLowerCase().includes('fight')) {
|
||||
this.logger.info('未找到攻击按钮, 光速拔刀跳过');
|
||||
new Alert('未找到攻击按钮, 光速拔刀跳过');
|
||||
} else {
|
||||
// 判断是否存在脚踢
|
||||
const hasKick = !!document.querySelector('#weapon_boots');
|
||||
// modal层
|
||||
// const modal: HTMLElement = document.querySelector('div[class^="modal___"]');
|
||||
let device = this.global.device;
|
||||
this.logger.info(`当前设备类型是${ device }`);
|
||||
// 区分设备
|
||||
switch (device) {
|
||||
case Device.PC: {
|
||||
this.logger.info(`开始调整按钮位置`);
|
||||
// 隐藏modal层
|
||||
// modal.style.display = 'none';
|
||||
// 根据选择的武器调整css
|
||||
let css_top = '0';
|
||||
switch (this.localConfigWrapper.config.quickAttIndex) {
|
||||
// weapon_second
|
||||
case 1: {
|
||||
css_top = '97px';
|
||||
break;
|
||||
}
|
||||
// weapon_melee
|
||||
case 2: {
|
||||
css_top = '194px';
|
||||
break;
|
||||
}
|
||||
// weapon_temp
|
||||
case 3: {
|
||||
css_top = '291px';
|
||||
break;
|
||||
}
|
||||
// weapon_fists
|
||||
case 4:
|
||||
// weapon_boots
|
||||
case 5: {
|
||||
css_top = '375px';
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.commonUtils.styleInject(ATTACK_HELPER_CSS);
|
||||
CommonUtils.addStyle(`.wh-move-btn #defender div[class^="modal___"]{top: ${ css_top };}`);
|
||||
document.body.classList.add('wh-move-btn');
|
||||
break;
|
||||
}
|
||||
case Device.MOBILE: {
|
||||
this.logger.info(`开始调整按钮位置`);
|
||||
// 加入css
|
||||
let css_top = '0';
|
||||
let slot_height = '76px';
|
||||
// 判断有没有脚踢
|
||||
if (hasKick) {
|
||||
// 根据选择的武器调整
|
||||
switch (this.localConfigWrapper.config.quickAttIndex) {
|
||||
case 1: { // weapon_second
|
||||
css_top = '76px';
|
||||
break;
|
||||
}
|
||||
case 2: { // weapon_melee
|
||||
css_top = '152px';
|
||||
break;
|
||||
}
|
||||
case 3: { // weapon_temp
|
||||
css_top = '228px';
|
||||
break;
|
||||
}
|
||||
case 4: { // weapon_fists
|
||||
css_top = '304px';
|
||||
break;
|
||||
}
|
||||
case 5: { // weapon_boots
|
||||
css_top = '380px';
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const slot = document.querySelector('#weapon_main') as HTMLElement;
|
||||
const height = slot.offsetHeight + 1;
|
||||
// TODO 待验证
|
||||
slot_height = height + 'px';
|
||||
// 根据选择的武器调整
|
||||
switch (this.localConfigWrapper.config.quickAttIndex) {
|
||||
case 1: { // weapon_second
|
||||
css_top = `${ height }px`;
|
||||
break;
|
||||
}
|
||||
case 2: { // weapon_melee
|
||||
css_top = `${ height * 2 }px`;
|
||||
break;
|
||||
}
|
||||
case 3: { // weapon_temp
|
||||
css_top = `${ height * 3 }px`;
|
||||
break;
|
||||
}
|
||||
case 4: { // weapon_fists
|
||||
css_top = `${ height * 4 }px`;
|
||||
break;
|
||||
}
|
||||
case 5: { // weapon_boots
|
||||
css_top = `${ height * 5 }px`;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
const css_rule = ATTACK_HELPER_CSS.replace('CSSVAR', css_top).replace('CSSVAR', slot_height);
|
||||
|
||||
this.commonUtils.styleInject(css_rule);
|
||||
document.body.classList.toggle('wh-move-btn');
|
||||
btn.onclick = () => {
|
||||
if (this.localConfigWrapper.config.quickFinishAtt !== 3) {
|
||||
btn.remove();
|
||||
// 停止自动刷新
|
||||
// stop_reload = true;
|
||||
} else {
|
||||
document.body.classList.toggle('wh-move-btn');
|
||||
}
|
||||
};
|
||||
break;
|
||||
}
|
||||
case Device.TABLET: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 光速跑路
|
||||
private quickFinishFight(btnList: NodeListOf<HTMLButtonElement>): void {
|
||||
if (this.currentStage === FIGHT_STAGE.FINISHED) {
|
||||
return;
|
||||
} else {
|
||||
this.currentStage = FIGHT_STAGE.FINISHED;
|
||||
}
|
||||
if (this.localConfigWrapper.config.quickFinishAtt === 3) {
|
||||
document.body.classList.remove('wh-move-btn');
|
||||
this.logger.info('移除body class wh-move-btn');
|
||||
return;
|
||||
}
|
||||
const user_btn_select = ['leave', 'mug', 'hosp'][this.localConfigWrapper.config.quickFinishAtt];
|
||||
// const wrap = document.querySelector('#react-root');
|
||||
this.logger.info('光速跑路选项选中:', user_btn_select);
|
||||
// const btn_arr: HTMLButtonElement[] = document.querySelectorAll('div[class^="dialogButtons___"] button') as unknown as HTMLButtonElement[];
|
||||
if (btnList.length > 1) btnList.forEach(btn => {
|
||||
const flag = btn.innerText.toLowerCase().includes(user_btn_select);
|
||||
this.logger.info('按钮内容:', btn.innerText, ',是否包含选中:', flag);
|
||||
if (!flag) btn.style.display = 'none';
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,68 +0,0 @@
|
||||
import ClassName from "../container/ClassName"
|
||||
import { Injectable } from "../container/Injectable"
|
||||
import IFeature from "../man/IFeature"
|
||||
import TornStyleBlock from "../class/utils/TornStyleBlock"
|
||||
import ADD_BEER_HEAD_HTML from "../../static/html/buyBeer/add_beer_head.html"
|
||||
import SHOP_BEER_STATIC_ITEM_HTML from "../../static/html/buyBeer/shop_beer_static_item.html"
|
||||
import globVars from "../globVars"
|
||||
import Logger from "../class/Logger";
|
||||
import BuyBeerHelper from "./BuyBeerHelper";
|
||||
|
||||
@ClassName('BeerShopModifier')
|
||||
@Injectable()
|
||||
export default class BeerShopModifier implements IFeature {
|
||||
private readonly logger = Logger.factory(BeerShopModifier)
|
||||
|
||||
constructor(
|
||||
private readonly buyBeerHelper: BuyBeerHelper,
|
||||
) {
|
||||
}
|
||||
|
||||
description(): string {
|
||||
return "啤酒店页面修改";
|
||||
}
|
||||
|
||||
iStart(): void | Promise<void> {
|
||||
this.start()
|
||||
}
|
||||
|
||||
urlExcludes(): RegExp[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
urlIncludes(): RegExp[] {
|
||||
return [/shops.php\?step=bitsnbobs/];
|
||||
}
|
||||
|
||||
start() {
|
||||
let block = new TornStyleBlock('啤酒助手').insert2Dom();
|
||||
block.setContent(ADD_BEER_HEAD_HTML);
|
||||
const msg_node = block.querySelector('#wh-msg');
|
||||
// 加入啤酒
|
||||
block.querySelector('button').addEventListener('click', e => {
|
||||
let node = document.querySelector('ul.items-list');
|
||||
if (!node) {
|
||||
msg_node.innerHTML = '❌ 商品未加载完';
|
||||
this.logger.error('商品未加载完');
|
||||
return;
|
||||
}
|
||||
if (node.querySelector('span[id="180-name"]')) {
|
||||
msg_node.innerHTML = '❌ 页面已经有啤酒了';
|
||||
this.logger.warn('商店页面已有啤酒');
|
||||
return;
|
||||
}
|
||||
const clear_node = node.querySelector('li.clear');
|
||||
const beer = document.createElement('li');
|
||||
beer.classList.add('torn-divider', 'divider-vertical');
|
||||
beer.style.backgroundColor = '#c8c8c8';
|
||||
beer.innerHTML = SHOP_BEER_STATIC_ITEM_HTML;
|
||||
if (clear_node) clear_node.before(beer);
|
||||
else node.append(beer);
|
||||
(<HTMLInputElement>e.target).disabled = true;
|
||||
msg_node.innerHTML = '添加成功';
|
||||
});
|
||||
|
||||
// 监听啤酒购买
|
||||
globVars.responseHandlers.push((...args: any[]) => this.buyBeerHelper.responseHandler.apply(this.buyBeerHelper, args));
|
||||
}
|
||||
}
|
||||
@ -1,25 +0,0 @@
|
||||
import ClassName from "../container/ClassName";
|
||||
import { Injectable } from "../container/Injectable";
|
||||
import IFeature from "../man/IFeature";
|
||||
import christmasTownHelper from "../func/module/christmasTownHelper";
|
||||
|
||||
@ClassName('ChristmasTown')
|
||||
@Injectable()
|
||||
export default class ChristmasTown implements IFeature {
|
||||
|
||||
urlIncludes(): RegExp[] {
|
||||
return [/christmas_town\.php/]
|
||||
}
|
||||
|
||||
urlExcludes(): RegExp[] {
|
||||
return []
|
||||
}
|
||||
|
||||
description(): string {
|
||||
return '圣诞小镇助手'
|
||||
}
|
||||
|
||||
iStart(): void | Promise<void> {
|
||||
christmasTownHelper()
|
||||
}
|
||||
}
|
||||
@ -1,78 +0,0 @@
|
||||
import ClassName from "../container/ClassName";
|
||||
import { Injectable } from "../container/Injectable";
|
||||
import IFeature from "../man/IFeature";
|
||||
import LocalConfigWrapper from "../class/LocalConfigWrapper";
|
||||
import CommonUtils from "../class/utils/CommonUtils";
|
||||
import QUICK_CRIMES_HTML from "../../static/html/quick_crimes.html";
|
||||
|
||||
@ClassName('CrimePageModifier')
|
||||
@Injectable()
|
||||
export default class CrimePageModifier implements IFeature {
|
||||
constructor(
|
||||
private readonly localConfigWrapper: LocalConfigWrapper
|
||||
) {
|
||||
}
|
||||
|
||||
description(): string {
|
||||
return "页面快速crime";
|
||||
}
|
||||
|
||||
iStart(): void | Promise<void> {
|
||||
this.start()
|
||||
}
|
||||
|
||||
urlExcludes(): RegExp[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
urlIncludes(): RegExp[] {
|
||||
return [/crimes\.php/];
|
||||
}
|
||||
|
||||
start() { // TODO 重构、与翻译解藕
|
||||
if (this.localConfigWrapper.config.quickCrime) {
|
||||
// iframe
|
||||
if (self !== top) {
|
||||
const isValidate = document.querySelector('h4#skip-to-content').innerText.toLowerCase().includes('validate');
|
||||
CommonUtils.elementReady('#header-root').then(e => e.style.display = 'none');
|
||||
CommonUtils.elementReady('#sidebarroot').then(e => e.style.display = 'none');
|
||||
CommonUtils.elementReady('#chatRoot').then(e => e.style.display = 'none');
|
||||
if (!isValidate) document.body.style.overflow = 'hidden';
|
||||
CommonUtils.elementReady('.content-wrapper').then(e => {
|
||||
e.style.margin = '0px';
|
||||
e.style.position = 'absolute';
|
||||
e.style.top = '-35px';
|
||||
});
|
||||
CommonUtils.elementReady('#go-to-top-btn button').then(e => e.style.display = 'none');
|
||||
}
|
||||
const element = document.querySelector('.content-wrapper');
|
||||
const OB = new MutationObserver(() => {
|
||||
OB.disconnect();
|
||||
trans();
|
||||
OB.observe(element, {
|
||||
characterData: true,
|
||||
attributes: true,
|
||||
subtree: true,
|
||||
childList: true
|
||||
});
|
||||
});
|
||||
const trans = () => {
|
||||
const dom = QUICK_CRIMES_HTML;
|
||||
const hasInserted = element.querySelector('.wh-translate') !== null;
|
||||
const $title = document.querySelector('div.content-title');
|
||||
const $info = document.querySelector('.info-msg-cont');
|
||||
if (!hasInserted) {
|
||||
if ($title) $title.insertAdjacentHTML('beforebegin', dom);
|
||||
else if ($info) $info.insertAdjacentHTML('beforebegin', dom);
|
||||
}
|
||||
};
|
||||
trans();
|
||||
OB.observe(element, {
|
||||
characterData: true,
|
||||
attributes: true,
|
||||
subtree: true,
|
||||
childList: true
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,76 +0,0 @@
|
||||
import Logger, { LoggerKey } from "../class/Logger"
|
||||
import ClassName from "../container/ClassName"
|
||||
import { Injectable } from "../container/Injectable"
|
||||
import CommonUtils, { CommonUtilsKey } from "../class/utils/CommonUtils"
|
||||
import LocalConfigWrapper, { LocalConfigWrapperKey } from "../class/LocalConfigWrapper"
|
||||
import { createApp } from "vue"
|
||||
import FloatMenu from "../../vue/FloatMenu.vue"
|
||||
import PopupWrapper, { PopupWrapperKey } from "../class/utils/PopupWrapper"
|
||||
import TravelItem from "./TravelItem"
|
||||
import QuickGymTrain, { QuickGymTrainKey } from "../class/action/QuickGymTrain"
|
||||
import QuickFlyBtnHandler, { QuickFlyBtnHandlerKey } from "../class/handler/QuickFlyBtnHandler"
|
||||
import ItemHelper, { ItemHelperKey } from "../class/utils/ItemHelper"
|
||||
import MathUtils, { MathUtilsKey } from "../class/utils/MathUtils"
|
||||
import IFeature from "../man/IFeature"
|
||||
import ALL_PAGE_REG from "./url/ALL_PAGE_REG"
|
||||
|
||||
@ClassName("IconHelper")
|
||||
@Injectable()
|
||||
export default class IconHelper implements IFeature {
|
||||
private readonly _element: HTMLElement = document.createElement('div');
|
||||
private readonly logger = Logger.factory(IconHelper)
|
||||
|
||||
description(): string {
|
||||
return "浮动图标、侧边菜单、标签式便携功能";
|
||||
}
|
||||
|
||||
iStart(): void | Promise<void> {
|
||||
this.init()
|
||||
}
|
||||
|
||||
urlExcludes(): RegExp[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
urlIncludes(): RegExp[] {
|
||||
return [ALL_PAGE_REG];
|
||||
}
|
||||
|
||||
constructor(
|
||||
private readonly commonUtils: CommonUtils,
|
||||
private readonly localConfigWrapper: LocalConfigWrapper,
|
||||
private readonly popupWrapper: PopupWrapper,
|
||||
private readonly travelItem: TravelItem,
|
||||
private readonly quickGymTrain: QuickGymTrain,
|
||||
private readonly quickFlyBtnHandler: QuickFlyBtnHandler,
|
||||
private readonly itemHelper: ItemHelper,
|
||||
private readonly mathUtils: MathUtils,
|
||||
) {
|
||||
}
|
||||
|
||||
get element() {
|
||||
return this._element;
|
||||
}
|
||||
|
||||
init() {
|
||||
this._element.id = 'WHMenu2023';
|
||||
document.body.append(this._element);
|
||||
let app = createApp(FloatMenu);
|
||||
this.logger.info('Vue实例已创建', { app })
|
||||
|
||||
app.config.errorHandler = (err) => this.logger.error('[VUE错误]', err);
|
||||
app.config.warnHandler = (err) => this.logger.warn('[VUE警告]', err);
|
||||
app.provide(LoggerKey, this.logger);
|
||||
app.provide(CommonUtilsKey, this.commonUtils);
|
||||
app.provide(MathUtilsKey, this.mathUtils);
|
||||
// app.provide(TravelItemKey, this.travelItem);
|
||||
app.provide(PopupWrapperKey, this.popupWrapper);
|
||||
app.provide(LocalConfigWrapperKey, this.localConfigWrapper);
|
||||
app.provide(QuickGymTrainKey, this.quickGymTrain);
|
||||
app.provide(QuickFlyBtnHandlerKey, this.quickFlyBtnHandler);
|
||||
app.provide(ItemHelperKey, this.itemHelper);
|
||||
app.mount(this._element);
|
||||
this.logger.info('Vue实例已挂载')
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,50 +0,0 @@
|
||||
import IFeature from "../man/IFeature";
|
||||
import ClassName from "../container/ClassName";
|
||||
import { Injectable } from "../container/Injectable";
|
||||
import TornStyleBlock from "../class/utils/TornStyleBlock";
|
||||
import TornStyleSwitch from "../class/utils/TornStyleSwitch";
|
||||
import cityFinder from "../func/module/cityFinder";
|
||||
import LocalConfigWrapper from "../class/LocalConfigWrapper";
|
||||
|
||||
@ClassName('MapItem')
|
||||
@Injectable()
|
||||
export default class MapItem implements IFeature {
|
||||
constructor(
|
||||
private readonly localConfigWrapper: LocalConfigWrapper
|
||||
) {
|
||||
}
|
||||
|
||||
description(): string {
|
||||
return "捡垃圾助手";
|
||||
}
|
||||
|
||||
iStart(): void | Promise<void> {
|
||||
this.start()
|
||||
}
|
||||
|
||||
urlExcludes(): RegExp[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
urlIncludes(): RegExp[] {
|
||||
return [/city\.php/];
|
||||
}
|
||||
|
||||
start() {
|
||||
if (this.localConfigWrapper.config.cityFinder) {
|
||||
let _base = new TornStyleBlock('芜湖助手').insert2Dom();
|
||||
// let reloadSwitch = new TornStyleSwitch('解决一直转圈(加载中)的问题');
|
||||
// reloadSwitch.getInput().checked = this.localConfigWrapper.config.SolveGoogleScriptPendingIssue;
|
||||
// _base.append(reloadSwitch.getBase()).insert2Dom();
|
||||
// reloadSwitch.getInput().addEventListener('change', () => {
|
||||
// if (reloadSwitch.getInput().checked) window.location.replace(window.location.href);
|
||||
// this.localConfigWrapper.config.SolveGoogleScriptPendingIssue = reloadSwitch.getInput().checked;
|
||||
// });
|
||||
|
||||
_base.append(document.createElement('br'));
|
||||
|
||||
cityFinder(_base);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,77 +0,0 @@
|
||||
import ClassName from "../container/ClassName";
|
||||
import { Injectable } from "../container/Injectable";
|
||||
import IFeature from "../man/IFeature";
|
||||
import LocalConfigWrapper from "../class/LocalConfigWrapper";
|
||||
import getTaskHint from "../func/translate/getTaskHint";
|
||||
import { missionDict } from "../dictionary/translation";
|
||||
|
||||
@ClassName('MissionPageModifier')
|
||||
@Injectable()
|
||||
export default class MissionPageModifier implements IFeature {
|
||||
constructor(
|
||||
private readonly localConfigWrapper: LocalConfigWrapper
|
||||
) {
|
||||
}
|
||||
|
||||
description(): string {
|
||||
return "页面快速crime";
|
||||
}
|
||||
|
||||
iStart(): void | Promise<void> {
|
||||
this.start()
|
||||
}
|
||||
|
||||
urlExcludes(): RegExp[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
urlIncludes(): RegExp[] {
|
||||
return [/crimes\.php/];
|
||||
}
|
||||
|
||||
start() {
|
||||
const anchor = document.querySelector('.content-wrapper');
|
||||
const OB = new MutationObserver(() => {
|
||||
OB.disconnect();
|
||||
trans();
|
||||
OB.observe(anchor, {
|
||||
characterData: true,
|
||||
attributes: true,
|
||||
subtree: true,
|
||||
childList: true
|
||||
});
|
||||
});
|
||||
const taskList = {};
|
||||
const trans = () => {
|
||||
$('ul#giver-tabs a.ui-tabs-anchor').each((i, e) => {
|
||||
let $e = $(e);
|
||||
if ($e.children().hasClass('mission-complete-icon')) {
|
||||
taskList[i] = e.innerText.trim();
|
||||
} else {
|
||||
taskList[i] = $e.clone().children().remove().end().text().trim();
|
||||
}
|
||||
});
|
||||
// 助手注入
|
||||
$('div.max-height-fix.info').each((i, e) => {
|
||||
let $e = $(e);
|
||||
if ($e.find('.wh-translated').length !== 0) return;
|
||||
$e.append(`<div class="wh-translated"><h6 style="color:green"><b>任务助手</b></h6><p>${ getTaskHint(taskList[i]) }</p></div>`);
|
||||
});
|
||||
// 任务目标
|
||||
$('ul.tasks-list span.title-wrap').contents().each((i, e) => {
|
||||
if (e.nodeType === 3) {
|
||||
if (missionDict[e.nodeValue.trim()]) {
|
||||
e.nodeValue = missionDict[e.nodeValue.trim()];
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
trans();
|
||||
OB.observe(anchor, {
|
||||
characterData: true,
|
||||
attributes: true,
|
||||
subtree: true,
|
||||
childList: true
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -1,47 +0,0 @@
|
||||
import TornStyleBlock from "../class/utils/TornStyleBlock";
|
||||
import TornStyleSwitch from "../class/utils/TornStyleSwitch";
|
||||
import { Injectable } from "../container/Injectable";
|
||||
import ClassName from "../container/ClassName";
|
||||
import LocalConfigWrapper from "../class/LocalConfigWrapper";
|
||||
import IFeature from "../man/IFeature";
|
||||
|
||||
@Injectable()
|
||||
@ClassName('StackHelper')
|
||||
export default class StackHelper implements IFeature {
|
||||
|
||||
constructor(
|
||||
private readonly localConfigWrapper: LocalConfigWrapper,
|
||||
) {
|
||||
}
|
||||
|
||||
description(): string {
|
||||
return "叠e助手";
|
||||
}
|
||||
|
||||
iStart(): void | Promise<void> {
|
||||
this.start()
|
||||
}
|
||||
|
||||
urlExcludes(): RegExp[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
urlIncludes(): RegExp[] {
|
||||
return [/gym\.php/];
|
||||
}
|
||||
|
||||
start() {
|
||||
let block = new TornStyleBlock('叠E保护').insert2Dom();
|
||||
let switcher = new TornStyleSwitch('启用');
|
||||
let input = switcher.getInput();
|
||||
block.append(switcher.getBase());
|
||||
input.checked = this.localConfigWrapper.config.SEProtect;
|
||||
if (input.checked) document.body.classList.add('wh-gym-stack');
|
||||
// 绑定点击事件
|
||||
input.onchange = e => {
|
||||
let target = e.target as HTMLInputElement;
|
||||
document.body.classList.toggle('wh-gym-stack');
|
||||
this.localConfigWrapper.config.SEProtect = target.checked;
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -1,196 +0,0 @@
|
||||
import CommonUtils from "../class/utils/CommonUtils";
|
||||
import UserScriptEngine from "../enum/UserScriptEngine";
|
||||
import Popup from "../class/utils/Popup";
|
||||
import STOCK_IMG_HTML from "../../static/html/stock_img.html";
|
||||
import WindowActiveState from "../class/action/WindowActiveState";
|
||||
import { Injectable } from "../container/Injectable";
|
||||
import ClassName from "../container/ClassName";
|
||||
import Logger from "../class/Logger";
|
||||
import IFeature from "../man/IFeature";
|
||||
import ATK_PAGE_REG from "./url/ATK_PAGE_REG";
|
||||
import ALL_PAGE_REG from "./url/ALL_PAGE_REG";
|
||||
|
||||
@Injectable()
|
||||
@ClassName('TravelItem')
|
||||
export default class TravelItem implements IFeature {
|
||||
private readonly logger: Logger = Logger.factory(TravelItem)
|
||||
|
||||
description(): string {
|
||||
return "海外货物存量静默获取";
|
||||
}
|
||||
|
||||
iStart(): void | Promise<void> {
|
||||
this.init()
|
||||
}
|
||||
|
||||
urlExcludes(): RegExp[] {
|
||||
return [ATK_PAGE_REG];
|
||||
}
|
||||
|
||||
private readonly apiUrl: string = 'https://yata.yt/api/v1/travel/export/';
|
||||
private foreignStockInfo: any = null;
|
||||
|
||||
urlIncludes(): RegExp[] {
|
||||
return [ALL_PAGE_REG];
|
||||
}
|
||||
|
||||
public constructor(
|
||||
private readonly windowActiveState: WindowActiveState,
|
||||
private readonly commonUtils: CommonUtils,
|
||||
) {
|
||||
}
|
||||
|
||||
public init() {
|
||||
|
||||
window.setInterval(async () => {
|
||||
if (!this.windowActiveState.get()) return;
|
||||
this.logger.info('COFetch ', this.apiUrl);
|
||||
try {
|
||||
this.foreignStockInfo = JSON.parse(await CommonUtils.COFetch(this.apiUrl));
|
||||
} catch (e) {
|
||||
this.logger.error('解析错误', e.stack || e.message || e);
|
||||
}
|
||||
this.logger.info({ info: 'TravelItem 跨域返回', 'returned': this.foreignStockInfo });
|
||||
}, 30 * 1000);
|
||||
}
|
||||
|
||||
public get itemFiler() {
|
||||
return [
|
||||
{
|
||||
"name": "mex",
|
||||
"show": "墨西哥",
|
||||
"stocks": {
|
||||
"Dahlia": "花",
|
||||
"Jaguar Plushie": "偶"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "cay",
|
||||
"show": "开曼",
|
||||
"stocks": {
|
||||
"Banana Orchid": "花",
|
||||
"Stingray Plushie": "偶"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "can",
|
||||
"show": "加拿大",
|
||||
"stocks": {
|
||||
"Crocus": "花",
|
||||
"Wolverine Plushie": "偶"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "haw",
|
||||
"show": "夏威夷",
|
||||
"stocks": {
|
||||
"Orchid": "花",
|
||||
"Large Suitcase": "大箱"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "uni",
|
||||
"show": "嘤国",
|
||||
"stocks": {
|
||||
"Heather": "花",
|
||||
"Red Fox Plushie": "赤狐",
|
||||
"Nessie Plushie": "水怪"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "arg",
|
||||
"show": "阿根廷",
|
||||
"stocks": {
|
||||
"Ceibo Flower": "花",
|
||||
"Monkey Plushie": "偶",
|
||||
"Tear Gas": "催泪弹"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "swi",
|
||||
"show": "瑞士",
|
||||
"stocks": {
|
||||
"Edelweiss": "花",
|
||||
"Chamois Plushie": "偶"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "jap",
|
||||
"show": "日本",
|
||||
"stocks": {
|
||||
"Cherry Blossom": "花"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "chi",
|
||||
"show": "祖国",
|
||||
"stocks": {
|
||||
"Peony": "花",
|
||||
"Panda Plushie": "偶"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "uae",
|
||||
"show": "阿联酋 (UAE)",
|
||||
"stocks": {
|
||||
"Tribulus Omanense": "花",
|
||||
"Camel Plushie": "偶"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "sou",
|
||||
"show": "南非",
|
||||
"stocks": {
|
||||
"African Violet": "花",
|
||||
"Lion Plushie": "偶",
|
||||
"Xanax": "XAN"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
// 呈现内容
|
||||
public async clickHandler(): Promise<void> {
|
||||
if (this.commonUtils.getScriptEngine() === UserScriptEngine.RAW) {
|
||||
new Popup(STOCK_IMG_HTML.replace('{{}}', performance.now().toString()), '飞花库存');
|
||||
} else {
|
||||
const popup = new Popup("请稍后 " + CommonUtils.loading_gif_html(), '飞花库存');
|
||||
let table = `<table><tr><th colspan="2">目的地 - 更新时间</th><th colspan="3">库存</th></tr>`;
|
||||
// const dest = FILTER.default;
|
||||
const dest = this.itemFiler;
|
||||
const now = new Date();
|
||||
const res = await this.get();
|
||||
this.logger.info({ res })
|
||||
if (!res || !res.stocks) return;
|
||||
dest.forEach(el => {
|
||||
const update = (now.getTime() - new Date(res.stocks[el.name]['update'] * 1000).getTime()) / 1000 | 0
|
||||
table += `<tr><td>${ el.show }</td><td>${ update / 60 | 0 }分${ update % 60 | 0 }秒前</td>`;
|
||||
let count = 0;
|
||||
res.stocks[el.name]['stocks'].forEach(stock => {
|
||||
if (el.stocks[stock.name]) {
|
||||
table += `<td${ stock['quantity'] === 0 ? ' style="background-color:#f44336;color:white;border-color:#000;"' : '' }>${ el.stocks[stock.name] } (${ stock['quantity'] })</td>`;
|
||||
count++;
|
||||
}
|
||||
});
|
||||
while (count < 3) {
|
||||
count++;
|
||||
table += '<td></td>';
|
||||
}
|
||||
table += '</tr>';
|
||||
});
|
||||
table += '</table>';
|
||||
popup.getElement().innerHTML = table;
|
||||
}
|
||||
}
|
||||
|
||||
public async get() {
|
||||
try {
|
||||
return this.foreignStockInfo ||= JSON.parse(await CommonUtils.COFetch(this.apiUrl));
|
||||
} catch (e) {
|
||||
this.logger.error('解析出错', e.stack || e.message || e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// export const TravelItemKey = Symbol('TravelItemKey') as InjectionKey<TravelItem>
|
||||
@ -1,2 +0,0 @@
|
||||
const ALL_PAGE_REG = /^/
|
||||
export default ALL_PAGE_REG
|
||||
@ -1,2 +0,0 @@
|
||||
const ATK_PAGE_REG = /\/loader.php\?sid=attack&user2ID=/
|
||||
export default ATK_PAGE_REG
|
||||
@ -1,2 +0,0 @@
|
||||
const INDEX_PAGE_REG = /index\.php/
|
||||
export default INDEX_PAGE_REG
|
||||
@ -1,10 +1,7 @@
|
||||
import Popup from "../../class/utils/Popup";
|
||||
import { Container } from "../../container/Container";
|
||||
import Logger from "../../class/Logger";
|
||||
|
||||
// 传单助手
|
||||
export default function adHelper() {
|
||||
Container.factory(Logger).error('adHelper')
|
||||
let popup = new Popup('', '传单助手').getElement();
|
||||
document.querySelector('#chatRoot').classList.remove('wh-hide');
|
||||
let info = document.createElement('p');
|
||||
|
||||
@ -280,7 +280,7 @@ export default function christmasTownHelper() {
|
||||
const history = Object.keys(dropHist).map(key => dropHist[key]).sort((a, b) => a.id - b.id);
|
||||
let table_html = '';
|
||||
history.forEach(e => {
|
||||
table_html += `<tr><td>${ e.pos }</td><td>${ e.map ?? e.data }</td><td>${ e.name }</td><td>${ e.last }</td><td>${ e.isPassed ? '已取得' : '不确定' }</td></tr>`;
|
||||
table_html += `<tr><td>${ e.pos }</td><td>${ e.map }</td><td>${ e.name }</td><td>${ e.last }</td><td>${ e.isPassed ? '已取得' : '不确定' }</td></tr>`;
|
||||
});
|
||||
$tbody.innerHTML = table_html;
|
||||
localStorage.setItem('wh-loot-store', JSON.stringify(dropHist));
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import toThousands from "../utils/toThousands";
|
||||
import CommonUtils from "../../class/utils/CommonUtils";
|
||||
import CITY_FINDER_CSS from "../../../static/css/city_finder.module.css";
|
||||
import CITY_FINDER_CSS from "../../../static/css/city_finder.css";
|
||||
import TornStyleBlock from "../../class/utils/TornStyleBlock";
|
||||
import ItemHelper from "../../class/utils/ItemHelper";
|
||||
import { Container } from "../../container/Container";
|
||||
@ -10,9 +10,7 @@ import { Container } from "../../container/Container";
|
||||
* @param _base
|
||||
*/
|
||||
export default function cityFinder(_base: TornStyleBlock): void {
|
||||
let commonUtils: CommonUtils = Container.factory(CommonUtils);
|
||||
commonUtils.styleInject(CITY_FINDER_CSS);
|
||||
let itemHelper: ItemHelper = Container.factory(ItemHelper);
|
||||
CommonUtils.addStyle(CITY_FINDER_CSS);
|
||||
// 物品名与价格
|
||||
let items: {
|
||||
[k: number]: {
|
||||
@ -20,28 +18,43 @@ export default function cityFinder(_base: TornStyleBlock): void {
|
||||
price: number
|
||||
}
|
||||
} = null;
|
||||
|
||||
// const base = document.createElement('div');
|
||||
// base.id = 'wh-city-finder';
|
||||
// const container = document.createElement('div');
|
||||
// container.id = 'wh-city-finder-cont';
|
||||
const header = document.createElement('div');
|
||||
|
||||
// header.id = 'wh-city-finder-header';
|
||||
header.innerHTML = '捡垃圾助手';
|
||||
const info = document.createElement('div');
|
||||
info.innerHTML = '已找到物品:';
|
||||
// container.append(info);
|
||||
// base.append(header);
|
||||
// base.append(container);
|
||||
|
||||
_base.append(header, info);
|
||||
document.body.classList.add('wh-city-finds');
|
||||
|
||||
commonUtils.querySelector('div.leaflet-marker-pane').then(elem => {
|
||||
// CommonUtils.COFetch('https://jjins.github.io/item_price_raw.json')
|
||||
// .then(r => items = JSON.parse(r))
|
||||
// .catch(err => {
|
||||
// Log.error(err);
|
||||
// items = undefined
|
||||
// });
|
||||
let itemHelper = Container.factory(ItemHelper);
|
||||
CommonUtils.elementReady('div.leaflet-marker-pane').then(elem => {
|
||||
// document.querySelector('.content-wrapper').prepend(base);
|
||||
|
||||
// 发现的物品id与map img node
|
||||
const founds = [];
|
||||
elem.querySelectorAll('img.map-user-item-icon').forEach(node => {
|
||||
const item_id = node.src.split('/')[5];
|
||||
const finder_item = document.createElement('span');
|
||||
|
||||
// finder_item.id = 'wh-city-finder-item' + item_id;
|
||||
finder_item.classList.add('wh-city-finder-item');
|
||||
finder_item.innerHTML = item_id;
|
||||
founds.push({ 'id': item_id, 'node': finder_item, 'map_item': node });
|
||||
|
||||
// container.append(finder_item);
|
||||
// _base.append(finder_item);
|
||||
info.append(finder_item);
|
||||
});
|
||||
// 未发现物品 返回
|
||||
|
||||
@ -1,20 +1,18 @@
|
||||
import CommonUtils from "../../class/utils/CommonUtils";
|
||||
import Log from "../../class/Log";
|
||||
import Alert from "../../class/utils/Alert";
|
||||
import ActionButtonUtils from "../../class/utils/ActionButtonUtils";
|
||||
import FetchUtils from "../../class/utils/FetchUtils";
|
||||
import DEPO_CSS from "../../../static/css/depo.module.css";
|
||||
import DEPO_CSS from "../../../static/css/depo.css";
|
||||
import TornStyleBlock from "../../class/utils/TornStyleBlock";
|
||||
import { Container } from "../../container/Container";
|
||||
import LocalConfigWrapper from "../../class/LocalConfigWrapper";
|
||||
import Logger from "../../class/Logger";
|
||||
|
||||
const fetchUtils = Container.factory(FetchUtils);
|
||||
|
||||
export default function depoHelper() {
|
||||
let logger: Logger = Container.factory(Logger);
|
||||
let actionButtonUtils: ActionButtonUtils = Container.factory(ActionButtonUtils);
|
||||
let localConfigWrapper: LocalConfigWrapper = Container.factory(LocalConfigWrapper);
|
||||
let commonUtils: CommonUtils = Container.factory(CommonUtils);
|
||||
let href = window.location.href;
|
||||
let channel: 'CMPY' | 'FAC';
|
||||
const selector = { 'CMPY': "div#funds div.deposit", 'FAC': "div#armoury-donate div.cash" };
|
||||
@ -26,7 +24,7 @@ export default function depoHelper() {
|
||||
const btn = document.getElementById('ui-id-9');
|
||||
if (btn) {
|
||||
btn.click();
|
||||
logger.info('已自动打开存钱页面');
|
||||
Log.info('已自动打开存钱页面');
|
||||
}
|
||||
}
|
||||
// 收起冰蛙表格
|
||||
@ -55,7 +53,7 @@ export default function depoHelper() {
|
||||
// 存钱框浮动
|
||||
if (localConfigWrapper.config.floatDepo && channel) {
|
||||
document.body.classList.add('wh-depo-helper');
|
||||
commonUtils.styleInject(DEPO_CSS);
|
||||
CommonUtils.addStyle(DEPO_CSS);
|
||||
CommonUtils.elementReady(selector[channel]).then(node => {
|
||||
const close_btn = document.createElement('button');
|
||||
close_btn.addEventListener('click', () => {
|
||||
@ -81,14 +79,14 @@ export default function depoHelper() {
|
||||
}
|
||||
return;
|
||||
}
|
||||
logger.info('已添加GT助手');
|
||||
Log.info('已添加GT助手');
|
||||
// 获取交易id
|
||||
let query_params = location.hash.slice(1);
|
||||
let traceId = id;
|
||||
if (!traceId) query_params.split('&').forEach(param =>
|
||||
(param.startsWith('ID=')) && (traceId = param.slice(3))
|
||||
);
|
||||
logger.info('交易id为', traceId);
|
||||
Log.info('交易id为', traceId);
|
||||
|
||||
// 获取全部的钱数
|
||||
let getTraceMoney = async () => {
|
||||
@ -102,7 +100,7 @@ export default function depoHelper() {
|
||||
}
|
||||
};
|
||||
// 监听jquery ajax请求
|
||||
if (logger.debug()) $(document).ajaxComplete((_, xhr, settings) => logger.info({ xhr, settings }));
|
||||
if (Log.debug()) $(document).ajaxComplete((_, xhr, settings) => Log.info({ xhr, settings }));
|
||||
// react 加载完成后将节点加入视图中
|
||||
CommonUtils.elementReady('#trade-container').then(() =>
|
||||
document.querySelector('#trade-container').before(_node.getBase())
|
||||
@ -198,7 +196,7 @@ export default function depoHelper() {
|
||||
} else {
|
||||
if (node_link) node_link.remove();
|
||||
node_link = null;
|
||||
logger.info('已移除GT助手');
|
||||
Log.info('已移除GT助手');
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -263,7 +261,7 @@ async function factionDeposit() {
|
||||
|
||||
// 所有页面公司一键存钱
|
||||
async function companyDepositAnywhere() {
|
||||
const logger: Logger = Container.factory(Logger);
|
||||
// let fetchUtils: FetchUtils = FetchUtils.getInstance();
|
||||
let { addRFC } = window;
|
||||
if (typeof addRFC !== 'function') return;
|
||||
let url = addRFC('https://www.torn.com/inputMoneyAction.php?step=generalAction');
|
||||
@ -275,7 +273,7 @@ async function companyDepositAnywhere() {
|
||||
body: 'deposit=' + money,
|
||||
headers: { 'X-Requested-With': 'XMLHttpRequest', 'Content-Type': 'application/x-www-form-urlencoded' }
|
||||
})).text();
|
||||
logger.info(res);
|
||||
Log.info(res);
|
||||
let node = document.createElement('div');
|
||||
node.innerHTML = res;
|
||||
let success = node.querySelector('.success-message');
|
||||
|
||||
@ -1,98 +0,0 @@
|
||||
import CommonUtils from "../../class/utils/CommonUtils"
|
||||
|
||||
type YataBSEstData = {
|
||||
"total": number,
|
||||
"score": number,
|
||||
"type": "Offensive" | "Defensive" | "Balanced",
|
||||
"skewness": number,
|
||||
"timestamp": number,
|
||||
"version": 1,
|
||||
}
|
||||
|
||||
type YataApiResponse = {
|
||||
// key为请求id
|
||||
[key: number]: YataBSEstData
|
||||
error?: { 'error': string, 'code': 1 | 2 | 3 | 4 }
|
||||
}
|
||||
|
||||
type YataApiDataWrap = YataBSEstData & {
|
||||
id: string,
|
||||
isCache: boolean,
|
||||
}
|
||||
|
||||
const cacheExpireMs = 86400000 // 一天
|
||||
const KEY = 'WHBSEstCache'
|
||||
|
||||
const getCacheObj = () => {
|
||||
let obj: { [key: string]: YataApiDataWrap }
|
||||
try {
|
||||
obj = JSON.parse(localStorage.getItem(KEY)) ?? {}
|
||||
} catch (e) {
|
||||
obj = {}
|
||||
}
|
||||
return obj
|
||||
}
|
||||
|
||||
const getCache = (id: number): YataApiDataWrap => {
|
||||
let cache: YataApiDataWrap = getCacheObj()[id]
|
||||
if (cache && ((Date.now() - (cache.timestamp * 1000)) < cacheExpireMs)) {
|
||||
cache.isCache = true
|
||||
} else {
|
||||
cache = null
|
||||
}
|
||||
return cache
|
||||
}
|
||||
|
||||
const setCache = (data: YataApiDataWrap): void => {
|
||||
const cache = getCacheObj()
|
||||
cache[data.id] = data
|
||||
localStorage.setItem(KEY, JSON.stringify(cache))
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空本地缓存
|
||||
*/
|
||||
const purge = () => {
|
||||
localStorage.removeItem(KEY)
|
||||
}
|
||||
|
||||
const fetchYata = async (id: number, apikey: string): Promise<YataApiDataWrap> => {
|
||||
if (!id || !apikey) {
|
||||
throw new TypeError('请求yata接口时出错: id和apikey不能为空')
|
||||
}
|
||||
const cache = getCache(id)
|
||||
if (cache) {
|
||||
return cache
|
||||
} else {
|
||||
let responseString: string, response: YataApiResponse
|
||||
try {
|
||||
responseString = await CommonUtils.COFetch(`https://yata.yt/api/v1/bs/${ id }?key=${ apikey }`)
|
||||
} catch (e) {
|
||||
throw new TypeError('请求yata接口时出错 ' + e.message)
|
||||
}
|
||||
try {
|
||||
response = JSON.parse(responseString)
|
||||
} catch (e) {
|
||||
throw new TypeError('解析yata接口响应时出错 ' + e.message)
|
||||
}
|
||||
if (response.error) {
|
||||
switch (response.error.code) {
|
||||
case 1:
|
||||
throw new TypeError('请求yata接口时出错: yata服务端错误-' + response.error.error)
|
||||
case 2:
|
||||
throw new TypeError('请求yata接口时出错: 脚本逻辑错误-' + response.error.error)
|
||||
case 3:
|
||||
throw new TypeError('请求yata接口时出错: 已达到次数限制-' + response.error.error)
|
||||
case 4:
|
||||
throw new TypeError('请求yata接口时出错: apikey错误-' + response.error.error)
|
||||
}
|
||||
}
|
||||
const wrapper = <YataApiDataWrap>response[id]
|
||||
wrapper.id = String(id)
|
||||
wrapper.isCache = false
|
||||
setCache(wrapper)
|
||||
return wrapper
|
||||
}
|
||||
}
|
||||
|
||||
export { fetchYata, YataApiDataWrap, purge }
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user