Compare commits
No commits in common. "master" and "v1.0.7" have entirely different histories.
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"
|
||||
}
|
||||
]
|
||||
}
|
||||
165
CHANGELOG.md
165
CHANGELOG.md
@ -1,165 +1,10 @@
|
||||
# TODO
|
||||
|
||||
- 翻译:baza npc商店、imarket、imarket搜索结果
|
||||
- log重构,通知重构
|
||||
|
||||
# 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日
|
||||
|
||||
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 安装。
|
||||
@ -21,6 +21,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
|
||||
|
||||
8
global.d.ts
vendored
8
global.d.ts
vendored
@ -122,8 +122,10 @@ declare module "*.module.css" {
|
||||
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;
|
||||
|
||||
60
package-lock.json
generated
60
package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "wuhu-torn-helper",
|
||||
"version": "1.2.2",
|
||||
"version": "0.8.7",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "wuhu-torn-helper",
|
||||
"version": "1.2.2",
|
||||
"version": "0.8.7",
|
||||
"devDependencies": {
|
||||
"@element-plus/icons-vue": "^2.1.0",
|
||||
"@rollup/plugin-alias": "^4.0.3",
|
||||
@ -17,11 +17,11 @@
|
||||
"@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",
|
||||
"element-plus": "^2.3.3",
|
||||
"just-clone": "^6.2.0",
|
||||
"npm": "^8.19.2",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
@ -1150,9 +1150,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "20.6.0",
|
||||
"resolved": "https://registry.npmmirror.com/@types/node/-/node-20.6.0.tgz",
|
||||
"integrity": "sha512-najjVq5KN2vsH2U/xyh2opaSEz6cZMR2SetLIlxlj08nOcmPOemJmUK2o4kUzfLqfrWE0PIrNeE16XhYDd3nqg==",
|
||||
"version": "18.0.6",
|
||||
"resolved": "https://registry.npmmirror.com/@types/node/-/node-18.0.6.tgz",
|
||||
"integrity": "sha512-/xUq6H2aQm261exT6iZTMifUySEt4GR5KX8eYyY+C4MSNPqSh9oNIP7tz2GLKTlFaiBbgZNxffoR3CVRG+cljw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/parse-json": {
|
||||
@ -1577,24 +1577,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001597",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001597.tgz",
|
||||
"integrity": "sha512-7LjJvmQU6Sj7bL0j5b5WY/3n7utXUJvAe1lxhsHDbLmwX9mdL86Yjtr+5SRCyf8qME4M7pU2hswj0FpyBVCv9w==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/browserslist"
|
||||
},
|
||||
{
|
||||
"type": "tidelift",
|
||||
"url": "https://tidelift.com/funding/github/npm/caniuse-lite"
|
||||
},
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
]
|
||||
"version": "1.0.30001457",
|
||||
"resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001457.tgz",
|
||||
"integrity": "sha512-SDIV6bgE1aVbK6XyxdURbUE89zY7+k1BBBaOwYwkNCglXlel/E7mELiHC64HQ+W0xSKlqWhV9Wh7iHxUjMs4fA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/chalk": {
|
||||
"version": "4.1.2",
|
||||
@ -1985,9 +1971,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/element-plus": {
|
||||
"version": "2.3.12",
|
||||
"resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.3.12.tgz",
|
||||
"integrity": "sha512-fAWpbKCyt+l1dsqSNPOs/F/dBN4Wp5CGAyxbiS5zqDwI4q3QPM+LxLU2h3GUHMIBtMGCvmsG98j5HPMkTKkvcA==",
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.3.3.tgz",
|
||||
"integrity": "sha512-Zy61OXrG6b4FF3h29A9ZOUkaEQXjCuFwNa7DlpB3Vo+42Tw5zBbHe5a4BY7i56TVJG5xTbS9UQyA726J91pDqg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@ctrl/tinycolor": "^3.4.1",
|
||||
@ -8404,9 +8390,9 @@
|
||||
}
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "20.6.0",
|
||||
"resolved": "https://registry.npmmirror.com/@types/node/-/node-20.6.0.tgz",
|
||||
"integrity": "sha512-najjVq5KN2vsH2U/xyh2opaSEz6cZMR2SetLIlxlj08nOcmPOemJmUK2o4kUzfLqfrWE0PIrNeE16XhYDd3nqg==",
|
||||
"version": "18.0.6",
|
||||
"resolved": "https://registry.npmmirror.com/@types/node/-/node-18.0.6.tgz",
|
||||
"integrity": "sha512-/xUq6H2aQm261exT6iZTMifUySEt4GR5KX8eYyY+C4MSNPqSh9oNIP7tz2GLKTlFaiBbgZNxffoR3CVRG+cljw==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/parse-json": {
|
||||
@ -8761,9 +8747,9 @@
|
||||
}
|
||||
},
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30001597",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001597.tgz",
|
||||
"integrity": "sha512-7LjJvmQU6Sj7bL0j5b5WY/3n7utXUJvAe1lxhsHDbLmwX9mdL86Yjtr+5SRCyf8qME4M7pU2hswj0FpyBVCv9w==",
|
||||
"version": "1.0.30001457",
|
||||
"resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001457.tgz",
|
||||
"integrity": "sha512-SDIV6bgE1aVbK6XyxdURbUE89zY7+k1BBBaOwYwkNCglXlel/E7mELiHC64HQ+W0xSKlqWhV9Wh7iHxUjMs4fA==",
|
||||
"dev": true
|
||||
},
|
||||
"chalk": {
|
||||
@ -9080,9 +9066,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"element-plus": {
|
||||
"version": "2.3.12",
|
||||
"resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.3.12.tgz",
|
||||
"integrity": "sha512-fAWpbKCyt+l1dsqSNPOs/F/dBN4Wp5CGAyxbiS5zqDwI4q3QPM+LxLU2h3GUHMIBtMGCvmsG98j5HPMkTKkvcA==",
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.3.3.tgz",
|
||||
"integrity": "sha512-Zy61OXrG6b4FF3h29A9ZOUkaEQXjCuFwNa7DlpB3Vo+42Tw5zBbHe5a4BY7i56TVJG5xTbS9UQyA726J91pDqg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@ctrl/tinycolor": "^3.4.1",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "wuhu-torn-helper",
|
||||
"version": "1.2.4",
|
||||
"version": "1.0.7",
|
||||
"description": "芜湖助手",
|
||||
"scripts": {
|
||||
"release": "cross-env NODE_ENV=production rollup -c && node build.mjs",
|
||||
@ -17,11 +17,11 @@
|
||||
"@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",
|
||||
"element-plus": "^2.3.3",
|
||||
"just-clone": "^6.2.0",
|
||||
"npm": "^8.19.2",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -283,10 +283,6 @@ div#wh-popup::after {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.mt-4 {
|
||||
margin-bottom: 4px;
|
||||
.el-overlay {
|
||||
backdrop-filter: blur(20px);
|
||||
}
|
||||
|
||||
/*.el-overlay {*/
|
||||
/* backdrop-filter: blur(20px);*/
|
||||
/*}*/
|
||||
|
||||
@ -1,71 +1,68 @@
|
||||
<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>
|
||||
<span class="item-desc" style="display: inline-block;">
|
||||
<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">
|
||||
</span>
|
||||
<span class="item-hover">
|
||||
<button aria-labelledby="Show info: 180-name 180-price 180-stock" class="view-info wai-btn" i-data="i_871_346_51_52"
|
||||
value="100"></button>
|
||||
<button aria-label="Buy: Bottle of Beer" class="buy-info wai-btn" i-data="i_922_346_51_52" value="100"></button>
|
||||
</span>
|
||||
</span>
|
||||
<span class="desc">
|
||||
<span id="180-name" class="name t-overflow bold">Bottle of Beer</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">800</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_1076_375_53_34" value="100">Buy<br></button>
|
||||
</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;" tabindex="0">
|
||||
<span class="confirm">
|
||||
<span>
|
||||
Are you sure you would like to buy
|
||||
</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_966_379_24_14">
|
||||
Yes
|
||||
</a>
|
||||
<span class="no bold">
|
||||
<a class="wai-support t-blue h" href="#" i-data="i_1001_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>
|
||||
</span>
|
||||
</span>
|
||||
<button aria-label="Close" class="close-icon p0 wai-btn" value="100"></button>
|
||||
<div class="success-wrap" style="display: none;">
|
||||
<span class="success"><span class="t-green bold"></span>
|
||||
<span class="confirm-act m-top5"></span></span>
|
||||
<button aria-label="Close" class="close-icon p0 wai-btn" i-data="i_1101_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>
|
||||
@ -1,61 +1,51 @@
|
||||
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 { 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 icon: ZhongIcon,
|
||||
private readonly wuhuBase: WuhuBase,
|
||||
private readonly tornHelper: WuHuTornHelper,
|
||||
private readonly common: Common,
|
||||
private readonly urlRouter: UrlRouter,
|
||||
private readonly configWrapper: LocalConfigWrapper,
|
||||
private readonly utils: CommonUtils,
|
||||
private readonly featureMan: FeatureMan,
|
||||
) {
|
||||
}
|
||||
|
||||
public run() {
|
||||
|
||||
this.interrupt.conditionInterrupt();
|
||||
this.wuhuBase.conditionInterrupt();
|
||||
|
||||
// 初始化
|
||||
this.initializer.init();
|
||||
|
||||
// this.featureMan.fStart().then(() => this.featureMan.printTable());
|
||||
this.tornHelper.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.apply(this.common, this.run);
|
||||
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,144 @@
|
||||
// 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 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";
|
||||
import IconHelper from "./IconHelper";
|
||||
import MsgWrapper from "./utils/MsgWrapper";
|
||||
|
||||
/**
|
||||
* 脚本不区分页面的通用功能入口
|
||||
*/
|
||||
@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,
|
||||
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);
|
||||
|
||||
/**
|
||||
* 解决一直转圈(加载中)的问题
|
||||
* 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();
|
||||
this.msgWrapper.create('现金变动提醒已关闭', { sysNotify: true });
|
||||
return;
|
||||
}
|
||||
this.logger.info("现金变动提醒", mutations);
|
||||
mutations.forEach(item => {
|
||||
if (item.attributeName === 'data-money') {
|
||||
// this.icon.updateCashView(userMoney.innerText);
|
||||
this.msgWrapper.create(
|
||||
'现金变动 ' + item.oldValue + ' ➡️ ' + userMoney.innerText,
|
||||
{ sysNotify: true }
|
||||
);
|
||||
}
|
||||
});
|
||||
}).observe(userMoney, { attributes: true, attributeOldValue: true })
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
62
src/ts/class/IconHelper.ts
Normal file
62
src/ts/class/IconHelper.ts
Normal file
@ -0,0 +1,62 @@
|
||||
import Logger, { LoggerKey } from "./Logger";
|
||||
import ClassName from "../container/ClassName";
|
||||
import { Injectable } from "../container/Injectable";
|
||||
import CommonUtils, { CommonUtilsKey } from "./utils/CommonUtils";
|
||||
import LocalConfigWrapper, { LocalConfigWrapperKey } from "./LocalConfigWrapper";
|
||||
import NNB from "./handler/NNB";
|
||||
import ItemPriceWatcherHandler from "./handler/ItemPriceWatcherHandler";
|
||||
import { createApp } from "vue";
|
||||
import FloatMenu from "../../vue/FloatMenu.vue";
|
||||
import PopupWrapper, { PopupWrapperKey } from "./utils/PopupWrapper";
|
||||
import InfoUtils from "./utils/InfoUtils";
|
||||
import TravelItem, { TravelItemKey } from "./action/TravelItem";
|
||||
import QuickGymTrain, { QuickGymTrainKey } from "./action/QuickGymTrain";
|
||||
import QuickFlyBtnHandler, { QuickFlyBtnHandlerKey } from "./handler/QuickFlyBtnHandler";
|
||||
import ItemHelper, { ItemHelperKey } from "./utils/ItemHelper";
|
||||
import MathUtils, { MathUtilsKey } from "./utils/MathUtils";
|
||||
|
||||
@ClassName("IconHelper")
|
||||
@Injectable()
|
||||
export default class IconHelper {
|
||||
private readonly _element: HTMLElement;
|
||||
|
||||
constructor(
|
||||
private readonly logger: Logger,
|
||||
private readonly commonUtils: CommonUtils,
|
||||
private readonly localConfigWrapper: LocalConfigWrapper,
|
||||
private readonly nnb: NNB,
|
||||
private readonly itemPriceWatcherHandler: ItemPriceWatcherHandler,
|
||||
private readonly popupWrapper: PopupWrapper,
|
||||
private readonly infoUtils: InfoUtils,
|
||||
private readonly travelItem: TravelItem,
|
||||
private readonly quickGymTrain: QuickGymTrain,
|
||||
private readonly quickFlyBtnHandler: QuickFlyBtnHandler,
|
||||
private readonly itemHelper: ItemHelper,
|
||||
private readonly mathUtils: MathUtils,
|
||||
) {
|
||||
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.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);
|
||||
}
|
||||
|
||||
}
|
||||
@ -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,5 +1,4 @@
|
||||
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";
|
||||
@ -30,23 +29,6 @@ export default class Logger {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,11 +7,11 @@ 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";
|
||||
@ -48,14 +48,14 @@ 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);
|
||||
this.localConfigWrapper.config.SolveGoogleScriptPendingIssue = reloadSwitch.getInput().checked;
|
||||
// WuhuConfig.set('SolveGoogleScriptPendingIssue', reloadSwitch.getInput().checked, true);
|
||||
});
|
||||
|
||||
_base.append(document.createElement('br'));
|
||||
|
||||
|
||||
@ -2,9 +2,12 @@ import ClassName from "../container/ClassName";
|
||||
import { Injectable } from "../container/Injectable";
|
||||
|
||||
|
||||
@ClassName('Interrupt')
|
||||
@ClassName('WuhuBase')
|
||||
@Injectable()
|
||||
export default class Interrupt {
|
||||
export default class WuhuBase {
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
public conditionInterrupt() {
|
||||
let title: HTMLElement | { innerText: string } = (document.querySelector('#skip-to-content') ||
|
||||
@ -14,6 +17,6 @@ export default class Interrupt {
|
||||
title.innerText.toLowerCase().includes('please validate') ||
|
||||
document.querySelector('div.container div.cf .iAmUnderAttack') !== null
|
||||
);
|
||||
if (condition) throw new Error('芜湖');
|
||||
if (condition) throw '芜湖';
|
||||
}
|
||||
}
|
||||
181
src/ts/class/WuhuTornHelper.ts
Normal file
181
src/ts/class/WuhuTornHelper.ts
Normal file
@ -0,0 +1,181 @@
|
||||
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";
|
||||
|
||||
@Injectable()
|
||||
@ClassName('WuHuTornHelper')
|
||||
export default class WuHuTornHelper {
|
||||
constructor(
|
||||
// private readonly travelItem: TravelItem,
|
||||
private readonly global: Global,
|
||||
private readonly logger: Logger,
|
||||
private readonly infoUtils: InfoUtils,
|
||||
private readonly commonUtils: CommonUtils,
|
||||
) {
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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");
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@ -5,7 +5,7 @@ import CommonUtils from "./utils/CommonUtils";
|
||||
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 +15,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";
|
||||
@ -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.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);
|
||||
// `
|
||||
// .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;}
|
||||
// `;
|
||||
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('盯梢关闭');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,37 +1,18 @@
|
||||
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 InfoUtils from "../utils/InfoUtils";
|
||||
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";
|
||||
import Logger from "../Logger";
|
||||
import MsgWrapper from "../utils/MsgWrapper";
|
||||
|
||||
@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;
|
||||
@ -1,44 +1,26 @@
|
||||
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 TRAVEL_STATE from "../../enum/TravelState";
|
||||
import LocalConfigWrapper from "../LocalConfigWrapper";
|
||||
import { Injectable } from "../../container/Injectable";
|
||||
import ClassName from "../../container/ClassName";
|
||||
import Logger from "../Logger";
|
||||
import MsgWrapper from "../utils/MsgWrapper";
|
||||
|
||||
/**
|
||||
* 公司助手
|
||||
*/
|
||||
@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 +30,10 @@ export default class CompanyHelper implements IFeature {
|
||||
this.localConfigWrapper.config.CHTrainsDetectSwitch && this.trainsDetect().then();
|
||||
}
|
||||
|
||||
// public detectNow(): void {
|
||||
// this.trainsDetect(true).then();
|
||||
// }
|
||||
|
||||
/**
|
||||
* 火车检测
|
||||
* 每日判断一次,非公司老板跳过检测
|
||||
@ -55,7 +41,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 +56,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('火车检测: 无法获取数据');
|
||||
@ -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 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";
|
||||
import Logger from "../Logger";
|
||||
|
||||
/**
|
||||
* 彩票助手
|
||||
*/
|
||||
@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,15 +26,12 @@ 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,
|
||||
private readonly fetchUtils: FetchUtils,
|
||||
private readonly infoUtils: InfoUtils,
|
||||
private readonly logger: Logger,
|
||||
) {
|
||||
}
|
||||
|
||||
@ -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('一键购买已关闭');
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -88,4 +66,4 @@ export default class PTHelper implements IFeature {
|
||||
let new_href = old_href.replace(/=buy1/, '=buy');
|
||||
el.setAttribute('href', new_href);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -8,46 +8,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 +36,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');
|
||||
this.localConfigWrapper.config.HideProfileImg = hideImgSwitch.getInput().checked;
|
||||
});
|
||||
if (this.localConfigWrapper.config.ShowNameHistory) {
|
||||
globVars.responseHandlers.push((...args: any[]) => this.responseHandler.apply(this, args));
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 ClassName from "../../container/ClassName";
|
||||
import { Injectable } from "../../container/Injectable";
|
||||
import LocalConfigWrapper from "../LocalConfigWrapper";
|
||||
import Logger from "../Logger";
|
||||
|
||||
/**
|
||||
* ### 边栏助手
|
||||
@ -16,32 +13,16 @@ 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,
|
||||
private readonly logger: Logger,
|
||||
) {
|
||||
this.sidebarRootNode = document.querySelector('#sidebarroot');
|
||||
this.toggleBtn = document.createElement('button');
|
||||
@ -54,7 +35,7 @@ export default class SidebarHelper implements IFeature {
|
||||
this.initToggleBtn();
|
||||
this.barRedirect();
|
||||
} else {
|
||||
this.logger.warn('页面未开启边栏,边栏助手退出');
|
||||
this.logger.warn('[SidebarHelper] 页面未开启边栏,边栏助手退出');
|
||||
}
|
||||
}
|
||||
|
||||
@ -92,10 +73,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';
|
||||
@ -6,29 +6,13 @@ 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,
|
||||
|
||||
@ -1,36 +1,15 @@
|
||||
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";
|
||||
import TornStyleBlock from "../utils/TornStyleBlock";
|
||||
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 implements IFeature {
|
||||
|
||||
export default class StackHelper {
|
||||
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();
|
||||
@ -44,4 +23,5 @@ export default class StackHelper implements IFeature {
|
||||
this.localConfigWrapper.config.SEProtect = target.checked;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,41 +1,22 @@
|
||||
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";
|
||||
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 WindowActiveState from "./WindowActiveState";
|
||||
import { Injectable } from "../../container/Injectable";
|
||||
import ClassName from "../../container/ClassName";
|
||||
import Logger from "../Logger";
|
||||
import { InjectionKey } from "vue";
|
||||
|
||||
@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];
|
||||
}
|
||||
|
||||
export default class TravelItem {
|
||||
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 logger: Logger,
|
||||
private readonly commonUtils: CommonUtils,
|
||||
) {
|
||||
}
|
||||
@ -193,4 +174,4 @@ export default class TravelItem implements IFeature {
|
||||
}
|
||||
}
|
||||
|
||||
// export const TravelItemKey = Symbol('TravelItemKey') as InjectionKey<TravelItem>
|
||||
export const TravelItemKey = Symbol('TravelItemKey') as InjectionKey<TravelItem>
|
||||
@ -7,7 +7,6 @@ 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;
|
||||
|
||||
@ -105,16 +105,6 @@ class DefaultConfigType {
|
||||
// 自定义css
|
||||
@Notified()
|
||||
CustomCss = '';
|
||||
|
||||
monitorOn = ['drugCDMonitor']
|
||||
drugCDMonitorInterval = 60000
|
||||
|
||||
// mini profile显示bs估算
|
||||
@Notified()
|
||||
isBSEstMiniProfOn = false
|
||||
// profile页面显示bs估算
|
||||
@Notified()
|
||||
isBSEstProfOn = true
|
||||
}
|
||||
|
||||
export type Config = DefaultConfigType;
|
||||
|
||||
@ -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,67 @@
|
||||
// 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 { 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";
|
||||
|
||||
@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()
|
||||
};
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -2,7 +2,7 @@ import CommonUtils from "../utils/CommonUtils";
|
||||
import QUICK_FLY_CSS from "../../../static/css/quick_fly.module.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";
|
||||
@ -123,31 +123,22 @@ export default class QuickFlyBtnHandler {
|
||||
|
||||
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;
|
||||
let key;
|
||||
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);
|
||||
const resp = await (await fetch('/travelagency.php')).text();
|
||||
key = resp.match(/data-key="([0-9]+)"/)[1];
|
||||
} catch (e) {
|
||||
this.msgWrapper.create('起飞时出现错误 ' + e.message, {}, 'error');
|
||||
this.msgWrapper.create('起飞参数获取失败', {}, 'error');
|
||||
this.logger.error(e.stack);
|
||||
throw new Error('起飞时出现错误 ' + e.message);
|
||||
throw new Error('起飞参数获取失败');
|
||||
}
|
||||
let msg;
|
||||
try {
|
||||
msg = this.netHighLvlWrapper.doTravelFly(QuickFlyBtnHandler.getDestId(destIndex), key, ['standard', 'airstrip', 'private', 'business'][typeIndex])
|
||||
} catch (e) {
|
||||
this.msgWrapper.create(msg, {}, 'error');
|
||||
this.logger.error(e.stack);
|
||||
throw new Error('起飞时出现错误');
|
||||
}
|
||||
this.msgWrapper.create('已起飞', {}, 'success');
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { MenuItemConfig } from "../ZhongIcon";
|
||||
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";
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -1,30 +1,32 @@
|
||||
import "reflect-metadata";
|
||||
import Logger from "../class/Logger";
|
||||
import globVars from "../globVars";
|
||||
import { Container } from "../container/Container";
|
||||
import { Container } from "../../container/Container";
|
||||
import Logger from "../Logger";
|
||||
import globVars from "../../globVars";
|
||||
|
||||
export default function EntryPoint(Index: ClassType<{}> & { main: () => void }) {
|
||||
const logger = Logger.factory(Index);
|
||||
export default function EntryPoint(T: { main: () => void }) {
|
||||
if (window.WHTRANS) {
|
||||
logger.warn('退出, 已运行次数' + window.WHTRANS)
|
||||
console.log('退出, 已运行次数' + window.WHTRANS)
|
||||
} else {
|
||||
window.WHTRANS = window.WHTRANS === undefined ? 1 : window.WHTRANS++;
|
||||
const logger = Container.factory(Logger);
|
||||
|
||||
let started = false;
|
||||
const starter = () => {
|
||||
console.log('starter init...');
|
||||
let started = performance.now();
|
||||
try {
|
||||
Container.setLogger(Container.factory(Logger))
|
||||
Index.main()
|
||||
T.main();
|
||||
} catch (e) {
|
||||
logger.error('加载出错: ' + e.stack || e.message);
|
||||
logger.error('[Starter]加载出错信息: ' + e.stack || e.message);
|
||||
}
|
||||
let runTime: number = (performance.now() - started) | 0;
|
||||
globVars.loadTime = runTime;
|
||||
logger.info(`芜湖脚本完成加载, 耗时${ runTime }ms`);
|
||||
// if (ZhongIcon.ZhongNode && ZhongIcon.ZhongNode.initTimer)
|
||||
// ZhongIcon.ZhongNode.initTimer.innerHTML = `加载时间 ${ runTime }ms`;
|
||||
};
|
||||
const evHandler = () => {
|
||||
// console.log('document.readyState: ' + document.readyState);
|
||||
if (!started && (document.readyState === 'complete' || document.readyState === 'interactive')) {
|
||||
document.removeEventListener('readystatechange', evHandler);
|
||||
started = !started;
|
||||
@ -2,7 +2,6 @@ import ClassWithName from "../../interface/ClassWithName";
|
||||
|
||||
/**
|
||||
* 基类、单例
|
||||
* @deprecated
|
||||
*/
|
||||
export default class Provider implements ClassWithName {
|
||||
readonly className: string = 'Provider';
|
||||
|
||||
@ -7,14 +7,30 @@ import globVars from "../../globVars";
|
||||
@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已存在');
|
||||
globVars.actionList.push({
|
||||
txt,
|
||||
func
|
||||
});
|
||||
}
|
||||
|
||||
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 });
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,7 +43,7 @@ export default class CommonUtils {
|
||||
let logger = Container.factory(Logger);
|
||||
let start = new Timer();
|
||||
const engine = this.getScriptEngine();
|
||||
logger.info(`跨域请求 -> ${url}, 脚本引擎: ${engine}`);
|
||||
logger.info('跨域获取数据开始, 脚本引擎: ' + engine);
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
switch (engine) {
|
||||
case UserScriptEngine.RAW: {
|
||||
|
||||
@ -48,7 +48,7 @@ export default class NetHighLvlWrapper {
|
||||
},
|
||||
"referrer": "https://www.torn.com/travelagency.php",
|
||||
"referrerPolicy": "strict-origin-when-cross-origin",
|
||||
"body": `step=travel&id=${ destId }&type=${ type }`,
|
||||
"body": `step=travel&id=${ destId }&key=${ key }&type=${ type }`,
|
||||
"method": "POST",
|
||||
"mode": "cors",
|
||||
"credentials": "include"
|
||||
|
||||
@ -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,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
|
||||
@ -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));
|
||||
@ -288,4 +288,4 @@ export default function christmasTownHelper() {
|
||||
});
|
||||
getDOMOb.observe($root, { childList: true, subtree: true });
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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 }
|
||||
@ -1,120 +1,120 @@
|
||||
// import UserScriptEngine from "../../enum/UserScriptEngine";
|
||||
// import CommonUtils from "../../class/utils/CommonUtils";
|
||||
// import Alert from "../../class/utils/Alert";
|
||||
// import { Container } from "../../container/Container";
|
||||
// import Logger from "../../class/Logger";
|
||||
//
|
||||
// // gs loader
|
||||
// export default function loadGS(use) {
|
||||
// let logger = Container.factory(Logger);
|
||||
// if (use === UserScriptEngine.PDA) {
|
||||
// let ifr: HTMLIFrameElement = document.querySelector('#wh-gs-loader-ifr');
|
||||
// if (ifr) {
|
||||
// new Alert('飞贼小助手已经加载了');
|
||||
// return;
|
||||
// }
|
||||
// const container = document.createElement('div');
|
||||
// container.id = 'wh-gs-loader';
|
||||
// ifr = document.createElement('iframe');
|
||||
// ifr.id = 'wh-gs-loader-ifr';
|
||||
// ifr.src = 'https://www.torn.com/crimes.php';
|
||||
// container.append(ifr);
|
||||
// document.body.append(container);
|
||||
// CommonUtils.addStyle(`
|
||||
// #wh-gs-loader {
|
||||
// position:fixed;
|
||||
// top:0;
|
||||
// left:0;
|
||||
// z-index:100001;
|
||||
// }
|
||||
// `);
|
||||
// let notify = new Alert('加载中');
|
||||
// ifr.onload = () => {
|
||||
// notify.close();
|
||||
// const _window = ifr.contentWindow;
|
||||
// const _docu = _window.document;
|
||||
// _docu.head.innerHTML = '';
|
||||
// _docu.body.innerHTML = '';
|
||||
// notify = new Alert('加载依赖');
|
||||
// CommonUtils.COFetch('https://cdn.staticfile.org/vue/2.2.2/vue.min.js')
|
||||
// .then(vuejs => {
|
||||
// notify.close();
|
||||
// _window.eval(vuejs);
|
||||
// _window.GM_getValue = (k, v = undefined) => {
|
||||
// const objV = JSON.parse(_window.localStorage.getItem('wh-gs-storage') || '{}')[k];
|
||||
// return objV || v;
|
||||
// };
|
||||
// _window.GM_setValue = (k, v) => {
|
||||
// const obj = JSON.parse(_window.localStorage.getItem('wh-gs-storage') || '{}');
|
||||
// obj[k] = v;
|
||||
// _window.localStorage.setItem('wh-gs-storage', JSON.stringify(obj));
|
||||
// };
|
||||
// _window.GM_xmlhttpRequest = function (opt) {
|
||||
// // 暂不适配pda post
|
||||
// if (opt.method.toLowerCase() === 'post') return;
|
||||
// CommonUtils.COFetch(opt.url).then(res => {
|
||||
// const obj = {
|
||||
// responseText: res
|
||||
// };
|
||||
// opt.onload(obj);
|
||||
// });
|
||||
// };
|
||||
// notify = new Alert('加载飞贼小助手');
|
||||
// CommonUtils.COFetch(`https://gitee.com/ameto_kasao/tornjs/raw/master/GoldenSnitch.js?${ performance.now() }`)
|
||||
// .then(res => {
|
||||
// _window.eval(res.replace('http://222.160.142.50:8154/mugger', `https://api.ljs-lyt.com/mugger`));
|
||||
// _window.GM_setValue("gsp_x", 10);
|
||||
// _window.GM_setValue("gsp_y", 10);
|
||||
// notify.close();
|
||||
// notify = new Alert('飞贼小助手已加载', { timeout: 1 });
|
||||
// const gsp: HTMLElement = _docu.querySelector('#gsp');
|
||||
// const thisRun = () => {
|
||||
// ifr.style.height = `${ gsp.offsetHeight + 10 }px`;
|
||||
// ifr.style.width = `${ gsp.offsetWidth + 20 }px`;
|
||||
// gsp.style.top = '10px';
|
||||
// gsp.style.left = '10px';
|
||||
// };
|
||||
// new MutationObserver(thisRun).observe(gsp, { childList: true, subtree: true });
|
||||
// thisRun();
|
||||
// if (logger.debug()) _window.GM_setValue("gsp_showContent", true)
|
||||
// });
|
||||
// });
|
||||
// };
|
||||
// return;
|
||||
// }
|
||||
// if (use === UserScriptEngine.GM) {
|
||||
// if (typeof window.Vue !== 'function') {
|
||||
// let notify = new Alert('正在加载依赖');
|
||||
// CommonUtils.COFetch('https://cdn.staticfile.org/vue/2.2.2/vue.min.js')
|
||||
// .then(VueJS => {
|
||||
// window.eval(VueJS);
|
||||
// notify.close();
|
||||
// notify = new Alert('已载入依赖');
|
||||
// window.GM_getValue = (k, v = undefined) => {
|
||||
// const objV = JSON.parse(window.localStorage.getItem('wh-gs-storage') || '{}')[k];
|
||||
// return objV || v;
|
||||
// };
|
||||
// window.GM_setValue = (k, v) => {
|
||||
// const obj = JSON.parse(window.localStorage.getItem('wh-gs-storage') || '{}');
|
||||
// obj[k] = v;
|
||||
// window.localStorage.setItem('wh-gs-storage', JSON.stringify(obj));
|
||||
// };
|
||||
// // TODO
|
||||
// // window.GM_xmlhttpRequest = GM_xmlhttpRequest;
|
||||
// CommonUtils.COFetch(`https://gitee.com/ameto_kasao/tornjs/raw/master/GoldenSnitch.js?${ performance.now() }`)
|
||||
// .then(GSJS => {
|
||||
// window.eval(GSJS);
|
||||
// if (logger.debug()) window.GM_setValue("gsp_showContent", true);
|
||||
// notify.close();
|
||||
// notify = new Alert('已载入飞贼助手');
|
||||
// })
|
||||
// .catch(err => new Alert(`PDA API错误。${ JSON.stringify(err) }`));
|
||||
// })
|
||||
// .catch(err => new Alert(JSON.stringify(err)));
|
||||
// } else {
|
||||
// new Alert('飞贼助手已经加载了');
|
||||
// }
|
||||
// return;
|
||||
// }
|
||||
// new Alert('暂不支持');
|
||||
// }
|
||||
import UserScriptEngine from "../../enum/UserScriptEngine";
|
||||
import CommonUtils from "../../class/utils/CommonUtils";
|
||||
import Alert from "../../class/utils/Alert";
|
||||
import { Container } from "../../container/Container";
|
||||
import Logger from "../../class/Logger";
|
||||
|
||||
// gs loader
|
||||
export default function loadGS(use) {
|
||||
let logger = Container.factory(Logger);
|
||||
if (use === UserScriptEngine.PDA) {
|
||||
let ifr: HTMLIFrameElement = document.querySelector('#wh-gs-loader-ifr');
|
||||
if (ifr) {
|
||||
new Alert('飞贼小助手已经加载了');
|
||||
return;
|
||||
}
|
||||
const container = document.createElement('div');
|
||||
container.id = 'wh-gs-loader';
|
||||
ifr = document.createElement('iframe');
|
||||
ifr.id = 'wh-gs-loader-ifr';
|
||||
ifr.src = 'https://www.torn.com/crimes.php';
|
||||
container.append(ifr);
|
||||
document.body.append(container);
|
||||
CommonUtils.addStyle(`
|
||||
#wh-gs-loader {
|
||||
position:fixed;
|
||||
top:0;
|
||||
left:0;
|
||||
z-index:100001;
|
||||
}
|
||||
`);
|
||||
let notify = new Alert('加载中');
|
||||
ifr.onload = () => {
|
||||
notify.close();
|
||||
const _window = ifr.contentWindow;
|
||||
const _docu = _window.document;
|
||||
_docu.head.innerHTML = '';
|
||||
_docu.body.innerHTML = '';
|
||||
notify = new Alert('加载依赖');
|
||||
CommonUtils.COFetch('https://cdn.staticfile.org/vue/2.2.2/vue.min.js')
|
||||
.then(vuejs => {
|
||||
notify.close();
|
||||
_window.eval(vuejs);
|
||||
_window.GM_getValue = (k, v = undefined) => {
|
||||
const objV = JSON.parse(_window.localStorage.getItem('wh-gs-storage') || '{}')[k];
|
||||
return objV || v;
|
||||
};
|
||||
_window.GM_setValue = (k, v) => {
|
||||
const obj = JSON.parse(_window.localStorage.getItem('wh-gs-storage') || '{}');
|
||||
obj[k] = v;
|
||||
_window.localStorage.setItem('wh-gs-storage', JSON.stringify(obj));
|
||||
};
|
||||
_window.GM_xmlhttpRequest = function (opt) {
|
||||
// 暂不适配pda post
|
||||
if (opt.method.toLowerCase() === 'post') return;
|
||||
CommonUtils.COFetch(opt.url).then(res => {
|
||||
const obj = {
|
||||
responseText: res
|
||||
};
|
||||
opt.onload(obj);
|
||||
});
|
||||
};
|
||||
notify = new Alert('加载飞贼小助手');
|
||||
CommonUtils.COFetch(`https://gitee.com/ameto_kasao/tornjs/raw/master/GoldenSnitch.js?${ performance.now() }`)
|
||||
.then(res => {
|
||||
_window.eval(res.replace('http://222.160.142.50:8154/mugger', `https://api.ljs-lyt.com/mugger`));
|
||||
_window.GM_setValue("gsp_x", 10);
|
||||
_window.GM_setValue("gsp_y", 10);
|
||||
notify.close();
|
||||
notify = new Alert('飞贼小助手已加载', { timeout: 1 });
|
||||
const gsp: HTMLElement = _docu.querySelector('#gsp');
|
||||
const thisRun = () => {
|
||||
ifr.style.height = `${ gsp.offsetHeight + 10 }px`;
|
||||
ifr.style.width = `${ gsp.offsetWidth + 20 }px`;
|
||||
gsp.style.top = '10px';
|
||||
gsp.style.left = '10px';
|
||||
};
|
||||
new MutationObserver(thisRun).observe(gsp, { childList: true, subtree: true });
|
||||
thisRun();
|
||||
if (logger.debug()) _window.GM_setValue("gsp_showContent", true)
|
||||
});
|
||||
});
|
||||
};
|
||||
return;
|
||||
}
|
||||
if (use === UserScriptEngine.GM) {
|
||||
if (typeof window.Vue !== 'function') {
|
||||
let notify = new Alert('正在加载依赖');
|
||||
CommonUtils.COFetch('https://cdn.staticfile.org/vue/2.2.2/vue.min.js')
|
||||
.then(VueJS => {
|
||||
window.eval(VueJS);
|
||||
notify.close();
|
||||
notify = new Alert('已载入依赖');
|
||||
window.GM_getValue = (k, v = undefined) => {
|
||||
const objV = JSON.parse(window.localStorage.getItem('wh-gs-storage') || '{}')[k];
|
||||
return objV || v;
|
||||
};
|
||||
window.GM_setValue = (k, v) => {
|
||||
const obj = JSON.parse(window.localStorage.getItem('wh-gs-storage') || '{}');
|
||||
obj[k] = v;
|
||||
window.localStorage.setItem('wh-gs-storage', JSON.stringify(obj));
|
||||
};
|
||||
// TODO
|
||||
// window.GM_xmlhttpRequest = GM_xmlhttpRequest;
|
||||
CommonUtils.COFetch(`https://gitee.com/ameto_kasao/tornjs/raw/master/GoldenSnitch.js?${ performance.now() }`)
|
||||
.then(GSJS => {
|
||||
window.eval(GSJS);
|
||||
if (logger.debug()) window.GM_setValue("gsp_showContent", true);
|
||||
notify.close();
|
||||
notify = new Alert('已载入飞贼助手');
|
||||
})
|
||||
.catch(err => new Alert(`PDA API错误。${ JSON.stringify(err) }`));
|
||||
})
|
||||
.catch(err => new Alert(JSON.stringify(err)));
|
||||
} else {
|
||||
new Alert('飞贼助手已经加载了');
|
||||
}
|
||||
return;
|
||||
}
|
||||
new Alert('暂不支持');
|
||||
}
|
||||
@ -1,20 +1,18 @@
|
||||
import titleTrans from "../func/translate/titleTrans";
|
||||
import contentTitleLinksTrans from "../func/translate/contentTitleLinksTrans";
|
||||
import Device from "../enum/Device";
|
||||
import ActionButtonUtils from "../class/utils/ActionButtonUtils";
|
||||
import CommonUtils from "../class/utils/CommonUtils";
|
||||
import TRAVEL_ALARM_CSS from "../../static/css/travel_alarm.module.css";
|
||||
import TRAVEL_ALARM_HTML from "../../static/html/travel_alarm.html";
|
||||
import TornStyleBlock from "../class/utils/TornStyleBlock";
|
||||
import QuickFlyBtnHandler from "../class/handler/QuickFlyBtnHandler";
|
||||
import TRAVEL_STATE from "../enum/TravelState";
|
||||
import Global from "../class/Global";
|
||||
import ClassName from "../container/ClassName";
|
||||
import { Injectable } from "../container/Injectable";
|
||||
import LocalConfigWrapper from "../class/LocalConfigWrapper";
|
||||
import MsgWrapper from "../class/utils/MsgWrapper";
|
||||
import IFeature from "../man/IFeature";
|
||||
import INDEX_PAGE_REG from "./url/INDEX_PAGE_REG";
|
||||
import titleTrans from "../translate/titleTrans";
|
||||
import contentTitleLinksTrans from "../translate/contentTitleLinksTrans";
|
||||
import Device from "../../enum/Device";
|
||||
import ActionButtonUtils from "../../class/utils/ActionButtonUtils";
|
||||
import CommonUtils from "../../class/utils/CommonUtils";
|
||||
import TRAVEL_ALARM_CSS from "../../../static/css/travel_alarm.module.css";
|
||||
import TRAVEL_ALARM_HTML from "../../../static/html/travel_alarm.html";
|
||||
import TornStyleBlock from "../../class/utils/TornStyleBlock";
|
||||
import QuickFlyBtnHandler from "../../class/handler/QuickFlyBtnHandler";
|
||||
import TRAVEL_STATE from "../../enum/TravelState";
|
||||
import Global from "../../class/Global";
|
||||
import ClassName from "../../container/ClassName";
|
||||
import { Injectable } from "../../container/Injectable";
|
||||
import LocalConfigWrapper from "../../class/LocalConfigWrapper";
|
||||
import MsgWrapper from "../../class/utils/MsgWrapper";
|
||||
|
||||
/**
|
||||
* 飞行助手
|
||||
@ -26,23 +24,7 @@ import INDEX_PAGE_REG from "./url/INDEX_PAGE_REG";
|
||||
*/
|
||||
@ClassName('TravelHelper')
|
||||
@Injectable()
|
||||
export default class TravelHelper implements IFeature {
|
||||
description(): string {
|
||||
return "飞行助手";
|
||||
}
|
||||
|
||||
iStart(): void | Promise<void> {
|
||||
this.init()
|
||||
}
|
||||
|
||||
urlExcludes(): RegExp[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
urlIncludes(): RegExp[] {
|
||||
return [INDEX_PAGE_REG, /travelagency\.php/];
|
||||
}
|
||||
|
||||
export default class TravelHelper {
|
||||
constructor(
|
||||
private readonly global: Global,
|
||||
private readonly commonUtils: CommonUtils,
|
||||
@ -171,7 +153,7 @@ export default class TravelHelper implements IFeature {
|
||||
// 响铃的方法
|
||||
let audio_play_handle = () => {
|
||||
if (user_stop_alert) {
|
||||
window.clearInterval(audio_play_id);
|
||||
clearInterval(audio_play_id);
|
||||
audio_play_id = null;
|
||||
return;
|
||||
}
|
||||
@ -212,7 +194,7 @@ export default class TravelHelper implements IFeature {
|
||||
} else {
|
||||
// flying_status.innerHTML = `飞行中...`;
|
||||
if (wh_trv_alarm.enable) {
|
||||
window.clearInterval(audio_play_id);
|
||||
clearInterval(audio_play_id);
|
||||
audio_play_id = null;
|
||||
stop_node.parentElement.classList.add('wh-trv-alarm-stop-hide');
|
||||
}
|
||||
@ -284,7 +266,6 @@ export default class TravelHelper implements IFeature {
|
||||
});
|
||||
const trans = () => {
|
||||
// 当前能量e
|
||||
// @ts-ignore
|
||||
const energyBarStr = $('#barEnergy p[class^="bar-value__"]').text().trim();
|
||||
const [curE, maxE] = energyBarStr.split('/').length === 2
|
||||
? [parseInt(energyBarStr.split('/')[0]), parseInt(energyBarStr.split('/')[1])]
|
||||
@ -293,7 +274,6 @@ export default class TravelHelper implements IFeature {
|
||||
const fullEnergyTime = !(isNaN(curE) || isNaN(maxE)) ? (maxE - 5 - curE) / 5 * incTime
|
||||
+ (incTime - new Date().getMinutes() % incTime) : NaN;
|
||||
// 起飞前提示
|
||||
// @ts-ignore
|
||||
$('.travel-confirm .travel-question .q-wrap span:nth-of-type(2)').each((i, e) => {
|
||||
if (isNaN(fullEnergyTime)) return;
|
||||
const spl = e.innerText.trim().split(' ');
|
||||
@ -324,6 +304,10 @@ export default class TravelHelper implements IFeature {
|
||||
}
|
||||
}
|
||||
|
||||
/** TODO */
|
||||
inTravelPage() {
|
||||
}
|
||||
|
||||
async doTravelBack(): Promise<void> {
|
||||
if (typeof window['getAction'] !== 'function') return;
|
||||
let backHomeAction = function (): Promise<string> {
|
||||
@ -67,57 +67,57 @@ export default function translateMain(href: string): void {
|
||||
};
|
||||
|
||||
// 边栏
|
||||
// let sidebarTimeOut = 60;
|
||||
// const sidebarInterval = setInterval(() => {
|
||||
// // 60秒后取消定时
|
||||
// if ($('div[class^="sidebar"]').length === 0) {
|
||||
// sidebarTimeOut--;
|
||||
// if (sidebarTimeOut < 0) {
|
||||
// clearInterval(sidebarInterval);
|
||||
// }
|
||||
// return;
|
||||
// }
|
||||
// // 边栏块标题
|
||||
// $('h2[class^="header"]').each((i, e) => {
|
||||
// if (!sidebarDict[e.firstChild.nodeValue]) return;
|
||||
// e.firstChild.nodeValue = sidebarDict[e.firstChild.nodeValue];
|
||||
// });
|
||||
// // 边栏人物名字
|
||||
// $('span[class^="menu-name"]').each((i, e) => {
|
||||
// e.firstChild.nodeValue = '名字:';
|
||||
// });
|
||||
// // 钱 等级 pt 天赋点
|
||||
// $('p[class^="point-block"]').each((i, e) => {
|
||||
// if (sidebarDict[e.firstChild.firstChild.nodeValue])
|
||||
// e.firstChild.firstChild.nodeValue = sidebarDict[e.firstChild.firstChild.nodeValue];
|
||||
// });
|
||||
// // 4条 状态条
|
||||
// $('p[class^="bar-name"]').each((i, e) => {
|
||||
// if (sidebarDict[e.firstChild.nodeValue])
|
||||
// e.firstChild.nodeValue = sidebarDict[e.firstChild.nodeValue];
|
||||
// });
|
||||
// // 边栏菜单
|
||||
// $('span[class^="linkName"]').each((i, e) => {
|
||||
// if (sidebarDict[e.firstChild.nodeValue])
|
||||
// e.firstChild.nodeValue = sidebarDict[e.firstChild.nodeValue];
|
||||
// });
|
||||
// // [use]按钮
|
||||
// if (document.querySelector('#pointsMerits'))
|
||||
// $('#pointsMerits')[0].firstChild.nodeValue = '[使用]';
|
||||
// if (document.querySelector('#pointsPoints'))
|
||||
// $('#pointsPoints')[0].firstChild.nodeValue = '[使用]';
|
||||
// if (document.querySelector('#pointsLevel'))
|
||||
// $('#pointsLevel')[0].firstChild.nodeValue = '[升级]';
|
||||
//
|
||||
// // 手机 区域菜单
|
||||
// $('div[class*="areas-mobile"] span:nth-child(2)').contents().each((i, e) => {
|
||||
// //log(e);
|
||||
// if (sidebarDict[e.nodeValue])
|
||||
// e.nodeValue = sidebarDict[e.nodeValue];
|
||||
// });
|
||||
//
|
||||
// clearInterval(sidebarInterval);
|
||||
// }, 1000);
|
||||
let sidebarTimeOut = 60;
|
||||
const sidebarInterval = setInterval(() => {
|
||||
// 60秒后取消定时
|
||||
if ($('div[class^="sidebar"]').length === 0) {
|
||||
sidebarTimeOut--;
|
||||
if (sidebarTimeOut < 0) {
|
||||
clearInterval(sidebarInterval);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// 边栏块标题
|
||||
$('h2[class^="header"]').each((i, e) => {
|
||||
if (!sidebarDict[e.firstChild.nodeValue]) return;
|
||||
e.firstChild.nodeValue = sidebarDict[e.firstChild.nodeValue];
|
||||
});
|
||||
// 边栏人物名字
|
||||
$('span[class^="menu-name"]').each((i, e) => {
|
||||
e.firstChild.nodeValue = '名字:';
|
||||
});
|
||||
// 钱 等级 pt 天赋点
|
||||
$('p[class^="point-block"]').each((i, e) => {
|
||||
if (sidebarDict[e.firstChild.firstChild.nodeValue])
|
||||
e.firstChild.firstChild.nodeValue = sidebarDict[e.firstChild.firstChild.nodeValue];
|
||||
});
|
||||
// 4条 状态条
|
||||
$('p[class^="bar-name"]').each((i, e) => {
|
||||
if (sidebarDict[e.firstChild.nodeValue])
|
||||
e.firstChild.nodeValue = sidebarDict[e.firstChild.nodeValue];
|
||||
});
|
||||
// 边栏菜单
|
||||
$('span[class^="linkName"]').each((i, e) => {
|
||||
if (sidebarDict[e.firstChild.nodeValue])
|
||||
e.firstChild.nodeValue = sidebarDict[e.firstChild.nodeValue];
|
||||
});
|
||||
// [use]按钮
|
||||
if (document.querySelector('#pointsMerits'))
|
||||
$('#pointsMerits')[0].firstChild.nodeValue = '[使用]';
|
||||
if (document.querySelector('#pointsPoints'))
|
||||
$('#pointsPoints')[0].firstChild.nodeValue = '[使用]';
|
||||
if (document.querySelector('#pointsLevel'))
|
||||
$('#pointsLevel')[0].firstChild.nodeValue = '[升级]';
|
||||
|
||||
// 手机 区域菜单
|
||||
$('div[class*="areas-mobile"] span:nth-child(2)').contents().each((i, e) => {
|
||||
//log(e);
|
||||
if (sidebarDict[e.nodeValue])
|
||||
e.nodeValue = sidebarDict[e.nodeValue];
|
||||
});
|
||||
|
||||
clearInterval(sidebarInterval);
|
||||
}, 1000);
|
||||
|
||||
// header
|
||||
if (document.querySelector('div#header-root')) {
|
||||
|
||||
@ -1,14 +0,0 @@
|
||||
const convertToCSV = (data: any[]) => {
|
||||
let csv = ''
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
let row = ''
|
||||
for (const key in data[i]) {
|
||||
row += `"${ data[i][key] }",`
|
||||
}
|
||||
row = row.slice(0, -1) // 删除最后一个逗号
|
||||
csv += row + '\r\n' // 添加换行符
|
||||
}
|
||||
return csv
|
||||
}
|
||||
|
||||
export { convertToCSV }
|
||||
@ -22,7 +22,3 @@ export const fetchCurrentMoney = async (action?: string): Promise<number> => {
|
||||
export const fetchCurrentCompanyAvailableMoney = () => {
|
||||
return fetchCurrentMoney("companyAction");
|
||||
};
|
||||
|
||||
export const fetchCurrentPropVaultAvailableMoney = () => {
|
||||
return fetchCurrentMoney("propertyDepositAction");
|
||||
};
|
||||
|
||||
@ -1,19 +0,0 @@
|
||||
import { SessionStoreDataType } from "../../interface/SessionStoreDataType";
|
||||
|
||||
/**
|
||||
* 寻找 session storage 中以 sidebarData 开头的数据以对象返回
|
||||
*/
|
||||
export default function (): SessionStoreDataType {
|
||||
let json: string = null
|
||||
for (let i = 0; i < sessionStorage.length; i++) {
|
||||
let key = sessionStorage.key(i)
|
||||
if (key.startsWith('sidebarData')) {
|
||||
json = sessionStorage.getItem(key)
|
||||
break
|
||||
}
|
||||
}
|
||||
if (!json) {
|
||||
throw new TypeError('未找到 sidebarData')
|
||||
}
|
||||
return JSON.parse(json)
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
const timePastFormat = (ts: number): string => {
|
||||
// 毫秒
|
||||
if (ts < 1000) {
|
||||
return ts + 'ms'
|
||||
}
|
||||
// 秒
|
||||
else if (ts < 60000) {
|
||||
return (ts / 1000 | 0) + 's'
|
||||
}
|
||||
// 分
|
||||
else if (ts < 3600000) {
|
||||
return (ts / 60000 | 0) + 'm'
|
||||
}
|
||||
// 时
|
||||
else {
|
||||
return (ts / 3600000 | 0) + 'h'
|
||||
}
|
||||
}
|
||||
|
||||
export { timePastFormat }
|
||||
@ -1,17 +1,6 @@
|
||||
import { ElMessage } from "element-plus"
|
||||
import { ElMessage } from "element-plus";
|
||||
|
||||
type CrimeResVo = { text: string, success: boolean }
|
||||
|
||||
const defaultCb = (res: CrimeResVo) => {
|
||||
ElMessage({
|
||||
message: res.text,
|
||||
type: res.success ? 'success' : 'error',
|
||||
dangerouslyUseHTMLString: true,
|
||||
grouping: true
|
||||
})
|
||||
}
|
||||
|
||||
const useItem = (itemId: string, cb = defaultCb) => {
|
||||
const useItem = (itemId: string) => {
|
||||
fetch(window.addRFC("https://www.torn.com/item.php"), {
|
||||
"headers": {
|
||||
"accept": "*/*",
|
||||
@ -30,22 +19,15 @@ const useItem = (itemId: string, cb = defaultCb) => {
|
||||
"credentials": "include"
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(res => cb(res))
|
||||
.then(res => ElMessage({
|
||||
message: res.text,
|
||||
type: res.success ? 'success' : 'error',
|
||||
dangerouslyUseHTMLString: true
|
||||
}))
|
||||
.catch(e => ElMessage({
|
||||
message: e.toString,
|
||||
type: 'error'
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
const useItemSync = (itemId: string, showMsg = true, cb = (response: CrimeResVo) => null) => {
|
||||
return new Promise((res, rej) => {
|
||||
useItem(itemId, (_res) => {
|
||||
if (showMsg) defaultCb(_res)
|
||||
cb(_res)
|
||||
res(null)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export default useItem
|
||||
export { useItemSync }
|
||||
export default useItem;
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import Popup from "./class/utils/Popup";
|
||||
import { reactive } from 'vue'
|
||||
import IFeatureResult from "./man/IFeatureResult";
|
||||
|
||||
|
||||
type ResponseHandlers = ((url: string, responseBody: {
|
||||
json: unknown,
|
||||
@ -21,14 +20,11 @@ class GlobVars {
|
||||
responseHandlers: ResponseHandlers = [];
|
||||
version = '$$WUHU_DEV_VERSION$$';
|
||||
popup_node: MyHTMLElement | Popup = null;
|
||||
actionList: {
|
||||
txt: string,
|
||||
func: (ev: Event) => void
|
||||
}[] = [];
|
||||
loadTime: number = 0;
|
||||
buttons = reactive<FloatButtonData[]>([])
|
||||
featureStatus = reactive<IFeatureResult[]>([])
|
||||
}
|
||||
|
||||
export default new GlobVars();
|
||||
|
||||
interface FloatButtonData {
|
||||
txt: string,
|
||||
func: (ev: Event) => void
|
||||
}
|
||||
|
||||
@ -1,15 +1,13 @@
|
||||
import "reflect-metadata";
|
||||
import App from "./App";
|
||||
import EntryPoint from "./starter/EntryPoint";
|
||||
import { Injectable } from "./container/Injectable";
|
||||
import ClassName from "./container/ClassName";
|
||||
import { Container } from "./container/Container";
|
||||
import App from "./App";
|
||||
import Logger from "./class/Logger";
|
||||
import EntryPoint from "./class/provider/EntryPoint";
|
||||
|
||||
@EntryPoint
|
||||
@ClassName('Index')
|
||||
@Injectable()
|
||||
class Index {
|
||||
public static main() {
|
||||
Container.factory(App).run()
|
||||
class _ {
|
||||
static main() {
|
||||
Container.setLogger(new Logger());
|
||||
Container.factory(App).run();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import Device from "../enum/Device";
|
||||
import { BeerMonitorLoop } from "../feature/BuyBeerHelper";
|
||||
import { BeerMonitorLoop } from "../class/action/BuyBeerHelper";
|
||||
import Popup from "../class/utils/Popup";
|
||||
import TravelItem from "../feature/TravelItem";
|
||||
import TravelItem from "../class/action/TravelItem";
|
||||
|
||||
export default interface IGlobal {
|
||||
GM_xmlhttpRequest?: Function;
|
||||
|
||||
@ -38,10 +38,7 @@ export default interface IUserProfileData {
|
||||
}
|
||||
};
|
||||
medalInformation: unknown;
|
||||
basicInformation: {
|
||||
icons: { id: number, title: string }[],
|
||||
lastAction: { seconds: number }
|
||||
};
|
||||
basicInformation: unknown;
|
||||
personalInformation: unknown;
|
||||
competitionStatus: unknown;
|
||||
staffTools: null;
|
||||
|
||||
@ -7,4 +7,4 @@ export default interface IWHNotify {
|
||||
sysNotifyClick?: Function;
|
||||
// 强制后台也通知
|
||||
force?: boolean;
|
||||
}
|
||||
}
|
||||
@ -1,566 +0,0 @@
|
||||
/**
|
||||
* 存在于 session storage 中的 sidebarData+uid
|
||||
*/
|
||||
export interface SessionStoreDataType {
|
||||
sliderHintDisabled: boolean
|
||||
selectedStatusIcon: any
|
||||
progressBarFetchActive: boolean
|
||||
linkWithContextMenu: number
|
||||
statusIcons: StatusIcons
|
||||
user: User
|
||||
listsStatuses: ListsStatuses
|
||||
listsLinksStatuses: ListsLinksStatuses
|
||||
bars: Bars
|
||||
account: Account
|
||||
areas: Areas
|
||||
lists: Lists
|
||||
footer: Footer
|
||||
dataSync: boolean
|
||||
sidebarFetched: boolean
|
||||
currentUrl: string
|
||||
}
|
||||
|
||||
export interface StatusIcons {
|
||||
size: string
|
||||
icons: Icons
|
||||
visible: boolean
|
||||
onTop: boolean
|
||||
}
|
||||
|
||||
export interface Icons {
|
||||
enbyGender: EnbyGender
|
||||
donator: Donator
|
||||
company: Company
|
||||
faction: Faction
|
||||
education: Education
|
||||
bazaar: Bazaar
|
||||
stock_market: StockMarket
|
||||
booster_cooldown?: BoosterCooldown
|
||||
drug_cooldown?: DrugCooldown
|
||||
}
|
||||
|
||||
export interface EnbyGender {
|
||||
iconID: string
|
||||
title: string
|
||||
}
|
||||
|
||||
export interface Donator {
|
||||
iconID: string
|
||||
title: string
|
||||
subtitle: string
|
||||
link: string
|
||||
}
|
||||
|
||||
export interface Company {
|
||||
iconID: string
|
||||
title: string
|
||||
subtitle: string
|
||||
link: string
|
||||
}
|
||||
|
||||
export interface Faction {
|
||||
iconID: string
|
||||
title: string
|
||||
subtitle: string
|
||||
link: string
|
||||
}
|
||||
|
||||
export interface Education {
|
||||
iconID: string
|
||||
title: string
|
||||
subtitle: string
|
||||
link: string
|
||||
serverTimestamp: number
|
||||
timerExpiresAt: number
|
||||
isShortFormatTimer: boolean
|
||||
}
|
||||
|
||||
export interface Bazaar {
|
||||
iconID: string
|
||||
title: string
|
||||
subtitle: string
|
||||
link: string
|
||||
}
|
||||
|
||||
export interface StockMarket {
|
||||
iconID: string
|
||||
title: string
|
||||
subtitle: string
|
||||
link: string
|
||||
}
|
||||
|
||||
export interface BoosterCooldown {
|
||||
iconID: string
|
||||
title: string
|
||||
factionUpgrade: string
|
||||
serverTimestamp: number
|
||||
timerExpiresAt: number
|
||||
isShortFormatTimer: boolean
|
||||
}
|
||||
|
||||
export interface DrugCooldown {
|
||||
iconID: string
|
||||
title: string
|
||||
subtitle: string
|
||||
serverTimestamp: number
|
||||
timerExpiresAt: number
|
||||
isShortFormatTimer: boolean
|
||||
}
|
||||
|
||||
export interface User {
|
||||
userID: number
|
||||
name: string
|
||||
link: string
|
||||
money: Money
|
||||
donator: boolean
|
||||
level: Level
|
||||
points: Points
|
||||
merits: Merits
|
||||
refills: Refills
|
||||
lifeModifier: number
|
||||
status: any
|
||||
}
|
||||
|
||||
export interface Money {
|
||||
value: number
|
||||
}
|
||||
|
||||
export interface Level {
|
||||
value: number
|
||||
upgradePossibility: boolean
|
||||
link: string
|
||||
}
|
||||
|
||||
export interface Points {
|
||||
value: number
|
||||
link: string
|
||||
}
|
||||
|
||||
export interface Merits {
|
||||
value: number
|
||||
link: string
|
||||
}
|
||||
|
||||
export interface Refills {
|
||||
value: string
|
||||
link: string
|
||||
}
|
||||
|
||||
export interface ListsStatuses {
|
||||
areas: boolean
|
||||
lists: boolean
|
||||
}
|
||||
|
||||
export interface ListsLinksStatuses {
|
||||
staff: boolean
|
||||
friends: boolean
|
||||
enemies: boolean
|
||||
}
|
||||
|
||||
export interface Bars {
|
||||
energy: Energy
|
||||
nerve: Nerve
|
||||
happy: Happy
|
||||
life: Life
|
||||
chain: Chain
|
||||
}
|
||||
|
||||
export interface Energy {
|
||||
name: string
|
||||
timestampToUpdate: number
|
||||
timeToUpdate: number
|
||||
statstamp: number
|
||||
amount: number
|
||||
max: number
|
||||
step: number
|
||||
}
|
||||
|
||||
export interface Nerve {
|
||||
name: string
|
||||
timestampToUpdate: number
|
||||
timeToUpdate: number
|
||||
statstamp: number
|
||||
amount: number
|
||||
max: number
|
||||
step: number
|
||||
}
|
||||
|
||||
export interface Happy {
|
||||
name: string
|
||||
timestampToUpdate: number
|
||||
timeToUpdate: number
|
||||
statstamp: number
|
||||
amount: number
|
||||
max: number
|
||||
step: number
|
||||
}
|
||||
|
||||
export interface Life {
|
||||
name: string
|
||||
timestampToUpdate: number
|
||||
timeToUpdate: any
|
||||
statstamp: number
|
||||
amount: number
|
||||
max: number
|
||||
step: number
|
||||
}
|
||||
|
||||
export interface Chain {
|
||||
name: string
|
||||
timestampToUpdate: number
|
||||
timeToUpdate: number
|
||||
amount: number
|
||||
max: number
|
||||
step: number
|
||||
coolDown: number
|
||||
endCoolDownTimestamp: number
|
||||
bonuses: number
|
||||
link: string
|
||||
}
|
||||
|
||||
export interface Account {
|
||||
messages: Messages
|
||||
events: Events
|
||||
awards: Awards
|
||||
}
|
||||
|
||||
export interface Messages {
|
||||
linkOrder: number
|
||||
name: string
|
||||
amount: number
|
||||
link: string
|
||||
icon: string
|
||||
highlightStatus: boolean
|
||||
status: any
|
||||
isMobileOnly: boolean
|
||||
}
|
||||
|
||||
export interface Events {
|
||||
linkOrder: number
|
||||
name: string
|
||||
amount: number
|
||||
link: string
|
||||
icon: string
|
||||
highlightStatus: boolean
|
||||
status: string
|
||||
isMobileOnly: boolean
|
||||
}
|
||||
|
||||
export interface Awards {
|
||||
linkOrder: number
|
||||
name: string
|
||||
amount: number
|
||||
link: string
|
||||
icon: string
|
||||
highlightStatus: boolean
|
||||
status: any
|
||||
isMobileOnly: boolean
|
||||
}
|
||||
|
||||
export interface Areas {
|
||||
messages: Messages2
|
||||
events: Events2
|
||||
awards: Awards2
|
||||
gym: Gym
|
||||
crimes: Crimes
|
||||
items: Items
|
||||
city: City
|
||||
missions: Missions
|
||||
casino: Casino
|
||||
calendar: Calendar
|
||||
education: Education2
|
||||
properties: Properties
|
||||
friends_list: FriendsList
|
||||
enemies_list: EnemiesList
|
||||
elimination: Elimination
|
||||
community_events: CommunityEvents
|
||||
}
|
||||
|
||||
export interface Messages2 {
|
||||
linkOrder: number
|
||||
name: string
|
||||
amount: number
|
||||
link: string
|
||||
icon: string
|
||||
highlightStatus: boolean
|
||||
status: any
|
||||
isMobileOnly: boolean
|
||||
}
|
||||
|
||||
export interface Events2 {
|
||||
linkOrder: number
|
||||
name: string
|
||||
amount: number
|
||||
link: string
|
||||
icon: string
|
||||
highlightStatus: boolean
|
||||
status: string
|
||||
isMobileOnly: boolean
|
||||
}
|
||||
|
||||
export interface Awards2 {
|
||||
linkOrder: number
|
||||
name: string
|
||||
amount: number
|
||||
link: string
|
||||
icon: string
|
||||
highlightStatus: boolean
|
||||
status: any
|
||||
isMobileOnly: boolean
|
||||
}
|
||||
|
||||
export interface Gym {
|
||||
linkOrder: number
|
||||
name: string
|
||||
shortName: any
|
||||
link: string
|
||||
icon: string
|
||||
styleStatus: any
|
||||
highlightStatus: boolean
|
||||
status: any
|
||||
activeStatusUrlRegex: any
|
||||
amount: any
|
||||
isMobileOnly: boolean
|
||||
}
|
||||
|
||||
export interface Crimes {
|
||||
linkOrder: number
|
||||
name: string
|
||||
shortName: any
|
||||
link: string
|
||||
icon: string
|
||||
styleStatus: any
|
||||
highlightStatus: boolean
|
||||
status: any
|
||||
activeStatusUrlRegex: any
|
||||
amount: any
|
||||
isMobileOnly: boolean
|
||||
}
|
||||
|
||||
export interface Items {
|
||||
linkOrder: number
|
||||
name: string
|
||||
shortName: any
|
||||
link: string
|
||||
icon: string
|
||||
styleStatus: any
|
||||
highlightStatus: boolean
|
||||
status: any
|
||||
activeStatusUrlRegex: any
|
||||
amount: any
|
||||
isMobileOnly: boolean
|
||||
}
|
||||
|
||||
export interface City {
|
||||
linkOrder: number
|
||||
name: string
|
||||
shortName: any
|
||||
link: string
|
||||
icon: string
|
||||
styleStatus: any
|
||||
highlightStatus: boolean
|
||||
status: any
|
||||
activeStatusUrlRegex: any
|
||||
amount: any
|
||||
isMobileOnly: boolean
|
||||
}
|
||||
|
||||
export interface Missions {
|
||||
linkOrder: number
|
||||
name: string
|
||||
shortName: any
|
||||
link: string
|
||||
icon: string
|
||||
styleStatus: any
|
||||
highlightStatus: boolean
|
||||
status: any
|
||||
activeStatusUrlRegex: any
|
||||
amount: any
|
||||
isMobileOnly: boolean
|
||||
}
|
||||
|
||||
export interface Casino {
|
||||
linkOrder: number
|
||||
name: string
|
||||
shortName: any
|
||||
link: string
|
||||
icon: string
|
||||
styleStatus: any
|
||||
highlightStatus: boolean
|
||||
status: any
|
||||
activeStatusUrlRegex: any
|
||||
amount: any
|
||||
isMobileOnly: boolean
|
||||
}
|
||||
|
||||
export interface Calendar {
|
||||
linkOrder: number
|
||||
name: string
|
||||
shortName: string
|
||||
link: string
|
||||
icon: string
|
||||
styleStatus: any
|
||||
highlightStatus: boolean
|
||||
status: any
|
||||
activeStatusUrlRegex: any
|
||||
amount: any
|
||||
isMobileOnly: boolean
|
||||
}
|
||||
|
||||
export interface Education2 {
|
||||
linkOrder: number
|
||||
name: string
|
||||
shortName: string
|
||||
link: string
|
||||
icon: string
|
||||
styleStatus: any
|
||||
highlightStatus: boolean
|
||||
status: any
|
||||
activeStatusUrlRegex: any
|
||||
amount: any
|
||||
isMobileOnly: boolean
|
||||
}
|
||||
|
||||
export interface Properties {
|
||||
linkOrder: number
|
||||
name: string
|
||||
shortName: string
|
||||
link: string
|
||||
icon: string
|
||||
styleStatus: any
|
||||
highlightStatus: boolean
|
||||
status: any
|
||||
activeStatusUrlRegex: any
|
||||
amount: any
|
||||
isMobileOnly: boolean
|
||||
}
|
||||
|
||||
export interface FriendsList {
|
||||
linkOrder: number
|
||||
name: string
|
||||
icon: string
|
||||
link: string
|
||||
elements: any
|
||||
status: any
|
||||
isMobileOnly: boolean
|
||||
}
|
||||
|
||||
export interface EnemiesList {
|
||||
linkOrder: number
|
||||
name: string
|
||||
icon: string
|
||||
link: string
|
||||
elements: Element[]
|
||||
status: any
|
||||
isMobileOnly: boolean
|
||||
}
|
||||
|
||||
export interface Element {
|
||||
name: string
|
||||
link: string
|
||||
status: string
|
||||
lastAction: number
|
||||
}
|
||||
|
||||
export interface Elimination {
|
||||
linkOrder: number
|
||||
name: string
|
||||
shortName: string
|
||||
link: string
|
||||
icon: string
|
||||
styleStatus: string
|
||||
highlightStatus: boolean
|
||||
status: any
|
||||
activeStatusUrlRegex: any
|
||||
amount: any
|
||||
isMobileOnly: boolean
|
||||
}
|
||||
|
||||
export interface CommunityEvents {
|
||||
linkOrder: number
|
||||
name: string
|
||||
shortName: string
|
||||
link: string
|
||||
icon: string
|
||||
styleStatus: string
|
||||
highlightStatus: boolean
|
||||
status: any
|
||||
activeStatusUrlRegex: any
|
||||
amount: any
|
||||
isMobileOnly: boolean
|
||||
}
|
||||
|
||||
export interface Lists {
|
||||
company_list: CompanyList
|
||||
faction_list: FactionList
|
||||
friends_list: FriendsList2
|
||||
enemies_list: EnemiesList2
|
||||
}
|
||||
|
||||
export interface CompanyList {
|
||||
linkOrder: number
|
||||
name: string
|
||||
icon: string
|
||||
link: string
|
||||
elements: Element2[]
|
||||
status: any
|
||||
isMobileOnly: boolean
|
||||
}
|
||||
|
||||
export interface Element2 {
|
||||
name: string
|
||||
link: string
|
||||
status: string
|
||||
lastAction: number
|
||||
}
|
||||
|
||||
export interface FactionList {
|
||||
linkOrder: number
|
||||
name: string
|
||||
icon: string
|
||||
link: string
|
||||
elements: Element3[]
|
||||
status: any
|
||||
isMobileOnly: boolean
|
||||
}
|
||||
|
||||
export interface Element3 {
|
||||
name: string
|
||||
link: string
|
||||
status: string
|
||||
lastAction: number
|
||||
}
|
||||
|
||||
export interface FriendsList2 {
|
||||
linkOrder: number
|
||||
name: string
|
||||
icon: string
|
||||
link: string
|
||||
elements: any
|
||||
status: any
|
||||
isMobileOnly: boolean
|
||||
}
|
||||
|
||||
export interface EnemiesList2 {
|
||||
linkOrder: number
|
||||
name: string
|
||||
icon: string
|
||||
link: string
|
||||
elements: Element4[]
|
||||
status: any
|
||||
isMobileOnly: boolean
|
||||
}
|
||||
|
||||
export interface Element4 {
|
||||
name: string
|
||||
link: string
|
||||
status: string
|
||||
lastAction: number
|
||||
}
|
||||
|
||||
export interface Footer {
|
||||
serverName: string
|
||||
dayTextualFormat: string
|
||||
dateFormat: string
|
||||
dayTimeFormat: string
|
||||
}
|
||||
@ -32,7 +32,6 @@ export interface MiniProfile {
|
||||
},
|
||||
sendMoneyWarning: string,
|
||||
playerName: string,
|
||||
userID: number,
|
||||
};
|
||||
userStatus: {
|
||||
status: {
|
||||
|
||||
@ -1,116 +0,0 @@
|
||||
import IFeature from "./IFeature"
|
||||
import { Container } from "../container/Container"
|
||||
import ClassName, { GetClassName } from "../container/ClassName"
|
||||
import Atk from "../feature/Atk"
|
||||
import { Injectable } from "../container/Injectable"
|
||||
import Logger from "../class/Logger"
|
||||
import BuyBeerHelper from "../feature/BuyBeerHelper"
|
||||
import SidebarHelper from "../feature/SidebarHelper"
|
||||
import TravelItem from "../feature/TravelItem"
|
||||
import TravelHelper from "../feature/TravelHelper"
|
||||
import CompanyHelper from "../feature/CompanyHelper"
|
||||
import IconHelper from "../feature/IconHelper"
|
||||
import MapItem from "../feature/MapItem"
|
||||
import PTHelper from "../class/action/PTHelper"
|
||||
import StackHelper from "../feature/StackHelper"
|
||||
import XZMZ from "../class/action/XZMZ"
|
||||
import BeerShopModifier from "../feature/BeerShopModifier"
|
||||
import CrimePageModifier from "../feature/CrimePageModifier"
|
||||
import ProfileHelper from "../class/action/ProfileHelper"
|
||||
import ChristmasTown from "../feature/ChristmasTown"
|
||||
import LotteryHelper from "../feature/LotteryHelper"
|
||||
import SlotsHelper from "../class/action/SlotsHelper"
|
||||
import SearchHelper from "../class/action/SearchHelper"
|
||||
import { WHIntervalLoader } from "../monitor/WHIntervalLoader"
|
||||
import IFeatureResult from "./IFeatureResult"
|
||||
import FeatureStatus from "./const/FeatureStatus"
|
||||
import globVars from "../globVars";
|
||||
|
||||
@ClassName('FeatureMan')
|
||||
@Injectable()
|
||||
export default class FeatureMan {
|
||||
private readonly features: ClassType<IFeature>[] = [
|
||||
/* 通配 */
|
||||
BuyBeerHelper,
|
||||
SidebarHelper,
|
||||
TravelItem,
|
||||
CompanyHelper,
|
||||
IconHelper,
|
||||
WHIntervalLoader,
|
||||
/* 页面匹配 */
|
||||
Atk,
|
||||
TravelHelper,
|
||||
MapItem,
|
||||
PTHelper,
|
||||
StackHelper,
|
||||
XZMZ,
|
||||
BeerShopModifier,
|
||||
CrimePageModifier,
|
||||
ProfileHelper,
|
||||
ChristmasTown,
|
||||
LotteryHelper,
|
||||
SlotsHelper,
|
||||
SearchHelper,
|
||||
]
|
||||
private result: IFeatureResult[] = null
|
||||
private readonly logger = Logger.factory(FeatureMan)
|
||||
|
||||
async fStart() {
|
||||
const manResult: IFeatureResult[] = []
|
||||
for (let i = 0; i < this.features.length; i++) {
|
||||
const className = GetClassName(this.features[i])
|
||||
const instant = Container.factory(this.features[i])
|
||||
const description = instant.description()
|
||||
const urlPath = location.href.replace(/^.+\/\/.+?\/(?!\/)?/, '/')
|
||||
let status = FeatureStatus.ADDED
|
||||
let isMatch = false
|
||||
const urlIncludes = instant.urlIncludes()
|
||||
let load = 0
|
||||
for (let j = 0; j < urlIncludes.length; j++) {
|
||||
if (urlIncludes[j].test(urlPath)) {
|
||||
isMatch = true
|
||||
const urlExcludes = instant.urlExcludes() ?? []
|
||||
for (let k = 0; k < urlExcludes.length; k++) {
|
||||
if (urlExcludes[k].test(urlPath)) {
|
||||
isMatch = false
|
||||
status = FeatureStatus.EXCLUDED
|
||||
break
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
if (isMatch) {
|
||||
try {
|
||||
const start = performance.now()
|
||||
let run = instant.iStart()
|
||||
if (run instanceof Promise) {
|
||||
run = await run
|
||||
}
|
||||
status = FeatureStatus.RUNNING
|
||||
load = ((performance.now() - start) * 10 | 0) / 10
|
||||
} catch (e) {
|
||||
this.logger.error(e.message)
|
||||
status = FeatureStatus.EXCEPTION
|
||||
}
|
||||
}
|
||||
// else {
|
||||
// status = FeatureStatus.EXCLUDED
|
||||
// }
|
||||
const result = {
|
||||
desc: description,
|
||||
status: status,
|
||||
clazz: className,
|
||||
load
|
||||
}
|
||||
manResult.push(result)
|
||||
globVars.featureStatus.push(result)
|
||||
}
|
||||
this.result = manResult
|
||||
}
|
||||
|
||||
printTable() {
|
||||
console.table(this.result)
|
||||
this.logger.info(this.result)
|
||||
}
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
export default interface IFeature {
|
||||
iStart(): void | Promise<void>
|
||||
|
||||
/**
|
||||
* 包含url、不能返回null
|
||||
*/
|
||||
urlIncludes(): RegExp[]
|
||||
|
||||
/**
|
||||
* 排除url
|
||||
*/
|
||||
urlExcludes(): RegExp[]
|
||||
|
||||
description(): string
|
||||
}
|
||||
@ -1,8 +0,0 @@
|
||||
import FeatureStatus from "./const/FeatureStatus";
|
||||
|
||||
export default interface IFeatureResult {
|
||||
desc: string
|
||||
status: FeatureStatus
|
||||
clazz: string
|
||||
load: number
|
||||
}
|
||||
@ -1,8 +0,0 @@
|
||||
enum FeatureStatus {
|
||||
ADDED = '已添加',
|
||||
RUNNING = '正常',
|
||||
EXCLUDED = '页面排除',
|
||||
EXCEPTION = '异常',
|
||||
}
|
||||
|
||||
export default FeatureStatus
|
||||
@ -1,47 +0,0 @@
|
||||
import IntervalType from "./WHIntervalLoader";
|
||||
import ClassName from "../container/ClassName";
|
||||
import IntervalSwitch from "./IntervalSwitch";
|
||||
import { SWITCHER } from "./SWITCHER";
|
||||
import getSidebarData from "../func/utils/getSidebarData";
|
||||
import { Container } from "../container/Container";
|
||||
import MsgWrapper from "../class/utils/MsgWrapper";
|
||||
import LocalConfigWrapper from "../class/LocalConfigWrapper";
|
||||
|
||||
@ClassName('DrugCDMonitor')
|
||||
class DrugCDMonitor implements IntervalType {
|
||||
private id: number = null
|
||||
private ms: number
|
||||
private readonly msgWrapper = Container.factory(MsgWrapper)
|
||||
|
||||
getId(): number {
|
||||
return this.id
|
||||
}
|
||||
|
||||
getMs(): number {
|
||||
return this.ms
|
||||
}
|
||||
|
||||
handler(): void {
|
||||
const data = getSidebarData()
|
||||
if (data?.statusIcons?.icons?.drug_cooldown?.timerExpiresAt * 1000 < Date.now()) {
|
||||
this.msgWrapper.create('警告: 药CD停转', { sysNotify: true })
|
||||
}
|
||||
}
|
||||
|
||||
setMs(ms: number): void {
|
||||
this.ms = ms
|
||||
}
|
||||
|
||||
switcher(s: IntervalSwitch): void {
|
||||
SWITCHER(this, DrugCDMonitor, s)
|
||||
}
|
||||
|
||||
setId(id: number): void {
|
||||
this.id = id
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const drugCDMonitor = new DrugCDMonitor()
|
||||
drugCDMonitor.setMs(Container.factory(LocalConfigWrapper).config.drugCDMonitorInterval)
|
||||
export default drugCDMonitor
|
||||
@ -1,5 +0,0 @@
|
||||
enum IntervalSwitch {
|
||||
ON = 9, OFF = 10
|
||||
}
|
||||
|
||||
export default IntervalSwitch
|
||||
@ -1,24 +0,0 @@
|
||||
import { GetClassName } from "../container/ClassName";
|
||||
import IntervalType from "./WHIntervalLoader";
|
||||
import IntervalSwitch from "./IntervalSwitch";
|
||||
|
||||
export function SWITCHER(self: IntervalType, clazz: new () => IntervalType, s: IntervalSwitch) {
|
||||
if (self.getMs() === null) {
|
||||
throw new Error('循环时间为空')
|
||||
}
|
||||
switch (s) {
|
||||
case IntervalSwitch.ON:
|
||||
if (self.getId()) {
|
||||
throw new TypeError(GetClassName(clazz) + ' 正在启用')
|
||||
}
|
||||
self.setId(window.setInterval(() => self.handler(), self.getMs()))
|
||||
break
|
||||
case IntervalSwitch.OFF:
|
||||
if (self.getId()) {
|
||||
window.clearInterval(self.getId())
|
||||
self.setId(null)
|
||||
} else {
|
||||
throw new TypeError(GetClassName(clazz) + ' 未启用')
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,57 +0,0 @@
|
||||
/**
|
||||
* 监控模块的循环处理部分
|
||||
*/
|
||||
|
||||
import drugCDMonitor from "./DrugCDMonitor";
|
||||
import { Injectable } from "../container/Injectable";
|
||||
import ClassName from "../container/ClassName";
|
||||
import LocalConfigWrapper from "../class/LocalConfigWrapper";
|
||||
import IntervalSwitch from "./IntervalSwitch";
|
||||
import IFeature from "../man/IFeature";
|
||||
import ATK_PAGE_REG from "../feature/url/ATK_PAGE_REG";
|
||||
import ALL_PAGE_REG from "../feature/url/ALL_PAGE_REG";
|
||||
|
||||
export default interface IntervalType {
|
||||
handler: () => void
|
||||
switcher: (s: IntervalSwitch) => void
|
||||
getId: () => number
|
||||
setId: (id: number) => void
|
||||
getMs: () => number
|
||||
setMs: (ms: number) => void
|
||||
}
|
||||
|
||||
const intervalUnits: { [key: string]: IntervalType } = {
|
||||
drugCDMonitor,
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
@ClassName('WHIntervalLoader')
|
||||
export class WHIntervalLoader implements IFeature {
|
||||
description(): string {
|
||||
return "新监控模块";
|
||||
}
|
||||
|
||||
iStart(): void | Promise<void> {
|
||||
this.init()
|
||||
}
|
||||
|
||||
urlExcludes(): RegExp[] {
|
||||
return [ATK_PAGE_REG];
|
||||
}
|
||||
|
||||
urlIncludes(): RegExp[] {
|
||||
return [ALL_PAGE_REG];
|
||||
}
|
||||
|
||||
constructor(
|
||||
private readonly localConfigWrapper: LocalConfigWrapper,
|
||||
) {
|
||||
}
|
||||
|
||||
init() {
|
||||
const list = this.localConfigWrapper.config.monitorOn
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
intervalUnits[list[i]].switcher(IntervalSwitch.ON)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4,6 +4,7 @@ import ClassName from "../container/ClassName";
|
||||
import Debug from "../class/provider/Debug";
|
||||
import "reflect-metadata";
|
||||
import { Injectable } from "../container/Injectable";
|
||||
import { ButtonHandler } from "../class/provider/ButtonHandler";
|
||||
import { Container } from "../container/Container";
|
||||
import NetHighLvlWrapper from "../class/utils/NetHighLvlWrapper";
|
||||
import Logger from "../class/Logger";
|
||||
@ -11,6 +12,7 @@ import QuickGymTrain from "../class/action/QuickGymTrain";
|
||||
import LocalConfigWrapper from "../class/LocalConfigWrapper";
|
||||
import { ElMessage } from "element-plus";
|
||||
|
||||
@ButtonHandler
|
||||
@ClassName('Test')
|
||||
@Injectable()
|
||||
class Test {
|
||||
|
||||
@ -1,262 +0,0 @@
|
||||
<script lang="ts" setup>
|
||||
import { inject, onMounted, ref } from "vue"
|
||||
import { LocalConfigWrapperKey } from "../ts/class/LocalConfigWrapper"
|
||||
import { ElMessage } from "element-plus"
|
||||
import { fetchYata, purge, YataApiDataWrap } from "../ts/func/module/fetchYata"
|
||||
import { LoggerKey } from "../ts/class/Logger"
|
||||
import toThousands from "../ts/func/utils/toThousands"
|
||||
import { Download, QuestionFilled, Refresh, Search } from "@element-plus/icons-vue"
|
||||
import { timePastFormat } from "../ts/func/utils/timePastFormat"
|
||||
import { convertToCSV } from "../ts/func/utils/convert2Csv"
|
||||
|
||||
const isMiniProfOn = ref<boolean>(false)
|
||||
const isProfOn = ref<boolean>(false)
|
||||
const apikey = ref<string>('')
|
||||
const targetId = ref<string>('')
|
||||
const tableData = ref<Partial<YataApiDataWrap>[]>([])
|
||||
const isLoading = ref(false)
|
||||
const idKey: { [key: string]: number } = {}
|
||||
const buildType = { Offensive: '攻击型', Defensive: '防御型', Balanced: '平衡型' }
|
||||
|
||||
const localConfigWrapper = inject(LocalConfigWrapperKey)
|
||||
const logger = inject(LoggerKey)
|
||||
|
||||
const saveApikey = () => {
|
||||
if (!apikey.value) {
|
||||
ElMessage({
|
||||
message: 'apikey保存时输入为空',
|
||||
type: 'error',
|
||||
showClose: true
|
||||
})
|
||||
throw new TypeError('apikey保存时输入为空')
|
||||
}
|
||||
localStorage.setItem('APIKey', apikey.value)
|
||||
ElMessage.success({
|
||||
message: 'APIKey设置成功',
|
||||
showClose: true
|
||||
})
|
||||
}
|
||||
const onMiniProfSwitchChange = () => localConfigWrapper.config.isBSEstMiniProfOn = isMiniProfOn.value
|
||||
const onProfSwitchChange = () => localConfigWrapper.config.isBSEstProfOn = isProfOn.value
|
||||
const doRequest = async () => {
|
||||
if (!apikey.value) {
|
||||
ElMessage.warning({
|
||||
message: '未设置APIKey',
|
||||
showClose: true
|
||||
})
|
||||
return
|
||||
}
|
||||
isLoading.value = true
|
||||
for (let i = 0; i < tableData.value.length; i++) {
|
||||
const item = tableData.value[i]
|
||||
if (!item.total) {
|
||||
let est: YataApiDataWrap
|
||||
try {
|
||||
est = await fetchYata(parseInt(item.id), apikey.value)
|
||||
} catch (e) {
|
||||
ElMessage.error({
|
||||
message: e.message,
|
||||
showClose: true
|
||||
})
|
||||
logger.error(e.stack)
|
||||
continue
|
||||
}
|
||||
item.total = est.total
|
||||
item.score = est.score
|
||||
item.type = est.type
|
||||
item.skewness = est.skewness
|
||||
item.timestamp = est.timestamp
|
||||
item.version = est.version
|
||||
item.isCache = est.isCache
|
||||
}
|
||||
}
|
||||
isLoading.value = false
|
||||
}
|
||||
/**
|
||||
* 查询列表中添加新的id
|
||||
* @param _id
|
||||
*/
|
||||
const add = (_id: string) => {
|
||||
const id = parseInt(_id)
|
||||
if (id) {
|
||||
// 重复id判断
|
||||
if (!idKey[_id]) {
|
||||
tableData.value.push({ id: _id })
|
||||
idKey[_id] = 1
|
||||
targetId.value = ''
|
||||
} else {
|
||||
ElMessage.warning({
|
||||
message: '重复的id',
|
||||
showClose: true
|
||||
})
|
||||
}
|
||||
} else {
|
||||
ElMessage.error({
|
||||
message: 'id有误',
|
||||
showClose: true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空查询列表和唯一id表
|
||||
*/
|
||||
const emptyList = () => {
|
||||
tableData.value = []
|
||||
const keys = Object.keys(idKey)
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
const key = keys[i]
|
||||
idKey[key] = 0
|
||||
}
|
||||
}
|
||||
|
||||
const purgeCache = () => {
|
||||
purge()
|
||||
ElMessage.warning({
|
||||
message: '本地缓存已清除',
|
||||
showClose: true
|
||||
})
|
||||
}
|
||||
|
||||
const exportCsv = () => {
|
||||
const exportList: any[] = [{
|
||||
id: "ID", total: "BS", score: "评分", type: "风格", skewness: "偏差", timestamp: "时间戳"
|
||||
}]
|
||||
for (let i = 0; i < tableData.value.length; i++) {
|
||||
const item = tableData.value[i]
|
||||
const newItem = {
|
||||
id: item.id ?? '-1',
|
||||
total: item.total ?? null,
|
||||
score: item.score ?? null,
|
||||
type: buildType[item.type] ?? null,
|
||||
skewness: item.skewness ?? null,
|
||||
timestamp: item.timestamp ?? null,
|
||||
// isCache: item.isCache ?? null,
|
||||
// version: item.version ?? null
|
||||
}
|
||||
exportList.push(newItem)
|
||||
}
|
||||
const csvContent = convertToCSV(exportList)
|
||||
let url: string
|
||||
let isBlob = false
|
||||
const UTF8 = "\uFEFF"
|
||||
if (window.Blob && window.URL && window.URL.createObjectURL) {
|
||||
const csvData = new window.Blob([UTF8 + csvContent], {
|
||||
type: 'text/csv'
|
||||
})
|
||||
url = window.URL.createObjectURL(csvData)
|
||||
isBlob = true
|
||||
} else {
|
||||
url = window.encodeURI(csvContent)
|
||||
}
|
||||
window.location.href = isBlob ? url : 'data:text/csv;charset=utf-8,' + UTF8 + url
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// APIKey
|
||||
const key = localStorage.getItem('APIKey')
|
||||
if (!key) {
|
||||
ElMessage.error({
|
||||
message: '尚未配置APIKey',
|
||||
showClose: true
|
||||
})
|
||||
} else {
|
||||
apikey.value = key
|
||||
}
|
||||
|
||||
// 获取配置
|
||||
isMiniProfOn.value = localConfigWrapper.config.isBSEstMiniProfOn
|
||||
isProfOn.value = localConfigWrapper.config.isBSEstProfOn
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-space :fill="true">
|
||||
<el-card shadow="never">
|
||||
<template #header>设置</template>
|
||||
<el-form label-width="auto" @submit.prevent>
|
||||
<el-form-item label="MINI资料卡中显示">
|
||||
<el-switch v-model="isMiniProfOn" @change="onMiniProfSwitchChange"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="个人资料中显示">
|
||||
<el-switch v-model="isProfOn" @change="onProfSwitchChange"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="API KEY">
|
||||
<el-input v-model="apikey">
|
||||
<template #append>
|
||||
<el-button :loading="isLoading" @click="saveApikey">保存</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-popconfirm cancel-button-text="取消" confirm-button-text="确定" title="确定操作" @confirm="purgeCache">
|
||||
<template #reference>
|
||||
<el-button type="danger">清空缓存</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
<el-card shadow="never">
|
||||
<template #header>使用</template>
|
||||
<p class="mt-4">BS估算功能使用了
|
||||
<el-link href="https://yata.yt/api/v1/" target="_blank">yata</el-link>
|
||||
神经网络模型接口,需要提供torn apikey (上面输入)
|
||||
</p>
|
||||
<p class="mt-4">本插件缓存机制:1天</p>
|
||||
<el-form label-width="auto" @submit="add(targetId)" @submit.prevent>
|
||||
<el-form-item label="目标数字ID">
|
||||
<el-input v-model="targetId" clearable/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button :loading="isLoading" type="primary" @click="add(targetId)">添加</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
<el-card shadow="never">
|
||||
<template #header>结果</template>
|
||||
<el-button-group>
|
||||
<el-button :icon="Search" :loading="isLoading" type="primary" @click="doRequest">估算</el-button>
|
||||
<el-button :icon="Refresh" :loading="isLoading" @click="emptyList">清空</el-button>
|
||||
<el-button :icon="Download" :loading="isLoading" @click="exportCsv">导出CSV</el-button>
|
||||
</el-button-group>
|
||||
<el-row>
|
||||
<el-col :span="23">
|
||||
<el-table :data="tableData" empty-text=" ">
|
||||
<el-table-column label="ID" prop="id"/>
|
||||
<el-table-column label="BS">
|
||||
<template #default="scope">
|
||||
{{ toThousands(scope.row.total) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="评分" prop="score"/>
|
||||
<el-table-column label="风格">
|
||||
<template #default="scope">
|
||||
{{ buildType[scope.row.type] }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column>
|
||||
<template #header>
|
||||
<el-tooltip content="越低越准" effect="light" placement="top">
|
||||
<span>偏差<el-icon><QuestionFilled/></el-icon></span>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
<template #default="scope">
|
||||
{{ scope.row.skewness }}%
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="时间">
|
||||
<template #default="scope">
|
||||
{{ timePastFormat(Date.now() - scope.row.timestamp * 1000) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</el-space>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@ -1,54 +0,0 @@
|
||||
<template>
|
||||
<el-card shadow="never">
|
||||
<el-row>
|
||||
<el-col span="24">
|
||||
<el-button @click="refresh">刷新</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col span="24">
|
||||
<el-link href="https://gitlab.com/JJins/wuhu-torn-helper/-/raw/dev/CHANGELOG.md" target="_blank">
|
||||
https://gitlab.com/JJins/wuhu-torn-helper/-/raw/dev/CHANGELOG.md
|
||||
</el-link>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col span="24">
|
||||
<div v-loading="!respond" class="wh-change-log-view-render" v-html="html"></div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref } from "vue";
|
||||
import CommonUtils from "../ts/class/utils/CommonUtils";
|
||||
import { Container } from "../ts/container/Container";
|
||||
import MDUtils from "../ts/class/utils/MDUtils";
|
||||
|
||||
const mdUtils = Container.factory(MDUtils)
|
||||
|
||||
const respond = ref('')
|
||||
const html = ref('')
|
||||
|
||||
const refresh = async () => {
|
||||
respond.value = ''
|
||||
html.value = ''
|
||||
try {
|
||||
respond.value = await CommonUtils.COFetch('https://gitlab.com/JJins/wuhu-torn-helper/-/raw/dev/CHANGELOG.md?' + performance.now())
|
||||
html.value = mdUtils.parse(respond.value).innerHTML
|
||||
} catch (e) {
|
||||
html.value = '错误: ' + e.message
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
refresh()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.wh-change-log-view-render h2, .wh-change-log-view-render h3, .wh-change-log-view-render h4 {
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
@ -124,13 +124,6 @@ onMounted(() => {
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-button-group>
|
||||
<el-button type="primary" @click="()=>inputMoney='1000000'">1m</el-button>
|
||||
<el-button type="primary" @click="()=>inputMoney='2000000'">2m</el-button>
|
||||
<el-button type="primary" @click="()=>inputMoney='5000000'">5m</el-button>
|
||||
<el-button type="primary" @click="()=>inputMoney='10000000'">10m</el-button>
|
||||
<el-button type="primary" @click="()=>inputMoney='20000000'">20m</el-button>
|
||||
</el-button-group>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
<script lang="ts" setup>
|
||||
import { inject, onMounted, Ref, ref } from "vue"
|
||||
import { LoggerKey } from "../ts/class/Logger"
|
||||
import { inject, onMounted, Ref, ref } from "vue";
|
||||
import { LoggerKey } from "../ts/class/Logger";
|
||||
|
||||
const logger = inject(LoggerKey)
|
||||
const loading = ref(true)
|
||||
const doFetch = () => fetch(window.addRFC("https://www.torn.com/page.php?sid=eventsData"), {
|
||||
const logger = inject(LoggerKey);
|
||||
const loading = ref(true);
|
||||
const doFetch = () => fetch("https://www.torn.com/page.php", {
|
||||
"headers": {
|
||||
"accept": "*/*",
|
||||
"sec-ch-ua-mobile": "?0",
|
||||
@ -24,7 +24,7 @@ const doFetch = () => fetch(window.addRFC("https://www.torn.com/page.php?sid=eve
|
||||
"mode": "cors",
|
||||
"credentials": "include"
|
||||
});
|
||||
const events: Ref<{ ID: string, message: string, time: string, date: string, isNew: boolean, ts: number }[]> = ref([]);
|
||||
const events: Ref<{ ID: string, message: string, time: number, isNew: boolean }[]> = ref([]);
|
||||
const DateTimeFormatter = (ts: number) => {
|
||||
let date = new Date(ts);
|
||||
return date.toLocaleDateString() + ' ' + date.toLocaleTimeString();
|
||||
@ -36,26 +36,11 @@ const loadData = async () => {
|
||||
try {
|
||||
res = await (await doFetch()).json();
|
||||
if (res.success) {
|
||||
events.value = res.list;
|
||||
let newEventsAmount = res['newEventsAmount']
|
||||
for (let i = 0; i < res.list.length; i++) {
|
||||
if (i < newEventsAmount) {
|
||||
events.value[i].isNew = true
|
||||
events.value = res.events;
|
||||
if (res['newEventsAmount']) {
|
||||
for (let i = 0; i < res['newEventsAmount']; i++) {
|
||||
events.value[i].isNew = true;
|
||||
}
|
||||
let date = new Date(0)
|
||||
try {
|
||||
let dateResponseSplit = events.value[i].date.split('/')
|
||||
let timeResponseSplit = events.value[i].time.split(':')
|
||||
date.setUTCDate(parseInt(dateResponseSplit[0]))
|
||||
date.setUTCMonth(parseInt(dateResponseSplit[1]) - 1)
|
||||
date.setUTCFullYear(2000 + parseInt(dateResponseSplit[2]))
|
||||
date.setUTCHours(parseInt(timeResponseSplit[0]))
|
||||
date.setUTCMinutes(parseInt(timeResponseSplit[1]))
|
||||
date.setUTCSeconds(parseInt(timeResponseSplit[2]))
|
||||
} catch (e) {
|
||||
logger.error('未能解析时间', e)
|
||||
}
|
||||
events.value[i].ts = date.getTime()
|
||||
}
|
||||
loading.value = false;
|
||||
}
|
||||
@ -72,7 +57,7 @@ onMounted(loadData);
|
||||
<el-divider/>
|
||||
<el-timeline v-if="!loading">
|
||||
<el-timeline-item v-for="ev in events" :color="ev.isNew?'#0bbd87':''"
|
||||
:timestamp="DateTimeFormatter(ev.ts)">
|
||||
:timestamp="DateTimeFormatter(ev.time*1000)">
|
||||
<span v-html="ev.message"></span>
|
||||
</el-timeline-item>
|
||||
</el-timeline>
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
<MoonNight/>
|
||||
</el-icon>
|
||||
</el-button>
|
||||
<el-button v-for="item in globVars.buttons" @click="item.func">{{ item.txt }}</el-button>
|
||||
<el-button v-for="item in _globVars.actionList" @click="item.func">{{ item.txt }}</el-button>
|
||||
<el-button v-if="editableTabs.length > 0" circle @click="showDrawer">
|
||||
<el-badge :value="editableTabs.length" type="primary">
|
||||
<el-icon>
|
||||
@ -22,159 +22,151 @@
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-dialog>
|
||||
<el-drawer v-model="expanded" :show-close="false" :size="isMobilePhone ? '85%' : '30%'" class="whDrawer"
|
||||
:with-header="false" direction="rtl">
|
||||
<el-card :body-style="{ 'padding': '0' }" class="innerCard" style="margin-bottom: 0.5em">
|
||||
<template #header>
|
||||
<div>快捷动作</div>
|
||||
</template>
|
||||
<el-menu :unique-opened="true">
|
||||
<el-sub-menu index="1">
|
||||
<template #title>
|
||||
<el-icon>✈️</el-icon>
|
||||
<span>起飞</span>
|
||||
</template>
|
||||
<el-sub-menu v-for="(item, i) in travelData" :index="'1-' + (i + 1)">
|
||||
<template #title>{{ item.cName }}</template>
|
||||
<el-menu-item :index="'1-' + (i + 1) + '1'" @click="travelConfirm(item.index, 0)">
|
||||
❌ 普通飞机
|
||||
</el-menu-item>
|
||||
<el-menu-item :index="'1-' + (i + 1) + '2'" @click="travelConfirm(item.index, 1)">
|
||||
✅ PI飞机
|
||||
</el-menu-item>
|
||||
<el-menu-item :index="'1-' + (i + 1) + '3'" @click="travelConfirm(item.index, 2)">
|
||||
👍 股票飞机
|
||||
</el-menu-item>
|
||||
<el-menu-item :index="'1-' + (i + 1) + '4'" @click="travelConfirm(item.index, 3)">
|
||||
🥵 商务飞机(机票或内衣店)
|
||||
</el-menu-item>
|
||||
</el-sub-menu>
|
||||
</el-sub-menu>
|
||||
<el-sub-menu index="2">
|
||||
<template #title>
|
||||
<el-icon>💪</el-icon>
|
||||
<span>锻炼</span>
|
||||
</template>
|
||||
<el-menu-item @click="quickGymTrain.doTrain(BATTLE_STAT.STR)">力量 STR
|
||||
</el-menu-item>
|
||||
<el-menu-item @click="quickGymTrain.doTrain(BATTLE_STAT.DEF)">防御 DEF
|
||||
</el-menu-item>
|
||||
<el-menu-item @click="quickGymTrain.doTrain(BATTLE_STAT.SPD)">速度 SPD
|
||||
</el-menu-item>
|
||||
<el-menu-item @click="quickGymTrain.doTrain(BATTLE_STAT.DEX)">闪避 DEX
|
||||
</el-menu-item>
|
||||
</el-sub-menu>
|
||||
<el-sub-menu index="3">
|
||||
<template #title>
|
||||
<el-icon>♻️</el-icon>
|
||||
<span>REFILL</span>
|
||||
</template>
|
||||
<el-menu-item @click="handleRefil('refillEnergy')">能量E
|
||||
</el-menu-item>
|
||||
<el-menu-item @click="handleRefil('refillNerve')">犯罪N
|
||||
</el-menu-item>
|
||||
<el-menu-item @click="handleRefil('refillCasinoTokens')">赌场代币
|
||||
</el-menu-item>
|
||||
</el-sub-menu>
|
||||
</el-menu>
|
||||
</el-card>
|
||||
<el-card :body-style="{ 'padding': '4px' }" class="innerCard">
|
||||
<template #header>
|
||||
<div>快捷功能</div>
|
||||
</template>
|
||||
<el-row style="display: flex;">
|
||||
<el-col v-for="item in menuItemList" class="featureCol">
|
||||
<el-card :body-class="'featureMenuBody'" class="featureMenu" shadow="never" @click="menuClick(item)">
|
||||
<div>
|
||||
<el-icon class="icon">{{ item.title.slice(0, 2) }}</el-icon>
|
||||
</div>
|
||||
<div class="title">
|
||||
<span>{{ item.title.slice(2, item.title.length) }}</span>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
<div style="margin-top: 1em; text-align: center">
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-tooltip content="更新?" placement="bottom-start">
|
||||
<el-button link @click="menuClick({ title: '关于助手', template: UpdateDate })">芜湖助手
|
||||
<el-icon>
|
||||
<Refresh/>
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
<el-drawer v-model="expanded" :show-close="false" :size="isMobilePhone ? '85%' : '30%'" direction="rtl">
|
||||
<template #header="{ close, titleId, titleClass }">
|
||||
<div :id="titleId" :class="titleClass">
|
||||
<el-tooltip content="更新?" placement="bottom-start">
|
||||
<el-button link @click="menuClick({ title: '更新', template: UpdateDate })">芜湖助手</el-button>
|
||||
</el-tooltip>
|
||||
<el-row>
|
||||
<el-tag size="small" type="info">{{
|
||||
globVars.version.startsWith('$') ? 'dev' : 'v' + globVars.version
|
||||
}}
|
||||
</el-tag>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-text v-if="_globVars.loadTime" size="small">
|
||||
{{ _globVars.loadTime }}ms
|
||||
</el-text>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-text size="small">
|
||||
2021-{{ new Date().getFullYear() }}
|
||||
</el-text>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</el-row>
|
||||
<el-row v-if="_globVars.loadTime">
|
||||
<el-text size="small">{{ _globVars.loadTime }}ms</el-text>
|
||||
</el-row>
|
||||
</div>
|
||||
<el-button type="danger" @click="close">
|
||||
<el-icon>
|
||||
<CircleCloseFilled/>
|
||||
</el-icon>
|
||||
关闭
|
||||
</el-button>
|
||||
</template>
|
||||
<el-menu :unique-opened="true">
|
||||
<el-sub-menu index="1">
|
||||
<template #title>
|
||||
<el-icon>✈️</el-icon>
|
||||
<span>起飞</span>
|
||||
</template>
|
||||
<el-sub-menu v-for="(item, i) in travelData" :index="'1-' + (i + 1)">
|
||||
<template #title>{{ item.cName }}</template>
|
||||
<el-menu-item :index="'1-' + (i + 1) + '1'" @click="travelConfirm(item.index, 0)">
|
||||
普通飞机
|
||||
</el-menu-item>
|
||||
<el-menu-item :index="'1-' + (i + 1) + '2'" @click="travelConfirm(item.index, 1)">
|
||||
PI飞机
|
||||
</el-menu-item>
|
||||
<el-menu-item :index="'1-' + (i + 1) + '3'" @click="travelConfirm(item.index, 2)">
|
||||
股票飞机
|
||||
</el-menu-item>
|
||||
<el-menu-item :index="'1-' + (i + 1) + '4'" @click="travelConfirm(item.index, 3)">
|
||||
商务飞机(机票或内衣店)
|
||||
</el-menu-item>
|
||||
</el-sub-menu>
|
||||
</el-sub-menu>
|
||||
<el-sub-menu index="2">
|
||||
<template #title>
|
||||
<el-icon>💪</el-icon>
|
||||
<span>锻炼</span>
|
||||
</template>
|
||||
<el-menu-item @click="quickGymTrain.doTrain(BATTLE_STAT.STR)">力量
|
||||
</el-menu-item>
|
||||
<el-menu-item @click="quickGymTrain.doTrain(BATTLE_STAT.DEF)">防御
|
||||
</el-menu-item>
|
||||
<el-menu-item @click="quickGymTrain.doTrain(BATTLE_STAT.SPD)">速度
|
||||
</el-menu-item>
|
||||
<el-menu-item @click="quickGymTrain.doTrain(BATTLE_STAT.DEX)">闪避
|
||||
</el-menu-item>
|
||||
</el-sub-menu>
|
||||
<el-sub-menu index="3">
|
||||
<template #title>
|
||||
<el-icon>🪓</el-icon>
|
||||
<span>老功能</span>
|
||||
</template>
|
||||
<el-menu-item index="3-1" @click="_adHelper">📜️ 传单助手</el-menu-item>
|
||||
<el-menu-item index="3-2" @click="_safeKeeper">🛡️ 守望者</el-menu-item>
|
||||
<el-menu-item index="3-3" @click="MUZHUANG">🌲 寻找木桩</el-menu-item>
|
||||
<el-menu-item index="3-4" @click="_setting">⚙️ 助手设置</el-menu-item>
|
||||
</el-sub-menu>
|
||||
<el-menu-item v-for="(item, i) in menuItemList" :index="(4 + i).toString()" @click="menuClick(item)">
|
||||
<el-icon>{{ item.title.slice(0, 2) }}</el-icon>
|
||||
<span>{{ item.title.slice(2, item.title.length) }}</span>
|
||||
</el-menu-item>
|
||||
</el-menu>
|
||||
</el-drawer>
|
||||
</el-config-provider>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
||||
import { CopyDocument, MoonNight, Refresh } from "@element-plus/icons-vue"
|
||||
import { ElMessage, ElMessageBox } from "element-plus"
|
||||
import { Component, inject, onMounted, ref, shallowRef, triggerRef } from 'vue'
|
||||
import { LoggerKey } from "../ts/class/Logger"
|
||||
import { QuickGymTrainKey } from "../ts/class/action/QuickGymTrain"
|
||||
import { QuickFlyBtnHandlerKey } from "../ts/class/handler/QuickFlyBtnHandler"
|
||||
import SettingsHandler from "../ts/class/handler/SettingsHandler"
|
||||
import { BATTLE_STAT } from "../ts/class/utils/NetHighLvlWrapper"
|
||||
import adHelper from "../ts/func/module/adHelper"
|
||||
import safeKeeper from "../ts/func/module/safeKeeper"
|
||||
import getSidebarData from "../ts/func/utils/getSidebarData"
|
||||
import useItem from "../ts/func/utils/useItem"
|
||||
import globVars from "../ts/globVars"
|
||||
import AutoLoginForm from "./AutoLoginForm.vue"
|
||||
import ChangeLogView from "./ChangeLogView.vue"
|
||||
import CityUItems from "./CityUItems.vue"
|
||||
import CompanyWithdraw from "./CompanyWithdraw.vue"
|
||||
import EventsViewer from "./EventsViewer.vue"
|
||||
import ForeignStock from "./ForeignStock.vue"
|
||||
import InventoryView from "./InventoryView.vue"
|
||||
import MarketHelper from "./MarketHelper.vue"
|
||||
import MonitorMgrView from "./MonitorMgrView.vue"
|
||||
import PTMarketView from "./PTMarketView.vue"
|
||||
import QuickCrime from "./QuickCrime.vue"
|
||||
import UpdateDate from "./UpdateScript.vue"
|
||||
import VirusProgramming from "./VirusProgramming.vue"
|
||||
import PropertyVault from "./PropertyVault.vue";
|
||||
import BSEstView from "./BSEstView.vue";
|
||||
import { CircleCloseFilled, CopyDocument, MoonNight } from "@element-plus/icons-vue";
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
import { Component, inject, onMounted, ref, shallowRef, triggerRef } from 'vue';
|
||||
import { LoggerKey } from "../ts/class/Logger";
|
||||
import { QuickGymTrainKey } from "../ts/class/action/QuickGymTrain";
|
||||
import { ChangeLogHandler } from "../ts/class/handler/ChangeLogHandler";
|
||||
import { QuickFlyBtnHandlerKey } from "../ts/class/handler/QuickFlyBtnHandler";
|
||||
import SettingsHandler from "../ts/class/handler/SettingsHandler";
|
||||
import { BATTLE_STAT } from "../ts/class/utils/NetHighLvlWrapper";
|
||||
import { Container } from "../ts/container/Container";
|
||||
import adHelper from "../ts/func/module/adHelper";
|
||||
import safeKeeper from "../ts/func/module/safeKeeper";
|
||||
import useItem from "../ts/func/utils/useItem";
|
||||
import globVars from "../ts/globVars";
|
||||
import AutoLoginForm from "./AutoLoginForm.vue";
|
||||
import CityUItems from "./CityUItems.vue";
|
||||
import CompanyWithdraw from "./CompanyWithdraw.vue";
|
||||
import EventsViewer from "./EventsViewer.vue";
|
||||
import ForeignStock from "./ForeignStock.vue";
|
||||
import InventoryView from "./InventoryView.vue";
|
||||
import MarketHelper from "./MarketHelper.vue";
|
||||
import PTMarketView from "./PTMarketView.vue";
|
||||
import QuickCrime from "./QuickCrime.vue";
|
||||
import UpdateDate from "./UpdateScript.vue";
|
||||
import VirusProgramming from "./VirusProgramming.vue";
|
||||
|
||||
const logger = inject(LoggerKey)
|
||||
const quickGymTrain = inject(QuickGymTrainKey)
|
||||
const quickFlyBtnHandler = inject(QuickFlyBtnHandlerKey)
|
||||
const logger = inject(LoggerKey);
|
||||
const quickGymTrain = inject(QuickGymTrainKey);
|
||||
const quickFlyBtnHandler = inject(QuickFlyBtnHandlerKey);
|
||||
|
||||
type MenuItem = { title: string, template?: Component, handler?: Function }
|
||||
type MenuItem = { title: string, template?: Component, handler?: Function };
|
||||
const menuItemList: MenuItem[] = [
|
||||
{
|
||||
title: '💊 吃 XAN',
|
||||
handler: () => {
|
||||
useItem('206')
|
||||
const sidebarData = getSidebarData()
|
||||
const cd = ((sidebarData.statusIcons.icons.drug_cooldown?.timerExpiresAt - sidebarData.statusIcons.icons.drug_cooldown?.serverTimestamp) / 36 | 0) / 100
|
||||
ElMessage({ message: '毒 CD: ' + cd + 'h', showClose: true })
|
||||
},
|
||||
handler: () => useItem('206'),
|
||||
},
|
||||
{
|
||||
title: '🍺 喝啤酒',
|
||||
handler: () => useItem('180'),
|
||||
},
|
||||
{
|
||||
title: '♻️ REFILL',
|
||||
handler: () => fetch(window.addRFC("https://www.torn.com/points.php?step=pointsbuy&action=energyrefill2"), {
|
||||
"headers": {
|
||||
"accept": "text/plain, */*; q=0.01",
|
||||
"sec-ch-ua-mobile": "?0",
|
||||
"sec-fetch-dest": "empty",
|
||||
"sec-fetch-mode": "cors",
|
||||
"sec-fetch-site": "same-origin",
|
||||
"x-requested-with": "XMLHttpRequest"
|
||||
},
|
||||
"referrer": "https://www.torn.com/points.php",
|
||||
"referrerPolicy": "strict-origin-when-cross-origin",
|
||||
"body": null,
|
||||
"method": "GET",
|
||||
"mode": "cors",
|
||||
"credentials": "include"
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(res => ElMessage({
|
||||
message: `<p>${ res.msg }</p><p>剩余refill: ${ res["refills"] }</p>`,
|
||||
type: res.state === 'done' ? 'success' : 'error',
|
||||
dangerouslyUseHTMLString: true
|
||||
}))
|
||||
.catch(e => ElMessage.error(e.toString)),
|
||||
},
|
||||
{
|
||||
title: '🚓 快速犯罪',
|
||||
@ -200,18 +192,10 @@ const menuItemList: MenuItem[] = [
|
||||
title: '💰 公司存钱',
|
||||
template: CompanyWithdraw,
|
||||
},
|
||||
{
|
||||
title: '💰 PI存钱',
|
||||
template: PropertyVault,
|
||||
},
|
||||
{
|
||||
title: '📦 物品',
|
||||
template: InventoryView,
|
||||
},
|
||||
{
|
||||
title: '🎯 BS估算',
|
||||
template: BSEstView,
|
||||
},
|
||||
{
|
||||
title: '🫵 关闭店铺(双击开启)',
|
||||
handler: () => bazaarControl.method(),
|
||||
@ -228,109 +212,67 @@ const menuItemList: MenuItem[] = [
|
||||
title: '🩼 配置自动登陆',
|
||||
template: AutoLoginForm,
|
||||
},
|
||||
{
|
||||
title: '🖥 监控',
|
||||
template: MonitorMgrView,
|
||||
},
|
||||
{
|
||||
title: '📜️ 传单助手',
|
||||
handler: () => {
|
||||
expanded.value = false
|
||||
adHelper()
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '🛡️ 守望者',
|
||||
handler: () => {
|
||||
expanded.value = false
|
||||
safeKeeper()
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '🌲 寻找木桩',
|
||||
handler: () => window.location.replace('https://www.torn.com/item.php?temp=4#xunzhaomuzhuang'),
|
||||
},
|
||||
{
|
||||
title: '🚀 更新历史',
|
||||
template: ChangeLogView
|
||||
},
|
||||
{
|
||||
title: '⚙️ 助手设置',
|
||||
handler: () => {
|
||||
expanded.value = false
|
||||
SettingsHandler.clickFunc()
|
||||
Container.factory(ChangeLogHandler).show()
|
||||
},
|
||||
},
|
||||
]
|
||||
const drawer = ref(false)
|
||||
const isMobilePhone = ref(false)
|
||||
const documentHeight = ref(0)
|
||||
const expanded = ref(false)
|
||||
const _globVars = ref(globVars)
|
||||
|
||||
// {
|
||||
// title: '⚙️ 插件配置',
|
||||
// template: Config,
|
||||
// },
|
||||
];
|
||||
const drawer = ref(false);
|
||||
const isMobilePhone = ref(false);
|
||||
const documentHeight = ref(0);
|
||||
const expanded = ref(false);
|
||||
const _globVars = ref(globVars);
|
||||
logger.info({ _globVars })
|
||||
// tabs
|
||||
const editableTabsValue = ref('')
|
||||
const editableTabs = shallowRef([])
|
||||
|
||||
// refil
|
||||
const handleRefil = (method: 'refillEnergy' | 'refillNerve' | 'refillCasinoTokens') => {
|
||||
fetch(window.addRFC("https://www.torn.com/page.php?sid=pointsBuildingExchange"), {
|
||||
"headers": {
|
||||
"accept": "*/*",
|
||||
"accept-language": "zh-CN,zh;q=0.9",
|
||||
"sec-fetch-dest": "empty",
|
||||
"sec-fetch-mode": "cors",
|
||||
"sec-fetch-site": "same-origin",
|
||||
"x-requested-with": "XMLHttpRequest"
|
||||
},
|
||||
"referrer": "https://www.torn.com/page.php?sid=points",
|
||||
"referrerPolicy": "strict-origin-when-cross-origin",
|
||||
"body": (() => {
|
||||
const data = new FormData();
|
||||
data.append('key', method);
|
||||
return data;
|
||||
})(),
|
||||
"method": "POST",
|
||||
"mode": "cors",
|
||||
"credentials": "include"
|
||||
})
|
||||
.then(res => res.json())
|
||||
.catch(e => ElMessage.error('REFILL异常: ' + e.toString))
|
||||
.then(res => {
|
||||
ElMessage({
|
||||
message: res.success ?
|
||||
`<p>成功</p><p>剩余次数: ${ res["specialRefills"] } 剩余点数: ${ res['points'] }</p>` :
|
||||
`REFILL异常: ${ res.error }`,
|
||||
type: res.success ? 'success' : 'error',
|
||||
dangerouslyUseHTMLString: true
|
||||
})
|
||||
throw new TypeError('REFILL异常: ' + res.error)
|
||||
})
|
||||
}
|
||||
const editableTabsValue = ref('');
|
||||
const editableTabs = shallowRef([]);
|
||||
|
||||
// fast travel
|
||||
const travelData = [
|
||||
{ cName: "🇲🇽 墨西哥", index: 0 },
|
||||
{ cName: "🇰🇾 开曼", index: 1 },
|
||||
{ cName: "🇨🇦 加拿大", index: 2 },
|
||||
{ cName: "🌺 夏威夷", index: 3 },
|
||||
{ cName: "🇬🇧 嘤国", index: 4 },
|
||||
{ cName: "🇦🇷 阿根廷", index: 5 },
|
||||
{ cName: "🇨🇭 瑞士 (解毒)", index: 6 },
|
||||
{ cName: "🇯🇵 立本", index: 7 },
|
||||
{ cName: "🇨🇳 祖国", index: 8 },
|
||||
{ cName: "🇦🇪 阿联酋 (UAE)", index: 9 },
|
||||
{ cName: "🇿🇦 南非", index: 10 },
|
||||
]
|
||||
{ cName: "墨西哥", index: 0 },
|
||||
{ cName: "开曼", index: 1 },
|
||||
{ cName: "加拿大", index: 2 },
|
||||
{ cName: "夏威夷", index: 3 },
|
||||
{ cName: "嘤国", index: 4 },
|
||||
{ cName: "阿根廷", index: 5 },
|
||||
{ cName: "瑞士 (解毒)", index: 6 },
|
||||
{ cName: "立本", index: 7 },
|
||||
{ cName: "祖国", index: 8 },
|
||||
{ cName: "阿联酋 (UAE)", index: 9 },
|
||||
{ cName: "南非", index: 10 },
|
||||
];
|
||||
|
||||
const MUZHUANG = () => window.location.replace('https://www.torn.com/item.php?temp=4#xunzhaomuzhuang');
|
||||
const _adHelper = () => {
|
||||
expanded.value = false;
|
||||
adHelper();
|
||||
}
|
||||
const _safeKeeper = () => {
|
||||
expanded.value = false;
|
||||
safeKeeper();
|
||||
}
|
||||
const _setting = () => {
|
||||
expanded.value = false;
|
||||
SettingsHandler.clickFunc();
|
||||
}
|
||||
|
||||
const menuClick = (menuItem: MenuItem) => {
|
||||
if (menuItem.handler) {
|
||||
menuItem.handler();
|
||||
} else if (menuItem.template) {
|
||||
drawer.value = true;
|
||||
// drawerTitle.value = menuItem.title;
|
||||
// drawerContent.value = menuItem.template;
|
||||
addTab(menuItem);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const showDrawer = () => {
|
||||
if (editableTabs.value.length < 1) {
|
||||
@ -388,6 +330,10 @@ const removeTab = (targetName: string) => {
|
||||
}
|
||||
};
|
||||
|
||||
// const tabClick = (pane: TabsPaneContext) => {
|
||||
// drawerTitle.value = <string>pane.paneName;
|
||||
// }
|
||||
|
||||
const travelConfirm = (destIndex: number, typeIndex: number) => {
|
||||
const destName = travelData[destIndex].cName;
|
||||
const typeName = ['普通飞机', 'PI飞机', '股票飞机', '商务飞机(机票或内衣店)'][typeIndex];
|
||||
@ -472,7 +418,6 @@ onMounted(() => {
|
||||
}
|
||||
documentHeight.value = document.documentElement.scrollHeight;
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@ -481,34 +426,4 @@ onMounted(() => {
|
||||
top: 32px;
|
||||
left: 10px;
|
||||
}
|
||||
|
||||
.featureCol {
|
||||
max-width: 33.33%;
|
||||
}
|
||||
|
||||
.featureMenu {
|
||||
cursor: pointer;
|
||||
margin: 4px;
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.featureMenu div {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.featureMenu .icon {
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
.featureMenu .title {
|
||||
font-size: 14px;
|
||||
height: 32px;
|
||||
margin-left: -0.5em;
|
||||
margin-right: -0.5em;
|
||||
}
|
||||
|
||||
.featureMenu:hover {
|
||||
background-color: #E9EEF6;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -14,12 +14,11 @@
|
||||
import { CommonUtilsKey } from "../ts/class/utils/CommonUtils";
|
||||
import { inject, onMounted, ref } from "vue";
|
||||
import UserScriptEngine from "../ts/enum/UserScriptEngine.js";
|
||||
import TravelItem from "../ts/feature/TravelItem";
|
||||
import { TravelItemKey } from "../ts/class/action/TravelItem";
|
||||
import { LoggerKey } from "../ts/class/Logger";
|
||||
import { Container } from "../ts/container/Container";
|
||||
|
||||
const commonUtils = inject(CommonUtilsKey);
|
||||
const travelItem = Container.factory(TravelItem)
|
||||
const travelItem = inject(TravelItemKey);
|
||||
const logger = inject(LoggerKey);
|
||||
const loading = ref(true);
|
||||
const staticImageSrc = 'https://jjins.github.io/t2i/stock.png?' + Date.now();
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
import { Check, Delete, Promotion } from "@element-plus/icons-vue"
|
||||
import { ElMessage } from "element-plus"
|
||||
import { inject, onMounted, ref } from "vue"
|
||||
import { inject, onMounted, ref, watch } from "vue"
|
||||
import { LoggerKey } from "../ts/class/Logger"
|
||||
import { itemNameDict } from "../ts/dictionary/translation"
|
||||
import Sleep from "../ts/func/utils/Sleep"
|
||||
@ -231,7 +231,7 @@ const _equipItem = async (item: Item) => {
|
||||
onMounted(async () => {
|
||||
itemList.value = parseListHtml(await fetchList())
|
||||
})
|
||||
|
||||
watch(itemList, (_cb) => logger.info(_cb))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@ -67,7 +67,6 @@ import { itemNameDict } from "../ts/dictionary/translation";
|
||||
import toThousands from "../ts/func/utils/toThousands";
|
||||
import Sleep from "../ts/func/utils/Sleep";
|
||||
import { MathUtilsKey } from "../ts/class/utils/MathUtils";
|
||||
import { timePastFormat } from "../ts/func/utils/timePastFormat";
|
||||
|
||||
const logger = inject(LoggerKey);
|
||||
const itemHelper = inject(ItemHelperKey);
|
||||
@ -91,6 +90,25 @@ const itemOnList = ref<ItemInfo[]>([]);
|
||||
const listLoading = ref<boolean>(false);
|
||||
const currentTs = ref<number>(Date.now());
|
||||
|
||||
const timePastFormat = (ts: number): string => {
|
||||
// 毫秒
|
||||
if (ts < 1000) {
|
||||
return ts + 'ms';
|
||||
}
|
||||
// 秒
|
||||
else if (ts < 60000) {
|
||||
return (ts / 1000 | 0) + 's';
|
||||
}
|
||||
// 分
|
||||
else if (ts < 3600000) {
|
||||
return (ts / 60000 | 0) + 'm';
|
||||
}
|
||||
// 时
|
||||
else {
|
||||
return (ts / 3600000 | 0) + 'h';
|
||||
}
|
||||
};
|
||||
|
||||
const doGetIMarketList = async (id: number) => {
|
||||
itemOnList.value = [];
|
||||
listLoading.value = true;
|
||||
|
||||
@ -1,70 +0,0 @@
|
||||
<template>
|
||||
<el-card shadow="never">
|
||||
<template #header>
|
||||
<span>毒 CD 空转</span>
|
||||
</template>
|
||||
<el-row>
|
||||
<el-col span="1"></el-col>
|
||||
<el-col span="23">
|
||||
<el-form class="form" label-position="left" label-width="30%">
|
||||
<el-form-item label="开启">
|
||||
<el-switch v-model="_drugCDMonitor"/>
|
||||
<span class="desc">开启后每个页面都会存在一个活跃的监视器,但是后台页面需要刷新后才会开启</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="检查间隔(毫秒)">
|
||||
<el-input v-model="drugCDMonitorLoop" :disabled="_drugCDMonitor" type="number"/>
|
||||
<span class="desc">每个监视器在间隔时间后会检查一次</span>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref, watch } from "vue";
|
||||
import drugCDMonitor from "../ts/monitor/DrugCDMonitor";
|
||||
import IntervalSwitch from "../ts/monitor/IntervalSwitch";
|
||||
import { Container } from "../ts/container/Container";
|
||||
import LocalConfigWrapper from "../ts/class/LocalConfigWrapper";
|
||||
import Logger from "../ts/class/Logger";
|
||||
|
||||
const _drugCDMonitor = ref(false)
|
||||
const drugCDMonitorLoop = ref(999999)
|
||||
|
||||
const localConfigWrapper = Container.factory(LocalConfigWrapper)
|
||||
const logger = Container.factory(Logger)
|
||||
|
||||
onMounted(() => {
|
||||
_drugCDMonitor.value = !!drugCDMonitor.getId() && localConfigWrapper.config.monitorOn.includes('drugCDMonitor')
|
||||
drugCDMonitorLoop.value = localConfigWrapper.config.drugCDMonitorInterval
|
||||
|
||||
watch([_drugCDMonitor, drugCDMonitorLoop], ([_drugCDMonitor, drugCDMonitorLoop]) => {
|
||||
logger.info('新变动', _drugCDMonitor, drugCDMonitorLoop)
|
||||
const monitorOn = localConfigWrapper.config.monitorOn
|
||||
if (_drugCDMonitor) {
|
||||
drugCDMonitor.setMs(drugCDMonitorLoop)
|
||||
drugCDMonitor.switcher(IntervalSwitch.ON)
|
||||
monitorOn.push('drugCDMonitor')
|
||||
} else {
|
||||
drugCDMonitor.switcher(IntervalSwitch.OFF)
|
||||
for (let i = 0; i < monitorOn.length; i++) {
|
||||
if (monitorOn[i] === 'drugCDMonitor') {
|
||||
monitorOn.splice(i, 1)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
localConfigWrapper.config.monitorOn = monitorOn
|
||||
localConfigWrapper.config.drugCDMonitorInterval = Number(drugCDMonitorLoop)
|
||||
})
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.form span.desc {
|
||||
width: 100%;
|
||||
color: #363636;
|
||||
}
|
||||
</style>
|
||||
@ -1,189 +0,0 @@
|
||||
<script lang="ts" setup>
|
||||
|
||||
import { inject, onMounted, ref } from "vue"
|
||||
import { LoggerKey } from "../ts/class/Logger"
|
||||
import { fetchCurrentMoney, fetchCurrentPropVaultAvailableMoney } from "../ts/func/utils/fetchCurrentMoney"
|
||||
import { ElMessage } from "element-plus"
|
||||
import toThousands from "../ts/func/utils/toThousands"
|
||||
|
||||
const logger = inject(LoggerKey)
|
||||
|
||||
const inputMoney = ref('')
|
||||
const inputWithdrawMoney = ref('')
|
||||
const formModel = ref({
|
||||
cash: 0, vault: 0,
|
||||
})
|
||||
const propId = ref(-1)
|
||||
|
||||
const updateCash = async () => {
|
||||
formModel.value.cash = await fetchCurrentMoney()
|
||||
return formModel.value.cash
|
||||
}
|
||||
const updateVault = async () => {
|
||||
formModel.value.vault = await fetchCurrentPropVaultAvailableMoney()
|
||||
return formModel.value.vault
|
||||
}
|
||||
|
||||
/**
|
||||
* 存取钱通用
|
||||
* @param amount
|
||||
* @param action {'deposit' | 'withdraw'}
|
||||
*/
|
||||
const deposit = async (amount: number, action: 'deposit' | 'withdraw' = 'deposit') => {
|
||||
if (amount < 1) {
|
||||
ElMessage.error('数额不能小于1')
|
||||
logger.error('数额不能小于1')
|
||||
throw new Error('数额不能小于1')
|
||||
}
|
||||
if (propId.value === -1) {
|
||||
ElMessage.error('未获取到房产id')
|
||||
logger.error('未获取到房产id')
|
||||
throw new Error('未获取到房产id')
|
||||
}
|
||||
|
||||
let response: string
|
||||
try {
|
||||
response = await (await fetch(window.addRFC("https://www.torn.com/properties.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/properties.php",
|
||||
"referrerPolicy": "strict-origin-when-cross-origin",
|
||||
"body": "step=vaultProperty&" + action + "=" + amount + "&ID=" + propId.value,
|
||||
"method": "POST",
|
||||
"mode": "cors",
|
||||
"credentials": "include"
|
||||
})).text()
|
||||
} catch (e) {
|
||||
ElMessage.error('请求出错 ' + e.message)
|
||||
logger.error(e.stack)
|
||||
throw e
|
||||
}
|
||||
|
||||
let error: string, text: string
|
||||
try {
|
||||
let json = JSON.parse(response)
|
||||
error = json.error
|
||||
text = json.text
|
||||
} catch (e) {
|
||||
}
|
||||
if (error) {
|
||||
ElMessage.error('$' + toThousands(amount) + ' 存取请求失败 ' + text)
|
||||
logger.error('存取请求失败 ' + text)
|
||||
throw new Error('存取请求失败 ' + text)
|
||||
} else {
|
||||
ElMessage.success('$' + toThousands(amount) + ' 存取请求完成')
|
||||
}
|
||||
|
||||
if (action === 'deposit') {
|
||||
inputWithdrawMoney.value = ''
|
||||
} else {
|
||||
inputMoney.value = ''
|
||||
}
|
||||
updateVault().then()
|
||||
updateCash().then()
|
||||
}
|
||||
|
||||
const getPropId = async () => {
|
||||
let response: string
|
||||
try {
|
||||
response = await (await fetch("https://www.torn.com/properties.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/properties.php",
|
||||
"referrerPolicy": "strict-origin-when-cross-origin",
|
||||
"body": "p=options&tab=vault&step=options",
|
||||
"method": "POST",
|
||||
"mode": "cors",
|
||||
"credentials": "include"
|
||||
})).text()
|
||||
} catch (e) {
|
||||
ElMessage.error('获取房产id失败,请重试')
|
||||
logger.error('获取房产id失败', e)
|
||||
throw e
|
||||
}
|
||||
const reg = /&ID=(\d+)"/
|
||||
const match = response.match(reg)
|
||||
if (match) {
|
||||
propId.value = Number(match[1])
|
||||
} else {
|
||||
ElMessage.error('获取房产id失败,报文未能成功匹配')
|
||||
logger.error('获取房产id失败,报文未能成功匹配')
|
||||
throw new Error('获取房产id失败,报文未能成功匹配')
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await getPropId()
|
||||
await updateCash()
|
||||
await updateVault()
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="gap4">
|
||||
<el-card shadow="never">当前默认房产id:{{ propId }}</el-card>
|
||||
<el-card shadow="never">
|
||||
<template #header>
|
||||
存钱:{{ toThousands(formModel.cash) }}
|
||||
</template>
|
||||
<el-row>
|
||||
<el-col :span="3">
|
||||
<el-button @click="async ()=>inputMoney=String(await updateCash())">$</el-button>
|
||||
</el-col>
|
||||
<el-col :span="18">
|
||||
<el-input v-model="inputMoney"/>
|
||||
</el-col>
|
||||
<el-col :span="3">
|
||||
<el-button @click="()=>{deposit(Number(inputMoney),'deposit');inputMoney=''}">确定</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
<el-card shadow="never">
|
||||
<template #header>
|
||||
取钱:{{ toThousands(formModel.vault) }}
|
||||
</template>
|
||||
<el-row>
|
||||
<el-button-group>
|
||||
<el-button type="primary" @click="()=>inputWithdrawMoney='1000000'">1m</el-button>
|
||||
<el-button type="primary" @click="()=>inputWithdrawMoney='2000000'">2m</el-button>
|
||||
<el-button type="primary" @click="()=>inputWithdrawMoney='5000000'">5m</el-button>
|
||||
<el-button type="primary" @click="()=>inputWithdrawMoney='10000000'">10m</el-button>
|
||||
<el-button type="primary" @click="()=>inputWithdrawMoney='20000000'">20m</el-button>
|
||||
</el-button-group>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="3">
|
||||
<el-button @click="async ()=>inputWithdrawMoney=String(await updateVault())">$</el-button>
|
||||
</el-col>
|
||||
<el-col :span="18">
|
||||
<el-input v-model="inputWithdrawMoney"/>
|
||||
</el-col>
|
||||
<el-col :span="3">
|
||||
<el-button @click="()=>{deposit(Number(inputWithdrawMoney),'withdraw');inputWithdrawMoney=''}">确定
|
||||
</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.gap4 .el-card {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
</style>
|
||||
@ -1,62 +1,21 @@
|
||||
<template>
|
||||
<!-- <el-row>-->
|
||||
<!-- <el-col :span="12">-->
|
||||
<div class="mt-4">
|
||||
<el-space>
|
||||
<el-button-group>
|
||||
<el-button @click="doCrime(11, 'warehouse')">烧仓库</el-button>
|
||||
<el-button @click="doCrime(15, 'napcop')">做15-3</el-button>
|
||||
<el-button @click="doCrime(18, 'hackbank')">做18-1</el-button>
|
||||
</el-button-group>
|
||||
<!-- </el-col>-->
|
||||
<!-- <el-col :span="12">-->
|
||||
<el-button type="primary" @click="doYouLikeABeer()">🍺 你喜欢啤酒吗</el-button>
|
||||
</el-space>
|
||||
</div>
|
||||
<!-- </el-col>-->
|
||||
<!-- </el-row>-->
|
||||
<!-- <el-row>-->
|
||||
<div class="mt-4">
|
||||
<el-space>
|
||||
<el-cascader v-model="crimeSelected" :options="CrimeData" :show-all-levels="false" clearable
|
||||
placeholder="选择其他"/>
|
||||
<el-button :disabled="!(crimeSelected && crimeSelected.length)"
|
||||
:icon="Coffee"
|
||||
round type="danger" @click="doCrime(crimeSelected[0], crimeSelected[1])">做
|
||||
</el-button>
|
||||
</el-space>
|
||||
</div>
|
||||
<!-- </el-row>-->
|
||||
<div class="mt-4">
|
||||
<el-space>
|
||||
<el-tag type="primary">NERVE {{ nerve }}</el-tag>
|
||||
<el-tag type="danger">CD {{ boostCoolDown }}</el-tag>
|
||||
</el-space>
|
||||
</div>
|
||||
<div v-if="responseHtmlString" v-html="responseHtmlString"></div>
|
||||
<el-button @click="doCrime(15,'warehouse')">烧仓库</el-button>
|
||||
<el-button @click="doCrime(18,'hackbank')">做18</el-button>
|
||||
<div v-if="results" v-html="results"></div>
|
||||
<el-skeleton v-if="loading" :rows="3" animated/>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { Coffee } from "@element-plus/icons-vue"
|
||||
import { inject, onBeforeUnmount, onMounted, ref } from 'vue'
|
||||
import { LoggerKey } from "../ts/class/Logger"
|
||||
import { CrimeData } from "./data/CrimeData"
|
||||
import { useItemSync } from "../ts/func/utils/useItem"
|
||||
import getSidebarData from "../ts/func/utils/getSidebarData"
|
||||
import { inject, ref } from 'vue';
|
||||
import { ElMessage } from "element-plus";
|
||||
import { LoggerKey } from "../ts/class/Logger";
|
||||
|
||||
const logger = inject(LoggerKey)
|
||||
const results = ref("")
|
||||
const loading = ref(false)
|
||||
const crimeSelected = ref(null)
|
||||
const responseHtmlString = ref('')
|
||||
const boostCoolDown = ref(0)
|
||||
const nerve = ref(0)
|
||||
|
||||
const doCrime = async (nerve, crime: "hackbank" | "warehouse" | 'napcop') => {
|
||||
loading.value = true
|
||||
results.value = ''
|
||||
const logger = inject(LoggerKey);
|
||||
const results = ref("");
|
||||
const loading = ref(false);
|
||||
const doCrime = async (nerve, crime: "hackbank" | "warehouse") => {
|
||||
loading.value = true;
|
||||
results.value = '';
|
||||
try {
|
||||
results.value = await (await fetch(window.addRFC("https://www.torn.com/crimes.php?step=docrime4×tamp=" + Date.now()), {
|
||||
"headers": {
|
||||
@ -74,48 +33,25 @@ const doCrime = async (nerve, crime: "hackbank" | "warehouse" | 'napcop') => {
|
||||
"method": "POST",
|
||||
"mode": "cors",
|
||||
"credentials": "include"
|
||||
})).text()
|
||||
})).text();
|
||||
} catch (e) {
|
||||
logger.error(e.stack)
|
||||
results.value = e.message
|
||||
logger.error(e.stack);
|
||||
results.value = e.message;
|
||||
}
|
||||
let err: string
|
||||
let err;
|
||||
try {
|
||||
err = JSON.parse(results.value).error
|
||||
err = JSON.parse(results.value).error;
|
||||
} catch (e) {
|
||||
}
|
||||
if (err) {
|
||||
results.value = '错误: ' + err
|
||||
// ElMessage.error('错误: ' + err)
|
||||
logger.error(err)
|
||||
results.value = '出错了';
|
||||
ElMessage.error('错误: ' + err);
|
||||
logger.error(err);
|
||||
}
|
||||
loading.value = false
|
||||
updateData()
|
||||
}
|
||||
|
||||
const doYouLikeABeer = async () => {
|
||||
await useItemSync('180', false, (res) => {
|
||||
responseHtmlString.value = res.text
|
||||
updateData()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const updateData = () => {
|
||||
const sidebarData = getSidebarData()
|
||||
nerve.value = sidebarData.bars.nerve.amount
|
||||
boostCoolDown.value = (sidebarData.statusIcons.icons.booster_cooldown?.timerExpiresAt - sidebarData.statusIcons.icons.booster_cooldown?.serverTimestamp) / 3600 | 0
|
||||
}
|
||||
|
||||
let intervalId = 0
|
||||
onMounted(() => {
|
||||
updateData()
|
||||
intervalId = window.setInterval(() => updateData(), 60000)
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (intervalId) window.clearInterval(intervalId)
|
||||
})
|
||||
loading.value = false;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
49
src/vue/Test.vue
Normal file
49
src/vue/Test.vue
Normal file
@ -0,0 +1,49 @@
|
||||
<template>
|
||||
<p>1</p>
|
||||
<p>1</p>
|
||||
<p>1</p>
|
||||
<p>1</p>
|
||||
<p>1</p>
|
||||
<p>1</p>
|
||||
<p>1</p>
|
||||
<p>1</p>
|
||||
<p>1</p>
|
||||
<p>1</p>
|
||||
<p>1</p>
|
||||
<p>1</p>
|
||||
<p>1</p>
|
||||
<p>1</p>
|
||||
<p>1</p>
|
||||
<p>1</p>
|
||||
<p>1</p>
|
||||
<p>1</p>
|
||||
<p>1</p>
|
||||
<p>1</p>
|
||||
<p>1</p>
|
||||
<p>1</p>
|
||||
<p>1</p>
|
||||
<p>1</p>
|
||||
<p>1</p>
|
||||
<p>1</p>
|
||||
<p>1</p>
|
||||
<p>1</p>
|
||||
<p>1</p>
|
||||
<p>1</p>
|
||||
<p>1</p>
|
||||
<p>1</p>
|
||||
<p>1</p>
|
||||
<p>1</p>
|
||||
<p>1</p>
|
||||
<p>1</p>
|
||||
<p>1</p>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "Test"
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
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