Compare commits

..

1 Commits

Author SHA1 Message Date
db6d98ff22
Add files via upload 2021-11-06 15:45:32 +08:00
263 changed files with 1135 additions and 72001 deletions

8
.gitignore vendored
View File

@ -1,8 +0,0 @@
/node_modules
/.fleet
/src/dist/bundle.min.js
/src/dist/bundle.js
/dist
auto-imports.d.ts
components.d.ts
aws.xml

8
.idea/.gitignore generated vendored
View File

@ -1,8 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View File

@ -1,20 +0,0 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<JSCodeStyleSettings version="0">
<option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
<option name="SPACES_WITHIN_IMPORTS" value="true" />
<option name="SPACES_WITHIN_INTERPOLATION_EXPRESSIONS" value="true" />
</JSCodeStyleSettings>
<JetCodeStyleSettings>
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</JetCodeStyleSettings>
<TypeScriptCodeStyleSettings version="0">
<option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
<option name="SPACES_WITHIN_IMPORTS" value="true" />
<option name="SPACES_WITHIN_INTERPOLATION_EXPRESSIONS" value="true" />
</TypeScriptCodeStyleSettings>
<codeStyleSettings language="kotlin">
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</codeStyleSettings>
</code_scheme>
</component>

View File

@ -1,5 +0,0 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
</state>
</component>

View File

@ -1,8 +0,0 @@
<component name="ProjectDictionaryState">
<dictionary name="Liwanyi">
<words>
<w>wuhu</w>
<w>zhong</w>
</words>
</dictionary>
</component>

View File

@ -1,66 +0,0 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="AliAccessStaticViaInstance" enabled="false" level="BLOCKER" enabled_by_default="false" />
<inspection_tool class="AliArrayNamingShouldHaveBracket" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AliControlFlowStatementWithoutBraces" enabled="false" level="BLOCKER" enabled_by_default="false" />
<inspection_tool class="AliDeprecation" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AliEqualsAvoidNull" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AliLongLiteralsEndingWithLowercaseL" enabled="false" level="BLOCKER" enabled_by_default="false" />
<inspection_tool class="AliMissingOverrideAnnotation" enabled="false" level="BLOCKER" enabled_by_default="false" />
<inspection_tool class="AliWrapperTypeEquality" enabled="false" level="BLOCKER" enabled_by_default="false" />
<inspection_tool class="AlibabaAbstractClassShouldStartWithAbstractNaming" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AlibabaAbstractMethodOrInterfaceMethodMustUseJavadoc" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaAvoidApacheBeanUtilsCopy" enabled="false" level="BLOCKER" enabled_by_default="false" />
<inspection_tool class="AlibabaAvoidCallStaticSimpleDateFormat" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AlibabaAvoidCommentBehindStatement" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaAvoidComplexCondition" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaAvoidConcurrentCompetitionRandom" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaAvoidDoubleOrFloatEqualCompare" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AlibabaAvoidManuallyCreateThread" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AlibabaAvoidMissUseOfMathRandom" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaAvoidNegationOperator" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaAvoidNewDateGetTime" enabled="false" level="BLOCKER" enabled_by_default="false" />
<inspection_tool class="AlibabaAvoidPatternCompileInMethod" enabled="false" level="BLOCKER" enabled_by_default="false" />
<inspection_tool class="AlibabaAvoidReturnInFinally" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AlibabaAvoidStartWithDollarAndUnderLineNaming" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AlibabaAvoidUseTimer" enabled="false" level="BLOCKER" enabled_by_default="false" />
<inspection_tool class="AlibabaBigDecimalAvoidDoubleConstructor" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaBooleanPropertyShouldNotStartWithIs" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AlibabaClassCastExceptionWithSubListToArrayList" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AlibabaClassCastExceptionWithToArray" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AlibabaClassMustHaveAuthor" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaClassNamingShouldBeCamel" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaCollectionInitShouldAssignCapacity" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaCommentsMustBeJavadocFormat" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaConcurrentExceptionWithModifyOriginSubList" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AlibabaConstantFieldShouldBeUpperCase" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AlibabaCountDownShouldInFinally" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaDontModifyInForeachCircle" enabled="false" level="BLOCKER" enabled_by_default="false" />
<inspection_tool class="AlibabaEnumConstantsMustHaveComment" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AlibabaExceptionClassShouldEndWithException" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AlibabaIbatisMethodQueryForList" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaLockShouldWithTryFinally" enabled="false" level="BLOCKER" enabled_by_default="false" />
<inspection_tool class="AlibabaLowerCamelCaseVariableNaming" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AlibabaMethodReturnWrapperType" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaMethodTooLong" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaPackageNaming" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaPojoMustOverrideToString" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaPojoMustUsePrimitiveField" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaPojoNoDefaultValue" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaRemoveCommentedCode" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaServiceOrDaoClassShouldEndWithImpl" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AlibabaStringConcat" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaSwitchStatement" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AlibabaTestClassShouldEndWithTestNaming" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaThreadLocalShouldRemove" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AlibabaThreadPoolCreation" enabled="false" level="BLOCKER" enabled_by_default="false" />
<inspection_tool class="AlibabaThreadShouldSetName" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AlibabaTransactionMustHaveRollback" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaUndefineMagicConstant" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaUnsupportedExceptionWithModifyAsList" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AlibabaUseQuietReferenceNotation" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaUseRightCaseForDateFormat" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="MapOrSetKeyShouldOverrideHashCodeEquals" enabled="false" level="CRITICAL" enabled_by_default="false" />
</profile>
</component>

6
.idea/misc.xml generated
View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="Python 3.8 (fstock)" project-jdk-type="Python SDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

8
.idea/modules.xml generated
View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/torncity-zhcn-translate.iml" filepath="$PROJECT_DIR$/.idea/torncity-zhcn-translate.iml" />
</modules>
</component>
</project>

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="SmartFoxProjectConfig">
<option name="projectInspectionClosed" value="true" />
</component>
</project>

View File

@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<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>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

6
.idea/vcs.xml generated
View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

14
.vscode/launch.json vendored
View File

@ -1,14 +0,0 @@
{
// 使 IntelliSense
//
// 访: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"command": "npm run rollup",
"name": "rollup",
"request": "launch",
"type": "node-terminal"
}
]
}

File diff suppressed because it is too large Load Diff

View File

@ -1 +0,0 @@

21
LICENSE
View File

@ -1,21 +0,0 @@
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.

View File

@ -1,23 +1 @@
# Wuhu Torn Helper # torncity-zhcn-translate
[![LICENSE](https://img.shields.io/badge/license-MIT-blue.svg)](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.

View File

@ -1,20 +0,0 @@
# 芜湖助手 Torncity 翻译插件
[![LICENSE](https://img.shields.io/badge/license-MIT-blue.svg)](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 安装。

View File

@ -1,39 +0,0 @@
/**
* 此脚本用于加入userscript meta
* 并生成日期时间与版本号
*/
import { readFileSync, writeFileSync } from "fs";
import { prodConfig } from "./rollup.config.js";
let date = new Date();
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 metaData =
`// ==UserScript==
// @lastmodified ${ formattedDateTime }
// @name 芜湖助手
// @namespace WOOH
// @version ${ version }
// @description 托恩,起飞!
// @author Woohoo[2687093] Sabrina_Devil[2696209]
// @match https://www.torn.com/*
// @downloadURL https://gitlab.com/JJins/wuhu-torn-helper/-/raw/dev/release.min.user.js
// @grant GM_xmlhttpRequest
// @grant unsafeWindow
// @connect yata.yt
// @connect github.io
// @connect gitlab.com
// @connect staticfile.org
// @connect gitee.com
// ==/UserScript==
`
const data = readFileSync('./' + prodConfig.output.file, 'utf8');
writeFileSync(
'./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
View File

@ -1,6 +0,0 @@
// declare module "*.module.css" {
// const css: string;
// const classes: { [key: string]: string };
// export default classes;
// export { css };
// }

View File

@ -1,21 +0,0 @@
export const customInjector = (varName) => {
let rt = ((__var) => {
const inject = (ob) => {
if (document && document.head) {
ob?.disconnect();
const style = document.createElement('style');
style.setAttribute('type', 'text/css');
style.innerHTML = __var;
document.head.appendChild(style);
}
};
if (document && document.head) {
inject();
} else {
new MutationObserver((_, ob) => {
inject(ob);
}).observe(document.documentElement, { childList: true });
}
}).toString();
return `(${ rt })(${ varName })`;
};

129
global.d.ts vendored
View File

@ -1,129 +0,0 @@
declare interface String {
contains(keywords: RegExp | string): boolean;
/* 翻译 */
// 时分秒转换
replaceHMS(): string;
// 数词转换 a an some
numWordTrans(): string;
}
declare interface Window {
$?: JQueryStatic;
jQuery?: JQueryStatic;
WHPARAMS?: any;
hasWHQuickFlyOpt?: boolean;
// 插件运行标识
WHTRANS?: number;
Vue?: Function;
/**
*
*/
unsafeWindow?: Window & typeof globalThis;
/**
* google
*/
_gaUserPrefs?: unknown;
GM_xmlhttpRequest(init: GM_RequestParams): void;
GM_getValue(k: string, def: any): unknown;
GM_setValue(k: string, v: any): void;
/**
* TORN自带
*/
ReactDOM?: any;
dataLayer?: unknown;
eval(exc: string): void;
addRFC(url: URL | string): string;
getAction(opt: TornGetActionParams): void;
initializeTooltip(selector: string, elemId: string): void;
renderMiniProfile(node: Element, props: any): never;
/**
* PDA自带
*/
PDA_httpGet(url: URL | string): Promise<PDA_Response>;
PDA_httpPost(url: URL | string, init: any, body: any): Promise<PDA_Response>;
// TODO 临时测试用
// [key: string]: unknown;
}
declare interface GM_RequestParams {
method?: string,
url?: URL | string,
data?: any,
headers?: any,
onload?: Function,
onerror?: Function,
ontimeout?: Function,
}
declare interface PDA_Response {
responseText: string
}
declare interface Element {
innerText?: string;
src?: string;
}
declare interface Notification {
id?: number;
}
declare interface Array<T> {
fest_date_dict?: { [key: string]: { name: string, eff: string } };
fest_date_list?: string[];
[key: string]: any;
}
declare interface Navigator {
userAgentData?: any;
}
declare interface TornGetActionParams {
type: 'post' | 'get',
action?: string,
data?: {
step?: string,
id?: number,
key?: string,
type?: string
},
success: Function,
before?: Function
}
declare module "*.html" {
const html: string;
export default html;
}
declare module "*.module.css" {
const css: string;
// const classes: { [key: string]: string };
// export default classes;
export default css;
// export { css };
}
declare function GM_xmlhttpRequest(init: any): void;
declare var unsafeWindow: Window & typeof globalThis;
declare type Constructor<T = any> = new (...args: any[]) => T;
declare interface ClassType<T> {
new(...args: unknown[]): T
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,15 +0,0 @@
import json
import requests
# URL = "https://jjins.github.io/item_price_raw.json"
URL = "https://script.google.com/macros/s/AKfycbyRfg1Cx2Jm3IuCWASUu8czKeP3wm5jKsie4T4bxwZHzXTmPbaw4ybPRA/exec?key=getItems"
resArr = requests.get(URL).json()['items']
obj = {}
for item in resArr:
obj[item[0]] = {'name': item[1], 'price': item[2]}
file = open('item_price_raw.json', 'w')
file.write(json.dumps(obj))
file.close()
print('物品价格表已更新')

View File

@ -1,118 +0,0 @@
import json
from datetime import datetime, timezone, timedelta
import os
import requests
DEST_ARR = ['mex', 'cay', 'can', 'haw', 'uni', 'arg', 'swi', 'jap', 'chi', 'uae', 'sou']
DEST_TRANS = {
'mex': '', 'cay': '', 'can': '',
'haw': '', 'uni': '', 'arg': '',
'swi': '', 'jap': '', 'chi': '', 'uae': '', 'sou': '',
}
VALUED_ITEM_ARR = [
'Dahlia', 'Jaguar Plushie',
'Banana Orchid', 'Stingray Plushie',
'Crocus', 'Wolverine Plushie',
'Orchid', 'Large Suitcase',
'Red Fox Plushie', 'Nessie Plushie', 'Heather',
'Ceibo Flower', 'Monkey Plushie', 'Tear Gas',
'Chamois Plushie', 'Edelweiss',
'Cherry Blossom',
'Panda Plushie', 'Peony',
'Camel Plushie', 'Tribulus Omanense',
'Lion Plushie', 'African Violet', 'Xanax',
]
ITEM_TRANS = {
'Dahlia': '', 'Jaguar Plushie': '',
'Banana Orchid': '', 'Stingray Plushie': '',
'Crocus': '', 'Wolverine Plushie': '',
'Orchid': '', 'Large Suitcase': '大箱',
'Red Fox Plushie': '赤狐', 'Nessie Plushie': '水怪', 'Heather': '',
'Ceibo Flower': '', 'Monkey Plushie': '', 'Tear Gas': '催泪弹',
'Edelweiss': '', 'Chamois Plushie': '',
'Cherry Blossom': '',
'Peony': '', 'Panda Plushie': '',
'Tribulus Omanense': '', 'Camel Plushie': '',
'African Violet': '', 'Lion Plushie': '', 'Xanax': 'XAN',
}
HISTORY_FILE = 'stock_hist.json'
HISTORY_EXIST = os.path.exists(HISTORY_FILE)
UTC_8 = timezone(timedelta(hours=8))
URL = "https://yata.yt/api/v1/travel/export/"
resObj = requests.get(URL).json()["stocks"]
# 更新时间
lastUpdate = 0
for dest in DEST_ARR:
res_update = resObj[dest]["update"]
if lastUpdate < res_update:
lastUpdate = res_update
lastUpdate = datetime.fromtimestamp(lastUpdate).astimezone(UTC_8)
UPDATE_TIME_STR = lastUpdate.strftime('%H:%M:%S')
# 整理过的对象
stockObj = {}
for dest in DEST_ARR:
arr = []
for f_item in resObj[dest]['stocks']:
for v_item in VALUED_ITEM_ARR:
if f_item['name'] == v_item:
arr.append(f_item)
stockObj[dest] = arr
# 移除亏本的xan
# 加拿大
index = -1
for i in range(len(stockObj['can'])):
if stockObj['can'][i]['name'] == 'Xanax':
index = i
if index != -1:
del stockObj['can'][index]
# 英国
index = -1
for i in range(len(stockObj['uni'])):
if stockObj['uni'][i]['name'] == 'Xanax':
index = i
if index != -1:
del stockObj['uni'][index]
# 日本
index = -1
for i in range(len(stockObj['jap'])):
if stockObj['jap'][i]['name'] == 'Xanax':
index = i
if index != -1:
del stockObj['jap'][index]
# 读取库存历史
stockHistObj = {}
if HISTORY_EXIST:
print('历史文件存在')
with open(HISTORY_FILE, 'r') as load_f:
stockHistObj = json.load(load_f)
else:
stockHistObj['json'] = []
stockHistObj['json'].append({str(int(datetime.now().timestamp())): stockObj})
if len(stockHistObj['json']) > 100:
del stockHistObj['json'][0]
with open(HISTORY_FILE, 'w') as f:
json.dump(stockHistObj, f)
hist_arr = stockHistObj['json']
# 用于写入文件的列表
seq = ["更新时间: %s\n" % UPDATE_TIME_STR]
for dest in DEST_ARR:
seq_str = '%s ' % DEST_TRANS[dest]
for i in range(len(stockObj[dest])):
seq_str += '%s%s' % (ITEM_TRANS[stockObj[dest][i]['name']], stockObj[dest][i]['quantity'])
if i != len(stockObj[dest]) - 1:
seq_str += ' '
seq_str += '\n'
seq.append(seq_str)
# 写入文件
fo = open(file="stock.txt", mode="w", encoding="utf-8")
fo.writelines(seq)
fo.close()
print("花偶库存更新完成")

File diff suppressed because it is too large Load Diff

View File

@ -1,22 +0,0 @@
// ==UserScript==
// @name Debug Userscript
// @namespace https://github.com/einverne/userscripts
// @version 0.1
// @description This is a debug script to load userscripts from local file system. NOTICE, you need to turn on Allow access to file URLs to @require local file https://www.tampermonkey.net/documentation.php
// @author Ein Verne
// @match http*://*
// @include http://*
// @include https://*
// @include *
// @grant GM_xmlhttpRequest
// @grant GM_addStyle
// @grant GM_getResourceText
// @require {{file path}}
// ==/UserScript==
(function () {
'use strict';
console.log("debug script start here");
// Your code here...
})();

16538
misc/vue.js

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

13205
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,43 +0,0 @@
{
"name": "wuhu-torn-helper",
"version": "1.2.4",
"description": "芜湖助手",
"scripts": {
"release": "cross-env NODE_ENV=production rollup -c && node build.mjs",
"watch": "cross-env NODE_ENV=development rollup -c -w",
"rollup": "cross-env NODE_ENV=development rollup -c"
},
"devDependencies": {
"@element-plus/icons-vue": "^2.1.0",
"@rollup/plugin-alias": "^4.0.3",
"@rollup/plugin-commonjs": "^24.0.1",
"@rollup/plugin-json": "^4.1.0",
"@rollup/plugin-node-resolve": "^15.0.1",
"@rollup/plugin-replace": "^5.0.2",
"@rollup/plugin-terser": "^0.4.0",
"@rollup/plugin-typescript": "^8.5.0",
"@types/jquery": "^3.5.14",
"@types/node": "^20.6.0",
"@vitejs/plugin-vue": "^4.0.0",
"@vue/tsconfig": "^0.1.3",
"cross-env": "^7.0.3",
"element-plus": "^2.3.10",
"just-clone": "^6.2.0",
"npm": "^8.19.2",
"reflect-metadata": "^0.1.13",
"rollup": "^2.79.0",
"rollup-plugin-postcss": "^4.0.2",
"rollup-plugin-string-html": "^1.0.0",
"rollup-plugin-styles": "^4.0.0",
"rollup-plugin-typescript2": "^0.34.1",
"tslib": "^2.4.0",
"typescript": "^4.8.3",
"unplugin-auto-import": "^0.15.2",
"unplugin-element-plus": "^0.7.0",
"unplugin-icons": "^0.16.1",
"unplugin-vue-components": "^0.24.1",
"vant": "^4.1.2",
"vue": "^3.2.47"
},
"type": "module"
}

File diff suppressed because one or more lines are too long

View File

@ -1,131 +0,0 @@
// [!] Error: Unexpected token (Note that you need plugins to import files that are not JavaScript)
// src/vue/ItemPrice.vue?vue&type=script&lang.ts (35:13)
// TODO 官方提供ts插件在vue模版中使用ts语言时报错
// import typescript from "@rollup/plugin-typescript";
// TODO 在rollup watch模式中不更新vue模版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: {
file: 'dist/bundle.js',
format: 'iife',
name: 'bundle.js',
},
plugins: [
json(),
html({
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",
}),
],
};
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 };

7
src/shims-vue.d.ts vendored
View File

@ -1,7 +0,0 @@
/* eslint-disable */
declare module '*.vue' {
import type { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}
/* eslint-enable */

View File

@ -1,82 +0,0 @@
.wh-move-btn #defender div[class^="modal___"] {
display: block;
width: 0 !important;
left: -169px !important;
background: none;
}
.wh-move-btn #defender div[class^="dialog___"] {
border: 0;
width: 159px;
height: 96px;
max-width: unset;
}
.wh-move-btn #defender div[class^="colored___"] {
display: block;
padding: 0;
}
.wh-move-btn #defender div[class^="title___"] {
height: 0;
}
/* 此处限制宽度,否则人物模型图片会溢出遮挡武器栏 */
.wh-move-btn #defender div[class^="modelWrap___"] {
max-width: 100%;
}
.wh-move-btn #defender button {
width: 100%;
margin: 17px 0;
height: 60px;
}
/* 解决按钮图标负边距被上层元素限制遮挡问题 */
.wh-move-btn #defender div[class^="playerWindow___"] {
overflow: unset;
}
/* 手机端 */
@media screen and (max-width: 600px) {
.wh-move-btn #attacker div[class^="playerWindow___"] {
overflow: unset;
}
.wh-move-btn #attacker div[class^="modelWrap___"] {
max-width: 100%;
}
.wh-move-btn #attacker div[class^="modal___"] {
display: block;
width: 0;
top: CSSVAR;
left: -80px;
height: 0;
}
.wh-move-btn #attacker div[class^="dialog___"] {
border: 0;
width: 80px;
/* torn的规则限制90% */
max-width: unset;
height: CSSVAR;
}
.wh-move-btn #attacker div[class^="colored___"] {
display: block;
padding: 0;
}
.wh-move-btn #attacker div[class^="title___"] {
height: 0;
}
.wh-move-btn #attacker button {
width: 100%;
margin: 0;
height: 63px;
white-space: normal;
}
}

View File

@ -1,57 +0,0 @@
.wh-city-finds .leaflet-marker-pane img[src*="torn.com/images/items/"] {
display: block !important;
box-sizing: border-box;
width: 40px !important;
height: 40px !important;
left: -20px !important;
top: -20px !important;
padding: 10px 0;
border: none;
border-radius: 100%;
background-color: #d2d2d28c;
box-shadow: 0 0 10px 5px #000;
z-index: 999 !important;
}
.wh-city-finds .leaflet-marker-pane.leaflet-marker-icon.user-item-pinpoint.leaflet-clickable {
display: none !important;
}
/*#wh-city-finder-header{*/
/* background-color: #3f51b5;*/
/* color: white;*/
/* padding: 8px;*/
/* font-size: 15px;*/
/* border-radius: 4px 4px 0 0;*/
/* text-shadow: 0 0 2px black;*/
/* background-image: linear-gradient(90deg,transparent 50%,rgba(0,0,0,.07) 0);*/
/* background-size: 4px;*/
/*}*/
/*#wh-city-finder{*/
/* box-shadow: 0 0 3px 0px #696969;*/
/* border-radius: 4px;*/
/*}*/
/*#wh-city-finder-cont{*/
/* background: #616161;*/
/* padding: 8px;*/
/* color: #c7c7c7;*/
/* border-radius: 0 0 4px 4px;*/
/* font-size: 13px;*/
/*}*/
/*#wh-city-finder-cont span{*/
/* margin:2px 4px 2px 0;*/
/* padding:2px;*/
/* border-radius:2px;*/
/* background:green;*/
/* color:white;*/
/* display:inline-block;*/
/*}*/
.wh-city-finder-item {
margin: 2px 4px 2px 0;
padding: 2px;
border-radius: 2px;
background: green;
color: white;
display: inline-block;
}

View File

@ -1,292 +0,0 @@
.wh-hide {
display: none;
}
#wh-trans-icon {
user-select: none;
display: inline-block;
position: fixed;
top: 5px;
left: 5px;
z-index: 100010;
border-radius: 4px;
max-width: 220px;
box-shadow: 0 0 3px 1px #8484848f;
}
div#effectiveness-wrap {
overflow-y: hidden;
}
@media screen and (max-width: 600px) {
#wh-trans-icon {
top: 0;
left: 112px;
}
/* 冰蛙公司效率表 */
div#effectiveness-wrap {
margin-left: -76px;
margin-right: -76px;
}
}
#wh-trans-icon select {
width: 110px;
}
#wh-trans-icon a {
text-decoration: none;
color: #006599;
background: none;
}
#wh-trans-icon:not(.wh-icon-expanded):hover {
background: #f8f8f8;
}
#wh-trans-icon button {
margin: 0;
padding: 0;
border: 0;
cursor: pointer;
}
#wh-inittimer {
margin-top: 6px;
color: #b0b0b0;
}
#wh-gSettings div {
margin: 4px 0;
}
#wh-trans-icon .wh-container {
margin: 0;
padding: 0 16px 16px;
border: 0;
}
#wh-trans-icon-btn {
height: 16px;
width: 16px;
background: url('data:image/svg+xml;utf8,<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M160 144a32 32 0 0 0-32 32V864a32 32 0 0 0 32 32h688a32 32 0 0 0 32-32V176a32 32 0 0 0-32-32H160z m0-64h688a96 96 0 0 1 96 96V864a96 96 0 0 1-96 96H160a96 96 0 0 1-96-96V176a96 96 0 0 1 96-96z"/><path d="M482.176 262.272h59.616v94.4h196v239.072h-196v184.416h-59.616v-184.416H286.72v-239.04h195.456V262.24z m-137.504 277.152h137.504v-126.4H344.64v126.4z m197.12 0h138.048v-126.4H541.76v126.4z"/></svg>') no-repeat center;
padding: 16px !important;
}
#wh-trans-icon .wh-container {
display: none;
}
#wh-trans-icon.wh-icon-expanded .wh-container {
display: block;
word-break: break-all;
}
.wh-icon-expanded {
min-width: 200px;
}
#wh-cash-monitor {
margin: 4px 8px;
font-size: 14px;
}
.wh-icon-expanded #wh-cash-monitor {
display: none;
}
#wh-latest-version {
display: inline-block;
background-image: url("https://jjins.github.io/t2i/version.png?{{}}");
height: 16px;
width: 66px;
}
/** 弹出窗口 **/
#wh-popup {
position: fixed;
z-index: 200000;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #00000090;
/*color: #333;*/
}
div#wh-popup::after {
content: '点击空白处关闭';
display: block;
color: #ffffffdb;
text-align: center;
font-size: 14px;
line-height: 22px;
}
#wh-popup-container {
max-width: 568px;
margin: 5em auto 0;
/*box-shadow: 0 0 5px 1px #898989;*/
}
#wh-popup-title p {
/*padding: 1em 0;*/
font-size: 16px;
font-weight: bold;
text-align: center;
}
/** 弹出窗口的内容 **/
#wh-popup-cont {
padding: 1em;
max-height: 30em;
overflow-y: auto;
font-size: 14px;
line-height: 16px;
min-height: 120px;
}
#wh-popup-cont .gSetting > div {
display: inline-block;
width: 47%;
margin: 2px 0;
}
/*#wh-popup-cont .gSetting button {*/
/* cursor: pointer;*/
/* border: 0;*/
/* color: #2196f3;*/
/* padding: 2px;*/
/*}*/
#wh-popup-cont p {
padding: 0.25em 0;
}
#wh-popup-cont a {
color: red;
text-decoration: none;
}
#wh-popup-cont li {
margin: 4px 0;
}
#wh-popup-cont h4 {
margin: 0;
padding: 0.5em 0;
}
#wh-popup-cont button:not(.torn-btn) {
margin: 0 4px 0 0;
padding: 5px 8px;
border: solid 2px black;
color: black;
border-radius: 3px;
}
#wh-popup-cont button[disabled] {
opacity: 0.5;
}
#wh-popup-cont input {
padding: 2px;
text-align: center;
border: 1px solid #fff0;
border-radius: 5px;
margin: 1px 2px;
}
#wh-popup-cont input:focus {
border-color: blue;
}
#wh-popup-cont table {
width: 100%;
border-collapse: collapse;
border: 1px solid;
}
#wh-popup-cont td, #wh-popup-cont th {
border-collapse: collapse;
padding: 4px;
border: 1px solid;
}
#wh-popup-cont textarea {
display: block;
width: 100%;
min-height: 4em;
margin-bottom: 1em;
}
.wh-display-none {
display: none !important;
}
.wh-gym-stack #gymroot {
display: none !important;
}
#wh-notify {
display: inline-block;
position: fixed;
top: 0;
left: calc(50% - 180px);
width: 360px;
z-index: 9999990;
color: #333;
pointer-events: none;
}
#wh-notify a, #wh-notify button { pointer-events: all; }
#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;
pointer-events: all;
}
#wh-notify .wh-notify-item .wh-notify-msg {
padding: 12px;
}
.non-selection {
user-select: none;
}
.mt-4 {
margin-bottom: 4px;
}
/*.el-overlay {*/
/* backdrop-filter: blur(20px);*/
/*}*/

View File

@ -1,9 +0,0 @@
.wh-depo-helper div#funds div.deposit,
.wh-depo-helper div#armoury-donate div.cash {
position: fixed !important;
top: 150px;
right: 12px;
box-shadow: 0 0 8px 1px #00000091;
background: #f2f2f2;
z-index: 999999;
}

View File

@ -1,57 +0,0 @@
#wh-quick-fly-opt {
position: fixed;
left: 64px;
top: 64px;
background: #008000db;
padding: 8px;
border-radius: 4px;
box-shadow: 0 0 5px 1px #ffffff29;
color: white;
font-size: 15px;
width: 220px;
z-index: 199999;
}
#wh-quick-fly-opt p {
margin: 4px 0;
}
#wh-quick-fly-opt a {
cursor: pointer;
border: 1px solid;
padding: 4px;
display: inline-block;
border-radius: 2px;
}
#wh-quick-fly-opt label {
display: block;
}
#wh-quick-fly-opt select {
width: 100%;
padding: 6px;
margin: 4px 0;
}
#wh-quick-fly-opt button {
font-size: 16px;
color: white;
cursor: pointer;
float: right;
background: #00BCD4;
padding: 8px;
border-radius: 4px;
}
#wh-quick-fly-opt.wh-quick-fly-opt-hide * {
display: none;
}
#wh-quick-fly-opt.wh-quick-fly-opt-hide input {
display: inline-block;
}
info {
display: block;
}

View File

@ -1,23 +0,0 @@
.wh-link-collection-cont a {
display: inline-block;
border: solid 1px #b3b3b3;
border-radius: 4px;
margin: 0 5px 2px 0;
padding: 4px 8px;
text-align: center;
background: #efefef;
background: linear-gradient(#f1f1f1, #e3e3e3);
color: black !important;
}
.wh-link-collection-cont span {
display: block;
/*padding: 0 4px 8px;*/
}
.wh-link-collection-cont .wh-link-collection-img {
display: block;
width: 60px;
height: 30px;
background-size: 100% auto !important;
}

View File

@ -1,67 +0,0 @@
#wh-trv-alarm {
position: absolute;
width: 248px;
background: white;
border-radius: 4px;
box-shadow: #0000001f 0 0 10px 4px;
border: solid 1px #aaa;
z-index: 100001;
margin: 2em;
}
#wh-trv-alarm button {
margin: 0;
}
#wh-trv-error {
position: absolute;
width: 100%;
height: 100%;
display: none;
z-index: 2;
}
#wh-trv-error p {
background: #ffd0d0;
color: red;
display: table-cell;
vertical-align: middle;
padding: 1em;
text-align: center;
}
#wh-trv-alarm-title {
height: 30px;
border-bottom: solid #aaa 1px;
cursor: move;
}
h5#wh-trv-alarm-header {
height: 100%;
line-height: 30px;
padding: 0 12px;
font-weight: bold;
text-align: center;
}
#wh-trv-alarm-bottom {
padding: 12px;
}
#wh-trv-alarm-remaining {
float: right;
color: red;
}
#wh-trv-alarm-cont {
line-height: 18px;
}
#wh-trv-alarm-cont input[type="number"] {
width: 42px;
border-bottom: solid 1px #aaa;
}
.wh-trv-alarm-stop-hide {
display: none;
}

View File

@ -1,3 +0,0 @@
body.wh-hide-title .content-title, body.wh-hide-title .info-msg-cont {
display: none !important;
}

View File

@ -1,5 +0,0 @@
<div>
<button class="torn-btn">👉添加啤酒商品</button>
<p>如果当前商店没有啤酒这个商品可以提前显示以省去刷新步骤,增加抢酒成功率。</p>
<p id="wh-msg"></p>
</div>

View File

@ -1,5 +0,0 @@
<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-{{}}">【今日不再提醒】</button><br/>
<a href="/shops.php?step=bitsnbobs#clickfromnotify" target="_blank">【啤酒店】</a>
<a href="/shops.php?step=pharmacy#clickfromnotify" target="_blank">【血包店】</a>

View File

@ -1,71 +0,0 @@
<div class="acc-title">
<span class="item-desc tt-buy">
<span class="item Alcohol" itemid="180" loaded="0">
<span class="item-plate">
<img alt="Bottle of Beer" class="torn-item large"
src="/images/items/180/large.png"
srcset="/images/items/180/large.png 1x, /images/items/180/large@2x.png 2x, /images/items/180/large@3x.png 3x, /images/items/180/large@4x.png 4x">
</span>
<span class="item-hover">
<button aria-labelledby="Show info: 180-name 180-price 180-stock" class="view-info wai-btn"
value="100"></button>
<button aria-label="Buy: Bottle of Beer" class="buy-info wai-btn" value="100"></button>
</span>
</span>
<span class="desc">
<input name="shoparea" type="hidden" value="100">
<span id="180-name" class="name t-overflow bold">Bottle of Beer</span>
<span id="180-price" class="price t-gray-6 tt-modified" data-sell="$5">$10<span
class="tt-profit positive"><i class="fas fa-caret-up"></i>$1,636</span></span>
<span id="180-stock" class="stock t-gray-6 t-overflow">Alcohol (<span class="instock">5,000</span> in
stock)</span>
</span>
<span class="buy-act-wrap">
<button aria-label="Close" class="close-icon p0 wai-btn" value="100"></button>
<label class="wai" for="180">Amount
of Bottle of Beer</label>
<input id="180" autocomplete="new-amount" maxlength="3" name="buyAmount[]" type="text" value="100">
<span class="buy-act bold">
<button class="wai-support t-blue h" value="100">Buy<br><span class="tt-max-buy">fill
max</span></button>
<div class="tt-max-buy-overlay"></div>
</span>
</span>
</span>
<div class="torn-divider divider-right"></div>
<div class="confirm-wrap" tabindex="0">
<span class="confirm">
<span>
Are you sure you would like to buy
</span>
<span>
<span class="count"></span>
x Bottle of Beer for
$<span class="total"></span>
</span>
<span class="confirm-act m-top5">
<a class="wai-support yes m-right10 bold t-blue h" data-id="180" href="#">
Yes
</a>
<span class="no bold">
<a class="wai-support t-blue h" href="#">
No
</a>
</span>
</span>
</span>
</div>
<div class="success-wrap">
<span class="success">
<span class="t-green bold">
<span class="ajax-preloader"></span>
</span>
</span>
<button aria-label="Close" class="close-icon p0 wai-btn" value="100"></button>
</div>
<div class="msg-wrap">
<span class="t-green bold">
<span class="ajax-preloader"></span>
</span>
</div>
</div>

View File

@ -1,5 +0,0 @@
<p>即将打开危险功能,使用这些功能可能会造成账号封禁。请自行考虑是否使用。</p>
<p><label><input type="checkbox" {{}}/> 知道了,开启</label></p>
<div>
<button class="torn-btn" disabled>保存</button>
</div>

View File

@ -1,54 +0,0 @@
<style>
html {
overflow: hidden !important;
}
#chatRoot {
display: none !important;
}
#wh-dialog {
position: absolute;
/*width: 100%;*/
/*height: 100%;*/
background: #00000066;
flex-direction: column;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 290001;
}
#wh-dialog .top-round {
text-align: center;
}
#wh-dialog div.wh-content {
padding: 1em;
}
#wh-dialog .border-round {
margin: auto;
max-width: 400px;
position: fixed;
top: 100px;
left: 0;
right: 0;
}
#wh-dialog .pin-bottom {
text-align: center;
padding: 8px 0;
}
</style>
<div class="border-round">
<div class="title-black top-round">{{}}</div>
<div class="cont-gray bottom-round">
<div class="wh-content">{{}}</div>
<div class="non-selection pin-bottom">
<button class="torn-btn">确定</button>
<button class="torn-btn">取消</button>
</div>
</div>
</div>

View File

@ -1,3 +0,0 @@
<img alt="LOADING"
src="data:image/svg+xml,%3Csvg t='1656084442571' class='icon' viewBox='0 0 1024 1024' version='1.1' xmlns='http://www.w3.org/2000/svg' p-id='3924' width='14' height='14'%3E%3Cpath d='M512.032002 237.105181a29.310168 29.310168 0 0 1-29.310168-29.246172V29.310168a29.310168 29.310168 0 0 1 58.620336 0v178.548841A29.310168 29.310168 0 0 1 512.032002 237.105181zM512.032002 1024a29.310168 29.310168 0 0 1-29.310168-29.310168v-178.484845a29.310168 29.310168 0 1 1 58.620336 0v178.548841A29.310168 29.310168 0 0 1 512.032002 1024z m482.657834-482.657834h-178.484845a29.310168 29.310168 0 1 1 0-58.620336h178.548841a29.310168 29.310168 0 1 1 0 58.620336z m-786.830823 0H29.310172a29.310168 29.310168 0 0 1 0-58.620336h178.548841a29.310168 29.310168 0 0 1 0 58.620336z m519.263546-215.090557a29.182176 29.182176 0 0 1-20.734704-49.980876l126.264108-126.264108a29.310168 29.310168 0 1 1 41.405412 41.405412l-126.264108 126.264108a29.182176 29.182176 0 0 1-20.670708 8.575464zM170.741333 882.568839a29.182176 29.182176 0 0 1-20.734704-49.980876l126.264108-126.264108a29.246172 29.246172 0 1 1 41.405412 41.405412L191.412041 874.057371a29.182176 29.182176 0 0 1-20.670708 8.575464z m682.581338 0a29.182176 29.182176 0 0 1-20.670708-8.575464l-126.264108-126.264108a29.310168 29.310168 0 1 1 41.405412-41.405412l126.264108 126.264108a29.310168 29.310168 0 0 1-20.734704 49.91688zM297.005441 326.251609a29.182176 29.182176 0 0 1-20.670708-8.575464L150.006629 191.412037a29.310168 29.310168 0 1 1 41.405412-41.405412l126.264108 126.264108a29.310168 29.310168 0 0 1-20.734704 49.91688z' p-id='3925'%3E%3C/path%3E%3C/svg%3E"
style="width:14px;height:14px;">

View File

@ -1,30 +0,0 @@
<style>
#wh-popup-cont label p {
padding: 0 0 0 1em;
}
#wh-popup-cont label span {
font-weight: bold;
}
</style>
<p id="wh-nnb-info-container"></p>
<p><b>NNB</b><b>N</b>atural <b>N</b>erve <b>B</b>ar意思是扣除所有加成后玩家本身的犯罪条上限可用于衡量大佬隐藏的犯罪技能等级
</p>
<p>一般来说,左侧红色的犯罪条(<b>N</b>erve <b>B</b>ar/<b>NB</b>)的上限都是包含加成的,如来自帮派、天赋的加成等。额外的加成不会影响玩家的犯罪技能
</p>
<p>查看NNB的方法很简单在Torn主页面的最下方有一栏PerksNB-Perks=NNB</p>
<div>
<p>以下是两种计算NNB的方法</p>
<label>
<input checked name="wh-nnb-check-select" type="radio" value="bw"/><b> 冰蛙或PDA (推荐)</b>
<p>由于需要用到APIKey因此需要冰蛙或PDA提供</p>
<p>当前可以使用的APIKey<br/>
<input readonly value="{{}}">(来自冰蛙)<br/>
<input readonly value="{{}}">(来自PDA)</p>
</label>
<label>
<input name="wh-nnb-check-select" type="radio" value="ori"/><b> 普通方法</b>
<p>该方法不需要APIKey但是仅限在主页面海外或飞行状态不可用的时候</p>
</label>
</div>
<button>计算</button>

View File

@ -1,5 +0,0 @@
<div class="wh-notify-bar"></div>
<div class="wh-notify-cont">
<div class="wh-notify-close"></div>
<div class="wh-notify-msg"><p>{{}}</p></div>
</div>

View File

@ -1,7 +0,0 @@
<style>html {
overflow: hidden !important;
}</style>
<div class="border-round" id="wh-popup-container">
<div class="title-black top-round" id="wh-popup-title"><p>{{}}</p></div>
<div class="scroll-area scrollbar-transparent cont-gray bottom-round" id="wh-popup-cont">{{}}</div>
</div>

View File

@ -1,19 +0,0 @@
<style>
#wh-popup-cont input {
width: 12em;
}
#wh-popup-cont input[type="number"] {
width: 8em;
}
</style>
<p>输入需要监视的价格,低于该价格发出通知,-1为关闭</p>
<p>需要APIKey当前可用APIKey为<br/>
<input readonly value="{{}}">(来自冰蛙)<br/>
<input readonly value="{{}}">(来自PDA)
</p>
<p><b>PT</b><label> $ <input type="number" value="{{}}"/></label></p>
<p><b>XAN</b><label> $ <input type="number" value="{{}}"/></label></p>
<p>
<button>确定</button>
</p>

View File

@ -1,55 +0,0 @@
<div class="wh-translate">
<div class="title-black" style="border-radius: 5px 5px 0 0;"><span>常用犯罪</span></div>
<div class="cont-gray" style="padding: 6px 0;border-radius: 0 0 5px 5px;">
<!--18-1-->
<form action="crimes.php?step=docrime4" method="post" style="display: inline-block;margin: 0 5px">
<input name="nervetake" type="hidden" value="18">
<input name="crime" type="hidden" value="hackbank">
<input style="-webkit-appearance:none;padding: 4px;background: #e91e63;border-radius: 5px;color: white;"
type="submit" value="18-1"/>
</form>
<!--15-3-->
<form action="crimes.php?step=docrime4" method="post" style="display: inline-block;margin: 0 5px">
<input name="nervetake" type="hidden" value="15">
<input name="crime" type="hidden" value="napcop">
<input style="-webkit-appearance:none;padding: 4px;background: #e91e63;border-radius: 5px;color: white;"
type="submit" value="15-3(慎)"/>
</form>
<!--仓库-->
<form action="crimes.php?step=docrime4" method="post" style="display: inline-block;margin: 0 5px">
<input name="nervetake" type="hidden" value="11">
<input name="crime" type="hidden" value="warehouse">
<input style="-webkit-appearance:none;padding: 4px;background: #2196f3;border-radius: 5px;color: white;"
type="submit" value="烧仓库"/>
</form>
<!--7-2-->
<form action="crimes.php?step=docrime4" method="post" style="display: inline-block;margin: 0 5px">
<input name="nervetake" type="hidden" value="7">
<input name="crime" type="hidden" value="thoroughrobbery">
<input style="-webkit-appearance:none;padding: 4px;background: #2196f3;border-radius: 5px;color: white;"
type="submit" value="7-2(仅过渡用)"/>
</form>
<!--偷夹克-->
<form action="crimes.php?step=docrime4" method="post" style="display: inline-block;margin: 0 5px">
<input name="nervetake" type="hidden" value="4">
<input name="crime" type="hidden" value="jacket">
<input style="-webkit-appearance:none;padding: 4px;background: #009688;border-radius: 5px;color: white;"
type="submit" value="偷夹克"/>
</form>
<!--卖碟3-1-->
<form action="crimes.php?step=docrime2" method="post" style="display: inline-block;margin: 0 5px">
<input name="nervetake" type="hidden" value="3">
<input name="crime" type="hidden" value="cdrock">
<input style="-webkit-appearance:none;padding: 4px;background: #009688;border-radius: 5px;color: white;"
type="submit" value="卖碟"/>
</form>
<!--捡钱-->
<form action="crimes.php?step=docrime2" method="post" style="display: inline-block;margin: 0 5px">
<input name="nervetake" type="hidden" value="2">
<input name="crime" type="hidden" value="searchtrainstation">
<input style="-webkit-appearance:none;padding: 4px;background: #009688;border-radius: 5px;color: white;"
type="submit" value="捡钱"/>
</form>
</div>
<hr class="page-head-delimiter m-top10 m-bottom10 r1854">
</div>

View File

@ -1,29 +0,0 @@
<input type="button" value=" - "/>
<p>主要用途:出院秒飞</p>
<p>点起飞,页面加载完成后会马上飞走</p>
<br/>
<div>
<label>目的地:<select>
<option selected>墨西哥</option>
<option>开曼</option>
<option>加拿大</option>
<option>󠁵󠁳夏威夷</option>
<option>嘤国</option>
<option>阿根廷</option>
<option>瑞士 (解毒)</option>
<option>立本</option>
<option>祖国</option>
<option>阿联酋 (UAE)</option>
<option>南非</option>
</select></label>
<label>飞机:<select>
<option>普通飞机 - 不推荐</option>
<option selected>PI小飞机</option>
<option>私人飞机 - WLT股票</option>
<option>商务飞机 - 机票或内衣店</option>
</select></label>
<p><a>查看花偶库存</a></p>
<p>注:需要验证时无法起飞</p>
<info></info>
<button>起飞</button>
</div>

View File

@ -1,23 +0,0 @@
<div class="m-top10">
<h4 class="left" id="skip-to-content">RW 雷达</h4>
<div class="clear"></div>
<hr class="page-head-delimiter">
</div>
<div class="content m-top10">
<a href="/profiles.php?XID=2687093" target="_blank">woohoo</a>
<table>
<thead>
<tr>
<th>123</th>
<th>456</th>
</tr>
</thead>
<tbody>
<tr>
<td>789</td>
<td>012</td>
</tr>
</tbody>
</table>
</div>

View File

@ -1,2 +0,0 @@
<img alt="stock.png" src="https://jjins.github.io/t2i/stock.png?{{}}"
style="max-width:100%;display:block;margin:0 auto;"/>

View File

@ -1,18 +0,0 @@
<div id="wh-trv-error"><p><b>❌ 没有权限</b><br/>点击网页内任意位置以激活闹钟</p></div>
<div id="wh-trv-alarm-title">
<h5 id="wh-trv-alarm-header">飞行闹钟</h5>
</div>
<div id="wh-trv-alarm-bottom">
<div id="wh-trv-alarm-cont">
<p id="wh-trv-alarm-remaining"></p>
<p><span id="wh-trv-status">正在{{}} </span><span></span></p>
<div><input class="checkbox-css" id="WHTravelAlarmToggle" type="checkbox" {{}}/><label
class="non-selection marker-css" for="WHTravelAlarmToggle">开启闹钟</label></div>
<div><label>落地前响铃时长(秒): <input type="number" value="{{}}"/></label>
<button>确定</button>
</div>
<div class="wh-trv-alarm-stop-hide">
<button>停止闹钟</button>
</div>
</div>
</div>

View File

@ -1,16 +0,0 @@
<style>
#WHLogsCont {
width: 100%;
height: 340px;
}
#WHLogsCont p {
overflow-x: auto;
white-space: nowrap;
word-break: keep-all;
}
</style>
<p>{{}}信息 {{}}警告 {{}}错误
<button class="torn-btn">导出日志</button>
</p>
<div id="WHLogsCont">加载中</div>

View File

@ -1,35 +0,0 @@
<div id="wh-xmas-cont">
<div class="title-black"><span>水晶球解密地图攻略</span><span><button style="color: white">[隐藏]</button></span>
</div>
<div class="cont-gray select-wrap dropdown-new dropdown-default">
<select>
<option value="None">未选择</option>
<option value="Christmas Town">Christmas Town</option>
<option value="Maltese Snow Globe">Maltese Snow Globe</option>
<option value="Long way from home">Long way from home</option>
<option value="Chedburn Towers">Chedburn Towers</option>
<option value="Kidnapped Santa">Kidnapped Santa</option>
<option value="Holiday terror">Holiday terror</option>
<option value="Among Us">Among Us</option>
<option value="Kiss My Festivus">Kiss My Festivus</option>
<option value="Stanley Hotel">Stanley Hotel</option>
<option value="DoggoQuest">DoggoQuest</option>
<option value="Pokemon CT">Pokemon CT v2.0</option>
<option value="Winter in Gatlin">Winter in Gatlin</option>
</select>
<div>
<p>来源Torn City公众号图文详情请查看公众号文章</p>
<div id="wt-content"></div>
</div>
</div>
<hr class="page-head-delimiter m-top10 m-bottom10 r1854">
</div>
<style>
#wh-xmas-cont .cont-gray {
padding: 0.5em;
}
#wh-xmas-cont p, #wh-xmas-cont select, #wh-xmas-cont li {
margin: 0 0 3px;
}
</style>

View File

@ -1,15 +0,0 @@
<ul>
<li>出生点步行到传送点进入地图 1 [399,12]</li>
<li>到达地图1你出现在食堂往下走绕到红色按钮处[502-1]</li>
<li>答案D B A A D D B B B C A D D D 最终: B (Green)</li>
<li>然后你会被传送到地图2</li>
<li>在地图2中你需要沿着小路向南走然后向东进入通风口前往下一个部分[55624]</li>
<li>穿过通风口后,进入食堂。向南走到红色按钮所在的位置 [571,32]</li>
<li>答题阶段答案如下BBACBDC A</li>
<li>被传送到地图3</li>
<li>先直接向南走一点,再沿着走廊走。进入左边的一个通风口[345170]</li>
<li>会传送到办公室,在那里找到最后一个红色按钮[356173]</li>
<li>答题阶段答案如下CCADABBCD</li>
<li>进入"PEEP SHOW",获得本地图的水晶球</li>
</ul>

View File

@ -1,13 +0,0 @@
<ul>
<li>进入地图后使用附近的FAST的T下方的厕所传送到Chedburn Towers</li>
<li>进入大厅,"之"字形上楼,每层都是如此。</li>
<li>最终会进入问答题区域,通过在相应的数字上穿过来回答问题</li>
<li>答案是3 9 5 4 9 2 6 8</li>
<li>答题后进入Ched的办公室向西走然后一直走到左边的楼梯上</li>
<li>向南走下楼梯,然后向东走,沿着小楼梯到地下室</li>
<li>向东走到牢房区域</li>
<li>先踩下开关,打开牢房门前往右上角的最后一个牢房</li>
<li>开关位于JAIL文字的左上方</li>
<li>沿着挖出来的隧道一直走,岔路口向左走</li>
<li>到金库Chedburn NPC会给你本地图的水晶球</li>
</ul>

View File

@ -1,30 +0,0 @@
<ul>
<li>你出现在一个房间里</li>
<li>向东走,然后向南走,沿着小走廊就可以离开这个房间</li>
<li>来到这个地牢的01层</li>
<li>首先向南走,然后绕过墙,攻击你看到的第一个怪物[101,1]</li>
<li>然后向西走到墙边,向北攻击<span style="color: #32CD32">史莱姆</span></li>
<li>继续向北,攻击下一个<span style="color: gold">怪物</span></li>
<li>向北走到拐角处,然后向东走到楼梯处继续前进[坐标为101,1]</li>
<li>来到第二层,直接向东走上楼梯[11-19]</li>
<li>来到了这个地牢的第03层</li>
<li>向东再向南走到墙边,然后向东走,与绿色<span style="color: #32CD32">史莱姆</span>战斗</li>
<li>继续向东走,经过被打败的史莱姆,然后向南和向西绕过墙,向北走一格,向西打败另一个<span
style="color: #32CD32">史莱姆</span></li>
<li>向西南方向走下楼梯[53-49]</li>
<li>来到了第 04 层</li>
<li>走到墙边,撞右边两个镣铐之间的墙,然后向北直接走到墙里[15-65]</li>
<li>直接向北走,踏上红色的东西</li>
<li>沿着楼梯向南和东南方向走右边楼梯[39-69]</li>
<li>来到第5层</li>
<li>向北走,然后向西绕过中间的十字架,向南走到下一个楼梯[29-93]</li>
<li>来到第 6 层</li>
<li>杀死那只<span style="color: #32CD32">大绿狗</span></li>
<li>回到刚才的楼梯来到05层[33-114]</li>
<li>在第05层你会看到原来的十字架位置附近出现了新的楼梯口</li>
<li>走上该楼梯[54, -99]</li>
<li>到达了最后的?层</li>
<li>沿着小路向下走然后沿着冰冷的台阶走到Rudolph NPC</li>
<li>在他身边来回走动</li>
<li>踩在他身上的次数足够多时Rudolph会把该图的水晶球交给你</li>
</ul>

View File

@ -1,18 +0,0 @@
<ul>
<li>1. 从出生地沿着路向东,然后向北。过桥并沿着穿过城镇的小路继续前行,避开任何明显的陷阱(道路上的洞、打开的井盖等)。
</li>
<li>2. 继续向东和向北前进,直到到达 Mansion's Labyrinth豪宅迷宫[121,29]</li>
<li>3. 豪宅入口在[131,41]</li>
<li>4. 进入豪宅后向北走,你会看到一条由骷髅守卫的道路</li>
<li>5. 沿着棕色的小路走,在黑色的<b>区域前</b>停下</li>
<li>6. 按照如下的方式行进</li>
<li> 上3格左2上2右4下1右3上6左2下1左6下2左2上4右5上4</li>
<li>7. 来到一个区域,在这里你必须在两个洞穴中做出选择</li>
<li>第一次选择答案是Christmas Miracle选择左边的洞窟。</li>
<li>第二次选择答案是24/12/2019选择左边的洞窟。</li>
<li>第三次选择答案是Hohoho Coldington选择右边的洞窟。</li>
<li>第四次选择答案是Christmas Miracle Cave选择左边的洞窟。</li>
<li>8. 出现在一个用糖果棒装饰的红色地板的房间里,去地图的右上角一个冰洞的入口[101-74]</li>
<li>9. 进入冰洞。向西走寻找叫Erik the last elf的黄色小NPC</li>
<li>10. 拿到水晶球</li>
</ul>

View File

@ -1,24 +0,0 @@
<ul>
<li>出生在一个类似城镇的地方</li>
<li>沿着这条路向东走,然后向南走</li>
<li>到达道路尽头的一个码头时,向西走一段路,踩在精灵的上面,乘坐渡船[124, -30]</li>
<li>搭船来到了Fantasy Island</li>
<li>小心那个游荡的<span style="color: #32CD32">绿色NPC</span>,不惜一切代价避开他,否则他会把你打回出发点</li>
<li>向西走,然后向北走,再向西绕过岩石。要非常小心,不要踩到水里或掉下悬崖,否则你会死</li>
<li>然后回到南边,在那里你会看到一些门</li>
<li>走进蓝色的门(左二)[111-60]</li>
<li>过了蓝门后继续沿路向南</li>
<li>然后沿路向东,再向南</li>
<li>再向东走,会看到「恐怖之家」,进入这栋楼[137, -84]</li>
<li>向北走,进入洞口[164, -81]</li>
<li>穿过隧道到达另一端的洞穴口[142, -63]<b>避开所有怪物和NPC</b></li>
<li>来到另一个岛上</li>
<li>向南走,然后向东绕过建筑物,可以进入圣诞老人的洞穴[133, -2]</li>
<li>在建筑物内向西走再向北走在圣诞老人家work shop的东北角你会看到一个楼梯走下去[1694]</li>
<li>在这一区域,<b>要避开所有出现破损或有异样的地砖</b>也要避开四处游荡的邪恶的格林奇NPC</li>
<li>沿着地牢里的走廊向东走,然后向南走,避开所有看起来不同的瓷砖</li>
<li>它们上面有一些小裂缝和花纹,如果你是用手机的话,我建议你把亮度调高,以防万一</li>
<li>最终会看到一个发绿光的小开关</li>
<li>走到开关上[165, 18],激活它,然后进入向北打开的大门</li>
<li>走到<span style="color: gold">黄色精灵NPC</span>脸上[16625],可以得到本地图的水晶球</li>
</ul>

View File

@ -1,19 +0,0 @@
<ul>
<li>从起点出发沿着小路向北走到出租车处乘坐前往Dark Forest的出租车 [96,16]</li>
<li>沿着公路向东走,继续向东进入雪地</li>
<li>沿着暗淡的蓝色轨迹向东南方向走,穿过树林,直到你到达一个铁栅栏[坐标为114,-89]</li>
<li>铁栅栏进不去。有人会告诉你乘坐他们的雪地车。</li>
<li>向西走到雪地车旁,注意不要踩到任何<b>冬青树</b>(鲜艳黄红色的矮树),否则你将回到起点。</li>
<li>被传送到锯木厂,在伐木工那里获得钥匙。</li>
<li>然后向南走,然后向东走(向东走很长一段路),沿着小路返回铁栅栏处。</li>
<li>来到一个炫酷的45°视角迷宫你要走到地图的东北部抵达另一个洞穴口[156,-74]</li>
<li>先往左下方走到岔路口,然后往右上方走,接下来将只有一条路</li>
<li>到达岛屿沿着小楼梯上去,绕到正下方那艘天鹅船</li>
<li>到一个新的岛屿,向南走几步,踩在[12, -79]的蓝色火花上</li>
<li>被传送到另一个有几辆拖车的岛上</li>
<li>向北走,进入一个新的山洞口</li>
<li>人被挡住了,要在冰层下向西北方向一直走,主要是向上和向左走</li>
<li>沿着这条路一直往上走,然后在开阔的地方往东走,你会看到一座房子[房子的入口在26,58]</li>
<li>进入房子,向北走几步,穿过闪闪发光的入口,你就可以进入房子了</li>
<li>沿着东南方向走你会看到Evil-Duck NPC他将给你本地图的水晶球</li>
</ul>

View File

@ -1,21 +0,0 @@
<ul>
<li>1.随便动一下</li>
<li>2.左边的管道口</li>
<li>3.右走到十字路口,往上,往右,从偏左的那个管道往上。</li>
<li>3.出小门,往右到底,往上到底,往右,进上面房间,右上角的电脑,电脑显示的是下面房间的走法,任意移动退出</li>
<li>4.去下面房间,右边橙色电力符号,进入解密。下,右下,右下,右上,右上,右,右下,右下,下,左下,左下,</li>
<li>左,左,左下,左下,进圈。</li>
<li>5.进入新的房间按钮</li>
<li>6.一直左走,走到有两个怪兽把手的桥那,进上面的房间,左上角的机器,*是重输密码</li>
<li>作者随时改密码,建议看纸条上的提示自己去数</li>
<li>7.桥上怪兽消失, 往左走到底,按钮</li>
<li>8.右走走到雪地走大路按钮开铁门上darkforest的蓝车</li>
<li>9.右走十几步,传送</li>
<li>10.右下走,看到铁丝网,顺着铁丝网右走,有个缺口,进去。</li>
<li>11.右走,直到看见三颗倒下的圣诞树(记住这里),顺着血迹和脚印走,进山洞。</li>
<li>12.顺着山洞走到一滩血,原路出山洞。</li>
<li>13.原路回到三颗倒下的圣诞树,正上方有个红色仓库,进入。</li>
<li>14.上,上,上,右,上,左,上,路就通了,去拿到右上角的锯子,原路出仓库。</li>
<li>15.出来就在车下面,上车,再上车。</li>
<li>16.左边的小橘人,完成</li>
</ul>

View File

@ -1,18 +0,0 @@
<ul>
<li>1.想办法进入前几层的楼梯口</li>
<li>2.出来之后往南走, 在码头找到天鹅船</li>
<li>3.按着数字1-12走过乐高博物馆</li>
<li>4.跟着大路走到天鹅船。</li>
<li>5.走到901,486的银行</li>
<li>6.最左上的楼梯</li>
<li>7.B-D-C-E-F-G-C-A</li>
<li>8.右,右,右,北,北,右,右</li>
<li>9.走到右上角铁路</li>
<li>10.小游戏:</li>
<li>移动1到最右移动2到中间移动1到2上面,移动3到最右,移动1到最左,移动2到3.上面移动1到2上面。</li>
<li>11.往上走出铁丝网往左绕一个大圈走到300,476</li>
<li>12.走到363,406的隧道走到361,400的隧道 ,往南走。</li>
<li>13.走到352,334的迷宫好像有好几条路,我说我的走法,往左下走,走倒最下了往右走走到1个不一样的绿色的时候往上走。
</li>
<li>14.走到迷宫中间的小人,后面就只有一条路走了,完成。</li>
</ul>

View File

@ -1,36 +0,0 @@
<ul>
<li>宝可梦新增了战斗系统,路过高草丛会几率进入战斗</li>
<li>战斗系统为一个十字形界面,上:技能/精灵球捕捉,下:逃跑,左:回血,右:攻击</li>
<li>战斗守则攻击当你血量为33时回血</li>
<li>打败最终BOSS需要捕捉两只捕捉地点</li>
<li>一:把包裹交给大木博士后,去常磐市的路上</li>
<li>二:进入森林后遇到的毛毛虫</li>
<li>捕捉时需要将其打到残血。</li>
<li>最终BOSS打法</li>
<li>第一个敌方精灵,毛虫进化的蝴蝶,先放技能,使其眩晕,在眩晕期间攻击,一旦醒过来就眩晕,重复。</li>
<li>第一个BOSS死后第二个BOSS会秒杀蝴蝶 此时用第二个精灵。</li>
<li>第二个精灵打法:攻击看见它放absorbing技能就去回血(当然你没血了也要去回血),重复。</li>
<li>【游戏开始】</li>
<li>出生在你房间的二楼</li>
<li>下楼梯离开房间。走出家门。从那里向东北方向进入高草丛将被传送到大木博士Professor Oak的实验室</li>
<li>踩大木博士</li>
<li>踏上桌子,选择你的宝可梦</li>
<li>现在出门去常磐市Veridian City拿一个包裹</li>
<li>离开大木博士的实验室向北走穿过草地前往常磐市Veridian City</li>
<li>进入城市后,前往 Poke Mart [134-3]</li>
<li>回到大木博士的实验室,返回时可以跳下小路西侧的山崖,避开高草丛</li>
<li>把包裹交给大木博士后。回常磐市</li>
<li>在房子和两个精灵之间的小路上继续向北走,穿过城市[79,-21]</li>
<li>过了精灵后一路向北</li>
<li>进入一所房子,经过它才能进入常磐森林</li>
<li>穿过常磐森林才能到达尼比市</li>
<li>森林的入口向东走,直到看到高草,然后向北走,直到下一片高草</li>
<li>绕过树木向东走,然后向北走</li>
<li>现在绕过树木向西走,然后向北走</li>
<li>然后穿过草地向西和向南走</li>
<li>沿着这条小路蜿蜒穿过高高的草丛</li>
<li>沿着小路穿过草地,最终离开森林</li>
<li>离开森林后,沿着草丛旁小路向北走,到达 Pewter City。向北向西绕到大房子处到达道馆</li>
<li>走到大胡桃夹子前,挑战小刚</li>
<li>赢得这场战斗后你会被带到大木博士那里,他会给本地图的水晶球</li>
</ul>

View File

@ -1,7 +0,0 @@
<ul>
<li>从起点开始,你会看到正北方有一座房子。向北走几步到门前,进入房子。</li>
<li>传送到一个有门的地方。绕过并向上走,激活位于[188,72]的大门开关。</li>
<li>向东北方向前进,沿着血迹穿过森林,直到你到达一个山洞。</li>
<li>依次使用使用防御(踩盾牌标记),然后攻击(剑),然后魔法(闪亮的蓝色气泡)来杀死怪物。</li>
<li>最后你会来到工人Bob的房间他将给你本地图的水晶球。</li>
</ul>

View File

@ -1,9 +0,0 @@
<ul>
<li>从出生点出发</li>
<li>往右走到达树林,往右上走跨过铁栅栏,再往右走,经过红车时从右边缝隙穿过往下走</li>
<li>沿公路向下走到第一个岔路向右走到废弃的小屋[14,80]</li>
<li>进入小屋时,你会在一个黑色的小房间里,走到亮起的圆圈处</li>
<li>在下一个房间里,会有一连串的数字,按以下顺序走到数字上</li>
<li>1,4,6,8,7,6,4</li>
<li>在最后一个房间Epic_Heasley NPC 会给你本图的水晶球</li>
</ul>

View File

@ -1,7 +0,0 @@
<ul>
<li>旧攻略提到的驯鹿车已被移除,只能手动找一条蓝色的小路[94,3]</li>
<li>向南走,然后上木桥,沿着它向西走到达冰湖</li>
<li>在冰湖[55,7][61,64]附近找Labyrinth传送门进入迷宫</li>
<li>迷宫的出口在中间的方向[395,397]一个冰湖,走进冰湖传送</li>
<li>走到企鹅</li>
</ul>

View File

@ -1,132 +0,0 @@
<div class="m-bottom10" id="wh-loot-container">
<audio src="https://www.torn.com/js/chat/sounds/Chirp_3.mp3" style="display:none"></audio>
<div class="title-black"><span>附近物品</span></div>
<div class="cont-gray" id="wh-loot-container-main">
<b>物品</b><span id="wh-loot-item-count"></span>
<div id="wh-loot-container-items"></div>
<b>箱子</b><span id="wh-loot-chest-count"></span>
<div id="wh-loot-container-chests"></div>
</div>
<div class="cont-gray wh-hide" id="wh-loot-container-ex">
<div><label><input id="wh-loot-setting-blink" type="checkbox" {{}}/> 闪烁提示</label></div>
<div><label><input id="wh-loot-setting-sound" type="checkbox" {{}}/> 声音提示
<del>(iOS)</del>
</label></div>
<div><label><input id="wh-loot-setting-chest" type="checkbox" {{}}/> 不记录需要钥匙的宝箱</label></div>
<div id="wh-hist">
<div id="wh-hist-clear">
<p>
<button>清空数据</button>
- 长时间不清空会出现奇怪的问题
</p>
</div>
<table>
<thead>
<tr>
<th colspan="5">历史记录</th>
</tr>
<tr>
<th>坐标</th>
<th>地图</th>
<th>类型</th>
<th>发现</th>
<th>获取</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
<div class="cont-gray" id="wh-loot-btn">
<button>设置</button>
</div>
</div>
<style>
#wh-loot-container-main {
padding: 0.5em;
}
#wh-loot-container-main div {
overflow-x: auto;
overflow-y: hidden;
white-space: nowrap;
min-height: 4em;
}
#wh-loot-container-main div span {
display: inline-block;
background-color: #2e8b57;
color: white;
margin: 0 1em 0 0;
border-radius: 4px;
padding: 0.5em;
}
#wh-loot-container-main div span img {
height: 1em;
width: 1em;
}
#wh-loot-container-ex {
padding: 0.5em;
}
#wh-loot-container-ex.wh-hide {
display: none;
}
#wh-loot-container-ex #wh-hist {
overflow-x: auto;
}
#wh-loot-container-ex table {
margin-top: 0.5em;
}
#wh-loot-container-ex tbody {
background-color: antiquewhite;
}
#wh-loot-container-ex table, #wh-loot-container-ex th, #wh-loot-container-ex td {
padding: 5px;
border: 1px solid black;
height: auto;
}
#wh-loot-container-ex th:nth-child(1) {
min-width: 5em;
}
#wh-loot-container-ex th:nth-child(2) {
min-width: 8em;
}
#wh-loot-container-ex th:nth-child(3) {
min-width: 4em;
}
#wh-loot-container-ex th:nth-child(4) {
min-width: 9em;
}
#wh-loot-container-ex th:nth-child(5) {
min-width: 3em;
}
#wh-loot-container-ex thead {
background-color: #2e8b57;
color: white;
}
@keyframes lootFoundAlert {
0% {
background: #f2f2f2
}
50% {
background: #2e8b57
}
100% {
background: #f2f2f2
}
}
</style>

View File

@ -1,30 +0,0 @@
<div id="deadman_div" style="width: inherit">
<div id="deadman_header" style="margin:10px 0px; border:1px solid darkgray; text-align:center;">
<button class="torn-btn" id="deadman-start-btn" style="margin:5px;">开始寻找木桩</button>
<button class="torn-btn" style="margin:5px;">停止</button>
</div>
<div id="deadman_tips" style="text-align:center; margin-bottom: 3px; font-size: 16px;">未开始</div>
<div id="deadman_wrapper"
style="min-height:700px;margin:10px 0px; border:1px solid darkgray; text-align:center;overflow:hidden;">
<table cellspacing="0" id="watchlist-table" style="width:100%; background-color: white; font-size:12px;">
<thead>
<th style="border: 1px solid darkgray;padding: 5px;background-color: black;color: white;font-weight: bold;text-align:center;">
ID
</th>
<th style="border: 1px solid darkgray;padding: 5px;background-color: black;color: white;font-weight: bold;text-align:center;">
名字
</th>
<th style="border: 1px solid darkgray;padding: 5px;background-color: black;color: white;font-weight: bold;text-align:center;">
等级
</th>
<th style="border: 1px solid darkgray;padding: 5px;background-color: black;color: white;font-weight: bold;text-align:center;">
攻击
</th>
<!-- <th style="border: 1px solid darkgray;padding: 5px;background-color: black;color: white;font-weight: bold;text-align:center;">-->
<!-- BS(M)-->
<!-- </th>-->
</thead>
<tbody id="table-body"></tbody>
</table>
</div>
</div>

View File

@ -1,50 +0,0 @@
<table id="wh-dev-info-tb">
<tr>
<td>URL</td>
<td>${ window.location.href }</td>
</tr>
<tr>
<td>页面尺寸</td>
<td>${ window.innerWidth }x${ window.innerHeight }</td>
</tr>
<tr>
<td>设备类型</td>
<td>${ CommonUtils.getDeviceType().toUpperCase() }</td>
</tr>
<tr>
<td>脚本运行方式</td>
<td>${ { 'gm': '油猴', 'raw': '直接运行', 'pda': 'TornPDA' }[CommonUtils.getScriptEngine()] }</td>
</tr>
<tr>
<td>时间</td>
<td>${ date.getFullYear() }/${ date.getMonth() + 1 }/${ date.getDate() } ${ date.getHours() }:${
date.getMinutes() }:${ date.getSeconds() }
</td>
</tr>
<tr>
<td>插件版本</td>
<td>${ glob.version }</td>
</tr>
<tr>
<td>操作系统</td>
<td>${ os }</td>
</tr>
<tr>
<td>UA</td>
<td>${ window.navigator.userAgent }</td>
</tr>
<tr>
<td>用户ID</td>
<td>${ glob.player_info.userID }</td>
</tr>
<tr>
<td>用户名</td>
<td>${ glob.player_info.playername }</td>
</tr>
</table>
<style>
#wh-dev-info-tb td {
padding: 2px 4px;
color: black;
}
</style>

View File

@ -1,10 +0,0 @@
<p>点击开打:</p>
<ul>
<li><a href="https://www.torn.com/loader.php?sid=attack&user2ID=4" target="_blank">Duke</a></li>
<li><a href="https://www.torn.com/loader.php?sid=attack&user2ID=15" target="_blank">Leslie</a></li>
<li><a href="https://www.torn.com/loader.php?sid=attack&user2ID=19" target="_blank">Jimmy(面包刀)</a></li>
<li><a href="https://www.torn.com/loader.php?sid=attack&user2ID=20" target="_blank">Fernando(毒伞)</a></li>
<li><a href="https://www.torn.com/loader.php?sid=attack&user2ID=21" target="_blank">Tiny(大锤)</a></li>
</ul>
<div><img alt="stock.png" src="https://jjins.github.io/t2i/loot.png?{{}}"
style="max-width:100%;display:block;margin:0 auto;"/></div>

View File

@ -1,16 +0,0 @@
<div>
<button id="wh-trans-icon-btn"></button>
</div>
<div class="wh-container">
<div class="wh-main">
<div><b>芜湖助手</b></div>
<div id="wh-gSettings"></div>
<div>
<p>当前版本: {{}}
<button id="wh-update-btn">更新</button>
</p>
</div>
<div><p>最新版本: <span id="wh-latest-version"></span></p></div>
<div><p id="wh-inittimer"></p></div>
</div>
</div>

View File

@ -1,15 +0,0 @@
<h4>电脑</h4>
<p>通常电脑浏览器装有油猴等用户脚本扩展时可以使用链接安装(自动更新):<a
href="https://gitlab.com/JJins/wuhu-torn-helper/-/raw/dev/release.min.user.js" target="_blank">点此安装</a></p>
<p>这些扩展长这样:<img alt="tm.png" src="//jjins.github.io/tm.png"/><img alt="vm.png" src="//jjins.github.io/vm.png"/>
</p>
<p></p>
<h4>手机</h4>
<p>安卓 KIWI 等可以用油猴脚本的浏览器也可以点上面的链接安装👆</p>
<p>Torn PDA app 或 Alook 用户可打开<a href="//jjins.github.io/fyfuzhi/" target="_blank">这个网页</a>快捷复制粘贴。</p>
<p>Torn PDA 中Injection time 请选择 Start 达到最好效果。</p>
<h4>直接复制</h4>
<p>加载脚本然后直接复制粘贴到用户脚本处。</p>
<p>
<button>加载</button>
</p>

View File

@ -1,3 +0,0 @@
{
"css": ".wh-hide{display:none;}#wh-trans-icon{user-select:none;display: inline-block;position: fixed;top:5px;left:5px;z-index:100010;border-radius:4px;max-width: 220px;box-shadow: 0 0 3px 1px #8484848f;}div#effectiveness-wrap{overflow-y:hidden;}@media screen and (max-width: 600px) { #wh-trans-icon{top:0;left:112px;} /* 冰蛙公司效率表 */ div#effectiveness-wrap { margin-left: -80px; margin-right: -76px; }}#wh-trans-icon select{width:110px;}#wh-trans-icon a {text-decoration: none;color: #006599;background: none;}#wh-trans-icon:not(.wh-icon-expanded):hover {background: #f8f8f8;}#wh-trans-icon button{margin:0;padding:0;border:0;cursor:pointer;}#wh-inittimer{margin-top:6px;color:#b0b0b0;}#wh-gSettings div{margin: 4px 0;}#wh-trans-icon .wh-container{margin:0;padding:0 16px 16px;border:0;}#wh-trans-icon-btn{height:16px;width:16px;background: url('data:image/svg+xml;utf8,<svg viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\"><path d=\"M160 144a32 32 0 0 0-32 32V864a32 32 0 0 0 32 32h688a32 32 0 0 0 32-32V176a32 32 0 0 0-32-32H160z m0-64h688a96 96 0 0 1 96 96V864a96 96 0 0 1-96 96H160a96 96 0 0 1-96-96V176a96 96 0 0 1 96-96z\"/><path d=\"M482.176 262.272h59.616v94.4h196v239.072h-196v184.416h-59.616v-184.416H286.72v-239.04h195.456V262.24z m-137.504 277.152h137.504v-126.4H344.64v126.4z m197.12 0h138.048v-126.4H541.76v126.4z\"/></svg>') no-repeat center;padding:16px !important;}#wh-trans-icon .wh-container{display:none;}#wh-trans-icon.wh-icon-expanded .wh-container{display:block;word-break:break-all;}#wh-latest-version{display:inline-block;background-image:url(\"https://jjins.github.io/t2i/version.png?{{}}\");height:16px;width: 66px;}/** 弹出窗口 **/#wh-popup{ position: fixed; z-index: 200000; top: 0; left: 0; width: 100%; height: 100%; background: #00000090; color:#333;}div#wh-popup::after { content: '点击空白处关闭'; display: block; color: #ffffffdb; text-align: center; font-size: 14px; line-height: 22px;}#wh-popup-container{ max-width: 568px; margin: 5em auto 0; background: #d7d7d7; min-height: 120px; box-shadow: 0 0 5px 1px #898989; border-radius: 4px;}#wh-popup-title p{ padding: 1em 0; font-size: 16px; font-weight: bold; text-align: center;}/** 弹出窗口的内容 **/#wh-popup-cont{ padding: 0 1em 1em; max-height: 30em; overflow-y: auto; font-size:14px; line-height: 16px;}#wh-popup-cont .gSetting > div{ display: inline-block; width: 47%; margin: 2px 0;}#wh-popup-cont .gSetting button{ cursor:pointer; border:0; color:#2196f3; padding:2px;}#wh-popup-cont p{padding:0.25em 0;}#wh-popup-cont a{color:red;text-decoration:none;}#wh-popup-cont li{margin:4px 0;}#wh-popup-cont h4{margin:0;padding: 0.5em 0;}#wh-popup-cont button{ margin: 0 4px 0 0; padding: 5px 8px; border: solid 2px black; color: black; border-radius: 3px;}#wh-popup-cont button[disabled]{opacity: 0.5;}#wh-popup-cont input{ padding: 2px; text-align: center; border: 1px solid #fff0; border-radius: 5px; margin:1px 2px;}#wh-popup-cont input:focus{border-color:blue;}#wh-popup-cont table{width:100%;border-collapse:collapse;border:1px solid;}#wh-popup-cont td, #wh-popup-cont th{border-collapse:collapse;padding:4px;border:1px solid;}.wh-display-none{display:none !important;}#wh-gym-info-cont{ background-color: #363636; color: white; padding: 8px; font-size: 15px; border-radius: 4px; text-shadow: 0 0 2px black; background-image: linear-gradient(90deg,transparent 50%,rgba(0,0,0,.07) 0); background-size: 4px; line-height: 20px;}#wh-gym-info-cont button{cursor:pointer;}#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;}"
}

View File

@ -1,100 +0,0 @@
[
{
"start": [
0,
16,
8
],
"end": [
0,
22,
8
],
"name": "捡垃圾周",
"eff": "获得捡垃圾概率提升的增益"
},
{
"start": [
3,
5,
20
],
"end": [
3,
25,
20
],
"name": "复活节狩猎",
"eff": "复活节彩蛋会随机出现集齐10个可兑换金蛋和一个独特的头像框(章)。"
},
{
"start": [
5,
20,
20
],
"end": [
5,
29,
20
],
"name": "狗牌",
"eff": "击败其他玩家以获得狗牌,小心保护你的狗牌。"
},
{
"start": [
6,
5,
20
],
"end": [
6,
25,
20
],
"name": "托恩先生和托恩女士",
"eff": "上传你的真实图片,然后拿章"
},
{
"start": [
8,
5,
20
],
"end": [
8,
23,
20
],
"name": "大逃杀",
"eff": "加入特定队伍后攻击其他队伍玩家存活下来的3个队伍可以拿章"
},
{
"start": [
9,
25,
20
],
"end": [
10,
1,
20
],
"name": "不给糖就捣蛋",
"eff": "买篮子之后攻击其他玩家后会随机掉落糖果,可用于兑换许多高价值物品"
},
{
"start": [
11,
19,
20
],
"end": [
11,
31,
20
],
"name": "圣诞小镇",
"eff": "在小镇中闲逛来获取随机掉落的物品"
}
]

View File

@ -1,68 +0,0 @@
{
"val": {
"0104": {
"name": "周末自驾游",
"eff": "获得双倍的赛车点数与赛车技能等级增益"
},
"0114": {
"name": "情人节",
"eff": "使用爱情果汁(Love Juice)后获得降低攻击与复活的能量消耗的增益"
},
"0203": {
"name": "员工激励日",
"eff": "获得三倍的工作点数与火车增益"
},
"0217": {
"name": "圣帕特里克日",
"eff": "获得双倍的酒类效果增益,城市中可以捡到绿色世涛(Green Stout)"
},
"0320": {
"name": "420日",
"eff": "获得三倍的大麻(Cannabis)效果增益"
},
"0418": {
"name": "博物馆日",
"eff": "获得10%提高的博物馆PT兑换增益"
},
"0514": {
"name": "世界献血日",
"eff": "获得减半的抽血CD和扣血增益"
},
"0611": {
"name": "世界人口日",
"eff": "获得双倍的通过攻击获取的经验的增益"
},
"0629": {
"name": "世界老虎日",
"eff": "获得5倍的狩猎技能增益"
},
"0704": {
"name": "国际啤酒节",
"eff": "获得5倍的啤酒物品效果增益"
},
"0827": {
"name": "旅游节",
"eff": "获得双倍的起飞后物品携带容量增益"
},
"0915": {
"name": "饮料节",
"eff": "获得双倍的能量饮料效果增益"
},
"1014": {
"name": "世界糖尿病日",
"eff": "获得三倍的糖类效果增益"
},
"1015": {
"name": "周年庆",
"eff": "左上角的TORN图标可以食用"
},
"1024": {
"name": "黑色星期五",
"eff": "某些商家将提供1元购活动"
},
"1113": {
"name": "住院日",
"eff": "获得降低75%的住院时间增益"
}
}
}

View File

@ -1,92 +0,0 @@
[
{
"name": "mex",
"show": "墨西哥",
"stocks": {
"Dahlia": "花",
"Jaguar Plushie": "偶"
}
},
{
"name": "cay",
"show": "开曼",
"stocks": {
"Banana Orchid": "花",
"Stingray Plushie": "偶"
}
},
{
"name": "can",
"show": "加拿大",
"stocks": {
"Crocus": "花",
"Wolverine Plushie": "偶"
}
},
{
"name": "haw",
"show": "夏威夷",
"stocks": {
"Orchid": "花",
"Large Suitcase": "大箱"
}
},
{
"name": "uni",
"show": "嘤国",
"stocks": {
"Heather": "花",
"Red Fox Plushie": "赤狐",
"Nessie Plushie": "水怪"
}
},
{
"name": "arg",
"show": "阿根廷",
"stocks": {
"Ceibo Flower": "花",
"Monkey Plushie": "偶",
"Tear Gas": "催泪弹"
}
},
{
"name": "swi",
"show": "瑞士",
"stocks": {
"Edelweiss": "花",
"Chamois Plushie": "偶"
}
},
{
"name": "jap",
"show": "日本",
"stocks": {
"Cherry Blossom": "花"
}
},
{
"name": "chi",
"show": "祖国",
"stocks": {
"Peony": "花",
"Panda Plushie": "偶"
}
},
{
"name": "uae",
"show": "阿联酋 (UAE)",
"stocks": {
"Tribulus Omanense": "花",
"Camel Plushie": "偶"
}
},
{
"name": "sou",
"show": "南非",
"stocks": {
"African Violet": "花",
"Lion Plushie": "偶",
"Xanax": "XAN"
}
}
]

View File

@ -1,184 +0,0 @@
[
17003,
251077,
340581,
313353,
498729,
279673,
353885,
514096,
753853,
458343,
464918,
491000,
237866,
451695,
953808,
162476,
802907,
800608,
342669,
67254,
147082,
792900,
275866,
112024,
365986,
264257,
464079,
342150,
372870,
14092,
905822,
654795,
575176,
815125,
983447,
330496,
436308,
1072681,
280295,
660205,
1180420,
478962,
382338,
229632,
488384,
465467,
381995,
342907,
332479,
190695,
346837,
79416,
432474,
378718,
1177887,
451753,
83039,
421949,
740967,
470180,
1082559,
644384,
484743,
281747,
1210736,
762865,
938350,
320161,
283188,
522960,
488552,
387822,
566484,
298167,
234429,
428732,
18798,
476620,
472351,
807823,
796316,
316768,
153910,
76096,
659852,
450465,
738073,
284536,
524912,
263120,
729174,
251566,
519062,
1489357,
669996,
191060,
454302,
684732,
1046495,
1199189,
485156,
1399310,
581300,
982173,
211286,
810355,
469582,
652354,
781161,
146715,
491724,
233040,
471136,
688148,
442427,
588113,
669588,
75522,
95057,
21631,
76480,
76583,
87572,
241909,
200728,
943004,
248808,
87461,
929257,
326028,
136660,
1514039,
34069,
556583,
130275,
173148,
247665,
320301,
264772,
583658,
813216,
41317,
50835,
14641,
222151,
26299,
340810,
27340,
54567,
228704,
359740,
185958,
374418,
316174,
431576,
244123,
188142,
1462209,
45179,
768356,
232564,
364079,
668705,
758810,
295155,
343321,
65146,
384786,
466947,
325378,
1278107,
463919,
930653,
380958,
349371,
184845,
931279,
355177,
228051,
545762,
507362,
28699
]

View File

@ -1,67 +0,0 @@
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());
}
}
}

View File

@ -1,160 +0,0 @@
// 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 })
// // });
// }
// }

View File

@ -1,93 +0,0 @@
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脚本参数初始化结束');
}
}

View File

@ -1,285 +0,0 @@
import CommonUtils from "./utils/CommonUtils";
import Global from "./Global";
import COMMON_CSS from "../../static/css/common.module.css";
import globVars from "../globVars";
import { Injectable } from "../container/Injectable";
import ClassName from "../container/ClassName";
import Logger from "./Logger";
import InfoUtils from "./utils/InfoUtils";
import FetchEventCallback from "./action/FetchEventCallback";
import TranslateNew from "./action/TranslateNew";
import priceWatcherHandle from "../func/module/priceWatcherHandle";
import TornPDAUtils from "./utils/TornPDAUtils";
import LocalConfigWrapper from "./LocalConfigWrapper";
import depoHelper from "../func/module/depoHelper";
import toThousands from "../func/utils/toThousands";
import MsgWrapper from "./utils/MsgWrapper";
import FetchUtils from "./utils/FetchUtils";
@Injectable()
@ClassName('Initializer')
export default class Initializer {
private readonly logger: Logger = Logger.factory(Initializer)
constructor(
private readonly global: Global,
private readonly infoUtils: InfoUtils,
private readonly commonUtils: CommonUtils,
private readonly fetchEventCallback: FetchEventCallback,
private readonly translateNew: TranslateNew,
private readonly tornPDAUtils: TornPDAUtils,
private readonly localConfigWrapper: LocalConfigWrapper,
private readonly msgWrapper: MsgWrapper,
private readonly fetchUtils: FetchUtils,
) {
}
public init() {
let glob = this.global;
// 请求通知权限
if (window.Notification) {
if (window.Notification.permission !== 'granted') {
this.logger.info("芜湖助手即将请求浏览器通知权限……");
window.Notification.requestPermission().then();
}
} else {
this.logger.error('该浏览器不支持系统通知');
}
// 扩展正则方法
String.prototype.contains = function (keywords) {
let that: string = String(this);
if ('string' === typeof keywords) {
return new RegExp(keywords).test(that);
} else {
return keywords.test(that);
}
};
/**
* xhrfetch
* @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;
}
}

View File

@ -1,19 +0,0 @@
import ClassName from "../container/ClassName";
import { Injectable } from "../container/Injectable";
@ClassName('Interrupt')
@Injectable()
export default class Interrupt {
public conditionInterrupt() {
let title: HTMLElement | { innerText: string } = (document.querySelector('#skip-to-content') ||
document.querySelector('[href*="#skip-to-content"]')) as HTMLElement || { innerText: '' };
let condition = (
document.title.toLowerCase().includes('just a moment') ||
title.innerText.toLowerCase().includes('please validate') ||
document.querySelector('div.container div.cf .iAmUnderAttack') !== null
);
if (condition) throw new Error('芜湖');
}
}

View File

@ -1,89 +0,0 @@
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>;

View File

@ -1,80 +0,0 @@
export default class Log {
private static logs = '';
private static counter = { info: 0, error: 0, warning: 0 };
public static info(...o): void {
Log.counter.info++;
let flag = '%c WH %cIFO%c' + this.getTime() + '%c';
if (this.debug()) {
console.log(flag, 'background:grey;color:white;', '', 'color:grey;', '', ...o);
}
this.saveLogs(flag, ...o);
}
public static error(...o): void {
Log.counter.error++;
let flag = '%c WH %cERR%c' + this.getTime() + '%c';
console.error(flag, 'background:grey;color:white;', 'background:red;color:white;', 'color:grey;', '', ...o);
this.saveLogs(flag, ...o);
}
public static warn(...o): void {
Log.counter.warning++;
let flag = '%c WH %cWRN%c' + this.getTime() + '%c';
console.warn(flag, 'background:grey;color:white;', 'background:#ff9800;color:white;', 'color:grey;', '', ...o);
this.saveLogs(flag, ...o);
}
public static debug(): boolean {
let ret: boolean = true;
try {
let local = JSON.parse(localStorage.getItem('wh_trans_settings'));
if (local) ret = local['isDev'];
} catch {
this.error('debug错误')
}
return ret;
}
public static getTime(): string {
let d = new Date();
let year = d.getFullYear();
let month = ('0' + (d.getMonth() + 1)).slice(-2);
let date = ('0' + d.getDate()).slice(-2);
let hours = ('0' + d.getHours()).slice(-2);
let minutes = ('0' + d.getMinutes()).slice(-2);
let seconds = ('0' + d.getSeconds()).slice(-2);
let ms = ('00' + d.getMilliseconds()).slice(-3);
return `${ year }-${ month }-${ date } ${ hours }:${ minutes }:${ seconds }.${ ms }`;
}
public static getLogs() {
return this.logs;
}
private static saveLogs(...o) {
o.forEach(item => {
if (typeof item === 'string') this.logs += item.replaceAll('%c', '');
else if (item !== null && item !== undefined) {
let json = '{}';
let name = Object.getPrototypeOf(item).constructor.name;
try {
json = JSON.stringify(item);
} catch {
}
this.logs += ` [${ name }] [${ json }] `;
if (item.message) this.logs += '错误信息: ' + item.message;
if (item.stack) this.logs += '错误堆栈: ' + item.stack;
}
})
this.logs += '\r\n';
}
public static getCounter() {
return {
info: Log.counter.info,
error: Log.counter.error,
warning: Log.counter.warning,
}
}
}

View File

@ -1,52 +0,0 @@
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>;

View File

@ -1,35 +0,0 @@
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);
}
}

View File

@ -1,279 +0,0 @@
import cityFinder from "../func/module/cityFinder";
import { missionDict } from "../dictionary/translation";
import getTaskHint from "../func/translate/getTaskHint";
import CommonUtils from "./utils/CommonUtils";
import SHOP_BEER_STATIC_ITEM_HTML from "../../static/html/buyBeer/shop_beer_static_item.html";
import ADD_BEER_HEAD_HTML from "../../static/html/buyBeer/add_beer_head.html";
import QUICK_CRIMES_HTML from "../../static/html/quick_crimes.html";
import RW_RIDER_HTML from "../../static/html/rw_rider.html";
import christmasTownHelper from "../func/module/christmasTownHelper";
import LotteryHelper from "../feature/LotteryHelper";
import TornStyleBlock from "./utils/TornStyleBlock";
import PTHelper from "./action/PTHelper";
import StackHelper from "../feature/StackHelper";
import BuyBeerHelper from "../feature/BuyBeerHelper";
import XZMZ from "./action/XZMZ";
import ProfileHelper from "./action/ProfileHelper";
import SearchHelper from "./action/SearchHelper";
import TornStyleSwitch from "./utils/TornStyleSwitch";
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
*/
@Injectable()
@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 {
let href = window.location.href;
let modules = [];
// 捡垃圾助手
if (href.includes('city.php') && this.localConfigWrapper.config.cityFinder) {
let _base = new TornStyleBlock('芜湖助手').insert2Dom();
// let reloadSwitch = new TornStyleSwitch('解决一直转圈(加载中)的问题');
// reloadSwitch.getInput().checked = this.localConfigWrapper.config.SolveGoogleScriptPendingIssue;
// _base.append(reloadSwitch.getBase()).insert2Dom();
// reloadSwitch.getInput().addEventListener('change', () => {
// if (reloadSwitch.getInput().checked) window.location.replace(window.location.href);
// this.localConfigWrapper.config.SolveGoogleScriptPendingIssue = reloadSwitch.getInput().checked;
// // WuhuConfig.set('SolveGoogleScriptPendingIssue', reloadSwitch.getInput().checked, true);
// });
_base.append(document.createElement('br'));
cityFinder(_base);
}
// pt一键购买
if (href.includes('pmarket.php')) Container.factory(PTHelper);
// 叠e助手
if (href.includes('gym.php')) Container.factory(StackHelper);
// 寻找木桩
if (href.includes('item.php?temp=4')) {
let hasInit: boolean = false;
let handle = () => {
if (!hasInit && window.location.hash === '#xunzhaomuzhuang') {
Container.factory(XZMZ).init();
hasInit = true;
}
}
window.addEventListener('hashchange', handle);
handle();
}
// 啤酒店
if (href.includes('shops.php?step=bitsnbobs')) {
let block = new TornStyleBlock('啤酒助手').insert2Dom();
block.setContent(ADD_BEER_HEAD_HTML);
const msg_node = block.querySelector('#wh-msg');
// 加入啤酒
block.querySelector('button').addEventListener('click', e => {
let node = document.querySelector('ul.items-list');
if (!node) {
msg_node.innerHTML = '❌ 商品未加载完';
this.logger.error('商品未加载完');
return;
}
if (node.querySelector('span[id="180-name"]')) {
msg_node.innerHTML = '❌ 页面已经有啤酒了';
this.logger.warn('商店页面已有啤酒');
return;
}
const clear_node = node.querySelector('li.clear');
const beer = document.createElement('li');
beer.classList.add('torn-divider', 'divider-vertical');
beer.style.backgroundColor = '#c8c8c8';
beer.innerHTML = SHOP_BEER_STATIC_ITEM_HTML;
if (clear_node) clear_node.before(beer);
else node.append(beer);
(<HTMLInputElement>e.target).disabled = true;
msg_node.innerHTML = '添加成功';
});
// 监听啤酒购买
globVars.responseHandlers.push((...args: any[]) => this.buyBeerHelper.responseHandler.apply(this.buyBeerHelper, args));
}
// 快速crime TODO 重构、与翻译解藕
if (href.contains(/crimes\.php/) && this.localConfigWrapper.config.quickCrime) {
// iframe
if (self !== top) {
const isValidate = document.querySelector('h4#skip-to-content').innerText.toLowerCase().includes('validate');
CommonUtils.elementReady('#header-root').then(e => e.style.display = 'none');
CommonUtils.elementReady('#sidebarroot').then(e => e.style.display = 'none');
CommonUtils.elementReady('#chatRoot').then(e => e.style.display = 'none');
if (!isValidate) document.body.style.overflow = 'hidden';
CommonUtils.elementReady('.content-wrapper').then(e => {
e.style.margin = '0px';
e.style.position = 'absolute';
e.style.top = '-35px';
});
CommonUtils.elementReady('#go-to-top-btn button').then(e => e.style.display = 'none');
}
const element = document.querySelector('.content-wrapper');
const OB = new MutationObserver(() => {
OB.disconnect();
// titleTrans();
// contentTitleLinksTrans();
trans();
OB.observe(element, {
characterData: true,
attributes: true,
subtree: true,
childList: true
});
});
const trans = () => {
const dom = QUICK_CRIMES_HTML;
const hasInserted = element.querySelector('.wh-translate') !== null;
// const is_captcha = element.querySelector('div#tab-menu.captcha') !== null;
const $title = document.querySelector('div.content-title');
const $info = document.querySelector('.info-msg-cont');
// if (!hasInserted && !is_captcha) {
if (!hasInserted) {
if ($title) $title.insertAdjacentHTML('beforebegin', dom);
else if ($info) $info.insertAdjacentHTML('beforebegin', dom);
}
};
trans();
OB.observe(element, {
characterData: true,
attributes: true,
subtree: true,
childList: true
});
}
// 任务助手 TODO 重构、与翻译解藕
if (href.contains(/loader\.php\?sid=missions/) && this.localConfigWrapper.config.missionHint) {
const anchor = document.querySelector('.content-wrapper');
const OB = new MutationObserver(() => {
OB.disconnect();
// titleTrans();
// contentTitleLinksTrans();
trans();
OB.observe(anchor, {
characterData: true,
attributes: true,
subtree: true,
childList: true
});
});
const taskList = {};
const trans = () => {
$('ul#giver-tabs a.ui-tabs-anchor').each((i, e) => {
let $e = $(e);
if ($e.children().hasClass('mission-complete-icon')) {
taskList[i] = e.innerText.trim();
} else {
taskList[i] = $e.clone().children().remove().end().text().trim();
}
});
// 助手注入
$('div.max-height-fix.info').each((i, e) => {
let $e = $(e);
if ($e.find('.wh-translated').length !== 0) return;
$e.append(`<div class="wh-translated"><h6 style="color:green"><b>任务助手</b></h6><p>${ getTaskHint(taskList[i]) }</p></div>`);
});
// 任务目标
$('ul.tasks-list span.title-wrap').contents().each((i, e) => {
if (e.nodeType === 3) {
if (missionDict[e.nodeValue.trim()]) {
e.nodeValue = missionDict[e.nodeValue.trim()];
}
}
});
};
trans();
OB.observe(anchor, {
characterData: true,
attributes: true,
subtree: true,
childList: true
});
}
// 个人资料
if (href.includes('profiles.php?XID=')) Container.factory(ProfileHelper);
// 圣诞小镇
if (href.contains(/christmas_town\.php/) && new Date().getMonth() > 9) christmasTownHelper();
// rw雷达
if (href.includes('profiles.php?XID=0')) {
const utl = {
set: function (k, v) {
const obj = JSON.parse(localStorage['wh_rw_raider']) || {};
obj[k] = v;
localStorage['wh_rw_raider'] = JSON.stringify(obj);
},
get: function (k) {
const obj = JSON.parse(localStorage['wh_rw_raider']) || {};
return obj[k];
},
setFactionID: function (id) {
this.set('faction', id);
},
setRWFactionID: function (id) {
this.set('rw_faction', id);
},
getFactionID: async function (apikey) {
const response = await window.fetch('https://api.torn.com/faction/?selections=basic&key=' + apikey);
const res_obj = await response.json();
const faction_id = res_obj['ID'];
if (faction_id) {
this.setFactionID(faction_id);
return faction_id;
} else return -1;
},
getRWFactionID: function (apikey) {
},
};
const rw_raider = async function () {
if (href.includes('#rader')) {
CommonUtils.addStyle('div.content-title,div.info-msg-cont{display:none;}');
const wh_node = document.createElement('div');
wh_node.id = 'wh-rd-cont';
wh_node.innerHTML = RW_RIDER_HTML;
// 原页面完全加载
await CommonUtils.elementReady('div.msg[role="alert"]');
const t_cont = document.querySelector('div.content-wrapper');
// t
t_cont.append(wh_node);
}
};
addEventListener('hashchange', rw_raider);
rw_raider().then();
}
// 彩票助手
if (href.includes('loader.php?sid=lottery')) this.lotteryHelper.init();
// 老虎机助手
if (href.includes('loader.php?sid=slots')) this.slotsHelper.init();
// 搜索助手
if (href.includes('page.php?sid=UserList')) this.searchHelper.init();
}
}

View File

@ -1,465 +0,0 @@
import adHelper from "../func/module/adHelper";
import safeKeeper from "../func/module/safeKeeper";
import initMiniProf from "../func/utils/initMiniProf";
import CommonUtils from "./utils/CommonUtils";
import * as EVENTS from "../../static/json/event.json";
import * as FEST from "../../static/json/fest.json";
import Popup from "./utils/Popup";
import TravelItem from "../feature/TravelItem";
import ZHONG_MENU_HTML from "../../static/html/zhong/zhong_menu.html";
import ZHONG_UPDATE_HTML from "../../static/html/zhong/zhong_update.html";
import ZHONG_LOOT_HTML from "../../static/html/zhong/zhong_loot.html";
import Test from "../test/Test";
import Timer from "./utils/Timer";
import QuickFlyBtnHandler from "./handler/QuickFlyBtnHandler";
import NNB from "./handler/NNB";
import QuickLinksHandler from "./handler/QuickLinksHandler";
import ItemPriceWatcherHandler from "./handler/ItemPriceWatcherHandler";
// import ChangeLogHandler from "./handler/ChangeLogHandler";
import ItemPriceHandler from "./handler/ItemPriceHandler";
import SettingsHandler from "./handler/SettingsHandler";
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";
@Injectable()
@ClassName('ZhongIcon')
export default class ZhongIcon {
public static ZhongNode: MyHTMLElement = null;
private menuItemList: MenuItemConfig[] = null;
private cashView: HTMLElement = null;
public constructor(
private readonly commonUtils: CommonUtils,
private readonly localConfigWrapper: LocalConfigWrapper,
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() {
this.constructMenuList()
.insert2Dom()
.dragHandler();
this.logger.info('设置图标结束');
}
public updateCashView(content: string): void {
if (!this.cashView || !ZhongIcon.ZhongNode.contains(this.cashView)) {
this.cashView = document.createElement('div');
this.cashView.id = 'wh-cash-monitor';
ZhongIcon.ZhongNode.append(this.cashView);
}
this.cashView.innerText = content;
}
private static setPosition(x: number, y: number) {
if (!(x && y)) return;
if (x > 0 && x < document.documentElement.offsetWidth - 100) {
ZhongIcon.ZhongNode.style.left = x + "px";
}
if (y > 0 && y < document.documentElement.offsetHeight - 60) {
ZhongIcon.ZhongNode.style.top = y + "px";
}
}
/**
*
*/
private insert2Dom(): ZhongIcon {
let zhongNode: MyHTMLElement = document.querySelector('div#wh-trans-icon');
let version = globVars.version;
if ((self !== top) || !!zhongNode) return null;
zhongNode = document.createElement('div');
ZhongIcon.ZhongNode = zhongNode;
zhongNode.id = 'wh-trans-icon';
zhongNode.classList.add('cont-gray');
zhongNode.innerHTML = ZHONG_MENU_HTML.replace('{{}}', version.slice(-1) === '$' ? 'DEV' : version);
// 助手菜单
const menu_cont = zhongNode.querySelector('#wh-gSettings');
// 遍历菜单node设置、生成node、插入dom
this.menuItemList.forEach(setting => this.commonUtils.elemGenerator(setting, menu_cont));
this.logger.info('生成元素插入完成');
// 计时node
zhongNode.initTimer = zhongNode.querySelector('#wh-inittimer');
// 芜湖助手图标点击事件
(<MyHTMLElement>zhongNode.querySelector('#wh-trans-icon-btn')).onclick = () => {
zhongNode.classList.toggle('wh-icon-expanded');
const click_func = e => {
this.logger.info(e.target);
if (e.target === zhongNode.querySelector('#wh-trans-icon-btn')) return;
if (!zhongNode.contains(e.target)) {
this.logger.info('移除事件监听器');
document.body.removeEventListener('click', click_func);
zhongNode.classList.remove('wh-icon-expanded');
}
};
if (zhongNode.classList.contains('wh-icon-expanded')) {
this.logger.info('芜湖助手图标点击->添加监听');
document.body.addEventListener('click', click_func);
} else {
this.logger.info('芜湖助手图标->移除监听');
document.body.removeEventListener('click', click_func);
}
};
// 更新按钮点击事件
(<MyHTMLElement>zhongNode.querySelector('#wh-update-btn')).onclick = e => {
(<HTMLButtonElement>e.target).blur();
// 直接复制的按钮
new Popup(ZHONG_UPDATE_HTML, '如何更新')
.element
.querySelector('button').onclick = async (e) => {
let target = e.target as HTMLButtonElement;
target.innerHTML = '加载中';
const js_text = await CommonUtils.COFetch(`https://jjins.github.io/fyfuzhi/release.min.user.js?${ performance.now() }`);
target.innerHTML = '点击复制到剪切板';
target.onclick = () => {
const textarea_node = document.createElement('textarea');
textarea_node.innerHTML = js_text;
target.parentElement.append(textarea_node);
textarea_node.focus();
textarea_node.select();
document.execCommand('Copy');
textarea_node.remove();
target.innerHTML = '已复制';
target.onclick = null;
this.msgWrapper.create('脚本已复制,请前往粘贴');
};
};
};
// 节日
zhongNode.querySelectorAll('#wh-trans-fest-date button').forEach((el, i) => i === 0
? el.addEventListener('click', () => {
let html = '<table>';
// TODO 动态节日数据
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>', '节日');
})
: el.addEventListener('click', null));
// 活动
zhongNode.querySelectorAll('#wh-trans-event-cont button').forEach((el, i) => i === 0
? el.addEventListener('click', () => {
let html = '<table>';
// 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>`);
new Popup(html += '</table><p>更多信息请关注群聊和公众号</p>', '活动');
})
: el.addEventListener('click', null));
// 调整图标至有记录的位置
if (this.localConfigWrapper.config.SaveIconPosition) {
let iconPosition = this.localConfigWrapper.config.IconPosition;
let documentSize = { x: document.documentElement.offsetWidth, y: document.documentElement.offsetHeight };
ZhongIcon.setPosition(
iconPosition.x > documentSize.x ? documentSize.x * 0.9 | 0 : iconPosition.x,
iconPosition.y > documentSize.y ? documentSize.y * 0.9 | 0 : iconPosition.y
);
}
document.body.append(zhongNode);
// 引入torn自带浮动提示
this.logger.info('引入torn浮动提示');
(window.initializeTooltip) && (window.initializeTooltip('.wh-container', 'white-tooltip'));
// 加载torn mini profile
this.logger.info('加载torn mini profile');
let miniProfileInterval = {
id: window.setInterval(() => {
miniProfileInterval.counter++;
if (window.$ || (window.unsafeWindow && window.unsafeWindow.$)) {
initMiniProf('#wh-trans-icon');
window.clearInterval(miniProfileInterval.id);
}
if (miniProfileInterval.counter > 30) window.clearInterval(miniProfileInterval.id);
}, 1000),
counter: 0
};
this.logger.info('图标加入文档树');
return this;
}
private dragHandler(): ZhongIcon {
let isMouseDown = false;
let isMouseMoved = false;
let offsetXY = { x: 0, y: 0 };
ZhongIcon.ZhongNode.addEventListener('mousedown', (e) => {
if (e.button === 0) {
e.preventDefault();
isMouseDown = true;
let nodeXY = ZhongIcon.getPosition();
offsetXY.x = e.x - nodeXY.x;
offsetXY.y = e.y - nodeXY.y;
}
});
document.addEventListener('mouseup', () => {
isMouseDown = false;
if (isMouseMoved) {
isMouseMoved = false;
if (this.localConfigWrapper.config.SaveIconPosition) {
this.localConfigWrapper.config.IconPosition = ZhongIcon.getPosition();
}
}
});
document.addEventListener('mousemove', (e) => {
if (isMouseDown) {
ZhongIcon.setPosition(e.x - offsetXY.x, e.y - offsetXY.y);
isMouseMoved = true;
}
});
return this;
}
private static getPosition(): { x: number, y: number } {
return {
x: ZhongIcon.ZhongNode.style.left ? parseInt(ZhongIcon.ZhongNode.style.left.slice(0, -2)) : ZhongIcon.ZhongNode.offsetLeft,
y: ZhongIcon.ZhongNode.style.top ? parseInt(ZhongIcon.ZhongNode.style.top.slice(0, -2)) : ZhongIcon.ZhongNode.offsetTop
}
}
// 菜单
private constructMenuList(): ZhongIcon {
this.logger.info('构造菜单列表开始');
let timer = new Timer();
const date = new Date();
let userInfo = this.infoUtils.getPlayerInfo();
let list: MenuItemConfig[] = [];
// 欢迎 显示玩家id
if (userInfo.userID !== 0) {
list.push({
domType: 'plain',
domId: 'wh-trans-welcome',
domHTML:
`<a href="/profiles.php?XID=${ userInfo.userID }" target="_blank">${ userInfo.playername }</a>[${ userInfo.userID }]`,
});
}
// 节日
let fest_date_html = '<button>节日</button>: ';
{
// 节日字典
const dict = FEST.val;
// list.fest_date_dict = dict;
// list.fest_date_list = Object.keys(dict);
const formatMMDD = (m, d) => {
const MM = m < 10 ? `0${ m }` : m.toString();
const DD = d < 10 ? `0${ d }` : d.toString();
return MM + DD;
}
const fest_date_key = formatMMDD(date.getUTCMonth(), date.getUTCDate());
if (dict[fest_date_key]) fest_date_html += `今天 - ${ dict[fest_date_key]['name'] }(<button title="${ dict[fest_date_key]['eff'] }">效果</button>)`;
else {
// 月日列表
let list = Object.keys(dict);
list.push(fest_date_key);
// 下个节日的位置
const index: number = list.sort().indexOf(fest_date_key) + 1;
// 下个节日obj
const next_fest_date = dict[list[index] || list[0]];
// 下个节日的时间
let next = new Date(
index !== list.length ? date.getUTCFullYear() : date.getUTCFullYear() + 1,
(list[index !== list.length ? index : 0] as any).slice(0, 2) | 0,
(list[index !== list.length ? index : 0] as any).slice(2) | 0,
8
).getTime();
// 剩余天数
const left = (next - date.getTime()) / 86400000 | 0;
fest_date_html += `${ left }天后 - ${ next_fest_date.name }(<button title="${ next_fest_date.eff }">效果</button>)`;
}
}
list.push({
domType: 'plain',
domId: 'wh-trans-fest-date',
domHTML: fest_date_html,
});
// 活动
let eventObj: EventWrapper = {
onEv: false,
daysLeft: Infinity,
events: EVENTS.default,
};
list.events = EVENTS.default;
eventObj.events.forEach((obj, index) => {
if (eventObj.onEv) return;
// 当前年份
const nowYear = date.getFullYear();
// 当前遍历的活动开始时间
const start = new Date(nowYear, obj.start[0], obj.start[1], obj.start[2]);
// 当前遍历的活动结束时间
const end = new Date(nowYear, obj.end[0], obj.end[1], obj.end[2]);
// 当前处于活动中
if (start < date && date < end) {
eventObj.onEv = true;
eventObj.daysLeft = (end.getTime() - date.getTime()) / 86400000 | 0;
eventObj.current = obj;
}
// 当前没有活动
else {
// 当前遍历的活动如果已经经过了,那么下次活动就是遍历的下一个活动对象,否则为当前活动。
// 如果本年度活动都经过了,那么下次活动是列表的第一个活动对象
const next = end < date ? eventObj.events[index + 1] || eventObj.events[0] : obj;
// 经过了最后一个活动所以下次活动开始时间是第二年
const start = new Date(next !== obj && index === eventObj.events.length - 1 ? nowYear + 1 : nowYear, next.start[0], next.start[1], next.start[2]);
const daysLeft = (start.getTime() - date.getTime()) / 86400000 | 0;
if (0 <= daysLeft && daysLeft < eventObj.daysLeft) {
eventObj.daysLeft = daysLeft;
eventObj.next = next;
}
}
});
eventObj.html = '<button>活动</button>: ';
eventObj.onEv
? eventObj.html += `${ eventObj.current.name }(<button title="${ eventObj.current.eff }">详情</button>) - 剩余${ eventObj.daysLeft }`
: eventObj.html += `${ eventObj.daysLeft }天后 - ${ eventObj.next.name }(<button title="${ eventObj.next.eff }">详情</button>)`;
list.push({
domType: 'plain',
domId: 'wh-trans-event-cont',
domHTML: eventObj.html,
});
// 一键起飞
list.push({
domType: 'button',
domId: 'wh-quick-fly-btn',
domText: '✈️ 一键起飞',
clickFunc: () => Container.factory(QuickFlyBtnHandler).handle(),
});
// 飞花库存
list.push({
domType: 'button',
domId: 'wh-foreign-stock-btn',
domText: '🌸 飞花库存',
clickFunc: () => Container.factory(TravelItem).clickHandler().then(),
});
// NPC LOOT
list.push({
domType: 'button',
domId: 'wh-npc-loot-btn',
domText: '🔫 LOOT',
clickFunc: () => {
const insert = ZHONG_LOOT_HTML.replace('{{}}', performance.now().toString());
new Popup(insert, 'NPC LOOT');
},
tip: '显示5个可击杀NPC的开打时间',
});
// 查看NNB
list.push({
domType: 'button',
domId: 'wh-nnb-info',
domText: '👮‍ 查看NNB',
clickFunc: () => this.nnb.handle(),
});
// 常用链接
list.push({
domType: 'button',
domId: 'wh-link-collection',
domText: '🔗 常用链接',
clickFunc: () => Container.factory(QuickLinksHandler).handle()
});
// 飞贼
// list.push({
// domType: 'button',
// domId: 'wh-gs-btn',
// domText: '🐏 飞贼小助手',
// clickFunc: () => loadGS(CommonUtils.getScriptEngine()),
// tip: '加载从PC端移植的伞佬的油猴版飞贼小助手',
// });
// 物品价格监视
list.push({
domType: 'button',
domId: 'wh-price-watcher-btn',
domText: '💊 价格监视',
clickFunc: () => this.itemPriceWatcherHandler.handle()
});
// 全屏
if (!this.tornPDAUtils.isPDA()) list.push({
domType: 'button', domId: '', domText: '🖥️ 进入全屏', clickFunc() {
document.documentElement.requestFullscreen().then();
}
});
// 传单助手
list.push({
domType: 'button',
domId: '',
domText: '📜️ 传单助手',
clickFunc: adHelper
});
// 守望者
list.push({
domType: 'button',
domId: '',
domText: '🛡️ 守望者',
clickFunc: function () {
safeKeeper();
},
});
// 寻找木桩
list.push({
domType: 'button',
domId: '',
domText: '🌲 寻找木桩',
clickFunc() {
window.location.replace('https://www.torn.com/item.php?temp=4#xunzhaomuzhuang')
}
});
// 物品查价
list.push(ItemPriceHandler);
// 更新历史
// list.push(ChangeLogHandler);
// 助手设置
list.push(SettingsHandler);
// 测试
if (this.logger.debug()) list.push(Test);
this.menuItemList = list;
this.logger.info('构造展开菜单列表结束' + timer.getTimeMs());
return this;
}
}
export interface MenuItemConfig {
domType: 'button' | 'plain' | 'checkbox' | 'select' | MENU_ITEM_TYPE;
tagName?: string;
domId?: string;
domText?: string;
clickFunc?: (ev?) => void;
domHTML?: string;
tip?: string;
dictName?: string;
changeEv?: (ev) => void;
domSelectOpt?: { domVal: string, domText: string }[];
/**
*
* @deprecated
*/
isHide?: boolean;
isTornBtn?: boolean;
}
interface EventWrapper {
onEv: boolean;
daysLeft: number;
events: Event[];
current?: Event;
next?: Event;
html?: string;
}
interface Event {
start: number[];
end: number[];
name: string;
eff: string;
}

View File

@ -1,352 +0,0 @@
// 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('盯梢关闭');
// }
// });
// }
// }

View File

@ -1 +0,0 @@
export default {};

View File

@ -1,75 +0,0 @@
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);
}
}
}

View File

@ -1,91 +0,0 @@
import TornStyleBlock from "../utils/TornStyleBlock";
import TornStyleSwitch from "../utils/TornStyleSwitch";
import { Injectable } from "../../container/Injectable";
import ClassName from "../../container/ClassName";
import LocalConfigWrapper from "../LocalConfigWrapper";
import IFeature from "../../man/IFeature";
import MsgWrapper from "../utils/MsgWrapper";
@Injectable()
@ClassName('PTHelper')
export default class PTHelper implements IFeature {
private observer: MutationObserver;
private usersPointSell: HTMLDivElement;
constructor(
private readonly localConfigWrapper: LocalConfigWrapper,
private readonly msgWrapper: MsgWrapper,
) {
}
description(): string {
return "pt一键购买";
}
iStart(): void | Promise<void> {
this.start()
}
urlExcludes(): RegExp[] {
return [];
}
urlIncludes(): RegExp[] {
return [/pmarket\.php/];
}
start() {
this.observer = new MutationObserver(e => {
for (const t of e) {
t.addedNodes.forEach(e => 'LI' === (e as HTMLElement).tagName && this.removeConfirm(e))
}
});
this.usersPointSell = document.querySelector<HTMLDivElement>('.users-point-sell');
let block = new TornStyleBlock('PT一键购买').insert2Dom();
let switcher = new TornStyleSwitch('开启');
block.append(switcher.getBase());
let toggle = switcher.getInput();
toggle.checked = this.localConfigWrapper.config.ptQuickBuy;
if (toggle.checked) {
this.msgWrapper.create('一键购买已开启');
for (const index in this.usersPointSell.children) {
'LI' === this.usersPointSell.children[index].tagName && this.removeConfirm(this.usersPointSell.children[index])
}
this.observer.observe(this.usersPointSell, { childList: true })
}
toggle.addEventListener('change', () => {
this.localConfigWrapper.config.ptQuickBuy = toggle.checked;
if (toggle.checked) {
for (const index in this.usersPointSell.children) {
'LI' === this.usersPointSell.children[index].tagName && this.removeConfirm(this.usersPointSell.children[index])
}
this.observer.observe(this.usersPointSell, { childList: true });
this.msgWrapper.create('一键购买已开启');
} else {
for (const index in this.usersPointSell.children) {
'LI' === this.usersPointSell.children[index].tagName && this.rollbackConfirm(this.usersPointSell.children[index])
}
this.observer.disconnect();
this.msgWrapper.create('一键购买已关闭');
}
});
}
private removeConfirm(elem): void {
let el = elem.firstElementChild;
el.classList.add('yes');
let old_href = el.getAttribute('href');
let new_href = old_href.replace(/=buy/, '=buy1').replace(/&points=\d{1,9}$/, '');
el.setAttribute('href', new_href);
}
private rollbackConfirm(elem): void {
let el = elem.firstElementChild;
el.classList.remove('yes');
let old_href = el.getAttribute('href');
let new_href = old_href.replace(/=buy1/, '=buy');
el.setAttribute('href', new_href);
}
}

View File

@ -1,151 +0,0 @@
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;
}
}
}

View File

@ -1,46 +0,0 @@
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>;

Some files were not shown because too many files have changed in this diff Show More