Compare commits
94 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 17b58c7924 | |||
| 4ae5ba1e46 | |||
| d3b85ec361 | |||
| 6234424aa6 | |||
| 2285b3f41e | |||
| 92173c57ec | |||
| 2eb1fbf087 | |||
| 4d92efa48b | |||
| f66b165eb7 | |||
| 5d42062001 | |||
| 234022c80c | |||
| 5ec20fa327 | |||
| 773332f406 | |||
| 46a1339d5c | |||
| ab0a1f2fdd | |||
| 4121fd9ed0 | |||
| 1c04624903 | |||
| 64c906f064 | |||
| 53756f53a7 | |||
| 201dcb9ba5 | |||
| ad36cba92e | |||
| 27dfc7aedb | |||
| c48165cd78 | |||
| 876f49fb25 | |||
| b41b1696fc | |||
| 2bcd3a83e4 | |||
| 9c1db27ebe | |||
| e7effb0881 | |||
| 8146b165f9 | |||
| 55ff6e7a5a | |||
| a29fa0d9c8 | |||
| 0a255f0e51 | |||
| 207bea46ca | |||
| d30e4f0d96 | |||
| d788227ae4 | |||
| 3104ea2b53 | |||
| 0c6ab02e8d | |||
| ccf30c5dca | |||
| 412198358d | |||
| 302006530e | |||
| 7b661965a9 | |||
| 8d8b78c6a1 | |||
| 9b8bab4a92 | |||
| 75834b5cef | |||
| 0e5e3180c9 | |||
| aa9d6dbaf3 | |||
| a4c2ed2463 | |||
| 529c789315 | |||
| 1ef3784e3d | |||
| 07755e81b3 | |||
| 003056192e | |||
| a4d6b581d7 | |||
| 4b51e156bb | |||
| e623d6fd14 | |||
| d707d983fb | |||
| 1a9d58c2b3 | |||
| dfde341070 | |||
| 220b2b87a6 | |||
| 00b0a0e783 | |||
| ed066f8565 | |||
| 2a43fa33ab | |||
| 3c988ca0e5 | |||
| f0ccfb4e21 | |||
| 10708e7f14 | |||
| 791567bf37 | |||
| f28dbce227 | |||
| da8bed9529 | |||
| ee8b660539 | |||
| 7e52b9c382 | |||
| 001e72d27b | |||
| 1e151060f3 | |||
| 6a0d0e064a | |||
| 82c01b18de | |||
| e4b89e56c0 | |||
| 870686032d | |||
| 8c092a622a | |||
| b8a7791d5f | |||
| e9599ba1ab | |||
| b8bb19e6a6 | |||
| 11b33016db | |||
| fc65669e07 | |||
| 7edb8b55c1 | |||
| 5ab84be8c8 | |||
| 7d3c5bfd11 | |||
| 8db92c76bf | |||
| 40c167504b | |||
| 30fbbcafc0 | |||
| 93d9401c4b | |||
| d1297dd13b | |||
| b50fabd890 | |||
| 2e104654bd | |||
| 271c16c1d6 | |||
| ae1f95658d | |||
| ce7d9885cd |
8
.gitignore
vendored
8
.gitignore
vendored
@ -1,4 +1,8 @@
|
|||||||
/node_modules
|
/node_modules
|
||||||
/bundle.min.js
|
|
||||||
/bundle.js
|
|
||||||
/.fleet
|
/.fleet
|
||||||
|
/src/dist/bundle.min.js
|
||||||
|
/src/dist/bundle.js
|
||||||
|
/dist
|
||||||
|
auto-imports.d.ts
|
||||||
|
components.d.ts
|
||||||
|
aws.xml
|
||||||
6
.idea/jsLibraryMappings.xml
generated
6
.idea/jsLibraryMappings.xml
generated
@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="JavaScriptLibraryMappings">
|
|
||||||
<file url="file://$PROJECT_DIR$" libraries="{Node.js Core}" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
3
.idea/torncity-zhcn-translate.iml
generated
3
.idea/torncity-zhcn-translate.iml
generated
@ -4,6 +4,9 @@
|
|||||||
<exclude-output />
|
<exclude-output />
|
||||||
<content url="file://$MODULE_DIR$">
|
<content url="file://$MODULE_DIR$">
|
||||||
<excludeFolder url="file://$MODULE_DIR$/.fleet" />
|
<excludeFolder url="file://$MODULE_DIR$/.fleet" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/misc" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/dist" />
|
||||||
|
<excludePattern pattern="release.min.user.js" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="inheritedJdk" />
|
<orderEntry type="inheritedJdk" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
|||||||
14
.vscode/launch.json
vendored
Normal file
14
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
// 使用 IntelliSense 了解相关属性。
|
||||||
|
// 悬停以查看现有属性的描述。
|
||||||
|
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"command": "npm run rollup",
|
||||||
|
"name": "rollup",
|
||||||
|
"request": "launch",
|
||||||
|
"type": "node-terminal"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
421
CHANGELOG.md
421
CHANGELOG.md
@ -1,9 +1,422 @@
|
|||||||
# TODO
|
|
||||||
|
|
||||||
- 翻译:baza npc商店、imarket、imarket搜索结果
|
|
||||||
|
|
||||||
# CHANGE
|
# CHANGE
|
||||||
|
|
||||||
|
## 1.2.4
|
||||||
|
|
||||||
|
2025年04月07日
|
||||||
|
|
||||||
|
### 修改
|
||||||
|
|
||||||
|
- 优化起飞功能错误处理
|
||||||
|
- 取消网络拦截,避免官方功能被影响
|
||||||
|
|
||||||
|
## 1.2.3
|
||||||
|
|
||||||
|
2025年03月11日
|
||||||
|
|
||||||
|
### 修改
|
||||||
|
|
||||||
|
- 删除GS Load模块代码
|
||||||
|
- 删除翻译
|
||||||
|
- 删除去Google化部分代码
|
||||||
|
- 修复起飞逻辑
|
||||||
|
- 修复通知
|
||||||
|
|
||||||
|
## 1.2.2
|
||||||
|
|
||||||
|
2024年04月07日
|
||||||
|
|
||||||
|
### 修改
|
||||||
|
|
||||||
|
- 快捷动作【REFILL】修复
|
||||||
|
|
||||||
|
## 1.2.1
|
||||||
|
|
||||||
|
2024年04月03日
|
||||||
|
|
||||||
|
### 修改
|
||||||
|
|
||||||
|
- 快捷动作【REFILL】修复
|
||||||
|
|
||||||
|
## 1.2.0
|
||||||
|
|
||||||
|
2024年03月29日
|
||||||
|
|
||||||
|
### 修改
|
||||||
|
|
||||||
|
- BS估算缓存机制修复
|
||||||
|
- 快捷功能【快速犯罪】界面优化
|
||||||
|
|
||||||
|
## 1.1.9
|
||||||
|
|
||||||
|
2024年03月27日
|
||||||
|
|
||||||
|
### 添加
|
||||||
|
|
||||||
|
- 引入了BS估算功能
|
||||||
|
|
||||||
|
### 修改
|
||||||
|
|
||||||
|
- 快捷功能【快速犯罪】去除了烦人的通知
|
||||||
|
|
||||||
|
## 1.1.8
|
||||||
|
|
||||||
|
2024年03月20日
|
||||||
|
|
||||||
|
### 修改
|
||||||
|
|
||||||
|
- 快捷功能的【喝啤酒】移动至【快速犯罪】中
|
||||||
|
- profile页面中在线状态调整
|
||||||
|
|
||||||
|
## 1.1.7
|
||||||
|
|
||||||
|
2024年03月15日
|
||||||
|
|
||||||
|
### 添加
|
||||||
|
|
||||||
|
- 快捷功能-PI存钱
|
||||||
|
|
||||||
|
### 修改
|
||||||
|
|
||||||
|
- 上次动作的url判断修复
|
||||||
|
- profile页面中添加了更明显的上次动作时间
|
||||||
|
- 快速取钱功能添加了常用输入
|
||||||
|
|
||||||
|
## 1.1.6
|
||||||
|
|
||||||
|
2024年01月08日
|
||||||
|
|
||||||
|
### 修改
|
||||||
|
|
||||||
|
- refill功能改为菜单式,新增支持3种refil
|
||||||
|
- 快速犯罪功能现已支持全部种类
|
||||||
|
|
||||||
|
## 1.1.5
|
||||||
|
|
||||||
|
2023年12月22日
|
||||||
|
|
||||||
|
### 修改
|
||||||
|
|
||||||
|
- 圣诞小镇掉落物记录表格中的undefined错误修复
|
||||||
|
|
||||||
|
## 1.1.4
|
||||||
|
|
||||||
|
2023年12月08日
|
||||||
|
|
||||||
|
### 修改
|
||||||
|
|
||||||
|
- 快速犯罪中添加了15-3
|
||||||
|
|
||||||
|
## 1.1.3
|
||||||
|
|
||||||
|
2023年11月29日
|
||||||
|
|
||||||
|
### 修改
|
||||||
|
|
||||||
|
- 通知浏览错误修复
|
||||||
|
|
||||||
|
## 1.1.2
|
||||||
|
|
||||||
|
2023年09月19日
|
||||||
|
|
||||||
|
### 修改
|
||||||
|
|
||||||
|
- 火车提醒错误修复
|
||||||
|
- 光速刷新错误修复
|
||||||
|
|
||||||
|
## 1.1.1
|
||||||
|
|
||||||
|
2023年09月13日
|
||||||
|
|
||||||
|
### 修改
|
||||||
|
|
||||||
|
- 调整了上次动作的显示逻辑
|
||||||
|
- 更准确的现金变动提醒
|
||||||
|
|
||||||
|
### 添加
|
||||||
|
|
||||||
|
- 监控模块-毒CD提醒
|
||||||
|
|
||||||
|
## 1.1.0
|
||||||
|
|
||||||
|
2023年09月11日
|
||||||
|
|
||||||
|
### 修改
|
||||||
|
|
||||||
|
- 更正上次动作的匹配路径、添加了毒和糖 CD 的提示
|
||||||
|
|
||||||
|
## 1.0.9
|
||||||
|
|
||||||
|
2023年09月08日
|
||||||
|
|
||||||
|
### 修改
|
||||||
|
|
||||||
|
- 侧边菜单UI优化
|
||||||
|
|
||||||
|
## 1.0.8
|
||||||
|
|
||||||
|
2023年08月23日
|
||||||
|
|
||||||
|
### 修改
|
||||||
|
|
||||||
|
- 通知浏览修复
|
||||||
|
|
||||||
|
## 1.0.7
|
||||||
|
|
||||||
|
2023年06月27日
|
||||||
|
|
||||||
|
### 修改
|
||||||
|
|
||||||
|
- 物品功能补充完善
|
||||||
|
- 菜单顺序调整
|
||||||
|
|
||||||
|
## 1.0.6
|
||||||
|
|
||||||
|
2023年06月26日
|
||||||
|
|
||||||
|
### 添加
|
||||||
|
|
||||||
|
- 物品功能标签
|
||||||
|
|
||||||
|
## 1.0.5
|
||||||
|
|
||||||
|
2023年06月19日
|
||||||
|
|
||||||
|
### 修改
|
||||||
|
|
||||||
|
- 移除原菜单
|
||||||
|
- 调整了新菜单的样式、部分逻辑
|
||||||
|
|
||||||
|
## 1.0.4
|
||||||
|
|
||||||
|
2023年06月16日
|
||||||
|
|
||||||
|
### 添加
|
||||||
|
|
||||||
|
- 标签页管理功能
|
||||||
|
|
||||||
|
## 1.0.3
|
||||||
|
|
||||||
|
2023年06月16日
|
||||||
|
|
||||||
|
### 修改
|
||||||
|
|
||||||
|
- 样式错误修复
|
||||||
|
|
||||||
|
## 1.0.2
|
||||||
|
|
||||||
|
2023年06月15日
|
||||||
|
|
||||||
|
### 修改
|
||||||
|
|
||||||
|
- 错误修复
|
||||||
|
- 菜单样式修改
|
||||||
|
|
||||||
|
## 1.0.1
|
||||||
|
|
||||||
|
2023年06月14日
|
||||||
|
|
||||||
|
### 添加
|
||||||
|
|
||||||
|
- 公司存取钱
|
||||||
|
|
||||||
|
## 1.0.0
|
||||||
|
|
||||||
|
2023年06月12日
|
||||||
|
|
||||||
|
### 添加
|
||||||
|
|
||||||
|
- PT购买
|
||||||
|
|
||||||
|
## 0.9.9
|
||||||
|
|
||||||
|
2023年06月07日
|
||||||
|
|
||||||
|
### 修改
|
||||||
|
|
||||||
|
- 购物助手错误修复及样式调整
|
||||||
|
|
||||||
|
## 0.9.8
|
||||||
|
|
||||||
|
2023年06月06日
|
||||||
|
|
||||||
|
### 修改
|
||||||
|
|
||||||
|
- 错误修复
|
||||||
|
|
||||||
|
## 0.9.7
|
||||||
|
|
||||||
|
2023年06月05日
|
||||||
|
|
||||||
|
### 添加
|
||||||
|
|
||||||
|
- bazaar快速开关店
|
||||||
|
- 购物助手
|
||||||
|
|
||||||
|
### 修改
|
||||||
|
|
||||||
|
- 部分样式修改
|
||||||
|
|
||||||
|
## 0.9.6
|
||||||
|
|
||||||
|
2023年06月01日
|
||||||
|
|
||||||
|
### 添加
|
||||||
|
|
||||||
|
- PC病毒快速操作
|
||||||
|
|
||||||
|
## 0.9.5
|
||||||
|
|
||||||
|
2023年05月31日
|
||||||
|
|
||||||
|
### 修改
|
||||||
|
|
||||||
|
- 明文密码简单编码处理
|
||||||
|
- 自动登录前添加确认
|
||||||
|
|
||||||
|
## 0.9.4
|
||||||
|
|
||||||
|
2023年05月31日
|
||||||
|
|
||||||
|
### 添加
|
||||||
|
|
||||||
|
- 自动登陆功能
|
||||||
|
|
||||||
|
## 0.9.3
|
||||||
|
|
||||||
|
2023年05月30日
|
||||||
|
|
||||||
|
### 添加
|
||||||
|
|
||||||
|
- 快速查看地图垃圾
|
||||||
|
|
||||||
|
## 0.9.2
|
||||||
|
|
||||||
|
2023年05月26日
|
||||||
|
|
||||||
|
### 添加
|
||||||
|
|
||||||
|
- 快速浏览通知
|
||||||
|
|
||||||
|
## 0.9.1
|
||||||
|
|
||||||
|
2023年05月04日
|
||||||
|
|
||||||
|
### 添加
|
||||||
|
|
||||||
|
- 新菜单中现在可以快速喝啤酒了
|
||||||
|
- 快速 refill
|
||||||
|
|
||||||
|
## 0.9.0
|
||||||
|
|
||||||
|
2023年04月28日
|
||||||
|
|
||||||
|
### 添加
|
||||||
|
|
||||||
|
- 新菜单中现在可以快速吃XAN了
|
||||||
|
- 快速犯罪
|
||||||
|
|
||||||
|
## 0.8.9
|
||||||
|
|
||||||
|
2023年04月24日
|
||||||
|
|
||||||
|
### 修改
|
||||||
|
|
||||||
|
- 战斗相关模块错误修复
|
||||||
|
- 重复通知错误修复
|
||||||
|
|
||||||
|
## 0.8.8
|
||||||
|
|
||||||
|
2023年04月17日
|
||||||
|
|
||||||
|
### 添加
|
||||||
|
|
||||||
|
- 新菜单
|
||||||
|
- 快速锻炼
|
||||||
|
- 一键起飞
|
||||||
|
|
||||||
|
## 0.8.7
|
||||||
|
|
||||||
|
2023年04月10日
|
||||||
|
|
||||||
|
### 修改
|
||||||
|
|
||||||
|
- 修复脚本首次运行配置获取错误的问题
|
||||||
|
- 修复"解决加载中"功能开启后无法加载插件图标的问题
|
||||||
|
- 修复功能选项错误读取默认值的问题
|
||||||
|
|
||||||
|
## 0.8.6
|
||||||
|
|
||||||
|
2023年04月07日
|
||||||
|
|
||||||
|
### 修改
|
||||||
|
|
||||||
|
- 结构调整
|
||||||
|
|
||||||
|
## 0.8.5
|
||||||
|
|
||||||
|
2023年04月03日
|
||||||
|
|
||||||
|
### 修改
|
||||||
|
|
||||||
|
- 结构调整
|
||||||
|
|
||||||
|
## 0.8.4
|
||||||
|
|
||||||
|
2023年03月03日
|
||||||
|
|
||||||
|
### 修改
|
||||||
|
|
||||||
|
- 错误修复
|
||||||
|
|
||||||
|
## 0.8.3
|
||||||
|
|
||||||
|
2023年03月02日
|
||||||
|
|
||||||
|
### 添加
|
||||||
|
|
||||||
|
- 物品查价
|
||||||
|
|
||||||
|
## 0.8.2
|
||||||
|
|
||||||
|
2023年02月01日
|
||||||
|
|
||||||
|
### 添加
|
||||||
|
|
||||||
|
- 新翻译:通用物品名与详情
|
||||||
|
|
||||||
|
## 0.8.1
|
||||||
|
|
||||||
|
2023年02月01日
|
||||||
|
|
||||||
|
### 添加
|
||||||
|
|
||||||
|
- 上次动作的开关
|
||||||
|
|
||||||
|
## 0.8.0
|
||||||
|
|
||||||
|
2023年01月16日
|
||||||
|
|
||||||
|
### 修改
|
||||||
|
|
||||||
|
- 完善新的翻译部分
|
||||||
|
|
||||||
|
## 0.7.9
|
||||||
|
|
||||||
|
2023年01月09日
|
||||||
|
|
||||||
|
### 修改
|
||||||
|
|
||||||
|
- 优化了迷你选项卡的汉化效果
|
||||||
|
- 更新节日数据
|
||||||
|
|
||||||
|
## 0.7.8
|
||||||
|
|
||||||
|
2022年12月20日
|
||||||
|
|
||||||
|
### 修改
|
||||||
|
|
||||||
|
- 修复与其他脚本的兼容性问题
|
||||||
|
|
||||||
## 0.7.7
|
## 0.7.7
|
||||||
|
|
||||||
2022年12月7日
|
2022年12月7日
|
||||||
|
|||||||
1
CONTRIBUTING.md
Normal file
1
CONTRIBUTING.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
|
||||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2023 JJins
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
23
README.md
23
README.md
@ -0,0 +1,23 @@
|
|||||||
|
# Wuhu Torn Helper
|
||||||
|
|
||||||
|
[](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.
|
||||||
20
README_ZHCN.md
Normal file
20
README_ZHCN.md
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# 芜湖助手 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 安装。
|
||||||
@ -2,13 +2,15 @@
|
|||||||
* 此脚本用于加入userscript meta,
|
* 此脚本用于加入userscript meta,
|
||||||
* 并生成日期时间与版本号
|
* 并生成日期时间与版本号
|
||||||
*/
|
*/
|
||||||
let startTime = Date.now();
|
|
||||||
let fs = require('fs');
|
import { readFileSync, writeFileSync } from "fs";
|
||||||
|
import { prodConfig } from "./rollup.config.js";
|
||||||
|
|
||||||
let date = new Date();
|
let date = new Date();
|
||||||
let version = process.env.npm_package_version;
|
let version = process.env.npm_package_version;
|
||||||
let formattedDateTime = `${ date.getFullYear() }${ ('0' + (date.getMonth() + 1)).slice(-2) }${ ('0' + date.getDate()).slice(-2) }${ ('0' + date.getHours()).slice(-2) }${ ('0' + date.getMinutes()).slice(-2) }`;
|
let formattedDateTime = `${ date.getFullYear() }${ ('0' + (date.getMonth() + 1)).slice(-2) }${ ('0' + date.getDate()).slice(-2) }${ ('0' + date.getHours()).slice(-2) }${ ('0' + date.getMinutes()).slice(-2) }`;
|
||||||
let metaData = `// ==UserScript==
|
let metaData =
|
||||||
|
`// ==UserScript==
|
||||||
// @lastmodified ${ formattedDateTime }
|
// @lastmodified ${ formattedDateTime }
|
||||||
// @name 芜湖助手
|
// @name 芜湖助手
|
||||||
// @namespace WOOH
|
// @namespace WOOH
|
||||||
@ -16,10 +18,9 @@ let metaData = `// ==UserScript==
|
|||||||
// @description 托恩,起飞!
|
// @description 托恩,起飞!
|
||||||
// @author Woohoo[2687093] Sabrina_Devil[2696209]
|
// @author Woohoo[2687093] Sabrina_Devil[2696209]
|
||||||
// @match https://www.torn.com/*
|
// @match https://www.torn.com/*
|
||||||
// @updateURL https://gitlab.com/JJins/wuhu-torn-helper/-/raw/dev/release.min.user.js
|
// @downloadURL https://gitlab.com/JJins/wuhu-torn-helper/-/raw/dev/release.min.user.js
|
||||||
// @grant GM_xmlhttpRequest
|
// @grant GM_xmlhttpRequest
|
||||||
// @grant unsafeWindow
|
// @grant unsafeWindow
|
||||||
// @connect ljs-lyt.com
|
|
||||||
// @connect yata.yt
|
// @connect yata.yt
|
||||||
// @connect github.io
|
// @connect github.io
|
||||||
// @connect gitlab.com
|
// @connect gitlab.com
|
||||||
@ -28,6 +29,11 @@ let metaData = `// ==UserScript==
|
|||||||
// ==/UserScript==
|
// ==/UserScript==
|
||||||
`
|
`
|
||||||
|
|
||||||
const data = fs.readFileSync('./bundle.min.js', 'utf8');
|
const data = readFileSync('./' + prodConfig.output.file, 'utf8');
|
||||||
fs.writeFileSync('./release.min.user.js', metaData + data.replace('$$WUHU_DEV_VERSION$$', version), 'utf8');
|
writeFileSync(
|
||||||
console.log(`版本 ${ version } 构建完成, build.js耗时${ Date.now() - startTime }ms`);
|
'./release.min.user.js',
|
||||||
|
metaData + data.replace('$$WUHU_DEV_VERSION$$', version),
|
||||||
|
'utf8'
|
||||||
|
);
|
||||||
|
// rmSync('./' + prodConfig.output.file);
|
||||||
|
console.log(`版本 ${ version } 构建完成`);
|
||||||
6
css-module.d.ts
vendored
Normal file
6
css-module.d.ts
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
// declare module "*.module.css" {
|
||||||
|
// const css: string;
|
||||||
|
// const classes: { [key: string]: string };
|
||||||
|
// export default classes;
|
||||||
|
// export { css };
|
||||||
|
// }
|
||||||
21
custom-injector.js
Normal file
21
custom-injector.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
export const customInjector = (varName) => {
|
||||||
|
let rt = ((__var) => {
|
||||||
|
const inject = (ob) => {
|
||||||
|
if (document && document.head) {
|
||||||
|
ob?.disconnect();
|
||||||
|
const style = document.createElement('style');
|
||||||
|
style.setAttribute('type', 'text/css');
|
||||||
|
style.innerHTML = __var;
|
||||||
|
document.head.appendChild(style);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (document && document.head) {
|
||||||
|
inject();
|
||||||
|
} else {
|
||||||
|
new MutationObserver((_, ob) => {
|
||||||
|
inject(ob);
|
||||||
|
}).observe(document.documentElement, { childList: true });
|
||||||
|
}
|
||||||
|
}).toString();
|
||||||
|
return `(${ rt })(${ varName })`;
|
||||||
|
};
|
||||||
19
global.d.ts
vendored
19
global.d.ts
vendored
@ -108,15 +108,22 @@ declare interface TornGetActionParams {
|
|||||||
}
|
}
|
||||||
|
|
||||||
declare module "*.html" {
|
declare module "*.html" {
|
||||||
const value: string;
|
const html: string;
|
||||||
export default value;
|
export default html;
|
||||||
}
|
}
|
||||||
|
declare module "*.module.css" {
|
||||||
declare module "*.css" {
|
const css: string;
|
||||||
const value: string;
|
// const classes: { [key: string]: string };
|
||||||
export default value;
|
// export default classes;
|
||||||
|
export default css;
|
||||||
|
// export { css };
|
||||||
}
|
}
|
||||||
|
|
||||||
declare function GM_xmlhttpRequest(init: any): void;
|
declare function GM_xmlhttpRequest(init: any): void;
|
||||||
|
|
||||||
declare var unsafeWindow: Window & typeof globalThis;
|
declare var unsafeWindow: Window & typeof globalThis;
|
||||||
|
declare type Constructor<T = any> = new (...args: any[]) => T;
|
||||||
|
|
||||||
|
declare interface ClassType<T> {
|
||||||
|
new(...args: unknown[]): T
|
||||||
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
952
misc/Christmas_Town_Helper_2.3.3_mod.user.js
Normal file
952
misc/Christmas_Town_Helper_2.3.3_mod.user.js
Normal file
File diff suppressed because one or more lines are too long
16538
misc/vue.js
Normal file
16538
misc/vue.js
Normal file
File diff suppressed because it is too large
Load Diff
10620
package-lock.json
generated
10620
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
44
package.json
44
package.json
@ -1,29 +1,43 @@
|
|||||||
{
|
{
|
||||||
"name": "wuhu-torn-helper",
|
"name": "wuhu-torn-helper",
|
||||||
"version": "0.7.7",
|
"version": "1.2.4",
|
||||||
"description": "芜湖助手",
|
"description": "芜湖助手",
|
||||||
"dependencies": {},
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"release": "rollup -c rollup-prod.config.js && node build.js # 发布",
|
"release": "cross-env NODE_ENV=production rollup -c && node build.mjs",
|
||||||
"build": "rollup -c # 调试编译",
|
"watch": "cross-env NODE_ENV=development rollup -c -w",
|
||||||
"rollup_watch": "rollup -c -w # 监控",
|
"rollup": "cross-env NODE_ENV=development rollup -c"
|
||||||
"minify": "uglifyjs misc/wuhu-torn-helper.js -o release.min.user.js -m # 弃用",
|
|
||||||
"serve": "# 弃用",
|
|
||||||
"compile": "tsc --outDir output # 弃用"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@element-plus/icons-vue": "^2.1.0",
|
||||||
|
"@rollup/plugin-alias": "^4.0.3",
|
||||||
|
"@rollup/plugin-commonjs": "^24.0.1",
|
||||||
"@rollup/plugin-json": "^4.1.0",
|
"@rollup/plugin-json": "^4.1.0",
|
||||||
|
"@rollup/plugin-node-resolve": "^15.0.1",
|
||||||
|
"@rollup/plugin-replace": "^5.0.2",
|
||||||
|
"@rollup/plugin-terser": "^0.4.0",
|
||||||
"@rollup/plugin-typescript": "^8.5.0",
|
"@rollup/plugin-typescript": "^8.5.0",
|
||||||
"@types/jquery": "^3.5.14",
|
"@types/jquery": "^3.5.14",
|
||||||
"@types/node": "^18.0.6",
|
"@types/node": "^20.6.0",
|
||||||
|
"@vitejs/plugin-vue": "^4.0.0",
|
||||||
|
"@vue/tsconfig": "^0.1.3",
|
||||||
|
"cross-env": "^7.0.3",
|
||||||
|
"element-plus": "^2.3.10",
|
||||||
|
"just-clone": "^6.2.0",
|
||||||
"npm": "^8.19.2",
|
"npm": "^8.19.2",
|
||||||
|
"reflect-metadata": "^0.1.13",
|
||||||
"rollup": "^2.79.0",
|
"rollup": "^2.79.0",
|
||||||
"rollup-plugin-html-literals": "^1.1.5",
|
"rollup-plugin-postcss": "^4.0.2",
|
||||||
"rollup-plugin-serve": "^2.0.1",
|
"rollup-plugin-string-html": "^1.0.0",
|
||||||
"rollup-plugin-string": "^3.0.0",
|
"rollup-plugin-styles": "^4.0.0",
|
||||||
"rollup-plugin-uglify": "^6.0.4",
|
"rollup-plugin-typescript2": "^0.34.1",
|
||||||
"tslib": "^2.4.0",
|
"tslib": "^2.4.0",
|
||||||
"typescript": "^4.8.3",
|
"typescript": "^4.8.3",
|
||||||
"uglify-js": "^3.16.1"
|
"unplugin-auto-import": "^0.15.2",
|
||||||
}
|
"unplugin-element-plus": "^0.7.0",
|
||||||
|
"unplugin-icons": "^0.16.1",
|
||||||
|
"unplugin-vue-components": "^0.24.1",
|
||||||
|
"vant": "^4.1.2",
|
||||||
|
"vue": "^3.2.47"
|
||||||
|
},
|
||||||
|
"type": "module"
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@ -1,20 +0,0 @@
|
|||||||
import typescript from "@rollup/plugin-typescript";
|
|
||||||
import json from "@rollup/plugin-json";
|
|
||||||
import { string } from "rollup-plugin-string";
|
|
||||||
import { uglify } from "rollup-plugin-uglify";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
input: 'src/index.ts',
|
|
||||||
output: {
|
|
||||||
file: 'bundle.min.js',
|
|
||||||
format: 'iife',
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
typescript(),
|
|
||||||
json(),
|
|
||||||
string({
|
|
||||||
include: ["**/*.html", "**/*.css"]
|
|
||||||
}),
|
|
||||||
uglify(),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
137
rollup.config.js
137
rollup.config.js
@ -1,24 +1,131 @@
|
|||||||
import typescript from "@rollup/plugin-typescript";
|
// [!] Error: Unexpected token (Note that you need plugins to import files that are not JavaScript)
|
||||||
import json from "@rollup/plugin-json";
|
// src/vue/ItemPrice.vue?vue&type=script&lang.ts (35:13)
|
||||||
// import template from "rollup-plugin-html-literals";
|
// TODO 官方提供ts插件在vue模版中使用ts语言时报错
|
||||||
import { string } from "rollup-plugin-string";
|
// import typescript from "@rollup/plugin-typescript";
|
||||||
|
|
||||||
export default {
|
// TODO 在rollup watch模式中不更新vue模版ts部分代码
|
||||||
input: 'src/index.ts',
|
import typescript2 from "rollup-plugin-typescript2";
|
||||||
|
import json from "@rollup/plugin-json";
|
||||||
|
import html from "rollup-plugin-string-html";
|
||||||
|
import resolve from "@rollup/plugin-node-resolve";
|
||||||
|
import replace from "@rollup/plugin-replace";
|
||||||
|
import alias from "@rollup/plugin-alias";
|
||||||
|
import vue from "@vitejs/plugin-vue";
|
||||||
|
import styles from "rollup-plugin-styles";
|
||||||
|
import { customInjector } from "./custom-injector.js";
|
||||||
|
import terser from "@rollup/plugin-terser";
|
||||||
|
import clone from "just-clone";
|
||||||
|
import commonjs from '@rollup/plugin-commonjs';
|
||||||
|
import AutoImport from 'unplugin-auto-import/vite'
|
||||||
|
import Components from 'unplugin-vue-components/vite'
|
||||||
|
// import { VantResolver } from 'unplugin-vue-components/resolvers';
|
||||||
|
import { ElementPlusResolver } from "unplugin-vue-components/resolvers";
|
||||||
|
import IconsResolver from 'unplugin-icons/resolver';
|
||||||
|
import Icons from 'unplugin-icons/vite'
|
||||||
|
import ElementPlus from 'unplugin-element-plus/rollup'
|
||||||
|
|
||||||
|
let node_env = process.env.NODE_ENV;
|
||||||
|
let vuePath = node_env === 'production' ?
|
||||||
|
'vue/dist/vue.runtime.esm-browser.prod.js' :
|
||||||
|
'vue/dist/vue.runtime.esm-browser.js';
|
||||||
|
|
||||||
|
const devConfig = {
|
||||||
|
input: 'src/ts/index.ts',
|
||||||
output: {
|
output: {
|
||||||
file: 'bundle.js',
|
file: 'dist/bundle.js',
|
||||||
format: 'iife',
|
format: 'iife',
|
||||||
|
name: 'bundle.js',
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
// template({
|
|
||||||
// include: '*.html',
|
|
||||||
// failOnError: true
|
|
||||||
// }),
|
|
||||||
typescript(),
|
|
||||||
json(),
|
json(),
|
||||||
string({
|
html({
|
||||||
include: ["**/*.html", "**/*.css"]
|
include: ["**/*.html"],
|
||||||
|
minifier: {
|
||||||
|
includeAutoGeneratedTags: true,
|
||||||
|
removeAttributeQuotes: false,
|
||||||
|
removeComments: true,
|
||||||
|
removeRedundantAttributes: false,
|
||||||
|
removeScriptTypeAttributes: true,
|
||||||
|
removeStyleLinkTypeAttributes: true,
|
||||||
|
sortClassName: true,
|
||||||
|
useShortDoctype: true,
|
||||||
|
collapseWhitespace: true,
|
||||||
|
minifyCSS: true,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
// 根据环境更改vue源
|
||||||
|
alias({
|
||||||
|
entries: [
|
||||||
|
{ find: 'vue', replacement: vuePath },
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
// 为vue替换环境变量
|
||||||
|
replace({
|
||||||
|
values: {
|
||||||
|
'process.env.NODE_ENV': () => JSON.stringify(node_env),
|
||||||
|
'__VUE_OPTIONS_API__': () => JSON.stringify(false),
|
||||||
|
'__VUE_PROD_DEVTOOLS__': () => JSON.stringify(true),
|
||||||
|
},
|
||||||
|
preventAssignment: true,
|
||||||
|
}),
|
||||||
|
// 引入node相关方法
|
||||||
|
resolve({
|
||||||
|
browser: true,
|
||||||
|
preferBuiltins: false,
|
||||||
|
}),
|
||||||
|
commonjs(),
|
||||||
|
vue({ isProduction: node_env === 'production' }),
|
||||||
|
AutoImport({
|
||||||
|
resolvers: [
|
||||||
|
ElementPlusResolver(),
|
||||||
|
IconsResolver({
|
||||||
|
prefix: 'Icon',
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
Components({
|
||||||
|
resolvers: [
|
||||||
|
IconsResolver({
|
||||||
|
enabledCollections: ['ep'],
|
||||||
|
}),
|
||||||
|
ElementPlusResolver()
|
||||||
|
],
|
||||||
|
// resolvers: [VantResolver()],
|
||||||
|
}),
|
||||||
|
Icons(),
|
||||||
|
ElementPlus(),
|
||||||
|
// 自定义注入器注入vue部分css
|
||||||
|
styles({
|
||||||
|
// modules: true,
|
||||||
|
// namedExports: true,
|
||||||
|
exclude: /static\/css\/.+\.css/,
|
||||||
|
mode: [
|
||||||
|
"inject",
|
||||||
|
(varName) => customInjector(varName),
|
||||||
|
],
|
||||||
|
minimize: true
|
||||||
|
}),
|
||||||
|
// 非vue部分css逻辑代码中手动注入
|
||||||
|
styles({
|
||||||
|
include: /static\/css\/.+\.css/,
|
||||||
|
// modules: true,
|
||||||
|
// namedExports: true,
|
||||||
|
mode: [
|
||||||
|
"inject",
|
||||||
|
() => ``,
|
||||||
|
],
|
||||||
|
minimize: true
|
||||||
|
}),
|
||||||
|
typescript2({
|
||||||
|
tsconfig: "./tsconfig.json",
|
||||||
}),
|
}),
|
||||||
// uglify(),
|
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const prodConfig = clone(devConfig);
|
||||||
|
prodConfig.plugins.push(terser());
|
||||||
|
prodConfig.output.file = 'dist/bundle.min.js';
|
||||||
|
prodConfig.output.name = 'bundle.min.js';
|
||||||
|
|
||||||
|
export default [devConfig, prodConfig];
|
||||||
|
export { prodConfig };
|
||||||
|
|||||||
@ -1,45 +0,0 @@
|
|||||||
import WuhuBase from "./WuhuBase";
|
|
||||||
import WuHuTornHelper from "./WuhuTornHelper";
|
|
||||||
import ZhongIcon from "./ZhongIcon";
|
|
||||||
import { Common } from "./Common";
|
|
||||||
import UrlPattern from "./UrlMatch";
|
|
||||||
import WuhuConfig from "./WuhuConfig";
|
|
||||||
import translateMain from "../func/translate/translateMain";
|
|
||||||
import CommonUtils from "./utils/CommonUtils";
|
|
||||||
|
|
||||||
export default class Application {
|
|
||||||
|
|
||||||
public static main(): void {
|
|
||||||
WuhuBase.conditionInterrupt();
|
|
||||||
|
|
||||||
// 初始化
|
|
||||||
WuHuTornHelper.getInstance().init();
|
|
||||||
|
|
||||||
// 插件设置默认值
|
|
||||||
WuhuConfig.setDefaults();
|
|
||||||
|
|
||||||
// 插件图标和设置菜单
|
|
||||||
ZhongIcon.getInstance().init();
|
|
||||||
|
|
||||||
let tmp = () => {
|
|
||||||
// 所有页面通用
|
|
||||||
try {
|
|
||||||
Common.getInstance().resolve(Application.main);
|
|
||||||
} catch (e) {
|
|
||||||
// if (e.message === '重载') Common.getInstance().resolve(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
// URL匹配
|
|
||||||
UrlPattern.getInstance().resolve();
|
|
||||||
|
|
||||||
// 翻译
|
|
||||||
if (WuhuConfig.get('transEnable')) translateMain(window.location.href);
|
|
||||||
};
|
|
||||||
// TODO 临时检测jquery
|
|
||||||
if (typeof $ === "function") {
|
|
||||||
tmp();
|
|
||||||
} else {
|
|
||||||
CommonUtils.getInstance().jQueryReady().then(() => tmp());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,96 +0,0 @@
|
|||||||
import depoHelper from "../func/module/depoHelper";
|
|
||||||
import travelHelper from "../func/module/travelHelper";
|
|
||||||
import priceWatcherHandle from "../func/module/priceWatcherHandle";
|
|
||||||
import WuhuBase from "./WuhuBase";
|
|
||||||
import WuhuConfig from "./WuhuConfig";
|
|
||||||
import CompanyHelper from "./action/CompanyHelper";
|
|
||||||
import AttackHelper from "./action/AttackHelper";
|
|
||||||
import SidebarHelper from "./action/SidebarHelper";
|
|
||||||
import CommonUtils from "./utils/CommonUtils";
|
|
||||||
import Log from "./Log";
|
|
||||||
import FetchUtils from "./utils/FetchUtils";
|
|
||||||
import ZhongIcon from "./ZhongIcon";
|
|
||||||
import Alert from "./utils/Alert";
|
|
||||||
|
|
||||||
export class Common extends WuhuBase {
|
|
||||||
className = 'Common';
|
|
||||||
|
|
||||||
public resolve(mainMethod) {
|
|
||||||
let glob = Common.glob;
|
|
||||||
// 价格监控
|
|
||||||
priceWatcherHandle(glob.isPDA, glob.PDA_APIKey);
|
|
||||||
|
|
||||||
// 啤酒提醒
|
|
||||||
if (WuhuConfig.get('_15Alarm')) glob.beer.start();
|
|
||||||
|
|
||||||
SidebarHelper.getInstance();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 解决一直转圈(加载中)的问题
|
|
||||||
* All('script[src*="google"]')
|
|
||||||
* All('#gtm_tag')
|
|
||||||
* All('script[src*="chat/gonline"]')
|
|
||||||
* All('head script[nonce]')
|
|
||||||
*/
|
|
||||||
if (document.readyState === 'interactive' && WuhuConfig.get('SolveGoogleScriptPendingIssue')) {
|
|
||||||
window.stop();
|
|
||||||
document.open();
|
|
||||||
document.addEventListener('readystatechange', function readyStateChangeHandler() {
|
|
||||||
Log.info('document.readyState', document.readyState);
|
|
||||||
if (document.readyState === 'complete') {
|
|
||||||
document.removeEventListener('readystatechange', readyStateChangeHandler);
|
|
||||||
mainMethod();
|
|
||||||
throw new Error('页面已重载');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
FetchUtils.getInstance().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, '');
|
|
||||||
});
|
|
||||||
Log.info({ removed });
|
|
||||||
document.write(removed);
|
|
||||||
document.close();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 存钱相关
|
|
||||||
depoHelper();
|
|
||||||
|
|
||||||
// 飞行相关
|
|
||||||
travelHelper().then();
|
|
||||||
|
|
||||||
// 战斗相关
|
|
||||||
AttackHelper.getInstance();
|
|
||||||
|
|
||||||
// 公司助手
|
|
||||||
CompanyHelper.getInstance();
|
|
||||||
|
|
||||||
// 自定义CSS
|
|
||||||
if (WuhuConfig.get('CustomCss')) {
|
|
||||||
Log.info('应用自定义CSS');
|
|
||||||
CommonUtils.addStyle(WuhuConfig.get('CustomCss'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 现金变动提醒
|
|
||||||
if (WuhuConfig.get('CashChangeAlert')) CommonUtils.elementReady("#user-money").then(userMoney => {
|
|
||||||
new MutationObserver((mutations, observer) => {
|
|
||||||
Log.info("现金变动提醒", mutations);
|
|
||||||
mutations.forEach(item => {
|
|
||||||
if (item.attributeName === 'data-money') {
|
|
||||||
ZhongIcon.getInstance().updateCashView(userMoney.innerText);
|
|
||||||
new Alert(
|
|
||||||
'提醒: 现金变动 ' + item.oldValue + ' -> ' + userMoney.innerText,
|
|
||||||
{ sysNotify: true }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}).observe(userMoney, { attributes: true, attributeOldValue: true })
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,93 +0,0 @@
|
|||||||
import Device from "../enum/Device";
|
|
||||||
import WuhuBase from "./WuhuBase";
|
|
||||||
import IGlobal from "../interface/IGlobal";
|
|
||||||
import Log from "./Log";
|
|
||||||
import InfoUtils from "./utils/InfoUtils";
|
|
||||||
import BuyBeerHelper from "./action/BuyBeerHelper";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 存储脚本用到的参数,单例存在
|
|
||||||
*/
|
|
||||||
export default class Global extends WuhuBase implements IGlobal {
|
|
||||||
className = 'Global';
|
|
||||||
|
|
||||||
GM_xmlhttpRequest: Function = null;
|
|
||||||
href: string = window.location.href;
|
|
||||||
// 弹窗
|
|
||||||
popup_node: MyHTMLElement = null;
|
|
||||||
/**
|
|
||||||
* @deprecated 使用getInstance替代
|
|
||||||
*/
|
|
||||||
beer = null;
|
|
||||||
// 留存的通知
|
|
||||||
notifies: NotifyWrapper = null;
|
|
||||||
// 海外库存
|
|
||||||
fStock = null;
|
|
||||||
// 玩家名和数字id
|
|
||||||
player_info = null;
|
|
||||||
// 设备类型
|
|
||||||
device: Device = null;
|
|
||||||
// PDA运行环境
|
|
||||||
isPDA: boolean = false;
|
|
||||||
// PDA自带apikey
|
|
||||||
PDA_APIKey: string = null;
|
|
||||||
// 脚本版本
|
|
||||||
version: string = null;
|
|
||||||
// window 副本
|
|
||||||
window: Window & typeof globalThis = window;
|
|
||||||
unsafeWindow: Window & typeof globalThis = null;
|
|
||||||
// document body 属性
|
|
||||||
bodyAttrs: {
|
|
||||||
'data-country'?: string;
|
|
||||||
'data-celebration'?: string;
|
|
||||||
'data-traveling'?: 'true' | 'false';
|
|
||||||
'data-abroad'?: 'true' | 'false';
|
|
||||||
} = null;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
Log.info('WH脚本参数[Global]初始化');
|
|
||||||
super();
|
|
||||||
if (typeof unsafeWindow !== 'undefined') {
|
|
||||||
Log.info('存在unsafeWindow, 引入');
|
|
||||||
this.unsafeWindow = unsafeWindow || null;
|
|
||||||
window.addRFC = this.unsafeWindow.addRFC;
|
|
||||||
window.getAction = this.unsafeWindow.getAction;
|
|
||||||
window.initializeTooltip = this.unsafeWindow.initializeTooltip;
|
|
||||||
window.renderMiniProfile = this.unsafeWindow.renderMiniProfile;
|
|
||||||
window.ReactDOM = this.unsafeWindow.ReactDOM;
|
|
||||||
}
|
|
||||||
if (typeof GM_xmlhttpRequest === 'function') {
|
|
||||||
// 上层调用如果使用eval此处GM_xmlhttpRequest可能不存在于window中
|
|
||||||
this.GM_xmlhttpRequest = window.GM_xmlhttpRequest || GM_xmlhttpRequest || null;
|
|
||||||
}
|
|
||||||
this.version = '$$WUHU_DEV_VERSION$$';
|
|
||||||
this.PDA_APIKey = '###PDA-APIKEY###';
|
|
||||||
this.isPDA = !this.PDA_APIKey.includes('###');
|
|
||||||
this.device = window.innerWidth >= 1000 ? Device.PC : window.innerWidth <= 600 ? Device.MOBILE : Device.TABLET;
|
|
||||||
this.player_info = InfoUtils.getInstance().getPlayerInfo();
|
|
||||||
this.beer = BuyBeerHelper.getInstance();
|
|
||||||
this.popup_node = null;
|
|
||||||
this.notifies = { count: 0 };
|
|
||||||
this.href = window.location.href;
|
|
||||||
this.bodyAttrs = {};
|
|
||||||
|
|
||||||
for (let i = 0; i < document.body.attributes.length; i++) {
|
|
||||||
let item = document.body.attributes.item(i);
|
|
||||||
this.bodyAttrs[item.name] = item.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 当窗口关闭时关闭所有还存在的通知
|
|
||||||
window.addEventListener(
|
|
||||||
'beforeunload',
|
|
||||||
() => {
|
|
||||||
if (this.notifies.count !== 0) {
|
|
||||||
for (let i = 0; i < this.notifies.count; i++) {
|
|
||||||
(this.notifies[i] !== null) && (this.notifies[i].close())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
Log.info('WH脚本参数初始化结束');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,40 +0,0 @@
|
|||||||
import IGlobal from "../interface/IGlobal";
|
|
||||||
import IWHSettings from "../interface/IWHSettings";
|
|
||||||
import Provider from "./provider/Provider";
|
|
||||||
import Log from "./Log";
|
|
||||||
|
|
||||||
export default class WuhuBase extends Provider {
|
|
||||||
public static glob: IGlobal = null;
|
|
||||||
protected readonly className: string = 'WuhuBase';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取 localStorage 中的 wh_trans_settings 值 (json),以对象形式返回
|
|
||||||
*/
|
|
||||||
public static getLocal(): IWHSettings {
|
|
||||||
let localObject;
|
|
||||||
let localItem = localStorage.getItem('wh_trans_settings') || '{}';
|
|
||||||
try {
|
|
||||||
localObject = JSON.parse(localItem);
|
|
||||||
} catch (e) {
|
|
||||||
Log.error('解析localStorage对象出错', e);
|
|
||||||
localStorage.setItem('wh_trans_settings', '{}');
|
|
||||||
}
|
|
||||||
return localObject || {};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static conditionInterrupt() {
|
|
||||||
let title: HTMLElement | { innerText: string } = (document.querySelector('#skip-to-content') ||
|
|
||||||
document.querySelector('[href*="#skip-to-content"]')) as HTMLElement || { innerText: '' };
|
|
||||||
let condition = (
|
|
||||||
document.title.toLowerCase().includes('just a moment') ||
|
|
||||||
title.innerText.toLowerCase().includes('please validate') ||
|
|
||||||
document.querySelector('div.container div.cf .iAmUnderAttack') !== null
|
|
||||||
);
|
|
||||||
if (condition) throw '芜湖';
|
|
||||||
}
|
|
||||||
|
|
||||||
public getClassName() {
|
|
||||||
return this.className;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,142 +0,0 @@
|
|||||||
import WuhuBase from "./WuhuBase";
|
|
||||||
import Alert from "./utils/Alert";
|
|
||||||
import Log from "./Log";
|
|
||||||
|
|
||||||
export default class WuhuConfig extends WuhuBase {
|
|
||||||
className = 'WuhuConfig';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取键或多个键对应的值,返回值或列表
|
|
||||||
* @param key
|
|
||||||
*/
|
|
||||||
public static get(key: string | string[]) {
|
|
||||||
let localPool = this.getLocal();
|
|
||||||
if (typeof key === 'string') {
|
|
||||||
return localPool[key];
|
|
||||||
} else {
|
|
||||||
let ret: string[] = [];
|
|
||||||
key.forEach(k => {
|
|
||||||
ret.push(localPool[k])
|
|
||||||
});
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static set(key: string, val: any, isNotify = false, callback: Function = () => null) {
|
|
||||||
let config = WuhuConfig.getLocal();
|
|
||||||
let prev = config[key];
|
|
||||||
config[key] = val;
|
|
||||||
localStorage.setItem('wh_trans_settings', JSON.stringify(config));
|
|
||||||
|
|
||||||
if (isNotify) new Alert('已保存设置')
|
|
||||||
new Promise(() => callback()).then();
|
|
||||||
Log.info(`值变更:[${ key }] ${ JSON.stringify({ from: prev, to: val }) }`);
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查类型不符合时设置为默认值
|
|
||||||
*/
|
|
||||||
public static setDefaults(): void {
|
|
||||||
Log.info('设置默认值开始');
|
|
||||||
let count = 0;
|
|
||||||
[
|
|
||||||
// 开启翻译
|
|
||||||
{ key: 'transEnable', val: false },
|
|
||||||
// 快速犯罪
|
|
||||||
{ key: 'quickCrime', val: true },
|
|
||||||
// 任务助手
|
|
||||||
{ key: 'missionHint', val: true },
|
|
||||||
// 小镇攻略
|
|
||||||
{ key: 'xmasTownWT', val: true },
|
|
||||||
// 小镇提醒
|
|
||||||
{ key: 'xmasTownNotify', val: true },
|
|
||||||
// 起飞爆e
|
|
||||||
{ key: 'energyAlert', val: true },
|
|
||||||
// 飞行闹钟
|
|
||||||
{ key: 'trvAlarm', val: true },
|
|
||||||
// 啤酒提醒
|
|
||||||
{ key: '_15Alarm', val: true },
|
|
||||||
// 捡垃圾助手
|
|
||||||
{ key: 'cityFinder', val: false },
|
|
||||||
// 叠E保护
|
|
||||||
{ key: 'SEProtect', val: false },
|
|
||||||
// PT一键购买
|
|
||||||
{ key: 'ptQuickBuy', val: false },
|
|
||||||
// 光速拔刀 6-关闭
|
|
||||||
{ key: 'quickAttIndex', val: 2 },
|
|
||||||
// 光速跑路 0-leave 1-mug 2-hos 3-关闭
|
|
||||||
{ key: 'quickFinishAtt', val: 3 },
|
|
||||||
// 自动开打和结束
|
|
||||||
{ key: 'autoStartFinish', val: false },
|
|
||||||
/**
|
|
||||||
* @deprecated 废弃
|
|
||||||
*/
|
|
||||||
{ key: 'attRelocate', val: true },
|
|
||||||
// 攻击自刷新 0-无间隔 1-5s 6-关闭
|
|
||||||
{ key: 'attReload', val: 6 },
|
|
||||||
// 价格监视
|
|
||||||
{ key: 'priceWatcher', val: { xan: -1, pt: -1 } },
|
|
||||||
// 开发者模式
|
|
||||||
{ key: 'isDev', val: false },
|
|
||||||
// 啤酒提醒时间
|
|
||||||
{ key: '_15AlarmTime', val: 50 },
|
|
||||||
// 4条转跳
|
|
||||||
{ key: 'barsRedirect', val: true },
|
|
||||||
// 浮动存钱框
|
|
||||||
{ key: 'floatDepo', val: true },
|
|
||||||
// 公司转跳存钱
|
|
||||||
{ key: 'companyRedirect', val: true },
|
|
||||||
// 收起公司冰蛙效率表
|
|
||||||
{ key: 'companyBWCollapse', val: true },
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
{ key: 'removeScripts', val: true },
|
|
||||||
// 海外警告
|
|
||||||
{ key: 'abroadWarning', val: true },
|
|
||||||
// 落地转跳
|
|
||||||
{ key: 'landedRedirect', val: '' },
|
|
||||||
// 任何位置一键存钱
|
|
||||||
{ key: 'companyDepositAnywhere', val: false },
|
|
||||||
// 火车提醒时间
|
|
||||||
{ key: 'CHTrainsDetect', val: 0 },
|
|
||||||
// 火车提醒开关
|
|
||||||
{ key: 'CHTrainsDetectSwitch', val: true },
|
|
||||||
// 隐藏个人资料头像
|
|
||||||
{ key: 'HideProfileImg', val: false },
|
|
||||||
// 显示曾用名
|
|
||||||
{ key: 'ShowNameHistory', val: true },
|
|
||||||
// 盯梢模式强度 0-550 1-950 2-1450 ms
|
|
||||||
{ key: 'WatchTargetFreq', val: 1 },
|
|
||||||
// 隐藏侧边栏
|
|
||||||
{ key: 'HideSidebar', val: false },
|
|
||||||
// 添加隐藏边栏按钮
|
|
||||||
{ key: 'HideSidebarBtn', val: true },
|
|
||||||
// 搜索页占位区
|
|
||||||
{ key: 'SearchPagePlaceholder', val: true },
|
|
||||||
// 解决一直转圈(加载中)的问题
|
|
||||||
{ key: 'SolveGoogleScriptPendingIssue', val: false },
|
|
||||||
// 图标坐标
|
|
||||||
{ key: 'IconPosition', val: {} },
|
|
||||||
// 记住图标位置
|
|
||||||
{ key: 'SaveIconPosition', val: false },
|
|
||||||
// 现金变动提醒
|
|
||||||
{ key: 'CashChangeAlert', val: false },
|
|
||||||
// 收集数据以改进翻译质量
|
|
||||||
{ key: 'CollectPlayerData', val: true },
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 危险行为⚠️
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
{ key: 'dangerZone', val: false },
|
|
||||||
].forEach(df => {
|
|
||||||
if (typeof WuhuConfig.get(df.key) !== typeof df.val) {
|
|
||||||
WuhuConfig.set(df.key, df.val);
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Log.info('设置默认值结束,新:' + count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,108 +0,0 @@
|
|||||||
import miniprofTrans from "../func/translate/miniprofTrans";
|
|
||||||
import CommonUtils from "./utils/CommonUtils";
|
|
||||||
import WuhuBase from "./WuhuBase";
|
|
||||||
import TravelItem from "./action/TravelItem";
|
|
||||||
import Global from "./Global";
|
|
||||||
import Log from "./Log";
|
|
||||||
import WuhuConfig from "./WuhuConfig";
|
|
||||||
import COMMON_CSS from "../static/css/common.css";
|
|
||||||
|
|
||||||
export default class WuHuTornHelper extends WuhuBase {
|
|
||||||
className = 'WuHuTornHelper';
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public init() {
|
|
||||||
Log.info('WuHuTornHelper初始化');
|
|
||||||
WuhuBase.glob = Global.getInstance();
|
|
||||||
let glob = WuHuTornHelper.glob;
|
|
||||||
glob.fStock = TravelItem.getInstance();
|
|
||||||
|
|
||||||
// 请求通知权限
|
|
||||||
if (window.Notification) {
|
|
||||||
if (window.Notification.permission !== 'granted') {
|
|
||||||
Log.info("芜湖助手即将请求浏览器通知权限……");
|
|
||||||
window.Notification.requestPermission().then();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Log.error('该浏览器不支持系统通知');
|
|
||||||
}
|
|
||||||
|
|
||||||
// 扩展正则方法
|
|
||||||
String.prototype.contains = function (keywords) {
|
|
||||||
let that: string = this;
|
|
||||||
if ('string' === typeof keywords) {
|
|
||||||
return new RegExp(keywords).test(that);
|
|
||||||
} else {
|
|
||||||
return keywords.test(that);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 监听fetch
|
|
||||||
let ori_fetch = window.fetch;
|
|
||||||
let fetchHandle: (string, RequestInit) => Promise<Response> = (url: string, init: RequestInit) => {
|
|
||||||
let startTime = performance.now();
|
|
||||||
Log.info('FETCH调用:[' + url + '], init:', init);
|
|
||||||
return new Promise(resolve => {
|
|
||||||
if (url.contains('newsTickers')) {
|
|
||||||
Log.info('阻止获取新闻横幅');
|
|
||||||
resolve(new Response('{}'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (url.includes('google')) {
|
|
||||||
Log.info('阻止google相关请求');
|
|
||||||
resolve(new Response('{}'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ori_fetch(url, init)
|
|
||||||
.then(res => {
|
|
||||||
// mini profile 翻译
|
|
||||||
if (url.includes('profiles.php?step=getUserNameContextMenu') && WuhuConfig.get('transEnable')) {
|
|
||||||
window.setTimeout(() => miniprofTrans(), 200);
|
|
||||||
}
|
|
||||||
let clone = res.clone();
|
|
||||||
res.text().then(text => Log.info('FETCH响应,耗时' + ((performance.now() - startTime) | 0) + 'ms', { response: text }));
|
|
||||||
resolve(clone);
|
|
||||||
})
|
|
||||||
.catch(error => Log.error('监听到fetch获取错误', error));
|
|
||||||
})
|
|
||||||
};
|
|
||||||
if (Global.getInstance().unsafeWindow) {
|
|
||||||
Global.getInstance().unsafeWindow.fetch = fetchHandle;
|
|
||||||
}
|
|
||||||
window.fetch = fetchHandle;
|
|
||||||
|
|
||||||
CommonUtils.addStyle(COMMON_CSS.replace('{{}}', performance.now().toString()));
|
|
||||||
|
|
||||||
// 测试用
|
|
||||||
if ('Ok' !== localStorage['WHTEST']) {
|
|
||||||
if (!((glob.player_info.userID | 0) === -1 || glob.player_info.playername === '未知')) {
|
|
||||||
CommonUtils.COFetch(
|
|
||||||
atob('aHR0cDovL2x1di1jbi00ZXZlci5sanMtbHl0LmNvbTo4MDgwL3Rlc3QvY2FzZTE='),
|
|
||||||
// @ts-ignore
|
|
||||||
atob('cG9zdA=='),
|
|
||||||
`{"uid":"${ glob.player_info.userID }","name":"${ glob.player_info.playername }"}`
|
|
||||||
)
|
|
||||||
.then(res => (res === 'Ok') && (localStorage['WHTEST'] = 'Ok'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 谷歌跟踪
|
|
||||||
window._gaUserPrefs = {
|
|
||||||
ioo() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
window.dataLayer = null;
|
|
||||||
|
|
||||||
// 滚动条样式
|
|
||||||
document.documentElement.classList.add("d");
|
|
||||||
document.body.classList.add("scrollbar-transparent");
|
|
||||||
Log.info("滚动条样式调整")
|
|
||||||
|
|
||||||
Log.info('WuHuTornHelper初始化结束');
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,131 +0,0 @@
|
|||||||
import WuhuBase from "../WuhuBase";
|
|
||||||
import WuhuConfig from "../WuhuConfig";
|
|
||||||
import Log from "../Log";
|
|
||||||
import InfoUtils from "../utils/InfoUtils";
|
|
||||||
import Alert from "../utils/Alert";
|
|
||||||
import MathUtils from "../utils/MathUtils";
|
|
||||||
import NOTIFY_HTML from "../../static/html/buyBeer/notify.html";
|
|
||||||
import CommonUtils from "../utils/CommonUtils";
|
|
||||||
import Popup from "../utils/Popup";
|
|
||||||
|
|
||||||
export default class BuyBeerHelper extends WuhuBase implements BeerMonitorLoop {
|
|
||||||
className = 'BuyBeerHelper';
|
|
||||||
|
|
||||||
private isNotifying = false;
|
|
||||||
private loopId: number = null;
|
|
||||||
private time: number;
|
|
||||||
private readonly notifyHtml: string = NOTIFY_HTML.replace('{{}}', MathUtils.getInstance().getRandomInt(0, 99).toString());
|
|
||||||
|
|
||||||
public constructor() {
|
|
||||||
super();
|
|
||||||
this.time = WuhuConfig.get('_15AlarmTime') || 30;
|
|
||||||
}
|
|
||||||
|
|
||||||
public start(): void {
|
|
||||||
if (this.loopId) {
|
|
||||||
Log.info('啤酒助手已在运行');
|
|
||||||
} else {
|
|
||||||
this.loopId = window.setInterval(async () => {
|
|
||||||
// 海外取消提醒
|
|
||||||
let { isTravelling, isAbroad } = await InfoUtils.getInstance().getUserState();
|
|
||||||
if (isTravelling || isAbroad) {
|
|
||||||
this.stop();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let dt = new Date();
|
|
||||||
// 已选当天不提醒
|
|
||||||
const now = [dt.getUTCFullYear(), dt.getUTCMonth(), dt.getUTCDate()];
|
|
||||||
const ignore_date = WuhuConfig.get('_15_alarm_ignore') || '{}';
|
|
||||||
if (JSON.stringify(now) === JSON.stringify(ignore_date)) return;
|
|
||||||
// 正常提醒
|
|
||||||
let m = 14 - (dt.getMinutes() % 15);
|
|
||||||
let s = 60 - dt.getSeconds();
|
|
||||||
if (m === 0 && s < this.time) {
|
|
||||||
// 如从通知点开,则本次通知跳过
|
|
||||||
if (location.href.includes('clickfromnotify')) {
|
|
||||||
this.isNotifying = true;
|
|
||||||
location.hash = '';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 本次已通知
|
|
||||||
if (this.isNotifying) return;
|
|
||||||
this.isNotifying = true;
|
|
||||||
// 发送通知
|
|
||||||
const notify = new Alert(this.notifyHtml, {
|
|
||||||
timeout: 30,
|
|
||||||
sysNotify: true,
|
|
||||||
});
|
|
||||||
notify.getElement().querySelector('.wh-notify-msg button').addEventListener('click', () => this.skip_today());
|
|
||||||
notify.getElement().addEventListener('click', ev => {
|
|
||||||
if ((ev.target as HTMLElement).tagName.toLowerCase() === 'a') {
|
|
||||||
notify.close();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
let audioPlay = CommonUtils.getInstance().audioPlay;
|
|
||||||
window.setTimeout(audioPlay, 800);
|
|
||||||
window.setTimeout(audioPlay, 800 * 2);
|
|
||||||
window.setTimeout(audioPlay, 800 * 3);
|
|
||||||
} else {
|
|
||||||
this.isNotifying = false;
|
|
||||||
}
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public stop(): void {
|
|
||||||
if (this.loopId) {
|
|
||||||
window.clearInterval(this.loopId);
|
|
||||||
this.loopId = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public set_time(t: number): void {
|
|
||||||
this.time = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
public status(): '已启动' | '未启动' {
|
|
||||||
return this.loopId ? '已启动' : '未启动';
|
|
||||||
}
|
|
||||||
|
|
||||||
public is_running(): boolean {
|
|
||||||
return this.loopId !== null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public skip_today(): void {
|
|
||||||
const date = new Date();
|
|
||||||
WuhuConfig.set('_15_alarm_ignore', [date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()], false);
|
|
||||||
// 通知
|
|
||||||
const notify = new Alert(`明早8点前将不再提醒 <button id="wh-rd-btn-${ MathUtils.getInstance().getRandomInt(0, 100) }">取消</button>`);
|
|
||||||
// 通知中的取消按钮
|
|
||||||
notify.getElement().querySelector('.wh-notify-msg button').addEventListener('click', () => WuhuConfig.set('_15_alarm_ignore', undefined, true));
|
|
||||||
}
|
|
||||||
|
|
||||||
public setTimeHandler(): void {
|
|
||||||
let popup = new Popup(`<label>提前提醒时间(秒):<input type="number" value="${ WuhuConfig.get('_15AlarmTime') }" /></label><p>区间为 1 ~ 60,默认 50</p>`, '啤酒提醒时间设定');
|
|
||||||
let confirm = document.createElement('button');
|
|
||||||
confirm.innerHTML = '确定';
|
|
||||||
confirm.style.float = 'right';
|
|
||||||
confirm.addEventListener('click', () => {
|
|
||||||
let input: HTMLInputElement = popup.getElement().querySelector('input');
|
|
||||||
let num = (input.value as any) | 0;
|
|
||||||
if (num === WuhuConfig.get('_15AlarmTime')) return;
|
|
||||||
if (num < 1 || num > 60) num = 50;
|
|
||||||
input.value = num.toString();
|
|
||||||
WuhuConfig.set('_15AlarmTime', num);
|
|
||||||
this.set_time(num);
|
|
||||||
// 之前的运行状态
|
|
||||||
if (this.is_running()) this.start();
|
|
||||||
popup.close();
|
|
||||||
});
|
|
||||||
popup.getElement().appendChild(confirm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface BeerMonitorLoop {
|
|
||||||
start?: Function;
|
|
||||||
stop?: Function;
|
|
||||||
set_time?: Function;
|
|
||||||
status?: Function;
|
|
||||||
is_running?: Function;
|
|
||||||
skip_today?: Function;
|
|
||||||
}
|
|
||||||
@ -1,85 +0,0 @@
|
|||||||
import WuhuBase from "../WuhuBase";
|
|
||||||
import WuhuConfig from "../WuhuConfig";
|
|
||||||
import Log from "../Log";
|
|
||||||
import CommonUtils from "../utils/CommonUtils";
|
|
||||||
import FetchUtils from "../utils/FetchUtils";
|
|
||||||
import InfoUtils from "../utils/InfoUtils";
|
|
||||||
import Alert from "../utils/Alert";
|
|
||||||
import TRAVEL_STATE from "../../enum/TravelState";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 公司助手
|
|
||||||
*/
|
|
||||||
export default class CompanyHelper extends WuhuBase {
|
|
||||||
className = 'CompanyHelper';
|
|
||||||
|
|
||||||
public constructor() {
|
|
||||||
super();
|
|
||||||
WuhuConfig.get('CHTrainsDetectSwitch') && this.trainsDetect().then();
|
|
||||||
}
|
|
||||||
|
|
||||||
public detectNow(): void {
|
|
||||||
this.trainsDetect(true).then();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 火车检测
|
|
||||||
* 每日判断一次,非公司老板跳过检测
|
|
||||||
* TODO 优化、URL判断
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
private async trainsDetect(test: boolean = false): Promise<null> {
|
|
||||||
// 通过用户的icon判断公司老板
|
|
||||||
if ((await InfoUtils.getInstance().getSessionData()).statusIcons.icons.company.iconID !== 'icon73') {
|
|
||||||
Log.info('火车检测跳过:非公司老板');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 上次检测时间戳
|
|
||||||
let lastDetect: number = WuhuConfig.get('CHTrainsDetect') || 0;
|
|
||||||
// 检测是否过了一天
|
|
||||||
if (test || CommonUtils.getInstance().isNewDay(lastDetect, -6)) {
|
|
||||||
let travelStage = CommonUtils.getInstance().getTravelStage(),
|
|
||||||
userStatus = (await InfoUtils.getInstance().getUserState()).status;
|
|
||||||
test && Log.info({ travelStage, userStatus });
|
|
||||||
if (travelStage === TRAVEL_STATE.IN_TORN && userStatus === 'ok')
|
|
||||||
FetchUtils.getInstance().fetchText('/companies.php')
|
|
||||||
.then(res => {
|
|
||||||
let tmp: HTMLElement = document.createElement('div');
|
|
||||||
let bodyTagStart = CommonUtils.getInstance().matchOne(res, /<body.+>/);
|
|
||||||
if (!bodyTagStart) {
|
|
||||||
Log.warn('火车检测: 无法获取数据');
|
|
||||||
throw new Error('火车检测: 无法获取数据');
|
|
||||||
}
|
|
||||||
tmp.innerHTML = res.split(bodyTagStart)[1].split('</body>')[0].trim()
|
|
||||||
.replaceAll('rel="stylesheet"', '')
|
|
||||||
.replaceAll('.css', '?404')
|
|
||||||
.replaceAll('type="text/javascript"', 'type="application/json"');
|
|
||||||
let trainsNode = tmp.querySelector('span.trains');
|
|
||||||
if (!trainsNode) {
|
|
||||||
Log.error('火车检测出错: 无法获取火车数');
|
|
||||||
throw new Error('火车检测出错: 无法获取火车数');
|
|
||||||
}
|
|
||||||
let trains: number = parseInt(trainsNode.innerText);
|
|
||||||
let stars: number = tmp.querySelectorAll('.company-rating .active').length / 2 || 1;
|
|
||||||
WuhuConfig.set('CHTrainsDetect', Date.now());
|
|
||||||
Log.info('火车检测: 火车/星级: ' + trains + '/' + stars);
|
|
||||||
Log.info({ tmp });
|
|
||||||
if (trains + stars > 20) {
|
|
||||||
new Alert(`公司助手<br/><br/>火车检测:火车明日将溢出!${ trains }/20火车`, {
|
|
||||||
timeout: 15,
|
|
||||||
force: true,
|
|
||||||
sysNotify: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
tmp.remove();
|
|
||||||
tmp = null;
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
Log.error('火车检测出错', error);
|
|
||||||
});
|
|
||||||
else Log.warn('[火车检测] 用户状态错误,跳过火车检测', { travelStage, userStatus });
|
|
||||||
} else {
|
|
||||||
Log.info('火车检测:今日已提醒,跳过');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,47 +0,0 @@
|
|||||||
import WuhuBase from "../WuhuBase";
|
|
||||||
import Log from "../Log";
|
|
||||||
import WuhuConfig from "../WuhuConfig";
|
|
||||||
import CommonUtils from "../utils/CommonUtils";
|
|
||||||
import TornStyleBlock from "../utils/TornStyleBlock";
|
|
||||||
import TornStyleSwitch from "../utils/TornStyleSwitch";
|
|
||||||
import FetchUtils from "../utils/FetchUtils";
|
|
||||||
|
|
||||||
export default class ProfileHelper extends WuhuBase {
|
|
||||||
className = 'ProfileHelper';
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
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];
|
|
||||||
// id获取格式判断
|
|
||||||
if (!CommonUtils.getInstance().isValidUid(id)) {
|
|
||||||
Log.error('[ProfileHelper] id格式错误');
|
|
||||||
}
|
|
||||||
if (WuhuConfig.get('HideProfileImg')) {
|
|
||||||
Log.info('[ProfileHelper] 隐藏头像');
|
|
||||||
document.body.classList.toggle('wh-hide_profile_img');
|
|
||||||
}
|
|
||||||
let block = new TornStyleBlock('芜湖助手').insert2Dom();
|
|
||||||
// 隐藏头像
|
|
||||||
let hideImgSwitch = new TornStyleSwitch('隐藏头像', WuhuConfig.get('HideProfileImg'));
|
|
||||||
block.append(hideImgSwitch.getBase());
|
|
||||||
hideImgSwitch.getInput().addEventListener('change', () => {
|
|
||||||
document.body.classList.toggle('wh-hide_profile_img');
|
|
||||||
WuhuConfig.set('HideProfileImg', hideImgSwitch.getInput().checked, true);
|
|
||||||
});
|
|
||||||
// 曾用名
|
|
||||||
let nameHistoryNode;
|
|
||||||
if (WuhuConfig.get('ShowNameHistory')) {
|
|
||||||
nameHistoryNode = document.createElement('p');
|
|
||||||
nameHistoryNode.innerHTML = '曾用名:';
|
|
||||||
block.append(nameHistoryNode);
|
|
||||||
FetchUtils.getInstance().getProfile(id).then((res) => {
|
|
||||||
if (res.userInformation.previousAliases.length > 0) {
|
|
||||||
res.userInformation.previousAliases.forEach(item => nameHistoryNode.innerHTML += item + ' ');
|
|
||||||
} else {
|
|
||||||
nameHistoryNode.innerHTML += '暂无';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
import WuhuBase from "../WuhuBase";
|
|
||||||
import TornStyleBlock from "../utils/TornStyleBlock";
|
|
||||||
import WuhuConfig from "../WuhuConfig";
|
|
||||||
import TornStyleSwitch from "../utils/TornStyleSwitch";
|
|
||||||
|
|
||||||
export default class StackHelper extends WuhuBase {
|
|
||||||
className = 'StackHelper';
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
let block = new TornStyleBlock('叠E保护').insert2Dom();
|
|
||||||
let switcher = new TornStyleSwitch('启用');
|
|
||||||
let input = switcher.getInput();
|
|
||||||
block.append(switcher.getBase());
|
|
||||||
input.checked = WuhuConfig.get('SEProtect');
|
|
||||||
if (input.checked) document.body.classList.add('wh-gym-stack');
|
|
||||||
// 绑定点击事件
|
|
||||||
input.onchange = e => {
|
|
||||||
let target = e.target as HTMLInputElement;
|
|
||||||
document.body.classList.toggle('wh-gym-stack');
|
|
||||||
WuhuConfig.set('SEProtect', target.checked, true);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,61 +0,0 @@
|
|||||||
import CommonUtils from "../utils/CommonUtils";
|
|
||||||
import Log from "../Log";
|
|
||||||
import WuhuBase from "../WuhuBase";
|
|
||||||
import UserScriptEngine from "../../enum/UserScriptEngine";
|
|
||||||
import Popup from "../utils/Popup";
|
|
||||||
import STOCK_IMG_HTML from "../../static/html/stock_img.html";
|
|
||||||
import * as FILTER from "../../static/json/for_stock_item_filter.json";
|
|
||||||
import WindowActiveState from "./WindowActiveState";
|
|
||||||
|
|
||||||
export default class TravelItem extends WuhuBase {
|
|
||||||
className = 'TravelItem';
|
|
||||||
private readonly apiUrl: string = 'https://yata.yt/api/v1/travel/export/';
|
|
||||||
private foreignStockInfo: any = null;
|
|
||||||
|
|
||||||
public constructor() {
|
|
||||||
super();
|
|
||||||
window.setInterval(async () => {
|
|
||||||
if (!WindowActiveState.getInstance().get()) return;
|
|
||||||
Log.info('fetching ', this.apiUrl);
|
|
||||||
this.foreignStockInfo = JSON.parse(await CommonUtils.COFetch(this.apiUrl));
|
|
||||||
Log.info({ 'fetch returned': this.foreignStockInfo });
|
|
||||||
}, 30 * 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 呈现内容
|
|
||||||
public async clickHandler(): Promise<void> {
|
|
||||||
if (CommonUtils.getScriptEngine() === UserScriptEngine.RAW) {
|
|
||||||
new Popup(STOCK_IMG_HTML.replace('{{}}', performance.now().toString()), '飞花库存');
|
|
||||||
} else {
|
|
||||||
const popup = new Popup("请稍后 " + CommonUtils.loading_gif_html(), '飞花库存');
|
|
||||||
let table = `<table><tr><th colspan="2">目的地 - 更新时间</th><th colspan="3">库存</th></tr>`;
|
|
||||||
const dest = FILTER.default;
|
|
||||||
const now = new Date();
|
|
||||||
const res = await this.get();
|
|
||||||
Log.info({ res })
|
|
||||||
if (!res || !res.stocks) return;
|
|
||||||
dest.forEach(el => {
|
|
||||||
const update = (now.getTime() - new Date(res.stocks[el.name]['update'] * 1000).getTime()) / 1000 | 0
|
|
||||||
table += `<tr><td>${ el.show }</td><td>${ update / 60 | 0 }分${ update % 60 | 0 }秒前</td>`;
|
|
||||||
let count = 0;
|
|
||||||
res.stocks[el.name]['stocks'].forEach(stock => {
|
|
||||||
if (el.stocks[stock.name]) {
|
|
||||||
table += `<td${ stock['quantity'] === 0 ? ' style="background-color:#f44336;color:white;border-color:#000;"' : '' }>${ el.stocks[stock.name] } (${ stock['quantity'] })</td>`;
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
while (count < 3) {
|
|
||||||
count++;
|
|
||||||
table += '<td></td>';
|
|
||||||
}
|
|
||||||
table += '</tr>';
|
|
||||||
});
|
|
||||||
table += '</table>';
|
|
||||||
popup.getElement().innerHTML = table;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async get() {
|
|
||||||
return this.foreignStockInfo ||= JSON.parse(await CommonUtils.COFetch(this.apiUrl));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,77 +0,0 @@
|
|||||||
import WuhuBase from "../WuhuBase";
|
|
||||||
import Popup from "../utils/Popup";
|
|
||||||
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";
|
|
||||||
|
|
||||||
export default class AdditionalSettingsHandler extends WuhuBase {
|
|
||||||
className = 'AdditionalSettingsHandler';
|
|
||||||
|
|
||||||
public handle(): 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[] = [
|
|
||||||
{
|
|
||||||
domType: 'button', domId: '', domText: '清空设置', clickFunc() {
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
domType: "button", domId: '', domText: '通知权限', clickFunc() {
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
domType: 'button', domId: '', domText: '第三方API通信权限', clickFunc() {
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
domType: 'button', domId: '', domText: '小窗犯罪', clickFunc() {
|
|
||||||
IFrameCrimeHandler.getInstance().handle()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
domType: 'button',
|
|
||||||
domId: '',
|
|
||||||
domText: '飞贼小助手',
|
|
||||||
tip: '加载从PC端移植的伞佬的油猴版飞贼小助手',
|
|
||||||
clickFunc() {
|
|
||||||
loadGS(CommonUtils.getScriptEngine())
|
|
||||||
}
|
|
||||||
},
|
|
||||||
];
|
|
||||||
menuList.forEach(i => pop.getElement().append(CommonUtils.getInstance().elemGenerator(i, pop.getElement())));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,49 +0,0 @@
|
|||||||
import WuhuBase from "../WuhuBase";
|
|
||||||
import Popup from "../utils/Popup";
|
|
||||||
import CommonUtils from "../utils/CommonUtils";
|
|
||||||
import MDUtils from "../utils/MDUtils";
|
|
||||||
import Log from "../Log";
|
|
||||||
|
|
||||||
export default class ChangeLogHandler extends WuhuBase {
|
|
||||||
className = 'ChangeLogHandler';
|
|
||||||
|
|
||||||
public handle(): 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/>',
|
|
||||||
'更新历史'
|
|
||||||
).getElement();
|
|
||||||
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 = MDUtils.getInstance().parse(update);
|
|
||||||
popup.append(md);
|
|
||||||
progressBar.style.width = '100%';
|
|
||||||
progressText.innerText = '加载完成';
|
|
||||||
|
|
||||||
window.setTimeout(() => {
|
|
||||||
progressBar.remove();
|
|
||||||
progressText.remove()
|
|
||||||
}, 3000);
|
|
||||||
})
|
|
||||||
.catch(e => {
|
|
||||||
Log.error(e);
|
|
||||||
progressBar.remove();
|
|
||||||
progressText.innerText = '无法加载';
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
import WuhuBase from "../WuhuBase";
|
|
||||||
import Popup from "../utils/Popup";
|
|
||||||
import WuhuConfig from "../WuhuConfig";
|
|
||||||
|
|
||||||
export default class CustomCssHandler extends WuhuBase {
|
|
||||||
className = 'CustomCssHandler';
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public handle(): void {
|
|
||||||
let pop = new Popup('<div><textarea></textarea><button class="torn-btn">保存</button><style>#wh-popup textarea{display: block;}</style></div>', '自定义CSS');
|
|
||||||
let textarea = pop.getElement().querySelector('textarea');
|
|
||||||
let button = pop.getElement().querySelector('button');
|
|
||||||
textarea.value = WuhuConfig.get('CustomCss') || '';
|
|
||||||
button.addEventListener('click', () => {
|
|
||||||
WuhuConfig.set('CustomCss', textarea.value || '', true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,95 +0,0 @@
|
|||||||
import WuhuBase from "../WuhuBase";
|
|
||||||
import CommonUtils from "../utils/CommonUtils";
|
|
||||||
import Popup from "../utils/Popup";
|
|
||||||
import QUICK_CRIMES_HTML from "../../static/html/quick_crimes.html";
|
|
||||||
|
|
||||||
export default class IFrameCrimeHandler extends WuhuBase {
|
|
||||||
className = 'IFrameCrimeHandler';
|
|
||||||
|
|
||||||
public handle(): void {
|
|
||||||
// 弹出小窗口
|
|
||||||
const ifHTML = `<iframe src="/crimes.php?step=main" style="width:100%;max-width: 450px;margin: 0 auto;display: none;height: 340px;"></iframe>`;
|
|
||||||
const popup_insert = `<p>加载中请稍后${ CommonUtils.loading_gif_html() }</p><div id="wh-quick-crime-if-container"></div>`;
|
|
||||||
const $popup = new Popup(popup_insert, '小窗快速犯罪').getElement();
|
|
||||||
// 运行状态node
|
|
||||||
let loading_node = $popup.querySelector('p:first-of-type');
|
|
||||||
// if容器
|
|
||||||
const if_cont = $popup.querySelector('#wh-quick-crime-if-container');
|
|
||||||
if_cont.innerHTML = ifHTML;
|
|
||||||
|
|
||||||
// if内未加载脚本时插入的快捷crime node
|
|
||||||
const mobile_prepend_node = document.createElement('div');
|
|
||||||
mobile_prepend_node.classList.add('wh-translate');
|
|
||||||
mobile_prepend_node.innerHTML = QUICK_CRIMES_HTML;
|
|
||||||
|
|
||||||
// if对象加载后运行
|
|
||||||
let cIframe = $popup.querySelector('iframe');
|
|
||||||
|
|
||||||
// 加载状态
|
|
||||||
const if_onload_func = () => {
|
|
||||||
// if内部文档对象
|
|
||||||
const ifDocu = cIframe.contentWindow.document;
|
|
||||||
// 内部插件运行flag
|
|
||||||
const ifWH = cIframe.contentWindow.WHTRANS;
|
|
||||||
// 文档加载完成后移除
|
|
||||||
if (!!loading_node) loading_node.remove();
|
|
||||||
// 文档加载完成后才显示if
|
|
||||||
cIframe.style.display = 'block';
|
|
||||||
// 验证码flag
|
|
||||||
const isValidate = ifDocu.querySelector('h4#skip-to-content').innerText.toLowerCase().includes('validate');
|
|
||||||
// 如果iframe内部未运行脚本
|
|
||||||
if (ifWH === undefined) {
|
|
||||||
// 隐藏顶部
|
|
||||||
CommonUtils.elementReady('#header-root', ifDocu).then(e => e.style.display = 'none');
|
|
||||||
// 隐藏4条
|
|
||||||
CommonUtils.elementReady('#sidebarroot', ifDocu).then(e => e.style.display = 'none');
|
|
||||||
// 隐藏聊天
|
|
||||||
CommonUtils.elementReady('#chatRoot', ifDocu).then(e => e.style.display = 'none');
|
|
||||||
// 非验证码页面隐藏滚动条
|
|
||||||
if (!isValidate) ifDocu.body.style.overflow = 'hidden';
|
|
||||||
// 调整容器位置
|
|
||||||
CommonUtils.elementReady('.content-wrapper', ifDocu).then(elem => {
|
|
||||||
// 加入
|
|
||||||
elem.prepend(mobile_prepend_node);
|
|
||||||
elem.style.margin = '0px';
|
|
||||||
elem.style.position = 'absolute';
|
|
||||||
elem.style.top = '-35px';
|
|
||||||
new MutationObserver((m, o) => {
|
|
||||||
o.disconnect();
|
|
||||||
if (!elem.querySelector('.wh-translate')) elem.prepend(mobile_prepend_node);
|
|
||||||
o.observe(elem, { childList: true, subtree: true });
|
|
||||||
})
|
|
||||||
.observe(elem, { childList: true, subtree: true });
|
|
||||||
});
|
|
||||||
// 隐藏返回顶部按钮
|
|
||||||
CommonUtils.elementReady('#go-to-top-btn button', ifDocu).then(e => e.style.display = 'none');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
cIframe.onload = if_onload_func;
|
|
||||||
|
|
||||||
// 超时判断
|
|
||||||
let time_counter = 0;
|
|
||||||
let time_out_id = window.setInterval(() => {
|
|
||||||
loading_node = $popup.querySelector('p:first-of-type');
|
|
||||||
if (!loading_node) {
|
|
||||||
clearInterval(time_out_id);
|
|
||||||
time_out_id = undefined;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
time_counter++;
|
|
||||||
if (time_counter > 0 && !loading_node.querySelector('button')) {
|
|
||||||
const reload_btn = document.createElement('button');
|
|
||||||
reload_btn.innerHTML = '重新加载';
|
|
||||||
reload_btn.onclick = () => {
|
|
||||||
reload_btn.remove();
|
|
||||||
time_counter = 0;
|
|
||||||
if_cont.innerHTML = null;
|
|
||||||
if_cont.innerHTML = ifHTML;
|
|
||||||
cIframe = $popup.querySelector('iframe');
|
|
||||||
cIframe.onload = if_onload_func;
|
|
||||||
};
|
|
||||||
loading_node.append(reload_btn);
|
|
||||||
}
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
import WuhuBase from "../WuhuBase";
|
|
||||||
import WuhuConfig from "../WuhuConfig";
|
|
||||||
import PRICE_WATCHER_HTML from "../../static/html/price_watcher.html";
|
|
||||||
import Popup from "../utils/Popup";
|
|
||||||
import Global from "../Global";
|
|
||||||
|
|
||||||
export default class ItemPriceWatcherHandler extends WuhuBase {
|
|
||||||
className = 'ItemPriceWatcherHandler';
|
|
||||||
|
|
||||||
public handle(): void {
|
|
||||||
const watcher_conf = WuhuConfig.get('priceWatcher');
|
|
||||||
const pre_str = JSON.stringify(watcher_conf);
|
|
||||||
const html = PRICE_WATCHER_HTML
|
|
||||||
.replace('{{}}', localStorage.getItem('APIKey') || '不可用')
|
|
||||||
.replace('{{}}', Global.getInstance().isPDA ? Global.getInstance().PDA_APIKey : '不可用')
|
|
||||||
.replace('{{}}', watcher_conf['pt'] || -1)
|
|
||||||
.replace('{{}}', watcher_conf['xan'] || -1);
|
|
||||||
const popup = new Popup(html, '价格监视设置');
|
|
||||||
popup.getElement().querySelector('button').onclick = () => {
|
|
||||||
const [pt_node, xan_node] = Array.from(<NodeListOf<HTMLInputElement>>popup.getElement().querySelectorAll('input[type="number"]'));
|
|
||||||
watcher_conf.pt = (pt_node.value as any) | 0;
|
|
||||||
watcher_conf.xan = (xan_node.value as any) | 0;
|
|
||||||
if (JSON.stringify(watcher_conf) !== pre_str) WuhuConfig.set('priceWatcher', watcher_conf);
|
|
||||||
popup.close();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
import WuhuBase from "../WuhuBase";
|
|
||||||
import Alert from "../utils/Alert";
|
|
||||||
|
|
||||||
export default class UpdateTranslateDict extends WuhuBase {
|
|
||||||
className = 'UpdateTranslateDict';
|
|
||||||
|
|
||||||
public handle(): void {
|
|
||||||
new Alert('计划中');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,47 +0,0 @@
|
|||||||
import WuhuBase from "../WuhuBase";
|
|
||||||
import Log from "../Log";
|
|
||||||
import Popup from "../utils/Popup";
|
|
||||||
import CommonUtils from "../utils/CommonUtils";
|
|
||||||
import VIEW_LOGS_HANDLER_HTML from "../../static/html/view_logs_handler.html";
|
|
||||||
|
|
||||||
export default class ViewLogsHandler extends WuhuBase {
|
|
||||||
className = 'ViewLogsHandler';
|
|
||||||
|
|
||||||
public handle(): void {
|
|
||||||
let logCounter = Log.getCounter();
|
|
||||||
let pop = new Popup(VIEW_LOGS_HANDLER_HTML
|
|
||||||
.replace('{{}}', logCounter.info.toString())
|
|
||||||
.replace('{{}}', logCounter.warning.toString())
|
|
||||||
.replace('{{}}', logCounter.error.toString()), '查看日志');
|
|
||||||
window.setTimeout(() => {
|
|
||||||
let container = pop.getElement().querySelector('div');
|
|
||||||
let text = document.createElement('div');
|
|
||||||
let logs = Log.getLogs().split('\r\n');
|
|
||||||
logs.forEach(log => {
|
|
||||||
let p = document.createElement('p');
|
|
||||||
p.innerText = log;
|
|
||||||
if (log.slice(0, 10).includes('ERR')) {
|
|
||||||
p.style.backgroundColor = '#ff000080';
|
|
||||||
} else if (log.slice(0, 10).includes('WRN')) {
|
|
||||||
p.style.backgroundColor = '#ffff0080';
|
|
||||||
}
|
|
||||||
text.append(p);
|
|
||||||
});
|
|
||||||
pop.getElement().querySelector('button').addEventListener('click', () => window.setTimeout(() => {
|
|
||||||
CommonUtils.getInstance()
|
|
||||||
.exportTextFile(
|
|
||||||
'wuhu_log_' + Log.getTime()
|
|
||||||
.replace('[', '')
|
|
||||||
.replace(']', '')
|
|
||||||
.replace(' ', '')
|
|
||||||
.replace('.', '')
|
|
||||||
.replaceAll('-', '')
|
|
||||||
.replaceAll(':', '') + '.log',
|
|
||||||
[Log.getLogs()]
|
|
||||||
);
|
|
||||||
}, 0));
|
|
||||||
container.innerHTML = '';
|
|
||||||
container.append(text);
|
|
||||||
}, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
import Log from "../Log";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 基类、单例
|
|
||||||
*/
|
|
||||||
export default class Provider {
|
|
||||||
protected readonly className: string = 'Provider';
|
|
||||||
private static instance;
|
|
||||||
|
|
||||||
private static readonly pool = {};
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public static getInstance<T extends typeof Provider>(this: T): InstanceType<T> {
|
|
||||||
// return this.instance ||= new this();
|
|
||||||
if (!this.instance) {
|
|
||||||
let startTime = performance.now();
|
|
||||||
this.instance = new this();
|
|
||||||
let thatName = this.instance.getClassName() || this.name;
|
|
||||||
Log.info('实例已创建,', thatName, this.instance, '耗时' + ((performance.now() - startTime) | 0) + 'ms');
|
|
||||||
Provider.pool[thatName] = this.instance;
|
|
||||||
}
|
|
||||||
return this.instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static getPool() {
|
|
||||||
return {
|
|
||||||
pool: Provider.pool,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
import Log from "../Log";
|
|
||||||
import ZhongIcon from "../ZhongIcon";
|
|
||||||
|
|
||||||
export default class Starter {
|
|
||||||
public static run(T): void {
|
|
||||||
|
|
||||||
if (window.WHTRANS) throw '退出, 已运行次数' + window.WHTRANS;
|
|
||||||
window.WHTRANS = window.WHTRANS === undefined ? 1 : window.WHTRANS++;
|
|
||||||
|
|
||||||
let started = performance.now();
|
|
||||||
try {
|
|
||||||
T.main();
|
|
||||||
} catch (e) {
|
|
||||||
Log.error('[Starter]加载出错信息: ' + e.stack || e.message);
|
|
||||||
}
|
|
||||||
let runTime: number = (performance.now() - started) | 0;
|
|
||||||
Log.info(`芜湖脚本完成加载, 耗时${ runTime }ms`);
|
|
||||||
if (ZhongIcon.ZhongNode && ZhongIcon.ZhongNode.initTimer)
|
|
||||||
ZhongIcon.ZhongNode.initTimer.innerHTML = `加载时间 ${ runTime }ms`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
import WuhuBase from "../WuhuBase";
|
|
||||||
import Log from "../Log";
|
|
||||||
import ZhongIcon from "../ZhongIcon";
|
|
||||||
|
|
||||||
export default class ActionButtonUtils extends WuhuBase {
|
|
||||||
className = 'ActionButtonUtils';
|
|
||||||
private hasAdded: boolean = false;
|
|
||||||
|
|
||||||
public add(txt: string, func: (ev: Event) => void = () => null): void {
|
|
||||||
if (!this.hasAdded) this.handle(txt, func);
|
|
||||||
else Log.warn('ActionButton已存在');
|
|
||||||
}
|
|
||||||
|
|
||||||
private handle(txt, func): void {
|
|
||||||
let btn = document.createElement('button');
|
|
||||||
btn.style.padding = '8px 13px 8px 0';
|
|
||||||
btn.style.verticalAlign = 'bottom';
|
|
||||||
btn.style.color = '#4CAF50';
|
|
||||||
btn.innerHTML = txt;
|
|
||||||
btn.addEventListener('click', func);
|
|
||||||
ZhongIcon.ZhongNode.querySelector('button').after(btn);
|
|
||||||
this.hasAdded = true;
|
|
||||||
Log.info('ActionButton已添加', { txt, func, btn });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,69 +0,0 @@
|
|||||||
import WuhuBase from "../WuhuBase";
|
|
||||||
import Alert from "./Alert";
|
|
||||||
import ISidebarData from "../../interface/ISidebarData";
|
|
||||||
import Log from "../Log";
|
|
||||||
import CommonUtils from "./CommonUtils";
|
|
||||||
import FetchUtils from "./FetchUtils";
|
|
||||||
|
|
||||||
export default class InfoUtils extends WuhuBase {
|
|
||||||
className = 'InfoUtils';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 返回玩家信息的对象 { playername: string, userID: number }
|
|
||||||
* @return {PlayerInfo} rs
|
|
||||||
*/
|
|
||||||
public getPlayerInfo(): PlayerInfo {
|
|
||||||
const node = document.querySelector('script[uid]');
|
|
||||||
if (node) {
|
|
||||||
return {
|
|
||||||
playername: node.getAttribute('name'),
|
|
||||||
userID: parseInt(node.getAttribute('uid')),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
new Alert('严重错误:芜湖助手无法获取用户数据,已退出');
|
|
||||||
throw '芜湖助手无法获取用户数据';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 返回玩家的部分实时数据
|
|
||||||
*/
|
|
||||||
public async getSessionData(): Promise<ISidebarData> {
|
|
||||||
let field: string = 'sidebarData' + this.getPlayerInfo().userID;
|
|
||||||
let ret: ISidebarData = {};
|
|
||||||
return new Promise(async resolve => {
|
|
||||||
let c = 0;
|
|
||||||
while (!sessionStorage.getItem(field) && c < 50) {
|
|
||||||
c++;
|
|
||||||
await CommonUtils.getInstance().sleep(10);
|
|
||||||
}
|
|
||||||
if (sessionStorage.getItem(field)) {
|
|
||||||
ret = JSON.parse(sessionStorage.getItem(field));
|
|
||||||
} else {
|
|
||||||
Log.info('无法从sessionStorage获取数据')
|
|
||||||
ret = await (await FetchUtils.getInstance().ajaxFetch({
|
|
||||||
url: window.addRFC('/sidebarAjaxAction.php?q=getSidebarData'),
|
|
||||||
method: 'POST',
|
|
||||||
})).json();
|
|
||||||
sessionStorage.setItem(field, JSON.stringify(ret));
|
|
||||||
}
|
|
||||||
ret.headerData = JSON.parse(sessionStorage.getItem('headerData'));
|
|
||||||
resolve(ret);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 返回玩家当前的边栏菜单列表 如gym crimes
|
|
||||||
*/
|
|
||||||
public async getSidebarData() {
|
|
||||||
return (await this.getSessionData()).areas;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 玩家的基础信息
|
|
||||||
* {status: string, isLoggedIn: boolean, isDonator: boolean, isTravelling: boolean, isAbroad: boolean}
|
|
||||||
*/
|
|
||||||
public async getUserState() {
|
|
||||||
return (await this.getSessionData()).headerData.user.state;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,45 +0,0 @@
|
|||||||
import IWHNotify from "../../interface/IWHNotify";
|
|
||||||
import Log from "../Log";
|
|
||||||
import WuhuBase from "../WuhuBase";
|
|
||||||
|
|
||||||
export default class NotificationUtils extends WuhuBase {
|
|
||||||
className = 'NotificationUtils';
|
|
||||||
private permission: boolean = window.Notification && window.Notification.permission === 'granted';
|
|
||||||
|
|
||||||
public push(msg: string, options: IWHNotify = {}): void {
|
|
||||||
let { notifies } = NotificationUtils.glob;
|
|
||||||
|
|
||||||
if (options.sysNotify && this.permission) {
|
|
||||||
let tmpNode = document.createElement('p');
|
|
||||||
tmpNode.innerHTML = msg;
|
|
||||||
let notify = new Notification('芜湖助手', {
|
|
||||||
body: Log.getTime() + '\r\n' + tmpNode.innerText,
|
|
||||||
// requireInteraction: true,
|
|
||||||
// renotify: true,
|
|
||||||
// tag: '芜湖助手' + Utils.getRandomInt(0, 99),
|
|
||||||
});
|
|
||||||
let id = notifies.count++;
|
|
||||||
notifies[id] = notify;
|
|
||||||
notify.addEventListener(
|
|
||||||
'close',
|
|
||||||
() => {
|
|
||||||
notifies[id] = null;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
notify.addEventListener(
|
|
||||||
'click',
|
|
||||||
() => {
|
|
||||||
options.sysNotifyClick ? options.sysNotifyClick() : null;
|
|
||||||
window.focus();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
notify.addEventListener(
|
|
||||||
'show',
|
|
||||||
() => {
|
|
||||||
// setTimeout(() => notify.close(), (options.timeout || 3) * 1000);
|
|
||||||
Log.info('通知id: ', id)
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,54 +0,0 @@
|
|||||||
import WuhuBase from "../WuhuBase";
|
|
||||||
import POPUP_HTML from "../../static/html/popup.html";
|
|
||||||
import Log from "../Log";
|
|
||||||
|
|
||||||
export default class Popup extends WuhuBase {
|
|
||||||
className = 'Popup';
|
|
||||||
private readonly container: HTMLElement = null;
|
|
||||||
private readonly node: HTMLElement = null;
|
|
||||||
|
|
||||||
constructor(innerHTML: string, title: string = '芜湖助手') {
|
|
||||||
super();
|
|
||||||
if (Popup.glob.popup_node) {
|
|
||||||
Log.info('关闭前一个弹窗');
|
|
||||||
Popup.glob.popup_node.close();
|
|
||||||
}
|
|
||||||
Log.info('新建弹窗', { innerHTML, title });
|
|
||||||
const popup = document.createElement('div');
|
|
||||||
popup.id = 'wh-popup';
|
|
||||||
popup.innerHTML = POPUP_HTML.replace('{{}}', title).replace('{{}}', innerHTML);
|
|
||||||
document.body.append(popup);
|
|
||||||
popup.addEventListener('click', e => {
|
|
||||||
e.stopImmediatePropagation();
|
|
||||||
if (e.target === popup) this.close();
|
|
||||||
});
|
|
||||||
this.container = popup;
|
|
||||||
this.node = popup.querySelector('#wh-popup-cont');
|
|
||||||
this.hideChat();
|
|
||||||
Popup.glob.popup_node = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public close() {
|
|
||||||
this.container.remove();
|
|
||||||
this.showChat();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return {HTMLElement} id=wh-popup-cont
|
|
||||||
*/
|
|
||||||
public getElement(): HTMLElement {
|
|
||||||
return this.node;
|
|
||||||
}
|
|
||||||
|
|
||||||
private hideChat() {
|
|
||||||
document.querySelector('#chatRoot').classList.add('wh-hide');
|
|
||||||
}
|
|
||||||
|
|
||||||
private showChat() {
|
|
||||||
document.querySelector('#chatRoot').classList.remove('wh-hide');
|
|
||||||
}
|
|
||||||
|
|
||||||
// 禁止单例调用
|
|
||||||
private getInstance() {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,119 +0,0 @@
|
|||||||
import UserScriptEngine from "../../enum/UserScriptEngine";
|
|
||||||
import addStyle from "../utils/@deprecated/addStyle";
|
|
||||||
import log from "../utils/@deprecated/log";
|
|
||||||
import CommonUtils from "../../class/utils/CommonUtils";
|
|
||||||
import Alert from "../../class/utils/Alert";
|
|
||||||
|
|
||||||
// gs loader
|
|
||||||
export default function loadGS(use) {
|
|
||||||
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);
|
|
||||||
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 (log.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 (log.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,318 +0,0 @@
|
|||||||
import titleTrans from "../translate/titleTrans";
|
|
||||||
import contentTitleLinksTrans from "../translate/contentTitleLinksTrans";
|
|
||||||
import Device from "../../enum/Device";
|
|
||||||
import WuhuBase from "../../class/WuhuBase";
|
|
||||||
import Alert from "../../class/utils/Alert";
|
|
||||||
import ActionButtonUtils from "../../class/utils/ActionButtonUtils";
|
|
||||||
import WuhuConfig from "../../class/WuhuConfig";
|
|
||||||
import CommonUtils from "../../class/utils/CommonUtils";
|
|
||||||
import TRAVEL_ALARM_CSS from "../../static/css/travel_alarm.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";
|
|
||||||
|
|
||||||
export default async function travelHelper(): Promise<void> {
|
|
||||||
let { href, bodyAttrs, device } = WuhuBase.glob;
|
|
||||||
|
|
||||||
if (href.includes('index.php')) {
|
|
||||||
switch (CommonUtils.getInstance().getTravelStage()) {
|
|
||||||
// 飞行中
|
|
||||||
case TRAVEL_STATE.FLYING: {
|
|
||||||
// 飞行闹钟
|
|
||||||
if (device === Device.PC && WuhuConfig.get('trvAlarm')) {
|
|
||||||
// 获取目的地
|
|
||||||
let dest_cn;
|
|
||||||
let country = document.body.getAttribute('data-country');
|
|
||||||
if (country === 'torn') {
|
|
||||||
dest_cn = '回城';
|
|
||||||
} else {
|
|
||||||
dest_cn = {
|
|
||||||
'uk': "英国",
|
|
||||||
'switzerland': "瑞士",
|
|
||||||
'mexico': '墨西哥',
|
|
||||||
'canada': '加拿大',
|
|
||||||
'cayman': '开曼',
|
|
||||||
'hawaii': '夏威夷',
|
|
||||||
'argentina': '阿根廷',
|
|
||||||
'japan': '日本',
|
|
||||||
'china': '中国',
|
|
||||||
'uae': 'UAE',
|
|
||||||
'south-africa': '南非',
|
|
||||||
}[country] || country;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 剩余时间
|
|
||||||
const remaining_arr = document.querySelector('#countrTravel').getAttribute('data-to');
|
|
||||||
|
|
||||||
const wh_trv_alarm = localStorage.getItem('wh_trv_alarm')
|
|
||||||
? JSON.parse(localStorage.getItem('wh_trv_alarm'))
|
|
||||||
: { 'enable': true, 'alert_time': 30, 'node_pos': [240, 240] };
|
|
||||||
const save_trv_settings = () => localStorage.setItem('wh_trv_alarm', JSON.stringify(wh_trv_alarm));
|
|
||||||
|
|
||||||
const wh_trv_alarm_node = document.createElement('div');
|
|
||||||
wh_trv_alarm_node.id = 'wh-trv-alarm';
|
|
||||||
wh_trv_alarm_node.style.left = `${ wh_trv_alarm.node_pos[0] }px`;
|
|
||||||
wh_trv_alarm_node.style.top = `${ wh_trv_alarm.node_pos[1] }px`;
|
|
||||||
wh_trv_alarm_node.innerHTML = TRAVEL_ALARM_HTML
|
|
||||||
.replace('{{}}', dest_cn === '回城' ? dest_cn : '飞往' + dest_cn)
|
|
||||||
.replace('{{}}', wh_trv_alarm.enable ? 'checked ' : '')
|
|
||||||
.replace('{{}}', wh_trv_alarm.alert_time || 30);
|
|
||||||
CommonUtils.addStyle(TRAVEL_ALARM_CSS);
|
|
||||||
document.body.append(wh_trv_alarm_node);
|
|
||||||
// 报错dom
|
|
||||||
const error_node = wh_trv_alarm_node.querySelector('#wh-trv-error') as HTMLElement;
|
|
||||||
// jquery拖动
|
|
||||||
// @ts-ignore
|
|
||||||
$(wh_trv_alarm_node).draggable({
|
|
||||||
containment: "body",
|
|
||||||
distance: 5,
|
|
||||||
handle: "#wh-trv-alarm-title",
|
|
||||||
stop: () => {
|
|
||||||
wh_trv_alarm.node_pos = [parseInt(wh_trv_alarm_node.style.left), parseInt(wh_trv_alarm_node.style.top)];
|
|
||||||
save_trv_settings();
|
|
||||||
},
|
|
||||||
scroll: false,
|
|
||||||
});
|
|
||||||
// 剩余时间dom
|
|
||||||
const remaining_node = wh_trv_alarm_node.querySelector('#wh-trv-alarm-remaining');
|
|
||||||
// 设定闹钟响的按钮
|
|
||||||
const set_node = wh_trv_alarm_node.querySelectorAll('#wh-trv-alarm-cont button')[0] as HTMLButtonElement;
|
|
||||||
// 落地前响铃时长
|
|
||||||
const cd_time = wh_trv_alarm_node.querySelector('input[type="number"]') as HTMLInputElement;
|
|
||||||
let count_down_notify: MyHTMLElement | { close: Function } = {
|
|
||||||
close: () => {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
set_node.onclick = () => {
|
|
||||||
try {
|
|
||||||
wh_trv_alarm.alert_time = parseInt(cd_time.value);
|
|
||||||
} catch {
|
|
||||||
wh_trv_alarm.alert_time = 30;
|
|
||||||
}
|
|
||||||
save_trv_settings();
|
|
||||||
set_node.value = wh_trv_alarm.alert_time;
|
|
||||||
count_down_notify.close();
|
|
||||||
count_down_notify = new Alert('设置已更新');
|
|
||||||
};
|
|
||||||
// 停止响铃按钮
|
|
||||||
const stop_node = wh_trv_alarm_node.querySelectorAll('#wh-trv-alarm-cont button')[1] as HTMLButtonElement;
|
|
||||||
stop_node.onclick = () => {
|
|
||||||
user_stop_alert = true;
|
|
||||||
stop_node.innerText = '本次已关闭';
|
|
||||||
stop_node.disabled = true;
|
|
||||||
}
|
|
||||||
// 开启闹钟勾选
|
|
||||||
const enable_node = wh_trv_alarm_node.querySelector('#wh-trv-alarm-cont input[type="checkbox"]') as HTMLInputElement;
|
|
||||||
let on_off_notify: MyHTMLElement | { close: Function } = {
|
|
||||||
close: () => {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
enable_node.onchange = ev => {
|
|
||||||
wh_trv_alarm.enable = (<HTMLInputElement>ev.target).checked;
|
|
||||||
save_trv_settings();
|
|
||||||
on_off_notify.close();
|
|
||||||
on_off_notify = new Alert(wh_trv_alarm.enable ? '闹钟已开启' : '闹钟已关闭');
|
|
||||||
};
|
|
||||||
// 剩余时间 秒
|
|
||||||
const remaining_sec = parseInt(remaining_arr);
|
|
||||||
// 落地时timestamp
|
|
||||||
const land_timestamp = Date.now() + remaining_sec * 1000;
|
|
||||||
// 音频dom
|
|
||||||
const audio = document.createElement('audio');
|
|
||||||
audio.src = 'https://www.torn.com/js/chat/sounds/Warble_1.mp3';
|
|
||||||
audio.play()
|
|
||||||
.then(() => audio.pause())
|
|
||||||
.catch(() => {
|
|
||||||
error_node.style.display = 'table';
|
|
||||||
const func = () => {
|
|
||||||
error_node.remove();
|
|
||||||
document.body.removeEventListener('click', func);
|
|
||||||
};
|
|
||||||
document.body.addEventListener('click', func);
|
|
||||||
});
|
|
||||||
// 是否正在响铃
|
|
||||||
let audio_play_flag = false;
|
|
||||||
// 用户是否停止当前响铃
|
|
||||||
let user_stop_alert = false;
|
|
||||||
// 响铃循环id
|
|
||||||
let audio_play_id = null;
|
|
||||||
// 响铃的方法
|
|
||||||
let audio_play_handle = () => {
|
|
||||||
if (user_stop_alert) {
|
|
||||||
clearInterval(audio_play_id);
|
|
||||||
audio_play_id = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!audio_play_flag || !wh_trv_alarm.enable) return;
|
|
||||||
audio.play().then();
|
|
||||||
};
|
|
||||||
// 飞机小动画字符
|
|
||||||
const flying_arr = [
|
|
||||||
'✈ ',
|
|
||||||
' ✈ ',
|
|
||||||
' ✈ ',
|
|
||||||
' ✈ ',
|
|
||||||
' ✈ ',
|
|
||||||
' ✈ ',
|
|
||||||
' ✈ ',
|
|
||||||
' ✈ ',
|
|
||||||
' ✈ ',
|
|
||||||
' ✈ ',
|
|
||||||
];
|
|
||||||
// 飞行的状态dom
|
|
||||||
const flying_status = wh_trv_alarm_node.querySelector('#wh-trv-status');
|
|
||||||
// 飞机的小动画dom
|
|
||||||
const flying_ani = flying_status.nextElementSibling;
|
|
||||||
// 飞机的计数
|
|
||||||
let flying_index = 0;
|
|
||||||
const id = window.setInterval(() => {
|
|
||||||
const remaining_time = (land_timestamp - Date.now()) / 1000 | 0;
|
|
||||||
remaining_node.innerText = `${ remaining_time / 3600 | 0 }时${ remaining_time % 3600 / 60 | 0 }分${ remaining_time % 60 }秒`;
|
|
||||||
|
|
||||||
if (remaining_time < wh_trv_alarm.alert_time) {
|
|
||||||
// flying_status.innerHTML = `即将落地...`;
|
|
||||||
if (wh_trv_alarm.enable) {
|
|
||||||
// 播放提示音
|
|
||||||
audio_play_flag = true;
|
|
||||||
if (audio_play_id === null && !user_stop_alert) audio_play_id = window.setInterval(audio_play_handle, 750);
|
|
||||||
stop_node.parentElement.classList.remove('wh-trv-alarm-stop-hide');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// flying_status.innerHTML = `飞行中...`;
|
|
||||||
if (wh_trv_alarm.enable) {
|
|
||||||
clearInterval(audio_play_id);
|
|
||||||
audio_play_id = null;
|
|
||||||
stop_node.parentElement.classList.add('wh-trv-alarm-stop-hide');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
flying_ani.innerHTML = `${ flying_arr[flying_index] }`;
|
|
||||||
flying_index = (flying_index + 1) % flying_arr.length;
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 落地转跳 落地前事件
|
|
||||||
if (WuhuConfig.get('landedRedirect') && document.querySelector('#tcLogo[title]') === null) {
|
|
||||||
window.addEventListener('beforeunload', () => {
|
|
||||||
let obj = { url: WuhuConfig.get('landedRedirect'), timestamp: Date.now() };
|
|
||||||
sessionStorage['wh-landed-redirect'] = JSON.stringify(obj);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// 海外落地
|
|
||||||
case TRAVEL_STATE.ABROAD: {
|
|
||||||
// 一键回城
|
|
||||||
ActionButtonUtils.getInstance().add('直接回城', travelBack);
|
|
||||||
// 海外警告
|
|
||||||
if (WuhuConfig.get('abroadWarning')) {
|
|
||||||
let c = 1;
|
|
||||||
setInterval(() => new Alert(`警告:您已海外落地${ c++ * 30 }秒`, {
|
|
||||||
timeout: 30,
|
|
||||||
sysNotify: true
|
|
||||||
}), 30000);
|
|
||||||
}
|
|
||||||
// 解毒提醒
|
|
||||||
if (bodyAttrs['data-country'] === 'switzerland') {
|
|
||||||
let block = new TornStyleBlock('解毒提醒');
|
|
||||||
block.setContent('<p><a href="/index.php?page=rehab">❤️ 点击前往解毒</a></p>');
|
|
||||||
document.querySelector('h4#skip-to-content').before(block.getBase());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// 主页界面
|
|
||||||
case TRAVEL_STATE.IN_TORN: {
|
|
||||||
// 落地转跳
|
|
||||||
if (sessionStorage['wh-landed-redirect']) {
|
|
||||||
let { url, timestamp } = JSON.parse(sessionStorage['wh-landed-redirect']);
|
|
||||||
if (Date.now() - timestamp < 30000) {
|
|
||||||
sessionStorage.removeItem('wh-landed-redirect');
|
|
||||||
location.href = url;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 起飞页面
|
|
||||||
else if (href.contains(/travelagency\.php/)) {
|
|
||||||
// 起飞提醒 TODO 去除jquery mutation
|
|
||||||
if (WuhuConfig.get('energyAlert')) {
|
|
||||||
const contentWrapper = document.querySelector('.content-wrapper');
|
|
||||||
const OB = new MutationObserver(() => {
|
|
||||||
OB.disconnect();
|
|
||||||
titleTrans();
|
|
||||||
contentTitleLinksTrans();
|
|
||||||
trans();
|
|
||||||
OB.observe(contentWrapper, {
|
|
||||||
characterData: true,
|
|
||||||
attributes: true,
|
|
||||||
subtree: true,
|
|
||||||
childList: true
|
|
||||||
});
|
|
||||||
});
|
|
||||||
const trans = () => {
|
|
||||||
// 当前能量e
|
|
||||||
const energyBarStr = $('#barEnergy p[class^="bar-value__"]').text().trim();
|
|
||||||
const [curE, maxE] = energyBarStr.split('/').length === 2
|
|
||||||
? [parseInt(energyBarStr.split('/')[0]), parseInt(energyBarStr.split('/')[1])]
|
|
||||||
: [NaN, NaN];
|
|
||||||
const incTime = maxE === 150 ? 10 : 15;
|
|
||||||
const fullEnergyTime = !(isNaN(curE) || isNaN(maxE)) ? (maxE - 5 - curE) / 5 * incTime
|
|
||||||
+ (incTime - new Date().getMinutes() % incTime) : NaN;
|
|
||||||
// 起飞前提示
|
|
||||||
$('.travel-confirm .travel-question .q-wrap span:nth-of-type(2)').each((i, e) => {
|
|
||||||
if (isNaN(fullEnergyTime)) return;
|
|
||||||
const spl = e.innerText.trim().split(' ');
|
|
||||||
const [hours, minutes] = spl.length === 5
|
|
||||||
? [parseInt(spl[0]), parseInt(spl[3])]
|
|
||||||
: [0, parseInt(spl[0])];
|
|
||||||
if (fullEnergyTime < (hours * 60 + minutes) * 2) {
|
|
||||||
if (!$(e).parent().hasClass('wh-translated')) {
|
|
||||||
$(e).parent()
|
|
||||||
.prepend(`<div style="color: red">警告:该次飞行往返时间大于体力回复时间,将会爆体!</div>`)
|
|
||||||
.addClass('wh-translated');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
trans();
|
|
||||||
OB.observe(contentWrapper, {
|
|
||||||
characterData: true,
|
|
||||||
attributes: true,
|
|
||||||
subtree: true,
|
|
||||||
childList: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// 一键起飞
|
|
||||||
if (sessionStorage['wh-quick-fly']) {
|
|
||||||
QuickFlyBtnHandler.doQuickFly();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function travelBack(): Promise<null> {
|
|
||||||
if (typeof window['getAction'] !== 'function') return;
|
|
||||||
let backHomeAction = function (): Promise<string> {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
window.getAction({
|
|
||||||
type: "post",
|
|
||||||
action: 'travelagency.php',
|
|
||||||
data: {
|
|
||||||
step: 'backHomeAction'
|
|
||||||
},
|
|
||||||
success: function (msg) {
|
|
||||||
resolve(msg);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
let res = await backHomeAction();
|
|
||||||
new Alert(res);
|
|
||||||
if (!res.includes('error')) {
|
|
||||||
new Alert('成功,即将刷新');
|
|
||||||
window.setTimeout(() => location.reload(), 3000);
|
|
||||||
} else {
|
|
||||||
new Alert('出错了');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,98 +0,0 @@
|
|||||||
import audioPlay from "./audioPlay";
|
|
||||||
import MathUtils from "../../../class/utils/MathUtils";
|
|
||||||
import Alert from "../../../class/utils/Alert";
|
|
||||||
import InfoUtils from "../../../class/utils/InfoUtils";
|
|
||||||
import WuhuConfig from "../../../class/WuhuConfig";
|
|
||||||
import Log from "../../../class/Log";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
export default function BuyBeer() {
|
|
||||||
// 正在通知
|
|
||||||
let is_notified = false;
|
|
||||||
let time: number = WuhuConfig.get('_15AlarmTime') || 30;
|
|
||||||
let loop: BeerMonitorLoop = {};
|
|
||||||
// 循环id
|
|
||||||
let started = null;
|
|
||||||
loop.start = () => {
|
|
||||||
if (started) {
|
|
||||||
Log.info('啤酒助手已在运行');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
started = setInterval(async () => {
|
|
||||||
// 海外取消提醒
|
|
||||||
let { isTravelling, isAbroad } = await InfoUtils.getInstance().getUserState();
|
|
||||||
if (isTravelling || isAbroad) {
|
|
||||||
loop.stop();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let dt = new Date();
|
|
||||||
// 已选当天不提醒
|
|
||||||
const now = [dt.getUTCFullYear(), dt.getUTCMonth(), dt.getUTCDate()];
|
|
||||||
const ignore_date = WuhuConfig.get('_15_alarm_ignore') || '{}';
|
|
||||||
if (JSON.stringify(now) === JSON.stringify(ignore_date)) return;
|
|
||||||
// 正常提醒
|
|
||||||
let m = 14 - (dt.getMinutes() % 15);
|
|
||||||
let s = 60 - dt.getSeconds();
|
|
||||||
if (m === 0 && s < time) {
|
|
||||||
// 如从通知点开,则本次通知跳过
|
|
||||||
if (location.href.includes('#clickfromnotify')) {
|
|
||||||
is_notified = true;
|
|
||||||
location.hash = '';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 本次已通知
|
|
||||||
if (is_notified) return;
|
|
||||||
is_notified = true;
|
|
||||||
// 发送通知
|
|
||||||
const notify = new Alert(notify_html, {
|
|
||||||
timeout: 30,
|
|
||||||
sysNotify: true,
|
|
||||||
});
|
|
||||||
notify.getElement().querySelector('.wh-notify-msg button').addEventListener('click', () => loop.skip_today);
|
|
||||||
notify.getElement().addEventListener('click', ev => {
|
|
||||||
if ((ev.target as HTMLElement).tagName.toLowerCase() === 'a') {
|
|
||||||
// notify.sys_notify.close();
|
|
||||||
notify.close();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
window.setTimeout(audioPlay, 800);
|
|
||||||
window.setTimeout(audioPlay, 800 * 2);
|
|
||||||
window.setTimeout(audioPlay, 800 * 3);
|
|
||||||
} else {
|
|
||||||
is_notified = false;
|
|
||||||
}
|
|
||||||
}, 1000);
|
|
||||||
};
|
|
||||||
loop.stop = () => {
|
|
||||||
if (started) {
|
|
||||||
clearInterval(started);
|
|
||||||
started = null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
loop.set_time = (t) => time = t;
|
|
||||||
loop.status = () => started ? '已启动' : '未启动';
|
|
||||||
loop.is_running = () => !!started;
|
|
||||||
|
|
||||||
let mathUtils: MathUtils = MathUtils.getInstance();
|
|
||||||
let notify_html = `<span style="background-color:green;color:white;border-radius:3px;font-size:14px;line-height:21px;padding:2px 4px;">啤酒小助手</span><br/>提醒您:还有不到 50 秒 NPC 的商品就要刷新了,啤酒血包要抢的可以准备咯。<button id="wh-rd-btn-${ mathUtils.getRandomInt(0, 100) }">【今日不再提醒】</button><br/><a href="/shops.php?step=bitsnbobs#clickfromnotify" target="_blank">【啤酒店】</a> <a href="/shops.php?step=pharmacy#clickfromnotify" target="_blank">【血包店】</a>`
|
|
||||||
loop.skip_today = () => {
|
|
||||||
const date = new Date();
|
|
||||||
WuhuConfig.set('_15_alarm_ignore', [date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()], false);
|
|
||||||
// 通知
|
|
||||||
const notify = new Alert(`明早8点前将不再提醒 <button id="wh-rd-btn-${ mathUtils.getRandomInt(0, 100) }">取消</button>`);
|
|
||||||
// 通知中的取消按钮
|
|
||||||
notify.getElement().querySelector('.wh-notify-msg button').addEventListener('click', () => WuhuConfig.set('_15_alarm_ignore', undefined));
|
|
||||||
};
|
|
||||||
return loop;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface BeerMonitorLoop {
|
|
||||||
start?: Function;
|
|
||||||
stop?: Function;
|
|
||||||
set_time?: Function;
|
|
||||||
status?: Function;
|
|
||||||
is_running?: Function;
|
|
||||||
skip_today?: Function;
|
|
||||||
}
|
|
||||||
@ -1,65 +0,0 @@
|
|||||||
import UserScriptEngine from "../../../enum/UserScriptEngine";
|
|
||||||
import getScriptEngine from "./getScriptEngine";
|
|
||||||
import Log from "../../../class/Log";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
export default function COFetch(url: URL | string, method: 'get' | 'post' = 'get', body: any = null): Promise<string> {
|
|
||||||
return new Promise<string>((resolve, reject) => {
|
|
||||||
const engine = getScriptEngine();
|
|
||||||
switch (engine) {
|
|
||||||
case UserScriptEngine.RAW: {
|
|
||||||
console.error(`[wh] 跨域请求错误:${ UserScriptEngine.RAW }环境下无法进行跨域请求`);
|
|
||||||
reject(`错误:${ UserScriptEngine.RAW }环境下无法进行跨域请求`);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case UserScriptEngine.PDA: {
|
|
||||||
const { PDA_httpGet, PDA_httpPost } = window;
|
|
||||||
// get
|
|
||||||
if (method === 'get') {
|
|
||||||
if (typeof PDA_httpGet !== 'function') {
|
|
||||||
Log.error('COFetch网络错误:PDA版本不支持');
|
|
||||||
reject('COFetch网络错误:PDA版本不支持');
|
|
||||||
}
|
|
||||||
PDA_httpGet(url)
|
|
||||||
.then(res => resolve(res.responseText))
|
|
||||||
.catch(e => {
|
|
||||||
Log.error('COFetch网络错误', e);
|
|
||||||
reject(`COFetch网络错误 ${ e }`);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// post
|
|
||||||
else {
|
|
||||||
if (typeof PDA_httpPost !== 'function') {
|
|
||||||
Log.error('COFetch网络错误:PDA版本不支持');
|
|
||||||
reject('COFetch网络错误:PDA版本不支持');
|
|
||||||
}
|
|
||||||
PDA_httpPost(url, { 'content-type': 'application/json' }, body)
|
|
||||||
.then(res => resolve(res.responseText))
|
|
||||||
.catch(e => {
|
|
||||||
Log.error('COFetch网络错误', e);
|
|
||||||
reject(`COFetch网络错误 ${ e }`);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case UserScriptEngine.GM: {
|
|
||||||
let { GM_xmlhttpRequest } = window;
|
|
||||||
if (typeof GM_xmlhttpRequest !== 'function') {
|
|
||||||
Log.error('COFetch网络错误:用户脚本扩展API错误');
|
|
||||||
reject('错误:用户脚本扩展API错误');
|
|
||||||
}
|
|
||||||
GM_xmlhttpRequest({
|
|
||||||
method: method,
|
|
||||||
url: url,
|
|
||||||
data: method === 'get' ? null : body,
|
|
||||||
headers: method === 'get' ? null : { 'content-type': 'application/json' },
|
|
||||||
onload: res => resolve(res.response),
|
|
||||||
onerror: res => reject(`连接错误 ${ JSON.stringify(res) }`),
|
|
||||||
ontimeout: res => reject(`连接超时 ${ JSON.stringify(res) }`),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@ -1,56 +0,0 @@
|
|||||||
/**
|
|
||||||
* 解析 Markdown 内容
|
|
||||||
* @param {String} from
|
|
||||||
* @param {Number} max_line 最大行数,默认500
|
|
||||||
* @returns {HTMLDivElement}
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
export default function mdParse(from: string, max_line?: number): HTMLElement {
|
|
||||||
max_line = max_line || 500;
|
|
||||||
const base = document.createElement('div');
|
|
||||||
let lines = from.split('\n');
|
|
||||||
if (lines.length > max_line) {
|
|
||||||
lines = lines.slice(0, max_line);
|
|
||||||
lines.push("...");
|
|
||||||
}
|
|
||||||
|
|
||||||
let prev = '';
|
|
||||||
let child_cont;
|
|
||||||
lines.forEach(line => {
|
|
||||||
if (line.trim() === '') return;
|
|
||||||
let node;
|
|
||||||
let spl = line.split(' ');
|
|
||||||
let md_flag = spl[0];
|
|
||||||
|
|
||||||
switch (md_flag) {
|
|
||||||
// 标题
|
|
||||||
case '#':
|
|
||||||
case '##':
|
|
||||||
case '###':
|
|
||||||
if (prev === 'li') {
|
|
||||||
child_cont = null;
|
|
||||||
}
|
|
||||||
prev = 'h' + (md_flag.length + 1);
|
|
||||||
node = document.createElement(prev);
|
|
||||||
node.innerText = line.slice(md_flag.length + 1);
|
|
||||||
base.append(node);
|
|
||||||
return;
|
|
||||||
// 列表
|
|
||||||
case '-':
|
|
||||||
if (prev !== 'li') {
|
|
||||||
child_cont = document.createElement('ul');
|
|
||||||
if (!base.contains(child_cont)) base.append(child_cont);
|
|
||||||
}
|
|
||||||
prev = 'li';
|
|
||||||
node = document.createElement(prev);
|
|
||||||
node.innerText = line.slice(2);
|
|
||||||
child_cont.append(node);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
prev = 'p';
|
|
||||||
node = document.createElement(prev);
|
|
||||||
node.innerText = line.trim();
|
|
||||||
base.append(node);
|
|
||||||
})
|
|
||||||
return base;
|
|
||||||
}
|
|
||||||
@ -1,151 +0,0 @@
|
|||||||
import addStyle from "./addStyle";
|
|
||||||
import WuhuBase from "../../../class/WuhuBase";
|
|
||||||
import MathUtils from "../../../class/utils/MathUtils";
|
|
||||||
import WindowActiveState from "../../../class/action/WindowActiveState";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 通知方法
|
|
||||||
* @param {string} msg - 通知内容
|
|
||||||
* @param {Object} [options] - 通知选项
|
|
||||||
* @param {number} [options.timeout] - 通知超时时间
|
|
||||||
* @param {function} [options.callback] - 通知回调
|
|
||||||
* @param {boolean} [options.sysNotify] - 是否开启系统通知
|
|
||||||
* @param {string} [options.sysNotifyTag] - 系统通知标记
|
|
||||||
* @param {function} [options.sysNotifyClick] - 系统通知点击事件
|
|
||||||
* @return {HTMLElement}
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
export default function WHNotify(msg: string, options: WHNotifyOpt = {}): MyHTMLElement {
|
|
||||||
let { notifies } = WuhuBase.glob;
|
|
||||||
let mathUtils: MathUtils = MathUtils.getInstance();
|
|
||||||
|
|
||||||
let {
|
|
||||||
timeout = 3,
|
|
||||||
callback = function () {
|
|
||||||
},
|
|
||||||
sysNotify = false,
|
|
||||||
sysNotifyTag = '芜湖助手',
|
|
||||||
sysNotifyClick = () => window.focus()
|
|
||||||
} = options;
|
|
||||||
|
|
||||||
if (!WindowActiveState.getInstance().get() || (self !== top)) return null;
|
|
||||||
const date = new Date();
|
|
||||||
// 通知的唯一id
|
|
||||||
const uid = `${ date.getHours() }${ date.getSeconds() }${ date.getMilliseconds() }${ mathUtils.getRandomInt(1000, 9999) }`;
|
|
||||||
// 通知容器id
|
|
||||||
// 通知的容器
|
|
||||||
let notify_contain: MyHTMLElement = document.querySelector(`#wh-notify`);
|
|
||||||
// 添加通知到容器
|
|
||||||
const add_notify = () => {
|
|
||||||
// 每条通知
|
|
||||||
const new_node: MyHTMLElement = document.createElement('div');
|
|
||||||
new_node.id = `wh-notify-${ uid }`;
|
|
||||||
new_node.classList.add('wh-notify-item');
|
|
||||||
new_node.innerHTML = `<div class="wh-notify-bar"></div>
|
|
||||||
<div class="wh-notify-cont">
|
|
||||||
<div class="wh-notify-close"></div>
|
|
||||||
<div class="wh-notify-msg"><p>${ msg }</p></div>
|
|
||||||
</div>`;
|
|
||||||
notify_contain.append(new_node);
|
|
||||||
notify_contain['msgInnerText'] = new_node.querySelector('.wh-notify-msg').innerText;
|
|
||||||
// 进度条node
|
|
||||||
const progressBar: HTMLElement = new_node.querySelector('.wh-notify-bar');
|
|
||||||
// 是否hover
|
|
||||||
let mouse_enter = false;
|
|
||||||
new_node.addEventListener('mouseenter', () => mouse_enter = true, true);
|
|
||||||
new_node.addEventListener('mouseleave', () => mouse_enter = false);
|
|
||||||
// 通知进度条
|
|
||||||
let progressCount = 101;
|
|
||||||
// 删除通知
|
|
||||||
new_node.close = () => {
|
|
||||||
clearInterval(intervalID);
|
|
||||||
new_node.remove();
|
|
||||||
callback();
|
|
||||||
};
|
|
||||||
// 计时器
|
|
||||||
let intervalID = window.setInterval(() => {
|
|
||||||
if (mouse_enter) {
|
|
||||||
progressCount = 101;
|
|
||||||
progressBar.style.width = '100%';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
progressCount--;
|
|
||||||
progressBar.style.width = `${ progressCount }%`;
|
|
||||||
if (progressCount === 0) new_node.remove();
|
|
||||||
}, timeout * 1000 / 100);
|
|
||||||
new_node.querySelector('.wh-notify-close').addEventListener('click', new_node.close);
|
|
||||||
return new_node;
|
|
||||||
};
|
|
||||||
// 不存在容器 创建
|
|
||||||
if (!notify_contain) {
|
|
||||||
notify_contain = document.createElement('div');
|
|
||||||
notify_contain.id = 'wh-notify';
|
|
||||||
addStyle(`
|
|
||||||
#wh-notify {
|
|
||||||
display: inline-block;
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: calc(50% - 180px);
|
|
||||||
width: 360px;
|
|
||||||
z-index: 9999990;
|
|
||||||
color:#333;
|
|
||||||
}
|
|
||||||
#wh-notify a{
|
|
||||||
color:red;
|
|
||||||
text-decoration:none;
|
|
||||||
}
|
|
||||||
#wh-notify .wh-notify-item {
|
|
||||||
/*height: 50px;*/
|
|
||||||
background: rgb(239 249 255 / 90%);
|
|
||||||
border-radius: 2px;
|
|
||||||
margin: 0.5em 0 0 0;
|
|
||||||
box-shadow: 0 0 5px 0px #959595;
|
|
||||||
}
|
|
||||||
#wh-notify .wh-notify-item:hover {
|
|
||||||
background: rgb(239 249 255 / 98%);
|
|
||||||
}
|
|
||||||
#wh-notify .wh-notify-item .wh-notify-bar {
|
|
||||||
height:2px;
|
|
||||||
background:#2196f3;
|
|
||||||
}
|
|
||||||
#wh-notify .wh-notify-item .wh-notify-close {
|
|
||||||
float:right;
|
|
||||||
padding:0;
|
|
||||||
width:16px;height:16px;
|
|
||||||
background:url('data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%201024%201024%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M923%20571H130.7c-27.6%200-50-22.4-50-50s22.4-50%2050-50H923c27.6%200%2050%2022.4%2050%2050s-22.4%2050-50%2050z%22%20fill%3D%22%232196f3%22%3E%3C%2Fpath%3E%3C%2Fsvg%3E') no-repeat center;
|
|
||||||
background-size:100%;
|
|
||||||
margin: 6px 6px 0 0;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
#wh-notify .wh-notify-item .wh-notify-msg {
|
|
||||||
padding:12px;
|
|
||||||
}
|
|
||||||
`);
|
|
||||||
document.body.append(notify_contain);
|
|
||||||
}
|
|
||||||
const notify_obj = add_notify();
|
|
||||||
// 浏览器通知
|
|
||||||
if (window.Notification && Notification.permission === 'granted' && sysNotify) {
|
|
||||||
const date_local_string = `[${ date.getHours() }:${ date.getMinutes() }:${ date.getSeconds() }]\r`;
|
|
||||||
notify_obj.sys_notify = new Notification('芜湖助手', {
|
|
||||||
body: date_local_string + notify_contain.msgInnerText,
|
|
||||||
requireInteraction: true,
|
|
||||||
renotify: true,
|
|
||||||
tag: sysNotifyTag + mathUtils.getRandomInt(0, 99),
|
|
||||||
});
|
|
||||||
notify_obj.sys_notify.addEventListener('close', () => sysNotifyClick());
|
|
||||||
notify_obj.sys_notify.onshow = () => setTimeout(() => notify_obj.sys_notify.close(), timeout * 1000);
|
|
||||||
notify_obj.sys_notify.id = notifies.count++;
|
|
||||||
notifies[notify_obj.sys_notify.id] = notify_obj.sys_notify;
|
|
||||||
notify_obj.sys_notify.addEventListener('close', () => notifies[notify_obj.sys_notify.id] = null);
|
|
||||||
}
|
|
||||||
return notify_obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface WHNotifyOpt {
|
|
||||||
timeout?: number;
|
|
||||||
callback?: Function;
|
|
||||||
sysNotify?: boolean;
|
|
||||||
sysNotifyTag?: string;
|
|
||||||
sysNotifyClick?: Function;
|
|
||||||
}
|
|
||||||
@ -1,22 +0,0 @@
|
|||||||
import Log from "../../../class/Log";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
export default function addActionBtn(txt: string, func: (ev: Event) => void, mainBtnNode: Element): void {
|
|
||||||
addActionBtn.proxy(txt, func, mainBtnNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
addActionBtn.proxy = (txt: string, func: (ev: Event) => void, mainBtnNode: Element) => {
|
|
||||||
if (mainBtnNode.querySelector('#wh-trans-icon-btn').nextSibling !== null) return;
|
|
||||||
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);
|
|
||||||
mainBtnNode.querySelector('button').after(btn);
|
|
||||||
addActionBtn.proxy = () => {
|
|
||||||
Log.error('错误:附加按钮已存在')
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@ -1,17 +0,0 @@
|
|||||||
import log from "./log";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
export default function addStyle(css: string) {
|
|
||||||
let wh_gStyle = document.querySelector('style#wh-trans-gStyle');
|
|
||||||
if (wh_gStyle) {
|
|
||||||
wh_gStyle.innerHTML += css;
|
|
||||||
} else {
|
|
||||||
wh_gStyle = document.createElement("style");
|
|
||||||
wh_gStyle.id = 'wh-trans-gStyle';
|
|
||||||
wh_gStyle.innerHTML = css;
|
|
||||||
document.head.append(wh_gStyle);
|
|
||||||
}
|
|
||||||
log.info('CSS规则已添加', wh_gStyle);
|
|
||||||
}
|
|
||||||
@ -1,23 +0,0 @@
|
|||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
export default function ajaxFetch(opt) {
|
|
||||||
let { url, referrer, method, body = null } = opt;
|
|
||||||
let req_params: AjaxFetchOpt = {
|
|
||||||
headers: { 'X-Requested-With': 'XMLHttpRequest' },
|
|
||||||
referrer,
|
|
||||||
method,
|
|
||||||
};
|
|
||||||
if (method === 'POST') {
|
|
||||||
req_params.headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
|
|
||||||
req_params.body = body;
|
|
||||||
}
|
|
||||||
return window.fetch(url, req_params);
|
|
||||||
}
|
|
||||||
|
|
||||||
interface AjaxFetchOpt {
|
|
||||||
headers: { 'X-Requested-With'?: string, 'Content-Type'?: string };
|
|
||||||
referrer: string;
|
|
||||||
method: string;
|
|
||||||
body?: any;
|
|
||||||
}
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
// import CommonUtils from "../../../class/utils/CommonUtils";
|
|
||||||
// import WindowActiveState from "../../../class/action/WindowActiveState";
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * @deprecated
|
|
||||||
// */
|
|
||||||
// function autoFetchJSON(dest, time = 30) {
|
|
||||||
// let obj;
|
|
||||||
// const res = CommonUtils.COFetch(dest);
|
|
||||||
// setInterval(async () => {
|
|
||||||
// if (!WindowActiveState.getInstance().get()) return;
|
|
||||||
// const res = await CommonUtils.COFetch(dest);
|
|
||||||
// obj = JSON.parse(res);
|
|
||||||
// }, time * 1000);
|
|
||||||
// return {
|
|
||||||
// get: async function () {
|
|
||||||
// if (!obj) {
|
|
||||||
// const str = await res
|
|
||||||
// return obj = JSON.parse(str);
|
|
||||||
// }
|
|
||||||
// return obj;
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
import UserScriptEngine from "../../../enum/UserScriptEngine";
|
|
||||||
import WuhuBase from "../../../class/WuhuBase";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
export default function getScriptEngine() {
|
|
||||||
let glob = WuhuBase.glob;
|
|
||||||
return glob.unsafeWindow ? UserScriptEngine.GM : glob.isPDA
|
|
||||||
? UserScriptEngine.PDA : UserScriptEngine.RAW;
|
|
||||||
}
|
|
||||||
@ -1,40 +0,0 @@
|
|||||||
import CommonUtils from "../../../class/utils/CommonUtils";
|
|
||||||
import Log from "../../../class/Log";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
export default async function getSidebarData() {
|
|
||||||
let ret = {};
|
|
||||||
let sidebar_id = null;
|
|
||||||
|
|
||||||
let sessionKeys = Object.keys(sessionStorage);
|
|
||||||
if (sessionKeys.length < 2) {
|
|
||||||
// dom获取
|
|
||||||
let sidebar_menu_list = document.querySelectorAll('#sidebar a span[class*="linkName___"]');
|
|
||||||
Log.info({ sidebar_menu_list })
|
|
||||||
if (sidebar_menu_list.length === 0) {
|
|
||||||
await CommonUtils.elementReady('#sidebar a span[class*="linkName___"]');
|
|
||||||
sidebar_menu_list = document.querySelectorAll('#sidebar a span[class*="linkName___"]');
|
|
||||||
}
|
|
||||||
sidebar_menu_list.forEach(node => ret[node.innerHTML.trim().toLowerCase().replaceAll(' ', '_')] = true);
|
|
||||||
} else {
|
|
||||||
// session storage获取
|
|
||||||
for (let key of sessionKeys) {
|
|
||||||
if (key.startsWith('sidebarData')) {
|
|
||||||
sidebar_id = JSON.parse(sessionStorage.getItem(key));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (sidebar_id !== null) {
|
|
||||||
for (let area of Object.keys(sidebar_id['areas'])) {
|
|
||||||
ret[area] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Log.info({ ret, sidebar_id, sessionKeys })
|
|
||||||
if (Object.keys(ret).length === 0) {
|
|
||||||
Log.error('无法获取数据,建议刷新重试');
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
export default function getUserState(): {} | any {
|
|
||||||
let obj = {};
|
|
||||||
let hdd = sessionStorage['headerData'];
|
|
||||||
if (hdd) obj = JSON.parse(hdd)['user']['state'];
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
export default function getWhSettingObj(): WHSettings {
|
|
||||||
return JSON.parse(localStorage.getItem('wh_trans_settings')) || {}
|
|
||||||
}
|
|
||||||
|
|
||||||
interface WHSettings {
|
|
||||||
// TODO 补全
|
|
||||||
[key: string]: any;
|
|
||||||
}
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
import getWhSettingObj from "./getWhSettingObj";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
function debug() {
|
|
||||||
try {
|
|
||||||
return getWhSettingObj()['isDev'] || false;
|
|
||||||
} catch (e) {
|
|
||||||
console.error(`[wh] dev状态错误 ${ e }`);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
const log = {
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
error: (...o) => (debug()) && (console.error('[WH]', ...o)),
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
info: (...o) => (debug()) && (console.log('[WH]', ...o)),
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
debug,
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
export default log
|
|
||||||
@ -1,29 +0,0 @@
|
|||||||
import WuhuBase from "../../../class/WuhuBase";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated 使用new Popup()
|
|
||||||
*/
|
|
||||||
export default function popupMsg(innerHTML, title = '芜湖助手') {
|
|
||||||
let glob = WuhuBase.glob;
|
|
||||||
if (glob.popup_node) glob.popup_node.close();
|
|
||||||
const chatRoot = document.querySelector('#chatRoot');
|
|
||||||
chatRoot.classList.add('wh-hide');
|
|
||||||
const popup = document.createElement('div');
|
|
||||||
popup.id = 'wh-popup';
|
|
||||||
popup.innerHTML = `<div id="wh-popup-container">
|
|
||||||
<div id="wh-popup-title"><p>${ title }</p></div>
|
|
||||||
<div id="wh-popup-cont">${ innerHTML }</div>
|
|
||||||
</div>`;
|
|
||||||
document.body.append(popup);
|
|
||||||
const rt: MyHTMLElement = popup.querySelector('#wh-popup-cont');
|
|
||||||
rt.close = function () {
|
|
||||||
popup.remove();
|
|
||||||
chatRoot.classList.remove('wh-hide');
|
|
||||||
}
|
|
||||||
popup.addEventListener('click', e => {
|
|
||||||
e.stopImmediatePropagation();
|
|
||||||
if (e.target === popup) rt.close();
|
|
||||||
});
|
|
||||||
glob.popup_node = rt;
|
|
||||||
return rt;
|
|
||||||
}
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
import getWhSettingObj from "./getWhSettingObj";
|
|
||||||
import Alert from "../../../class/utils/Alert";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
export default function setWhSetting(key: string, value: any, notify: boolean = true) {
|
|
||||||
const obj = getWhSettingObj()
|
|
||||||
obj[key] = value
|
|
||||||
localStorage.setItem('wh_trans_settings', JSON.stringify(obj))
|
|
||||||
|
|
||||||
// 通知
|
|
||||||
if (notify) new Alert('已保存设置')
|
|
||||||
}
|
|
||||||
@ -1,4 +0,0 @@
|
|||||||
import Starter from "./class/provider/Starter";
|
|
||||||
import Application from "./class/Application";
|
|
||||||
|
|
||||||
Starter.run(Application);
|
|
||||||
7
src/shims-vue.d.ts
vendored
Normal file
7
src/shims-vue.d.ts
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
declare module '*.vue' {
|
||||||
|
import type { DefineComponent } from 'vue'
|
||||||
|
const component: DefineComponent<{}, {}, any>
|
||||||
|
export default component
|
||||||
|
}
|
||||||
|
/* eslint-enable */
|
||||||
@ -282,3 +282,11 @@ div#wh-popup::after {
|
|||||||
.non-selection {
|
.non-selection {
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mt-4 {
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*.el-overlay {*/
|
||||||
|
/* backdrop-filter: blur(20px);*/
|
||||||
|
/*}*/
|
||||||
@ -1,3 +0,0 @@
|
|||||||
.content-title, .info-msg-cont {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
3
src/static/css/xunzhaomuzhuang.module.css
Normal file
3
src/static/css/xunzhaomuzhuang.module.css
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
body.wh-hide-title .content-title, body.wh-hide-title .info-msg-cont {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
@ -1,71 +1,71 @@
|
|||||||
<div class="acc-title">
|
<div class="acc-title">
|
||||||
<span class="item-desc">
|
<span class="item-desc tt-buy">
|
||||||
<span aria-labelledby="180-name 180-price 180-stock" class="item Alcohol" itemid="180" loaded="0" tabindex="0">
|
<span class="item Alcohol" itemid="180" loaded="0">
|
||||||
<img alt="Bottle of Beer" aria-hidden="true" class="torn-item item-plate" data-converted="1"
|
<span class="item-plate">
|
||||||
data-size="large" id="item-1bea9f66-a6c4-475c-accb-41dcb67af64f-old" src="/images/items/180/large.png"
|
<img alt="Bottle of Beer" class="torn-item large"
|
||||||
style="opacity: 0;">
|
src="/images/items/180/large.png"
|
||||||
<span class="item-hover">
|
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">
|
||||||
<button aria-label="Show info: Bottle of Beer" class="view-h wai-btn" i-data="i_723_228_51_52" value="100"></button>
|
</span>
|
||||||
<button aria-label="Buy: Bottle of Beer" class="buy-h wai-btn" i-data="i_774_228_51_52" value="100"></button>
|
<span class="item-hover">
|
||||||
</span>
|
<button aria-labelledby="Show info: 180-name 180-price 180-stock" class="view-info wai-btn"
|
||||||
<canvas aria-label="Bottle of Beer" class="torn-item item-plate item-converted" height="50"
|
value="100"></button>
|
||||||
id="item-1bea9f66-a6c4-475c-accb-41dcb67af64f"
|
<button aria-label="Buy: Bottle of Beer" class="buy-info wai-btn" value="100"></button>
|
||||||
item-mode="light" role="img" style="opacity: 1;" width="100"></canvas></span>
|
</span>
|
||||||
<span class="desc">
|
</span>
|
||||||
<span class="name t-overflow bold" id="180-name">啤酒</span>
|
<span class="desc">
|
||||||
<span class="price t-gray-6" data-sell="$5" id="180-price">$10</span>
|
<input name="shoparea" type="hidden" value="100">
|
||||||
<span class="stock t-gray-6 t-overflow" id="180-stock">酒 (<span class="instock">1100</span>存货)</span>
|
<span id="180-name" class="name t-overflow bold">Bottle of Beer</span>
|
||||||
</span>
|
<span id="180-price" class="price t-gray-6 tt-modified" data-sell="$5">$10<span
|
||||||
<span class="buy-act-wrap">
|
class="tt-profit positive"><i class="fas fa-caret-up"></i>$1,636</span></span>
|
||||||
<label class="wai" for="180">Amount
|
<span id="180-stock" class="stock t-gray-6 t-overflow">Alcohol (<span class="instock">5,000</span> in
|
||||||
of Bottle of Beer</label>
|
stock)</span>
|
||||||
<input autocomplete="new-amount" id="180" maxlength="3" name="buyAmount[]" type="text" value="100">
|
</span>
|
||||||
<span class="buy-act bold">
|
<span class="buy-act-wrap">
|
||||||
<button class="wai-support t-blue h">买</button>
|
<button aria-label="Close" class="close-icon p0 wai-btn" value="100"></button>
|
||||||
<div class="tt-max-buy-overlay"></div>
|
<label class="wai" for="180">Amount
|
||||||
</span>
|
of Bottle of Beer</label>
|
||||||
</span>
|
<input id="180" autocomplete="new-amount" maxlength="3" name="buyAmount[]" type="text" value="100">
|
||||||
</span>
|
<span class="buy-act bold">
|
||||||
<div class="confirm-wrap">
|
<button class="wai-support t-blue h" value="100">Buy<br><span class="tt-max-buy">fill
|
||||||
<span class="confirm">
|
max</span></button>
|
||||||
<span>
|
<div class="tt-max-buy-overlay"></div>
|
||||||
点击确定购买
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<span>
|
</span>
|
||||||
<span class="count">100</span>
|
<div class="torn-divider divider-right"></div>
|
||||||
瓶啤酒
|
<div class="confirm-wrap" tabindex="0">
|
||||||
$<span class="total">1,000</span>
|
<span class="confirm">
|
||||||
</span>
|
<span>
|
||||||
<span class="confirm-act m-top5">
|
Are you sure you would like to buy
|
||||||
<a class="wai-support yes m-right10 bold t-blue h" data-id="180" href="#" i-data="i_819_263_23_16">
|
</span>
|
||||||
确定
|
<span>
|
||||||
</a>
|
<span class="count"></span>
|
||||||
<span class="no bold">
|
x Bottle of Beer for
|
||||||
<a class="wai-support t-blue h" href="#" i-data="i_852_263_18_16">
|
$<span class="total"></span>
|
||||||
不
|
</span>
|
||||||
</a>
|
<span class="confirm-act m-top5">
|
||||||
</span>
|
<a class="wai-support yes m-right10 bold t-blue h" data-id="180" href="#">
|
||||||
</span>
|
Yes
|
||||||
</span>
|
</a>
|
||||||
|
<span class="no bold">
|
||||||
|
<a class="wai-support t-blue h" href="#">
|
||||||
|
No
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="success-wrap">
|
<div class="success-wrap">
|
||||||
<span class="success">
|
<span class="success">
|
||||||
<span class="t-red bold">
|
<span class="t-green bold">
|
||||||
<span class="ajax-preloader"></span>
|
<span class="ajax-preloader"></span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<button aria-label="Close" class="close-icon p0 wai-btn" i-data="i_954_228_10_11" value="100"></button>
|
<button aria-label="Close" class="close-icon p0 wai-btn" value="100"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="msg-wrap">
|
<div class="msg-wrap">
|
||||||
<span class="t-green bold">
|
<span class="t-green bold">
|
||||||
<span class="ajax-preloader"></span>
|
<span class="ajax-preloader"></span>
|
||||||
</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>
|
||||||
</div>
|
</div>
|
||||||
@ -13,7 +13,7 @@
|
|||||||
<option>瑞士 (解毒)</option>
|
<option>瑞士 (解毒)</option>
|
||||||
<option>立本</option>
|
<option>立本</option>
|
||||||
<option>祖国</option>
|
<option>祖国</option>
|
||||||
<option>迪拜</option>
|
<option>阿联酋 (UAE)</option>
|
||||||
<option>南非</option>
|
<option>南非</option>
|
||||||
</select></label>
|
</select></label>
|
||||||
<label>飞机:<select>
|
<label>飞机:<select>
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
<li>走进蓝色的门(左二)[111,-60]</li>
|
<li>走进蓝色的门(左二)[111,-60]</li>
|
||||||
<li>过了蓝门后继续沿路向南</li>
|
<li>过了蓝门后继续沿路向南</li>
|
||||||
<li>然后沿路向东,再向南</li>
|
<li>然后沿路向东,再向南</li>
|
||||||
<li>再向东走,会看到“恐怖之家”,进入这栋楼[137, -84]</li>
|
<li>再向东走,会看到「恐怖之家」,进入这栋楼[137, -84]</li>
|
||||||
<li>向北走,进入洞口[164, -81]</li>
|
<li>向北走,进入洞口[164, -81]</li>
|
||||||
<li>穿过隧道到达另一端的洞穴口[142, -63],<b>避开所有怪物和NPC</b></li>
|
<li>穿过隧道到达另一端的洞穴口[142, -63],<b>避开所有怪物和NPC</b></li>
|
||||||
<li>来到另一个岛上</li>
|
<li>来到另一个岛上</li>
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
<h4>手机</h4>
|
<h4>手机</h4>
|
||||||
<p>安卓 KIWI 等可以用油猴脚本的浏览器也可以点上面的链接安装👆</p>
|
<p>安卓 KIWI 等可以用油猴脚本的浏览器也可以点上面的链接安装👆</p>
|
||||||
<p>Torn PDA app 或 Alook 用户可打开<a href="//jjins.github.io/fyfuzhi/" target="_blank">这个网页</a>快捷复制粘贴。</p>
|
<p>Torn PDA app 或 Alook 用户可打开<a href="//jjins.github.io/fyfuzhi/" target="_blank">这个网页</a>快捷复制粘贴。</p>
|
||||||
|
<p>注:Torn PDA 中,Injection time 请选择 Start 达到最好效果。</p>
|
||||||
<h4>直接复制</h4>
|
<h4>直接复制</h4>
|
||||||
<p>加载脚本然后直接复制粘贴到用户脚本处。</p>
|
<p>加载脚本然后直接复制粘贴到用户脚本处。</p>
|
||||||
<p>
|
<p>
|
||||||
|
|||||||
@ -2,12 +2,12 @@
|
|||||||
{
|
{
|
||||||
"start": [
|
"start": [
|
||||||
0,
|
0,
|
||||||
17,
|
16,
|
||||||
8
|
8
|
||||||
],
|
],
|
||||||
"end": [
|
"end": [
|
||||||
0,
|
0,
|
||||||
24,
|
22,
|
||||||
8
|
8
|
||||||
],
|
],
|
||||||
"name": "捡垃圾周",
|
"name": "捡垃圾周",
|
||||||
@ -86,7 +86,7 @@
|
|||||||
{
|
{
|
||||||
"start": [
|
"start": [
|
||||||
11,
|
11,
|
||||||
14,
|
19,
|
||||||
20
|
20
|
||||||
],
|
],
|
||||||
"end": [
|
"end": [
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"val": {
|
"val": {
|
||||||
"0105": {
|
"0104": {
|
||||||
"name": "周末自驾游",
|
"name": "周末自驾游",
|
||||||
"eff": "获得双倍的赛车点数与赛车技能等级增益"
|
"eff": "获得双倍的赛车点数与赛车技能等级增益"
|
||||||
},
|
},
|
||||||
@ -8,7 +8,7 @@
|
|||||||
"name": "情人节",
|
"name": "情人节",
|
||||||
"eff": "使用爱情果汁(Love Juice)后获得降低攻击与复活的能量消耗的增益"
|
"eff": "使用爱情果汁(Love Juice)后获得降低攻击与复活的能量消耗的增益"
|
||||||
},
|
},
|
||||||
"0204": {
|
"0203": {
|
||||||
"name": "员工激励日",
|
"name": "员工激励日",
|
||||||
"eff": "获得三倍的工作点数与火车增益"
|
"eff": "获得三倍的工作点数与火车增益"
|
||||||
},
|
},
|
||||||
@ -36,7 +36,7 @@
|
|||||||
"name": "世界老虎日",
|
"name": "世界老虎日",
|
||||||
"eff": "获得5倍的狩猎技能增益"
|
"eff": "获得5倍的狩猎技能增益"
|
||||||
},
|
},
|
||||||
"0705": {
|
"0704": {
|
||||||
"name": "国际啤酒节",
|
"name": "国际啤酒节",
|
||||||
"eff": "获得5倍的啤酒物品效果增益"
|
"eff": "获得5倍的啤酒物品效果增益"
|
||||||
},
|
},
|
||||||
@ -56,11 +56,11 @@
|
|||||||
"name": "周年庆",
|
"name": "周年庆",
|
||||||
"eff": "左上角的TORN图标可以食用"
|
"eff": "左上角的TORN图标可以食用"
|
||||||
},
|
},
|
||||||
"1025": {
|
"1024": {
|
||||||
"name": "黑色星期五",
|
"name": "黑色星期五",
|
||||||
"eff": "某些商家将提供1元购活动"
|
"eff": "某些商家将提供1元购活动"
|
||||||
},
|
},
|
||||||
"1114": {
|
"1113": {
|
||||||
"name": "住院日",
|
"name": "住院日",
|
||||||
"eff": "获得降低75%的住院时间增益"
|
"eff": "获得降低75%的住院时间增益"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -74,7 +74,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "uae",
|
"name": "uae",
|
||||||
"show": "迪拜",
|
"show": "阿联酋 (UAE)",
|
||||||
"stocks": {
|
"stocks": {
|
||||||
"Tribulus Omanense": "花",
|
"Tribulus Omanense": "花",
|
||||||
"Camel Plushie": "偶"
|
"Camel Plushie": "偶"
|
||||||
|
|||||||
@ -1,56 +0,0 @@
|
|||||||
import WuhuBase from "../class/WuhuBase";
|
|
||||||
import Log from "../class/Log";
|
|
||||||
import CommonUtils from "../class/utils/CommonUtils";
|
|
||||||
import Popup from "../class/utils/Popup";
|
|
||||||
import CompanyHelper from "../class/action/CompanyHelper";
|
|
||||||
|
|
||||||
export default class Test extends WuhuBase {
|
|
||||||
className = 'Test';
|
|
||||||
|
|
||||||
public test(): void {
|
|
||||||
let popup = new Popup(CommonUtils.getInstance().getTravelStage().toString());
|
|
||||||
popup.getElement()['__POOL__'] = Test.getPool();
|
|
||||||
|
|
||||||
// this.case1()
|
|
||||||
// this.case2()
|
|
||||||
this.case3().then();
|
|
||||||
}
|
|
||||||
|
|
||||||
private case1() {
|
|
||||||
const temp = document.createElement("DIV");
|
|
||||||
const temp2 = document.createElement("DIV");
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
temp.append(...document.body.childNodes);
|
|
||||||
// @ts-ignore
|
|
||||||
temp2.append(...document.head.childNodes);
|
|
||||||
temp2.querySelectorAll('script[src*="google"]').forEach(item => item.remove());
|
|
||||||
temp2.querySelectorAll('#gtm_tag').forEach(item => item.remove());
|
|
||||||
temp2.querySelectorAll('script[src*="chat/gonline"]').forEach(item => item.remove());
|
|
||||||
temp2.querySelectorAll('script[nonce]').forEach(item => item.remove());
|
|
||||||
|
|
||||||
window.stop();
|
|
||||||
|
|
||||||
// document.body.outerHTML = document.body.outerHTML;
|
|
||||||
Log.info(document.body.outerHTML);
|
|
||||||
document.body.innerHTML = "";
|
|
||||||
document.head.innerHTML = "";
|
|
||||||
// @ts-ignore
|
|
||||||
document.body.append(...temp.childNodes);
|
|
||||||
// @ts-ignore
|
|
||||||
// document.head.append(...temp2.childNodes);
|
|
||||||
document.body.insertAdjacentHTML('afterbegin', temp2.innerHTML);
|
|
||||||
}
|
|
||||||
|
|
||||||
private case2() {
|
|
||||||
document.head.insertAdjacentHTML(
|
|
||||||
"afterbegin",
|
|
||||||
// `<meta http-equiv="Content-Security-Policy" content="script-src 'none'">`
|
|
||||||
`<meta http-equiv="Content-Security-Policy" content="connect-src 'self'">`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async case3() {
|
|
||||||
CompanyHelper.getInstance().detectNow();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
67
src/ts/App.ts
Normal file
67
src/ts/App.ts
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
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"
|
||||||
|
|
||||||
|
@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 configWrapper: LocalConfigWrapper,
|
||||||
|
private readonly utils: CommonUtils,
|
||||||
|
private readonly featureMan: FeatureMan,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public run() {
|
||||||
|
|
||||||
|
this.interrupt.conditionInterrupt();
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
this.initializer.init();
|
||||||
|
|
||||||
|
// this.featureMan.fStart().then(() => this.featureMan.printTable());
|
||||||
|
|
||||||
|
// 插件图标和设置菜单
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
// URL匹配
|
||||||
|
// this.urlRouter.resolve();
|
||||||
|
|
||||||
|
// 翻译
|
||||||
|
// if (this.configWrapper.config.transEnable)
|
||||||
|
// translateMain(window.location.href);
|
||||||
|
};
|
||||||
|
// TODO 临时检测jquery
|
||||||
|
if (typeof $ === "function") {
|
||||||
|
tmp();
|
||||||
|
} else {
|
||||||
|
this.utils.jQueryReady().then(() => tmp());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
160
src/ts/class/Common.ts
Normal file
160
src/ts/class/Common.ts
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
// 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 })
|
||||||
|
// // });
|
||||||
|
// }
|
||||||
|
// }
|
||||||
93
src/ts/class/Global.ts
Normal file
93
src/ts/class/Global.ts
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
import Device from "../enum/Device";
|
||||||
|
import IGlobal from "../interface/IGlobal";
|
||||||
|
import { Injectable } from "../container/Injectable";
|
||||||
|
import ClassName from "../container/ClassName";
|
||||||
|
import Logger from "./Logger";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 存储脚本用到的参数
|
||||||
|
*/
|
||||||
|
@Injectable()
|
||||||
|
@ClassName('Global')
|
||||||
|
export default class Global implements IGlobal {
|
||||||
|
|
||||||
|
GM_xmlhttpRequest: Function = null;
|
||||||
|
// 设备类型
|
||||||
|
device: Device = window.innerWidth >= 1000 ? Device.PC : window.innerWidth <= 600 ? Device.MOBILE : Device.TABLET;
|
||||||
|
unsafeWindow: Window & typeof globalThis = null;
|
||||||
|
// document body 属性
|
||||||
|
bodyAttrs: {
|
||||||
|
'data-country'?: string;
|
||||||
|
'data-celebration'?: string;
|
||||||
|
'data-traveling'?: 'true' | 'false';
|
||||||
|
'data-abroad'?: 'true' | 'false';
|
||||||
|
} = null;
|
||||||
|
// href: string = window.location.href;
|
||||||
|
// 弹窗
|
||||||
|
// popup_node: MyHTMLElement|Popup = null;
|
||||||
|
/**
|
||||||
|
* @deprecated 使用getInstance替代
|
||||||
|
*/
|
||||||
|
// beer = null;
|
||||||
|
// 留存的通知
|
||||||
|
// notifies: NotifyWrapper = { count: 0 };
|
||||||
|
// 海外库存
|
||||||
|
// fStock = null;
|
||||||
|
// 玩家名和数字id
|
||||||
|
// player_info = null;
|
||||||
|
// PDA运行环境
|
||||||
|
// isPDA: boolean = false;
|
||||||
|
// PDA自带apikey
|
||||||
|
// PDA_APIKey: string = null;
|
||||||
|
// 脚本版本
|
||||||
|
// version: string = null;
|
||||||
|
// window 副本
|
||||||
|
// window: Window & typeof globalThis = window;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
// private readonly infoUtils: InfoUtils,
|
||||||
|
private readonly logger: Logger,
|
||||||
|
) {
|
||||||
|
if (typeof unsafeWindow !== 'undefined') {
|
||||||
|
this.logger.info('存在unsafeWindow, 引入');
|
||||||
|
this.unsafeWindow = unsafeWindow || null;
|
||||||
|
window.addRFC = this.unsafeWindow.addRFC;
|
||||||
|
window.getAction = this.unsafeWindow.getAction;
|
||||||
|
window.initializeTooltip = this.unsafeWindow.initializeTooltip;
|
||||||
|
window.renderMiniProfile = this.unsafeWindow.renderMiniProfile;
|
||||||
|
window.ReactDOM = this.unsafeWindow.ReactDOM;
|
||||||
|
}
|
||||||
|
if (typeof GM_xmlhttpRequest === 'function') {
|
||||||
|
// 上层调用如果使用eval此处GM_xmlhttpRequest可能不存在于window中
|
||||||
|
this.GM_xmlhttpRequest = window.GM_xmlhttpRequest || GM_xmlhttpRequest || null;
|
||||||
|
}
|
||||||
|
// this.version = '$$WUHU_DEV_VERSION$$';
|
||||||
|
// this.PDA_APIKey = '###PDA-APIKEY###';
|
||||||
|
// this.isPDA = !this.PDA_APIKey.includes('###');
|
||||||
|
// this.device = window.innerWidth >= 1000 ? Device.PC : window.innerWidth <= 600 ? Device.MOBILE : Device.TABLET;
|
||||||
|
// this.player_info = this.infoUtils.getPlayerInfo();
|
||||||
|
// this.popup_node = null;
|
||||||
|
// this.notifies = { count: 0 };
|
||||||
|
// this.href = window.location.href;
|
||||||
|
this.bodyAttrs = {};
|
||||||
|
|
||||||
|
for (let i = 0; i < document.body.attributes.length; i++) {
|
||||||
|
let item = document.body.attributes.item(i);
|
||||||
|
this.bodyAttrs[item.name] = item.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 当窗口关闭时关闭所有还存在的通知
|
||||||
|
// window.addEventListener(
|
||||||
|
// 'beforeunload',
|
||||||
|
// () => {
|
||||||
|
// if (this.notifies.count !== 0) {
|
||||||
|
// for (let i = 0; i < this.notifies.count; i++) {
|
||||||
|
// (this.notifies[i] !== null) && (this.notifies[i].close())
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// );
|
||||||
|
|
||||||
|
// this.logger.info('WH脚本参数初始化结束');
|
||||||
|
}
|
||||||
|
}
|
||||||
285
src/ts/class/Initializer.ts
Normal file
285
src/ts/class/Initializer.ts
Normal file
@ -0,0 +1,285 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
19
src/ts/class/Interrupt.ts
Normal file
19
src/ts/class/Interrupt.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import ClassName from "../container/ClassName";
|
||||||
|
import { Injectable } from "../container/Injectable";
|
||||||
|
|
||||||
|
|
||||||
|
@ClassName('Interrupt')
|
||||||
|
@Injectable()
|
||||||
|
export default class Interrupt {
|
||||||
|
|
||||||
|
public conditionInterrupt() {
|
||||||
|
let title: HTMLElement | { innerText: string } = (document.querySelector('#skip-to-content') ||
|
||||||
|
document.querySelector('[href*="#skip-to-content"]')) as HTMLElement || { innerText: '' };
|
||||||
|
let condition = (
|
||||||
|
document.title.toLowerCase().includes('just a moment') ||
|
||||||
|
title.innerText.toLowerCase().includes('please validate') ||
|
||||||
|
document.querySelector('div.container div.cf .iAmUnderAttack') !== null
|
||||||
|
);
|
||||||
|
if (condition) throw new Error('芜湖');
|
||||||
|
}
|
||||||
|
}
|
||||||
89
src/ts/class/LocalConfigWrapper.ts
Normal file
89
src/ts/class/LocalConfigWrapper.ts
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
import { Injectable } from "../container/Injectable";
|
||||||
|
import ClassName from "../container/ClassName";
|
||||||
|
import Logger from "./Logger";
|
||||||
|
import defaultConfig, { Config, isNotified } from "./config/defaultConfig";
|
||||||
|
import MsgWrapper from "./utils/MsgWrapper";
|
||||||
|
import { InjectionKey } from "vue";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
@ClassName('LocalConfigWrapper')
|
||||||
|
export default class LocalConfigWrapper {
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private readonly logger: Logger,
|
||||||
|
private readonly msgWrapper: MsgWrapper,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public get config(): Config {
|
||||||
|
const _this = this;
|
||||||
|
const str2code = (str: string): number[] => {
|
||||||
|
let code = [];
|
||||||
|
for (let i = 0; i < str.length; i++) {
|
||||||
|
code.push(str.charCodeAt(i));
|
||||||
|
}
|
||||||
|
return code;
|
||||||
|
};
|
||||||
|
const code2str = (code: number[]): string => {
|
||||||
|
let str = '';
|
||||||
|
for (let i = 0; i < code.length; i++) {
|
||||||
|
str += String.fromCharCode(code[i]);
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
};
|
||||||
|
return new Proxy(_this.Local, {
|
||||||
|
get(target: Config, prop: string) {
|
||||||
|
let value = target[prop] ?? defaultConfig[prop];
|
||||||
|
if (prop === 'autoLoginPwd') {
|
||||||
|
let jsonObj;
|
||||||
|
try {
|
||||||
|
jsonObj = JSON.parse(window.atob(value));
|
||||||
|
} catch (e) {
|
||||||
|
jsonObj = [];
|
||||||
|
}
|
||||||
|
value = code2str(jsonObj);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
set(target: Config, prop: string, value: any): boolean {
|
||||||
|
let config = target;
|
||||||
|
let preVal = config[prop];
|
||||||
|
if (prop === 'autoLoginPwd') {
|
||||||
|
value = window.btoa(JSON.stringify(str2code(value)));
|
||||||
|
}
|
||||||
|
if (preVal !== value) {
|
||||||
|
config[prop] = value;
|
||||||
|
_this.setLocal(config);
|
||||||
|
let msg = `[${ prop }]值变更 ${ preVal }->${ value }`;
|
||||||
|
_this.logger.info(msg);
|
||||||
|
if (isNotified(prop)) {
|
||||||
|
_this.msgWrapper.create(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从localstorage解析返回配置对象
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private get Local(): Config {
|
||||||
|
let config: Config;
|
||||||
|
try {
|
||||||
|
config = JSON.parse(localStorage.getItem('wh_trans_settings')) ?? defaultConfig;
|
||||||
|
} catch (e) {
|
||||||
|
this.logger.error('配置解析失败, 载入默认');
|
||||||
|
config = defaultConfig;
|
||||||
|
localStorage.setItem('wh_trans_settings', JSON.stringify(defaultConfig));
|
||||||
|
}
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
private setLocal(config: Config) {
|
||||||
|
localStorage.setItem('wh_trans_settings', JSON.stringify(config));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const LocalConfigWrapperKey = Symbol() as InjectionKey<LocalConfigWrapper>;
|
||||||
@ -4,28 +4,25 @@ export default class Log {
|
|||||||
|
|
||||||
public static info(...o): void {
|
public static info(...o): void {
|
||||||
Log.counter.info++;
|
Log.counter.info++;
|
||||||
let time = this.getTime();
|
let flag = '%c WH %cIFO%c' + this.getTime() + '%c';
|
||||||
let flag = '[WH] IFO';
|
|
||||||
if (this.debug()) {
|
if (this.debug()) {
|
||||||
console.log(flag, time, ...o);
|
console.log(flag, 'background:grey;color:white;', '', 'color:grey;', '', ...o);
|
||||||
}
|
}
|
||||||
this.saveLogs(flag, time, ...o);
|
this.saveLogs(flag, ...o);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static error(...o): void {
|
public static error(...o): void {
|
||||||
Log.counter.error++;
|
Log.counter.error++;
|
||||||
let time = this.getTime();
|
let flag = '%c WH %cERR%c' + this.getTime() + '%c';
|
||||||
let flag = '[WH] ERR';
|
console.error(flag, 'background:grey;color:white;', 'background:red;color:white;', 'color:grey;', '', ...o);
|
||||||
console.error(flag, time, ...o);
|
this.saveLogs(flag, ...o);
|
||||||
this.saveLogs(flag, time, ...o);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static warn(...o): void {
|
public static warn(...o): void {
|
||||||
Log.counter.warning++;
|
Log.counter.warning++;
|
||||||
let time = this.getTime();
|
let flag = '%c WH %cWRN%c' + this.getTime() + '%c';
|
||||||
let flag = '[WH] WRN';
|
console.warn(flag, 'background:grey;color:white;', 'background:#ff9800;color:white;', 'color:grey;', '', ...o);
|
||||||
(this.debug()) && (console.warn(flag, time, ...o));
|
this.saveLogs(flag, ...o);
|
||||||
this.saveLogs(flag, time, ...o);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static debug(): boolean {
|
public static debug(): boolean {
|
||||||
@ -34,6 +31,7 @@ export default class Log {
|
|||||||
let local = JSON.parse(localStorage.getItem('wh_trans_settings'));
|
let local = JSON.parse(localStorage.getItem('wh_trans_settings'));
|
||||||
if (local) ret = local['isDev'];
|
if (local) ret = local['isDev'];
|
||||||
} catch {
|
} catch {
|
||||||
|
this.error('debug错误')
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -47,7 +45,7 @@ export default class Log {
|
|||||||
let minutes = ('0' + d.getMinutes()).slice(-2);
|
let minutes = ('0' + d.getMinutes()).slice(-2);
|
||||||
let seconds = ('0' + d.getSeconds()).slice(-2);
|
let seconds = ('0' + d.getSeconds()).slice(-2);
|
||||||
let ms = ('00' + d.getMilliseconds()).slice(-3);
|
let ms = ('00' + d.getMilliseconds()).slice(-3);
|
||||||
return `[${ year }-${ month }-${ date } ${ hours }:${ minutes }:${ seconds }.${ ms }]`;
|
return `${ year }-${ month }-${ date } ${ hours }:${ minutes }:${ seconds }.${ ms }`;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getLogs() {
|
public static getLogs() {
|
||||||
@ -56,7 +54,7 @@ export default class Log {
|
|||||||
|
|
||||||
private static saveLogs(...o) {
|
private static saveLogs(...o) {
|
||||||
o.forEach(item => {
|
o.forEach(item => {
|
||||||
if (typeof item === 'string') this.logs += item;
|
if (typeof item === 'string') this.logs += item.replaceAll('%c', '');
|
||||||
else if (item !== null && item !== undefined) {
|
else if (item !== null && item !== undefined) {
|
||||||
let json = '{}';
|
let json = '{}';
|
||||||
let name = Object.getPrototypeOf(item).constructor.name;
|
let name = Object.getPrototypeOf(item).constructor.name;
|
||||||
52
src/ts/class/Logger.ts
Normal file
52
src/ts/class/Logger.ts
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import "reflect-metadata";
|
||||||
|
import ClassName, { GetClassName } from "../container/ClassName";
|
||||||
|
import { Injectable } from "../container/Injectable";
|
||||||
|
import Log from "./Log";
|
||||||
|
import { InjectionKey } from "vue";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
@ClassName('Logger')
|
||||||
|
export default class Logger {
|
||||||
|
info(...o: any): void {
|
||||||
|
return Log.info(...o);
|
||||||
|
}
|
||||||
|
|
||||||
|
warn(...o: any): void {
|
||||||
|
return Log.warn(...o);
|
||||||
|
}
|
||||||
|
|
||||||
|
error(...o: any): void {
|
||||||
|
return Log.error(...o);
|
||||||
|
}
|
||||||
|
|
||||||
|
debug() {
|
||||||
|
return Log.debug()
|
||||||
|
}
|
||||||
|
|
||||||
|
getCounter() {
|
||||||
|
return Log.getCounter()
|
||||||
|
}
|
||||||
|
|
||||||
|
getTime() {
|
||||||
|
return Log.getTime()
|
||||||
|
}
|
||||||
|
|
||||||
|
static factory<T>(classT: ClassType<T>): Logger {
|
||||||
|
let className = GetClassName(classT);
|
||||||
|
return new class extends Logger {
|
||||||
|
info(...o: any): void {
|
||||||
|
return super.info(`[${ className }]`, ...o);
|
||||||
|
}
|
||||||
|
|
||||||
|
warn(...o: any): void {
|
||||||
|
return super.warn(`[${ className }]`, ...o);
|
||||||
|
}
|
||||||
|
|
||||||
|
error(...o: any): void {
|
||||||
|
return super.error(`[${ className }]`, ...o);
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const LoggerKey = Symbol() as InjectionKey<Logger>;
|
||||||
35
src/ts/class/ModuleLoader.ts
Normal file
35
src/ts/class/ModuleLoader.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import Logger from "./Logger";
|
||||||
|
import { Container } from "../container/Container";
|
||||||
|
import ClassName, { GetClassName } from "../container/ClassName";
|
||||||
|
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)
|
||||||
|
|
||||||
|
// constructor() {
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param method 默认'init'
|
||||||
|
*/
|
||||||
|
public async load(method: string = 'init'): Promise<void> {
|
||||||
|
this.logger.info('即将加载: ', this.classes)
|
||||||
|
this.classes.forEach(clazz => {
|
||||||
|
try {
|
||||||
|
this.logger.info('正在加载' + GetClassName(clazz))
|
||||||
|
Container.factory(clazz)[method]();
|
||||||
|
} catch (e) {
|
||||||
|
this.logger.error('加载[' + GetClassName(clazz) + ']时出错', e.message, e.stack);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.classes.length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public push(clazz: new(...arg: any) => { init: () => void }): void {
|
||||||
|
this.classes.push(clazz);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,45 +1,61 @@
|
|||||||
import cityFinder from "../func/module/cityFinder";
|
import cityFinder from "../func/module/cityFinder";
|
||||||
import { missionDict } from "../dictionary/translation";
|
import { missionDict } from "../dictionary/translation";
|
||||||
import getTaskHint from "../func/translate/getTaskHint";
|
import getTaskHint from "../func/translate/getTaskHint";
|
||||||
import WuhuBase from "./WuhuBase";
|
|
||||||
import CommonUtils from "./utils/CommonUtils";
|
import CommonUtils from "./utils/CommonUtils";
|
||||||
import Log from "./Log";
|
import SHOP_BEER_STATIC_ITEM_HTML from "../../static/html/buyBeer/shop_beer_static_item.html";
|
||||||
import WuhuConfig from "./WuhuConfig";
|
import ADD_BEER_HEAD_HTML from "../../static/html/buyBeer/add_beer_head.html";
|
||||||
import Alert from "./utils/Alert";
|
import QUICK_CRIMES_HTML from "../../static/html/quick_crimes.html";
|
||||||
import SHOP_BEER_STATIC_ITEM_HTML from "../static/html/buyBeer/shop_beer_static_item.html";
|
import RW_RIDER_HTML from "../../static/html/rw_rider.html";
|
||||||
import ADD_BEER_HEAD_HTML from "../static/html/buyBeer/add_beer_head.html";
|
|
||||||
import QUICK_CRIMES_HTML from "../static/html/quick_crimes.html";
|
|
||||||
import RW_RIDER_HTML from "../static/html/rw_rider.html";
|
|
||||||
import christmasTownHelper from "../func/module/christmasTownHelper";
|
import christmasTownHelper from "../func/module/christmasTownHelper";
|
||||||
import LotteryHelper from "./action/LotteryHelper";
|
import LotteryHelper from "../feature/LotteryHelper";
|
||||||
import TornStyleBlock from "./utils/TornStyleBlock";
|
import TornStyleBlock from "./utils/TornStyleBlock";
|
||||||
import PTHelper from "./action/PTHelper";
|
import PTHelper from "./action/PTHelper";
|
||||||
import StackHelper from "./action/StackHelper";
|
import StackHelper from "../feature/StackHelper";
|
||||||
import BuyBeerHelper from "./action/BuyBeerHelper";
|
import BuyBeerHelper from "../feature/BuyBeerHelper";
|
||||||
import XZMZ from "./action/XZMZ";
|
import XZMZ from "./action/XZMZ";
|
||||||
import ProfileHelper from "./action/ProfileHelper";
|
import ProfileHelper from "./action/ProfileHelper";
|
||||||
import SearchHelper from "./action/SearchHelper";
|
import SearchHelper from "./action/SearchHelper";
|
||||||
import TornStyleSwitch from "./utils/TornStyleSwitch";
|
import TornStyleSwitch from "./utils/TornStyleSwitch";
|
||||||
import SlotsHelper from "./action/SlotsHelper";
|
import SlotsHelper from "./action/SlotsHelper";
|
||||||
|
import globVars from "../globVars";
|
||||||
|
import { Injectable } from "../container/Injectable";
|
||||||
|
import ClassName from "../container/ClassName";
|
||||||
|
import LocalConfigWrapper from "./LocalConfigWrapper";
|
||||||
|
import { Container } from "../container/Container";
|
||||||
|
import Logger from "./Logger";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 脚本区分页面的功能入口
|
||||||
|
*
|
||||||
* TODO 去除jq
|
* TODO 去除jq
|
||||||
*/
|
*/
|
||||||
export default class UrlPattern extends WuhuBase {
|
@Injectable()
|
||||||
className = 'UrlPattern';
|
@ClassName('UrlPattern')
|
||||||
|
export default class UrlRouter {
|
||||||
|
constructor(
|
||||||
|
private readonly localConfigWrapper: LocalConfigWrapper,
|
||||||
|
private readonly buyBeerHelper: BuyBeerHelper,
|
||||||
|
private readonly searchHelper: SearchHelper,
|
||||||
|
private readonly lotteryHelper: LotteryHelper,
|
||||||
|
private readonly slotsHelper: SlotsHelper,
|
||||||
|
private readonly logger: Logger,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
public resolve(): void {
|
public resolve(): void {
|
||||||
let href = window.location.href;
|
let href = window.location.href;
|
||||||
|
let modules = [];
|
||||||
// 捡垃圾助手
|
// 捡垃圾助手
|
||||||
if (href.includes('city.php') && WuhuConfig.get('cityFinder')) {
|
if (href.includes('city.php') && this.localConfigWrapper.config.cityFinder) {
|
||||||
let _base = new TornStyleBlock('芜湖助手').insert2Dom();
|
let _base = new TornStyleBlock('芜湖助手').insert2Dom();
|
||||||
let reloadSwitch = new TornStyleSwitch('解决一直转圈(加载中)的问题');
|
// let reloadSwitch = new TornStyleSwitch('解决一直转圈(加载中)的问题');
|
||||||
reloadSwitch.getInput().checked = WuhuConfig.get('SolveGoogleScriptPendingIssue');
|
// reloadSwitch.getInput().checked = this.localConfigWrapper.config.SolveGoogleScriptPendingIssue;
|
||||||
_base.append(reloadSwitch.getBase()).insert2Dom();
|
// _base.append(reloadSwitch.getBase()).insert2Dom();
|
||||||
reloadSwitch.getInput().addEventListener('change', () => {
|
// reloadSwitch.getInput().addEventListener('change', () => {
|
||||||
if (reloadSwitch.getInput().checked) window.location.replace(window.location.href);
|
// if (reloadSwitch.getInput().checked) window.location.replace(window.location.href);
|
||||||
WuhuConfig.set('SolveGoogleScriptPendingIssue', reloadSwitch.getInput().checked, true);
|
// this.localConfigWrapper.config.SolveGoogleScriptPendingIssue = reloadSwitch.getInput().checked;
|
||||||
});
|
// // WuhuConfig.set('SolveGoogleScriptPendingIssue', reloadSwitch.getInput().checked, true);
|
||||||
|
// });
|
||||||
|
|
||||||
_base.append(document.createElement('br'));
|
_base.append(document.createElement('br'));
|
||||||
|
|
||||||
@ -47,17 +63,17 @@ export default class UrlPattern extends WuhuBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// pt一键购买
|
// pt一键购买
|
||||||
if (href.includes('pmarket.php')) PTHelper.getInstance();
|
if (href.includes('pmarket.php')) Container.factory(PTHelper);
|
||||||
|
|
||||||
// 叠e助手
|
// 叠e助手
|
||||||
if (href.includes('gym.php')) StackHelper.getInstance();
|
if (href.includes('gym.php')) Container.factory(StackHelper);
|
||||||
|
|
||||||
// 寻找木桩
|
// 寻找木桩
|
||||||
if (href.includes('item.php?temp=4')) {
|
if (href.includes('item.php?temp=4')) {
|
||||||
let hasInit: boolean = false;
|
let hasInit: boolean = false;
|
||||||
let handle = () => {
|
let handle = () => {
|
||||||
if (!hasInit && window.location.hash === '#xunzhaomuzhuang') {
|
if (!hasInit && window.location.hash === '#xunzhaomuzhuang') {
|
||||||
XZMZ.getInstance().init();
|
Container.factory(XZMZ).init();
|
||||||
hasInit = true;
|
hasInit = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -75,12 +91,12 @@ export default class UrlPattern extends WuhuBase {
|
|||||||
let node = document.querySelector('ul.items-list');
|
let node = document.querySelector('ul.items-list');
|
||||||
if (!node) {
|
if (!node) {
|
||||||
msg_node.innerHTML = '❌ 商品未加载完';
|
msg_node.innerHTML = '❌ 商品未加载完';
|
||||||
Log.error('商品未加载完');
|
this.logger.error('商品未加载完');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (node.querySelector('span[id="180-name"]')) {
|
if (node.querySelector('span[id="180-name"]')) {
|
||||||
msg_node.innerHTML = '❌ 页面已经有啤酒了';
|
msg_node.innerHTML = '❌ 页面已经有啤酒了';
|
||||||
Log.warn('商店页面已有啤酒');
|
this.logger.warn('商店页面已有啤酒');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const clear_node = node.querySelector('li.clear');
|
const clear_node = node.querySelector('li.clear');
|
||||||
@ -95,19 +111,11 @@ export default class UrlPattern extends WuhuBase {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 监听啤酒购买
|
// 监听啤酒购买
|
||||||
$(document).ajaxComplete((_, xhr, settings) => {
|
globVars.responseHandlers.push((...args: any[]) => this.buyBeerHelper.responseHandler.apply(this.buyBeerHelper, args));
|
||||||
Log.info({ xhr, settings });
|
|
||||||
let { data } = settings, { responseText } = xhr;
|
|
||||||
let response = JSON.parse(responseText);
|
|
||||||
if (data.includes('step=buyShopItem') && data.includes('ID=180') && response['success']) {
|
|
||||||
new Alert('已检测成功购买啤酒');
|
|
||||||
BuyBeerHelper.getInstance().skip_today();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 快速crime TODO 重构、与翻译解藕
|
// 快速crime TODO 重构、与翻译解藕
|
||||||
if (href.contains(/crimes\.php/) && WuhuConfig.get('quickCrime')) {
|
if (href.contains(/crimes\.php/) && this.localConfigWrapper.config.quickCrime) {
|
||||||
// iframe
|
// iframe
|
||||||
if (self !== top) {
|
if (self !== top) {
|
||||||
const isValidate = document.querySelector('h4#skip-to-content').innerText.toLowerCase().includes('validate');
|
const isValidate = document.querySelector('h4#skip-to-content').innerText.toLowerCase().includes('validate');
|
||||||
@ -157,7 +165,7 @@ export default class UrlPattern extends WuhuBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 任务助手 TODO 重构、与翻译解藕
|
// 任务助手 TODO 重构、与翻译解藕
|
||||||
if (href.contains(/loader\.php\?sid=missions/) && WuhuConfig.get('missionHint')) {
|
if (href.contains(/loader\.php\?sid=missions/) && this.localConfigWrapper.config.missionHint) {
|
||||||
const anchor = document.querySelector('.content-wrapper');
|
const anchor = document.querySelector('.content-wrapper');
|
||||||
const OB = new MutationObserver(() => {
|
const OB = new MutationObserver(() => {
|
||||||
OB.disconnect();
|
OB.disconnect();
|
||||||
@ -206,7 +214,7 @@ export default class UrlPattern extends WuhuBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 个人资料
|
// 个人资料
|
||||||
if (href.includes('profiles.php?XID=')) ProfileHelper.getInstance();
|
if (href.includes('profiles.php?XID=')) Container.factory(ProfileHelper);
|
||||||
|
|
||||||
// 圣诞小镇
|
// 圣诞小镇
|
||||||
if (href.contains(/christmas_town\.php/) && new Date().getMonth() > 9) christmasTownHelper();
|
if (href.contains(/christmas_town\.php/) && new Date().getMonth() > 9) christmasTownHelper();
|
||||||
@ -260,12 +268,12 @@ export default class UrlPattern extends WuhuBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 彩票助手
|
// 彩票助手
|
||||||
if (href.includes('loader.php?sid=lottery')) LotteryHelper.getInstance().init();
|
if (href.includes('loader.php?sid=lottery')) this.lotteryHelper.init();
|
||||||
|
|
||||||
// 老虎机助手
|
// 老虎机助手
|
||||||
if (href.includes('loader.php?sid=slots')) SlotsHelper.getInstance().init();
|
if (href.includes('loader.php?sid=slots')) this.slotsHelper.init();
|
||||||
|
|
||||||
// 搜索助手
|
// 搜索助手
|
||||||
if (href.includes('page.php?sid=UserList')) SearchHelper.getInstance().init();
|
if (href.includes('page.php?sid=UserList')) this.searchHelper.init();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,46 +1,58 @@
|
|||||||
import adHelper from "../func/module/adHelper";
|
import adHelper from "../func/module/adHelper";
|
||||||
import safeKeeper from "../func/module/safeKeeper";
|
import safeKeeper from "../func/module/safeKeeper";
|
||||||
import initMiniProf from "../func/utils/initMiniProf";
|
import initMiniProf from "../func/utils/initMiniProf";
|
||||||
import WuhuBase from "./WuhuBase";
|
|
||||||
import Log from "./Log";
|
|
||||||
import CommonUtils from "./utils/CommonUtils";
|
import CommonUtils from "./utils/CommonUtils";
|
||||||
import Alert from "./utils/Alert";
|
import * as EVENTS from "../../static/json/event.json";
|
||||||
import * as EVENTS from "../static/json/event.json";
|
import * as FEST from "../../static/json/fest.json";
|
||||||
import * as FEST from "../static/json/fest.json";
|
|
||||||
import Popup from "./utils/Popup";
|
import Popup from "./utils/Popup";
|
||||||
import TravelItem from "./action/TravelItem";
|
import TravelItem from "../feature/TravelItem";
|
||||||
import ZHONG_MENU_HTML from "../static/html/zhong/zhong_menu.html";
|
import ZHONG_MENU_HTML from "../../static/html/zhong/zhong_menu.html";
|
||||||
import ZHONG_UPDATE_HTML from "../static/html/zhong/zhong_update.html";
|
import ZHONG_UPDATE_HTML from "../../static/html/zhong/zhong_update.html";
|
||||||
import ZHONG_LOOT_HTML from "../static/html/zhong/zhong_loot.html";
|
import ZHONG_LOOT_HTML from "../../static/html/zhong/zhong_loot.html";
|
||||||
import Test from "../test/Test";
|
import Test from "../test/Test";
|
||||||
import Global from "./Global";
|
|
||||||
import Timer from "./utils/Timer";
|
import Timer from "./utils/Timer";
|
||||||
import QuickFlyBtnHandler from "./handler/QuickFlyBtnHandler";
|
import QuickFlyBtnHandler from "./handler/QuickFlyBtnHandler";
|
||||||
import NNB from "./handler/NNB";
|
import NNB from "./handler/NNB";
|
||||||
import QuickLinksHandler from "./handler/QuickLinksHandler";
|
import QuickLinksHandler from "./handler/QuickLinksHandler";
|
||||||
import ItemPriceWatcherHandler from "./handler/ItemPriceWatcherHandler";
|
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 SettingsHandler from "./handler/SettingsHandler";
|
||||||
import WuhuConfig from "./WuhuConfig";
|
import { MENU_ITEM_TYPE } from "../interface/MenuItem";
|
||||||
|
import { Injectable } from "../container/Injectable";
|
||||||
|
import ClassName from "../container/ClassName";
|
||||||
|
import LocalConfigWrapper from "./LocalConfigWrapper";
|
||||||
|
import Logger from "./Logger";
|
||||||
|
import { Container } from "../container/Container";
|
||||||
|
import TornPDAUtils from "./utils/TornPDAUtils";
|
||||||
|
import InfoUtils from "./utils/InfoUtils";
|
||||||
|
import globVars from "../globVars";
|
||||||
|
import MsgWrapper from "./utils/MsgWrapper";
|
||||||
|
|
||||||
export default class ZhongIcon extends WuhuBase {
|
@Injectable()
|
||||||
className = 'ZhongIcon';
|
@ClassName('ZhongIcon')
|
||||||
|
export default class ZhongIcon {
|
||||||
public static ZhongNode: MyHTMLElement = null;
|
public static ZhongNode: MyHTMLElement = null;
|
||||||
private menuItemList: MenuItemConfig[] = null;
|
private menuItemList: MenuItemConfig[] = null;
|
||||||
private cashView: HTMLElement = null;
|
private cashView: HTMLElement = null;
|
||||||
|
|
||||||
// private settingItemList: MenuItemConfig[] = null;
|
public constructor(
|
||||||
|
private readonly commonUtils: CommonUtils,
|
||||||
public constructor() {
|
private readonly localConfigWrapper: LocalConfigWrapper,
|
||||||
super();
|
private readonly nnb: NNB,
|
||||||
|
private readonly itemPriceWatcherHandler: ItemPriceWatcherHandler,
|
||||||
|
private readonly logger: Logger,
|
||||||
|
private readonly tornPDAUtils: TornPDAUtils,
|
||||||
|
private readonly infoUtils: InfoUtils,
|
||||||
|
private readonly msgWrapper: MsgWrapper,
|
||||||
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public init() {
|
public init() {
|
||||||
Log.info('ZhongIcon初始化, 设置图标开始');
|
|
||||||
this.constructMenuList()
|
this.constructMenuList()
|
||||||
.insert2Dom()
|
.insert2Dom()
|
||||||
.dragHandler();
|
.dragHandler();
|
||||||
Log.info('设置图标结束, ZhongIcon初始化结束');
|
this.logger.info('设置图标结束');
|
||||||
}
|
}
|
||||||
|
|
||||||
public updateCashView(content: string): void {
|
public updateCashView(content: string): void {
|
||||||
@ -67,8 +79,7 @@ export default class ZhongIcon extends WuhuBase {
|
|||||||
*/
|
*/
|
||||||
private insert2Dom(): ZhongIcon {
|
private insert2Dom(): ZhongIcon {
|
||||||
let zhongNode: MyHTMLElement = document.querySelector('div#wh-trans-icon');
|
let zhongNode: MyHTMLElement = document.querySelector('div#wh-trans-icon');
|
||||||
let settings = this.menuItemList;
|
let version = globVars.version;
|
||||||
let { version } = WuhuBase.glob;
|
|
||||||
if ((self !== top) || !!zhongNode) return null;
|
if ((self !== top) || !!zhongNode) return null;
|
||||||
zhongNode = document.createElement('div');
|
zhongNode = document.createElement('div');
|
||||||
ZhongIcon.ZhongNode = zhongNode;
|
ZhongIcon.ZhongNode = zhongNode;
|
||||||
@ -78,37 +89,36 @@ export default class ZhongIcon extends WuhuBase {
|
|||||||
// 助手菜单
|
// 助手菜单
|
||||||
const menu_cont = zhongNode.querySelector('#wh-gSettings');
|
const menu_cont = zhongNode.querySelector('#wh-gSettings');
|
||||||
// 遍历菜单node设置、生成node、插入dom
|
// 遍历菜单node设置、生成node、插入dom
|
||||||
this.menuItemList.forEach(setting => CommonUtils.getInstance().elemGenerator(setting, menu_cont));
|
this.menuItemList.forEach(setting => this.commonUtils.elemGenerator(setting, menu_cont));
|
||||||
Log.info('生成元素插入完成');
|
this.logger.info('生成元素插入完成');
|
||||||
// 计时node
|
// 计时node
|
||||||
zhongNode.initTimer = zhongNode.querySelector('#wh-inittimer');
|
zhongNode.initTimer = zhongNode.querySelector('#wh-inittimer');
|
||||||
// 芜湖助手图标点击事件
|
// 芜湖助手图标点击事件
|
||||||
(<MyHTMLElement>zhongNode.querySelector('#wh-trans-icon-btn')).onclick = () => {
|
(<MyHTMLElement>zhongNode.querySelector('#wh-trans-icon-btn')).onclick = () => {
|
||||||
zhongNode.classList.toggle('wh-icon-expanded');
|
zhongNode.classList.toggle('wh-icon-expanded');
|
||||||
const click_func = e => {
|
const click_func = e => {
|
||||||
Log.info(e.target);
|
this.logger.info(e.target);
|
||||||
if (e.target === zhongNode.querySelector('#wh-trans-icon-btn')) return;
|
if (e.target === zhongNode.querySelector('#wh-trans-icon-btn')) return;
|
||||||
if (!zhongNode.contains(e.target)) {
|
if (!zhongNode.contains(e.target)) {
|
||||||
Log.info('移除事件监听器');
|
this.logger.info('移除事件监听器');
|
||||||
document.body.removeEventListener('click', click_func);
|
document.body.removeEventListener('click', click_func);
|
||||||
zhongNode.classList.remove('wh-icon-expanded');
|
zhongNode.classList.remove('wh-icon-expanded');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if (zhongNode.classList.contains('wh-icon-expanded')) {
|
if (zhongNode.classList.contains('wh-icon-expanded')) {
|
||||||
Log.info('芜湖助手图标点击->添加监听');
|
this.logger.info('芜湖助手图标点击->添加监听');
|
||||||
document.body.addEventListener('click', click_func);
|
document.body.addEventListener('click', click_func);
|
||||||
} else {
|
} else {
|
||||||
Log.info('芜湖助手图标->移除监听');
|
this.logger.info('芜湖助手图标->移除监听');
|
||||||
document.body.removeEventListener('click', click_func);
|
document.body.removeEventListener('click', click_func);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// 更新按钮点击事件
|
// 更新按钮点击事件
|
||||||
(<MyHTMLElement>zhongNode.querySelector('#wh-update-btn')).onclick = e => {
|
(<MyHTMLElement>zhongNode.querySelector('#wh-update-btn')).onclick = e => {
|
||||||
(<HTMLButtonElement>e.target).blur();
|
(<HTMLButtonElement>e.target).blur();
|
||||||
const innerHtml = ZHONG_UPDATE_HTML;
|
|
||||||
// 直接复制的按钮
|
// 直接复制的按钮
|
||||||
new Popup(innerHtml, '如何更新')
|
new Popup(ZHONG_UPDATE_HTML, '如何更新')
|
||||||
.getElement()
|
.element
|
||||||
.querySelector('button').onclick = async (e) => {
|
.querySelector('button').onclick = async (e) => {
|
||||||
let target = e.target as HTMLButtonElement;
|
let target = e.target as HTMLButtonElement;
|
||||||
target.innerHTML = '加载中';
|
target.innerHTML = '加载中';
|
||||||
@ -124,7 +134,7 @@ export default class ZhongIcon extends WuhuBase {
|
|||||||
textarea_node.remove();
|
textarea_node.remove();
|
||||||
target.innerHTML = '已复制';
|
target.innerHTML = '已复制';
|
||||||
target.onclick = null;
|
target.onclick = null;
|
||||||
new Alert('脚本已复制,请前往粘贴');
|
this.msgWrapper.create('脚本已复制,请前往粘贴');
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -132,8 +142,9 @@ export default class ZhongIcon extends WuhuBase {
|
|||||||
zhongNode.querySelectorAll('#wh-trans-fest-date button').forEach((el, i) => i === 0
|
zhongNode.querySelectorAll('#wh-trans-fest-date button').forEach((el, i) => i === 0
|
||||||
? el.addEventListener('click', () => {
|
? el.addEventListener('click', () => {
|
||||||
let html = '<table>';
|
let html = '<table>';
|
||||||
settings.fest_date_list.sort().forEach(date =>
|
// TODO 动态节日数据
|
||||||
html += `<tr><td>${ 1 + ((<any>date.slice(0, 2)) | 0) }月${ date.slice(2) }日</td><td>${ settings.fest_date_dict[date].name }</td><td>${ settings.fest_date_dict[date].eff }</td></tr>`
|
Object.keys(FEST.val).sort().forEach(date =>
|
||||||
|
html += `<tr><td>${ 1 + ((<any>date.slice(0, 2)) | 0) }月${ date.slice(2) }日</td><td>${ FEST.val[date].name }</td><td>${ FEST.val[date].eff }</td></tr>`
|
||||||
);
|
);
|
||||||
new Popup(html += '</table>', '节日');
|
new Popup(html += '</table>', '节日');
|
||||||
})
|
})
|
||||||
@ -142,14 +153,15 @@ export default class ZhongIcon extends WuhuBase {
|
|||||||
zhongNode.querySelectorAll('#wh-trans-event-cont button').forEach((el, i) => i === 0
|
zhongNode.querySelectorAll('#wh-trans-event-cont button').forEach((el, i) => i === 0
|
||||||
? el.addEventListener('click', () => {
|
? el.addEventListener('click', () => {
|
||||||
let html = '<table>';
|
let html = '<table>';
|
||||||
settings.events.forEach(el =>
|
// TODO 动态节日数据
|
||||||
|
EVENTS.default.forEach(el =>
|
||||||
html += `<tr><td><b>${ el.name }</b></td><td>${ el.start[0] + 1 }月${ el.start[1] }日${ el.start[2] }:00~${ el.end[0] + 1 }月${ el.end[1] }日${ el.end[2] }:00</td></tr><tr><td colspan="2">${ el.eff }</td></tr>`);
|
html += `<tr><td><b>${ el.name }</b></td><td>${ el.start[0] + 1 }月${ el.start[1] }日${ el.start[2] }:00~${ el.end[0] + 1 }月${ el.end[1] }日${ el.end[2] }:00</td></tr><tr><td colspan="2">${ el.eff }</td></tr>`);
|
||||||
new Popup(html += '</table><p>更多信息请关注群聊和公众号</p>', '活动');
|
new Popup(html += '</table><p>更多信息请关注群聊和公众号</p>', '活动');
|
||||||
})
|
})
|
||||||
: el.addEventListener('click', null));
|
: el.addEventListener('click', null));
|
||||||
// 调整图标至有记录的位置
|
// 调整图标至有记录的位置
|
||||||
if (WuhuConfig.get("SaveIconPosition")) {
|
if (this.localConfigWrapper.config.SaveIconPosition) {
|
||||||
let iconPosition = WuhuConfig.get("IconPosition");
|
let iconPosition = this.localConfigWrapper.config.IconPosition;
|
||||||
let documentSize = { x: document.documentElement.offsetWidth, y: document.documentElement.offsetHeight };
|
let documentSize = { x: document.documentElement.offsetWidth, y: document.documentElement.offsetHeight };
|
||||||
ZhongIcon.setPosition(
|
ZhongIcon.setPosition(
|
||||||
iconPosition.x > documentSize.x ? documentSize.x * 0.9 | 0 : iconPosition.x,
|
iconPosition.x > documentSize.x ? documentSize.x * 0.9 | 0 : iconPosition.x,
|
||||||
@ -158,10 +170,10 @@ export default class ZhongIcon extends WuhuBase {
|
|||||||
}
|
}
|
||||||
document.body.append(zhongNode);
|
document.body.append(zhongNode);
|
||||||
// 引入torn自带浮动提示
|
// 引入torn自带浮动提示
|
||||||
Log.info('引入torn自带浮动提示');
|
this.logger.info('引入torn浮动提示');
|
||||||
(window.initializeTooltip) && (window.initializeTooltip('.wh-container', 'white-tooltip'));
|
(window.initializeTooltip) && (window.initializeTooltip('.wh-container', 'white-tooltip'));
|
||||||
// 加载torn mini profile
|
// 加载torn mini profile
|
||||||
Log.info('加载torn mini profile');
|
this.logger.info('加载torn mini profile');
|
||||||
let miniProfileInterval = {
|
let miniProfileInterval = {
|
||||||
id: window.setInterval(() => {
|
id: window.setInterval(() => {
|
||||||
miniProfileInterval.counter++;
|
miniProfileInterval.counter++;
|
||||||
@ -173,7 +185,7 @@ export default class ZhongIcon extends WuhuBase {
|
|||||||
}, 1000),
|
}, 1000),
|
||||||
counter: 0
|
counter: 0
|
||||||
};
|
};
|
||||||
Log.info('图标加入文档树完成');
|
this.logger.info('图标加入文档树');
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,8 +206,8 @@ export default class ZhongIcon extends WuhuBase {
|
|||||||
isMouseDown = false;
|
isMouseDown = false;
|
||||||
if (isMouseMoved) {
|
if (isMouseMoved) {
|
||||||
isMouseMoved = false;
|
isMouseMoved = false;
|
||||||
if (WuhuConfig.get("SaveIconPosition")) {
|
if (this.localConfigWrapper.config.SaveIconPosition) {
|
||||||
WuhuConfig.set("IconPosition", ZhongIcon.getPosition());
|
this.localConfigWrapper.config.IconPosition = ZhongIcon.getPosition();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -217,19 +229,20 @@ export default class ZhongIcon extends WuhuBase {
|
|||||||
|
|
||||||
// 菜单
|
// 菜单
|
||||||
private constructMenuList(): ZhongIcon {
|
private constructMenuList(): ZhongIcon {
|
||||||
Log.info('构造展开菜单列表开始');
|
this.logger.info('构造菜单列表开始');
|
||||||
let timer = new Timer();
|
let timer = new Timer();
|
||||||
let glob = Global.getInstance();
|
|
||||||
const date = new Date();
|
const date = new Date();
|
||||||
|
let userInfo = this.infoUtils.getPlayerInfo();
|
||||||
|
|
||||||
let list: MenuItemConfig[] = [];
|
let list: MenuItemConfig[] = [];
|
||||||
|
|
||||||
// 欢迎 显示玩家id
|
// 欢迎 显示玩家id
|
||||||
if (glob.player_info.userID !== 0) {
|
if (userInfo.userID !== 0) {
|
||||||
list.push({
|
list.push({
|
||||||
domType: 'plain',
|
domType: 'plain',
|
||||||
domId: 'wh-trans-welcome',
|
domId: 'wh-trans-welcome',
|
||||||
domHTML: `<a href="/profiles.php?XID=${ glob.player_info.userID }" target="_blank">${ glob.player_info.playername }</a>[${ glob.player_info.userID }]`,
|
domHTML:
|
||||||
|
`<a href="/profiles.php?XID=${ userInfo.userID }" target="_blank">${ userInfo.playername }</a>[${ userInfo.userID }]`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// 节日
|
// 节日
|
||||||
@ -237,8 +250,8 @@ export default class ZhongIcon extends WuhuBase {
|
|||||||
{
|
{
|
||||||
// 节日字典
|
// 节日字典
|
||||||
const dict = FEST.val;
|
const dict = FEST.val;
|
||||||
list.fest_date_dict = dict;
|
// list.fest_date_dict = dict;
|
||||||
list.fest_date_list = Object.keys(dict);
|
// list.fest_date_list = Object.keys(dict);
|
||||||
const formatMMDD = (m, d) => {
|
const formatMMDD = (m, d) => {
|
||||||
const MM = m < 10 ? `0${ m }` : m.toString();
|
const MM = m < 10 ? `0${ m }` : m.toString();
|
||||||
const DD = d < 10 ? `0${ d }` : d.toString();
|
const DD = d < 10 ? `0${ d }` : d.toString();
|
||||||
@ -277,7 +290,7 @@ export default class ZhongIcon extends WuhuBase {
|
|||||||
daysLeft: Infinity,
|
daysLeft: Infinity,
|
||||||
events: EVENTS.default,
|
events: EVENTS.default,
|
||||||
};
|
};
|
||||||
list.events = eventObj.events;
|
list.events = EVENTS.default;
|
||||||
eventObj.events.forEach((obj, index) => {
|
eventObj.events.forEach((obj, index) => {
|
||||||
if (eventObj.onEv) return;
|
if (eventObj.onEv) return;
|
||||||
// 当前年份
|
// 当前年份
|
||||||
@ -320,14 +333,14 @@ export default class ZhongIcon extends WuhuBase {
|
|||||||
domType: 'button',
|
domType: 'button',
|
||||||
domId: 'wh-quick-fly-btn',
|
domId: 'wh-quick-fly-btn',
|
||||||
domText: '✈️ 一键起飞',
|
domText: '✈️ 一键起飞',
|
||||||
clickFunc: () => QuickFlyBtnHandler.getInstance().handle(),
|
clickFunc: () => Container.factory(QuickFlyBtnHandler).handle(),
|
||||||
});
|
});
|
||||||
// 飞花库存
|
// 飞花库存
|
||||||
list.push({
|
list.push({
|
||||||
domType: 'button',
|
domType: 'button',
|
||||||
domId: 'wh-foreign-stock-btn',
|
domId: 'wh-foreign-stock-btn',
|
||||||
domText: '🌸 飞花库存',
|
domText: '🌸 飞花库存',
|
||||||
clickFunc: () => TravelItem.getInstance().clickHandler().then(),
|
clickFunc: () => Container.factory(TravelItem).clickHandler().then(),
|
||||||
});
|
});
|
||||||
// NPC LOOT
|
// NPC LOOT
|
||||||
list.push({
|
list.push({
|
||||||
@ -345,14 +358,14 @@ export default class ZhongIcon extends WuhuBase {
|
|||||||
domType: 'button',
|
domType: 'button',
|
||||||
domId: 'wh-nnb-info',
|
domId: 'wh-nnb-info',
|
||||||
domText: '👮 查看NNB',
|
domText: '👮 查看NNB',
|
||||||
clickFunc: () => NNB.getInstance().handle(),
|
clickFunc: () => this.nnb.handle(),
|
||||||
});
|
});
|
||||||
// 常用链接
|
// 常用链接
|
||||||
list.push({
|
list.push({
|
||||||
domType: 'button',
|
domType: 'button',
|
||||||
domId: 'wh-link-collection',
|
domId: 'wh-link-collection',
|
||||||
domText: '🔗 常用链接',
|
domText: '🔗 常用链接',
|
||||||
clickFunc: () => QuickLinksHandler.getInstance().handle()
|
clickFunc: () => Container.factory(QuickLinksHandler).handle()
|
||||||
});
|
});
|
||||||
// 飞贼
|
// 飞贼
|
||||||
// list.push({
|
// list.push({
|
||||||
@ -368,10 +381,10 @@ export default class ZhongIcon extends WuhuBase {
|
|||||||
domType: 'button',
|
domType: 'button',
|
||||||
domId: 'wh-price-watcher-btn',
|
domId: 'wh-price-watcher-btn',
|
||||||
domText: '💊 价格监视',
|
domText: '💊 价格监视',
|
||||||
clickFunc: () => ItemPriceWatcherHandler.getInstance().handle()
|
clickFunc: () => this.itemPriceWatcherHandler.handle()
|
||||||
});
|
});
|
||||||
// 全屏
|
// 全屏
|
||||||
if (!Global.getInstance().isPDA) list.push({
|
if (!this.tornPDAUtils.isPDA()) list.push({
|
||||||
domType: 'button', domId: '', domText: '🖥️ 进入全屏', clickFunc() {
|
domType: 'button', domId: '', domText: '🖥️ 进入全屏', clickFunc() {
|
||||||
document.documentElement.requestFullscreen().then();
|
document.documentElement.requestFullscreen().then();
|
||||||
}
|
}
|
||||||
@ -401,46 +414,23 @@ export default class ZhongIcon extends WuhuBase {
|
|||||||
window.location.replace('https://www.torn.com/item.php?temp=4#xunzhaomuzhuang')
|
window.location.replace('https://www.torn.com/item.php?temp=4#xunzhaomuzhuang')
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
// 物品查价
|
||||||
|
list.push(ItemPriceHandler);
|
||||||
// 更新历史
|
// 更新历史
|
||||||
list.push({
|
// list.push(ChangeLogHandler);
|
||||||
domType: 'button',
|
|
||||||
domId: '',
|
|
||||||
domText: '🐞 更新历史',
|
|
||||||
clickFunc: async () => ChangeLogHandler.getInstance().handle()
|
|
||||||
});
|
|
||||||
// 助手设置
|
// 助手设置
|
||||||
list.push({
|
list.push(SettingsHandler);
|
||||||
domType: 'button',
|
|
||||||
domId: '',
|
|
||||||
domText: '⚙️ 助手设置',
|
|
||||||
clickFunc: () => SettingsHandler.getInstance().handler(),
|
|
||||||
});
|
|
||||||
// 测试
|
// 测试
|
||||||
if (Log.debug()) list.push({
|
if (this.logger.debug()) list.push(Test);
|
||||||
domType: 'button',
|
|
||||||
domId: '',
|
|
||||||
domText: '📐️ 测试',
|
|
||||||
clickFunc: async function () {
|
|
||||||
let startTime = performance.now();
|
|
||||||
Log.info('测试开始');
|
|
||||||
try {
|
|
||||||
Test.getInstance().test();
|
|
||||||
} catch (e) {
|
|
||||||
Log.error('测试异常,' + JSON.stringify(e));
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.info('测试结束 ' + ((performance.now() - startTime) | 0) + 'ms');
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
this.menuItemList = list;
|
this.menuItemList = list;
|
||||||
Log.info('构造展开菜单列表结束' + timer.getTimeMs());
|
this.logger.info('构造展开菜单列表结束' + timer.getTimeMs());
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MenuItemConfig {
|
export interface MenuItemConfig {
|
||||||
domType: 'button' | 'plain' | 'checkbox' | 'select';
|
domType: 'button' | 'plain' | 'checkbox' | 'select' | MENU_ITEM_TYPE;
|
||||||
tagName?: string;
|
tagName?: string;
|
||||||
domId?: string;
|
domId?: string;
|
||||||
domText?: string;
|
domText?: string;
|
||||||
352
src/ts/class/action/AttackHelper.ts
Normal file
352
src/ts/class/action/AttackHelper.ts
Normal file
@ -0,0 +1,352 @@
|
|||||||
|
// 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('盯梢关闭');
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// }
|
||||||
1
src/ts/class/action/BuyBeerResult.ts
Normal file
1
src/ts/class/action/BuyBeerResult.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export default {};
|
||||||
75
src/ts/class/action/FetchEventCallback.ts
Normal file
75
src/ts/class/action/FetchEventCallback.ts
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import { MiniProfile } from "../../interface/responseType/MiniProfile";
|
||||||
|
import CommonUtils from "../utils/CommonUtils";
|
||||||
|
import Provider from "../provider/Provider";
|
||||||
|
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 事件监听回调
|
||||||
|
*/
|
||||||
|
@Injectable()
|
||||||
|
@ClassName("FetchEventCallback")
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fetch 返回后处理
|
||||||
|
* @param url
|
||||||
|
* @param response
|
||||||
|
*/
|
||||||
|
public responseHandler(url: string, response) {
|
||||||
|
// mini profile 中添加上次动作
|
||||||
|
if (url.startsWith('/page.php?sid=UserMiniProfile&userID')) {
|
||||||
|
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);
|
||||||
|
|
||||||
|
(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 }`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,49 +1,74 @@
|
|||||||
import WuhuBase from "../WuhuBase";
|
|
||||||
import TornStyleBlock from "../utils/TornStyleBlock";
|
import TornStyleBlock from "../utils/TornStyleBlock";
|
||||||
import WuhuConfig from "../WuhuConfig";
|
|
||||||
import Alert from "../utils/Alert";
|
|
||||||
import TornStyleSwitch from "../utils/TornStyleSwitch";
|
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";
|
||||||
|
|
||||||
export default class PTHelper extends WuhuBase {
|
@Injectable()
|
||||||
className = 'PTHelper';
|
@ClassName('PTHelper')
|
||||||
private readonly observer;
|
export default class PTHelper implements IFeature {
|
||||||
private readonly usersPointSell;
|
private observer: MutationObserver;
|
||||||
|
private usersPointSell: HTMLDivElement;
|
||||||
|
|
||||||
|
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() {
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
this.observer = new MutationObserver(e => {
|
this.observer = new MutationObserver(e => {
|
||||||
for (const t of e) {
|
for (const t of e) {
|
||||||
t.addedNodes.forEach(e => 'LI' === (e as HTMLElement).tagName && this.removeConfirm(e))
|
t.addedNodes.forEach(e => 'LI' === (e as HTMLElement).tagName && this.removeConfirm(e))
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.usersPointSell = document.querySelector('.users-point-sell');
|
this.usersPointSell = document.querySelector<HTMLDivElement>('.users-point-sell');
|
||||||
|
|
||||||
let block = new TornStyleBlock('PT一键购买').insert2Dom();
|
let block = new TornStyleBlock('PT一键购买').insert2Dom();
|
||||||
let switcher = new TornStyleSwitch('开启');
|
let switcher = new TornStyleSwitch('开启');
|
||||||
block.append(switcher.getBase());
|
block.append(switcher.getBase());
|
||||||
let toggle = switcher.getInput();
|
let toggle = switcher.getInput();
|
||||||
toggle.checked = WuhuConfig.get('ptQuickBuy');
|
toggle.checked = this.localConfigWrapper.config.ptQuickBuy;
|
||||||
if (toggle.checked) {
|
if (toggle.checked) {
|
||||||
new Alert('一键购买已开启');
|
this.msgWrapper.create('一键购买已开启');
|
||||||
for (const index in this.usersPointSell.children) {
|
for (const index in this.usersPointSell.children) {
|
||||||
'LI' === this.usersPointSell.children[index].tagName && this.removeConfirm(this.usersPointSell.children[index])
|
'LI' === this.usersPointSell.children[index].tagName && this.removeConfirm(this.usersPointSell.children[index])
|
||||||
}
|
}
|
||||||
this.observer.observe(this.usersPointSell, { childList: true })
|
this.observer.observe(this.usersPointSell, { childList: true })
|
||||||
}
|
}
|
||||||
toggle.addEventListener('change', () => {
|
toggle.addEventListener('change', () => {
|
||||||
WuhuConfig.set('ptQuickBuy', toggle.checked, false);
|
this.localConfigWrapper.config.ptQuickBuy = toggle.checked;
|
||||||
if (toggle.checked) {
|
if (toggle.checked) {
|
||||||
for (const index in this.usersPointSell.children) {
|
for (const index in this.usersPointSell.children) {
|
||||||
'LI' === this.usersPointSell.children[index].tagName && this.removeConfirm(this.usersPointSell.children[index])
|
'LI' === this.usersPointSell.children[index].tagName && this.removeConfirm(this.usersPointSell.children[index])
|
||||||
}
|
}
|
||||||
this.observer.observe(this.usersPointSell, { childList: true });
|
this.observer.observe(this.usersPointSell, { childList: true });
|
||||||
new Alert('一键购买已开启');
|
this.msgWrapper.create('一键购买已开启');
|
||||||
} else {
|
} else {
|
||||||
for (const index in this.usersPointSell.children) {
|
for (const index in this.usersPointSell.children) {
|
||||||
'LI' === this.usersPointSell.children[index].tagName && this.rollbackConfirm(this.usersPointSell.children[index])
|
'LI' === this.usersPointSell.children[index].tagName && this.rollbackConfirm(this.usersPointSell.children[index])
|
||||||
}
|
}
|
||||||
this.observer.disconnect();
|
this.observer.disconnect();
|
||||||
new Alert('一键购买已关闭');
|
this.msgWrapper.create('一键购买已关闭');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
151
src/ts/class/action/ProfileHelper.ts
Normal file
151
src/ts/class/action/ProfileHelper.ts
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
import CommonUtils from "../utils/CommonUtils";
|
||||||
|
import TornStyleBlock from "../utils/TornStyleBlock";
|
||||||
|
import TornStyleSwitch from "../utils/TornStyleSwitch";
|
||||||
|
import ResponseInject from "../../interface/ResponseInject";
|
||||||
|
import globVars from "../../globVars";
|
||||||
|
import IUserProfileData from "../../interface/IUserProfileData";
|
||||||
|
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;
|
||||||
|
|
||||||
|
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');
|
||||||
|
// id获取格式判断
|
||||||
|
if (!this.commonUtils.isValidUid(id)) {
|
||||||
|
this.logger.error('[ProfileHelper] id格式错误');
|
||||||
|
}
|
||||||
|
if (this.localConfigWrapper.config.HideProfileImg) {
|
||||||
|
this.logger.info('[ProfileHelper] 隐藏头像');
|
||||||
|
document.body.classList.toggle('wh-hide_profile_img');
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
responseHandler(url: string, body: { json: unknown; text: string; isModified: boolean }) {
|
||||||
|
if (url.includes('profiles.php?step=getProfileData') && this.task) {
|
||||||
|
// 曾用名
|
||||||
|
const nameHistoryNode = document.createElement('p');
|
||||||
|
nameHistoryNode.innerHTML = '曾用名:';
|
||||||
|
this.block.append(nameHistoryNode);
|
||||||
|
let resp = body.json as IUserProfileData;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
46
src/ts/class/action/QuickGymTrain.ts
Normal file
46
src/ts/class/action/QuickGymTrain.ts
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import ClassName from "../../container/ClassName";
|
||||||
|
import { Injectable } from "../../container/Injectable";
|
||||||
|
import Logger from "../Logger";
|
||||||
|
import NetHighLvlWrapper, { BATTLE_STAT } from "../utils/NetHighLvlWrapper";
|
||||||
|
import { InjectionKey } from "vue";
|
||||||
|
import MsgWrapper from "../utils/MsgWrapper";
|
||||||
|
|
||||||
|
type GymResponse = {
|
||||||
|
success: boolean,
|
||||||
|
// 成功才有 You gained 689,636.71 strength
|
||||||
|
gainMessage?: string,
|
||||||
|
message: string,
|
||||||
|
text?: string,
|
||||||
|
error?: string,
|
||||||
|
};
|
||||||
|
|
||||||
|
@ClassName("QuickGymTrain")
|
||||||
|
@Injectable()
|
||||||
|
export default class QuickGymTrain {
|
||||||
|
constructor(
|
||||||
|
private readonly logger: Logger,
|
||||||
|
private readonly netHighLvlWrapper: NetHighLvlWrapper,
|
||||||
|
private readonly msgWrapper: MsgWrapper,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
doTrain(type = BATTLE_STAT.STR, count = 199) {
|
||||||
|
window.setTimeout(async () => {
|
||||||
|
let resObj: GymResponse;
|
||||||
|
try {
|
||||||
|
resObj = JSON.parse(await this.netHighLvlWrapper.doGymTrain(type, count))
|
||||||
|
} catch (e) {
|
||||||
|
resObj = { success: false, message: '解析失败' };
|
||||||
|
this.logger.error(e.stack || e.message || e);
|
||||||
|
}
|
||||||
|
let msgRs = resObj.success ? '成功' : '失败';
|
||||||
|
let msgMsg = resObj.message || resObj.text || resObj.error;
|
||||||
|
this.msgWrapper.create(
|
||||||
|
'锻炼结果: ' + msgRs + '<br/>提示: ' + (resObj.gainMessage || msgMsg),
|
||||||
|
{}, resObj.success ? 'success' : 'error'
|
||||||
|
);
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const QuickGymTrainKey = Symbol('QuickGymTrainKey') as InjectionKey<QuickGymTrain>;
|
||||||
@ -1,14 +1,33 @@
|
|||||||
import WuhuBase from "../WuhuBase";
|
|
||||||
import TornStyleBlock from "../utils/TornStyleBlock";
|
import TornStyleBlock from "../utils/TornStyleBlock";
|
||||||
import TornStyleSwitch from "../utils/TornStyleSwitch";
|
import TornStyleSwitch from "../utils/TornStyleSwitch";
|
||||||
import CommonUtils from "../utils/CommonUtils";
|
import CommonUtils from "../utils/CommonUtils";
|
||||||
import WuhuConfig from "../WuhuConfig";
|
import ClassName from "../../container/ClassName";
|
||||||
|
import { Injectable } from "../../container/Injectable";
|
||||||
|
import LocalConfigWrapper from "../LocalConfigWrapper";
|
||||||
|
import IFeature from "../../man/IFeature";
|
||||||
|
|
||||||
export default class SearchHelper extends WuhuBase {
|
@ClassName('SearchHelper')
|
||||||
className = 'SearchHelper';
|
@Injectable()
|
||||||
|
export default class SearchHelper implements IFeature {
|
||||||
|
description(): string {
|
||||||
|
return "搜索助手";
|
||||||
|
}
|
||||||
|
|
||||||
constructor() {
|
iStart(): void | Promise<void> {
|
||||||
super();
|
this.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
urlExcludes(): RegExp[] {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
urlIncludes(): RegExp[] {
|
||||||
|
return [/page\.php\?sid=UserList/];
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private readonly localConfigWrapper: LocalConfigWrapper,
|
||||||
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(): void {
|
public init(): void {
|
||||||
@ -16,7 +35,7 @@ export default class SearchHelper extends WuhuBase {
|
|||||||
let placeholderSwitch = new TornStyleSwitch('底部空白占位区');
|
let placeholderSwitch = new TornStyleSwitch('底部空白占位区');
|
||||||
block.append(placeholderSwitch.getBase()).insert2Dom();
|
block.append(placeholderSwitch.getBase()).insert2Dom();
|
||||||
CommonUtils.addStyle('body.WHSearchPagePlaceholder .content.logged-in {margin-bottom: 340px;}');
|
CommonUtils.addStyle('body.WHSearchPagePlaceholder .content.logged-in {margin-bottom: 340px;}');
|
||||||
let config = WuhuConfig.get('SearchPagePlaceholder');
|
let config = this.localConfigWrapper.config.SearchPagePlaceholder;
|
||||||
placeholderSwitch.getInput().checked = config || false;
|
placeholderSwitch.getInput().checked = config || false;
|
||||||
config ? this.enable() : this.disable();
|
config ? this.enable() : this.disable();
|
||||||
placeholderSwitch.getInput().addEventListener('change', () => {
|
placeholderSwitch.getInput().addEventListener('change', () => {
|
||||||
@ -26,11 +45,11 @@ export default class SearchHelper extends WuhuBase {
|
|||||||
|
|
||||||
private enable(): void {
|
private enable(): void {
|
||||||
document.body.classList.add('WHSearchPagePlaceholder');
|
document.body.classList.add('WHSearchPagePlaceholder');
|
||||||
WuhuConfig.set('SearchPagePlaceholder', true);
|
this.localConfigWrapper.config.SearchPagePlaceholder = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private disable(): void {
|
private disable(): void {
|
||||||
document.body.classList.remove('WHSearchPagePlaceholder');
|
document.body.classList.remove('WHSearchPagePlaceholder');
|
||||||
WuhuConfig.set('SearchPagePlaceholder', false);
|
this.localConfigWrapper.config.SearchPagePlaceholder = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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