This commit is contained in:
Liwanyi 2022-11-03 16:34:58 +08:00
parent 0b6c2cda4f
commit f5e4a5cfe3
29 changed files with 1481 additions and 706 deletions

View File

@ -4,6 +4,18 @@
# CHANGE # CHANGE
## 0.6.7
2022年11月3日
### 修改
- 重做光速跑路(需要更多测试)
### 添加
- 战斗-盯梢模式
## 0.6.6 ## 0.6.6
2022年10月31日 2022年10月31日

View File

@ -1,6 +1,6 @@
{ {
"name": "wuhu-torn-helper", "name": "wuhu-torn-helper",
"version": "0.6.6", "version": "0.6.7",
"description": "芜湖助手", "description": "芜湖助手",
"dependencies": {}, "dependencies": {},
"scripts": { "scripts": {

File diff suppressed because one or more lines are too long

View File

@ -5,7 +5,6 @@ import { Common } from "./Common";
import UrlPattern from "./UrlMatch"; import UrlPattern from "./UrlMatch";
import WuhuConfig from "./WuhuConfig"; import WuhuConfig from "./WuhuConfig";
import translateMain from "../func/translate/translateMain"; import translateMain from "../func/translate/translateMain";
import Global from "./Global";
import CommonUtils from "./utils/CommonUtils"; import CommonUtils from "./utils/CommonUtils";
export default class Application { export default class Application {
@ -22,11 +21,7 @@ export default class Application {
// 插件图标和设置菜单 // 插件图标和设置菜单
ZhongIcon.getInstance(); ZhongIcon.getInstance();
// TODO 临时关闭光速跑路 let tmp = () => {
WuhuConfig.set('quickFinishAtt', 3);
// TODO 临时检测jquery
if (typeof $ === "function") {
// 所有页面通用 // 所有页面通用
Common.getInstance().resolve(); Common.getInstance().resolve();
@ -34,18 +29,13 @@ export default class Application {
UrlPattern.getInstance().resolve(); UrlPattern.getInstance().resolve();
// 翻译 // 翻译
if (WuhuConfig.get('transEnable')) translateMain(Global.getInstance().href); if (WuhuConfig.get('transEnable')) translateMain(window.location.href);
};
// TODO 临时检测jquery
if (typeof $ === "function") {
tmp();
} else { } else {
CommonUtils.getInstance().jQueryReady().then(() => { CommonUtils.getInstance().jQueryReady().then(() => tmp());
// 所有页面通用
Common.getInstance().resolve();
// URL匹配
UrlPattern.getInstance().resolve();
// 翻译
if (WuhuConfig.get('transEnable')) translateMain(Global.getInstance().href);
});
} }
} }
} }

View File

@ -1,11 +1,11 @@
import depoHelper from "../func/module/depoHelper"; import depoHelper from "../func/module/depoHelper";
import travelHelper from "../func/module/travelHelper"; import travelHelper from "../func/module/travelHelper";
import attackHelper from "../func/module/attackHelper";
import priceWatcherHandle from "../func/module/priceWatcherHandle"; import priceWatcherHandle from "../func/module/priceWatcherHandle";
import WuhuBase from "./WuhuBase"; import WuhuBase from "./WuhuBase";
import WuhuConfig from "./WuhuConfig"; import WuhuConfig from "./WuhuConfig";
import CommonUtils from "./utils/CommonUtils"; import CommonUtils from "./utils/CommonUtils";
import CompanyHelper from "./action/CompanyHelper"; import CompanyHelper from "./action/CompanyHelper";
import AttackHelper from "./action/AttackHelper";
export class Common extends WuhuBase { export class Common extends WuhuBase {
className = 'Common'; className = 'Common';
@ -79,7 +79,8 @@ export class Common extends WuhuBase {
travelHelper().then(); travelHelper().then();
// 战斗相关 // 战斗相关
attackHelper().then(); // attackHelper().then();
AttackHelper.getInstance();
// 公司助手 // 公司助手
CompanyHelper.getInstance(); CompanyHelper.getInstance();

View File

@ -40,8 +40,8 @@ export default class Global extends WuhuBase implements IGlobal {
bodyAttrs: { bodyAttrs: {
'data-country'?: string; 'data-country'?: string;
'data-celebration'?: string; 'data-celebration'?: string;
'data-traveling'?: string; 'data-traveling'?: 'true' | 'false';
'data-abroad'?: string; 'data-abroad'?: 'true' | 'false';
} = null; } = null;
constructor() { constructor() {

View File

@ -29,13 +29,11 @@ export default class Log {
} }
public static debug(): boolean { public static debug(): boolean {
let ret: boolean; let ret: boolean = true;
try { try {
let local = JSON.parse(localStorage.getItem('wh_trans_settings')); let local = JSON.parse(localStorage.getItem('wh_trans_settings'));
if (local) ret = local['isDev']; if (local) ret = local['isDev'];
else ret = false;
} catch { } catch {
ret = false;
} }
return ret; return ret;
} }

View File

@ -11,14 +11,15 @@ export default class WuhuBase extends Provider {
* localStorage wh_trans_settings (json) * localStorage wh_trans_settings (json)
*/ */
public static getLocal(): IWHSettings { public static getLocal(): IWHSettings {
let localObject = {}; let localObject;
let localItem = localStorage.getItem('wh_trans_settings') || '{}';
try { try {
localObject = JSON.parse(localStorage.getItem('wh_trans_settings')); localObject = JSON.parse(localItem);
} catch (e) { } catch (e) {
Log.error('解析localStorage对象出错', e); Log.error('解析localStorage对象出错', e);
localStorage.setItem('wh_trans_settings', '{}'); localStorage.setItem('wh_trans_settings', '{}');
} }
return localObject; return localObject || {};
} }
public static conditionInterrupt() { public static conditionInterrupt() {

View File

@ -11,8 +11,9 @@ export default class WuhuConfig extends WuhuBase {
*/ */
public static get(key: string | string[]) { public static get(key: string | string[]) {
let localPool = this.getLocal(); let localPool = this.getLocal();
if (typeof key === 'string') return localPool[key]; if (typeof key === 'string') {
else { return localPool[key];
} else {
let ret: string[] = []; let ret: string[] = [];
key.forEach(k => { key.forEach(k => {
ret.push(localPool[k]) ret.push(localPool[k])
@ -106,6 +107,8 @@ export default class WuhuConfig extends WuhuBase {
{ key: 'HideProfileImg', val: false }, { key: 'HideProfileImg', val: false },
// 显示曾用名 // 显示曾用名
{ key: 'ShowNameHistory', val: true }, { key: 'ShowNameHistory', val: true },
// 盯梢模式强度 0-550 1-950 2-1450 ms
{ key: 'WatchTargetFreq', val: 1 },
// 危险行为⚠️ // 危险行为⚠️
{ key: 'dangerZone', val: false }, { key: 'dangerZone', val: false },

View File

@ -77,10 +77,10 @@ export default class ZhongIcon extends WuhuBase {
} }
}; };
if (zhongNode.classList.contains('wh-icon-expanded')) { if (zhongNode.classList.contains('wh-icon-expanded')) {
Log.info('添加事件监听'); Log.info('芜湖助手图标点击->添加监听');
document.body.addEventListener('click', click_func); document.body.addEventListener('click', click_func);
} else { } else {
Log.info('移除事件监听'); Log.info('芜湖助手图标->移除监听');
document.body.removeEventListener('click', click_func); document.body.removeEventListener('click', click_func);
} }
}; };

View File

@ -0,0 +1,328 @@
import WuhuBase from "../WuhuBase";
import WuhuConfig from "../WuhuConfig";
import CommonUtils from "../utils/CommonUtils";
import Log from "../Log";
import Alert from "../utils/Alert";
import Global from "../Global";
import Device from "../../enum/Device";
import ATTACK_HELPER_CSS from "../../static/css/attack_helper.css";
import ActionButtonUtils from "../utils/ActionButtonUtils";
import TornStyleBlock from "../utils/TornStyleBlock";
import TornStyleSwitch from "../utils/TornStyleSwitch";
import DialogMsgBox from "../utils/DialogMsgBox";
import FetchUtils from "../utils/FetchUtils";
import MathUtils from "../utils/MathUtils";
import LoopHelper from "../utils/LoopHelper";
import TRAVEL_STATE from "../../enum/TravelState";
enum FIGHT_STAGE {
READY = 'ready',
IN_PROGRESS_OR_ERROR = 'in_progress_or_error',
FINISHED = 'finished',
END = 'end',
OTHER = 'other'
}
/**
*
*/
export default class AttackHelper extends WuhuBase {
className = 'AttackHelper';
private currentStage: FIGHT_STAGE = FIGHT_STAGE.OTHER;
constructor() {
super();
window.setTimeout(() => this.urlMatch(), 0);
}
private urlMatch(): void {
if (window.location.href.contains(/loader\.php\?sid=attack/)) {
this.fightingPageHandle();
}
// 错误的攻击页面转跳
else if (window.location.href.includes('loader2.php') && WuhuConfig.get('attRelocate')) {
const spl = window.location.href.trim().split('=');
const uid = spl[spl.length - 1];
if (CommonUtils.getInstance().isValidUid(uid)) {
window.location.href = 'https://www.torn.com/loader.php?sid=attack&user2ID=' + uid;
} else {
Log.error('[AttackHelper] UID格式不正确');
}
}
}
private fightingPageHandle(): void {
// 光速刷新按钮
ActionButtonUtils.getInstance().add('光速刷新', () => this.doAttackReload());
// 盯梢
this.watchTarget();
new MutationObserver((_, observer) => {
let btnList = document.querySelectorAll('div[class^="dialogButtons___"] button') as NodeListOf<HTMLButtonElement>;
if (btnList.length === 0) {
// 错误或正在打
this.currentStage = FIGHT_STAGE.IN_PROGRESS_OR_ERROR;
Log.info('[attackHelper] currentStage', this.currentStage);
return;
}
btnList.forEach(btn => {
if (btn.innerText.toLowerCase().includes('start')) {
// 开始
this.quickStartFight();
} else if (btn.innerText.toLowerCase().includes('continue')) {
// 结束end
this.currentStage = FIGHT_STAGE.END;
observer.disconnect();
} else if (btn.innerText.toLowerCase().includes('leave')) {
// 无意识状态FINISHED
this.quickFinishFight(btnList);
}
Log.info('[attackHelper] currentStage', this.currentStage);
})
})
.observe(document.querySelector('#react-root'), { childList: true, subtree: true });
}
// 战斗页面快速刷新
private doAttackReload(): void {
if (!window.ReactDOM) {
new Alert('光速刷新失败未找到React对象');
Log.error('光速刷新失败未找到React对象');
return;
}
if (!document.querySelector('#react-root').querySelector('#attacker')) return;
let script = document.querySelector('script[src*="/builds/attack/"]');
let url = script.src;
if (!url.contains('app.js')) 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 (WuhuConfig.get('quickAttIndex') === 6) return;
/**
* pc #defender
* mobile #attacker
*/
const btn = <HTMLInputElement>(document.querySelector('#attacker button') || document.querySelector('#defender button'));
Log.info('操作按钮', { btn });
if (!btn.innerText.toLowerCase().includes('fight')) {
Log.info('未找到攻击按钮, 光速拔刀跳过');
new Alert('未找到攻击按钮, 光速拔刀跳过');
} else {
// 判断是否存在脚踢
const hasKick = !!document.querySelector('#weapon_boots');
// modal层
// const modal: HTMLElement = document.querySelector('div[class^="modal___"]');
let device = Global.getInstance().device;
Log.info(`当前设备类型是${ device }`);
// 区分设备
switch (device) {
case Device.PC: {
Log.info(`开始调整按钮位置`);
// 隐藏modal层
// modal.style.display = 'none';
// 根据选择的武器调整css
let css_top = '0';
switch (WuhuConfig.get('quickAttIndex')) {
// weapon_second
case 1: {
css_top = '97px';
break;
}
// weapon_melee
case 2: {
css_top = '194px';
break;
}
// weapon_temp
case 3: {
css_top = '291px';
break;
}
// weapon_fists
case 4:
// weapon_boots
case 5: {
css_top = '375px';
break;
}
}
CommonUtils.addStyle(ATTACK_HELPER_CSS);
CommonUtils.addStyle(`.wh-move-btn #defender div[class^="modal___"]{top: ${ css_top };}`);
document.body.classList.add('wh-move-btn');
break;
}
case Device.MOBILE: {
Log.info(`开始调整按钮位置`);
// 加入css
let css_top = '0';
let slot_height = '76px';
// 判断有没有脚踢
if (hasKick) {
// 根据选择的武器调整
switch (WuhuConfig.get('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 (WuhuConfig.get('quickAttIndex')) {
case 1: { // weapon_second
css_top = `${ height }px`;
break;
}
case 2: { // weapon_melee
css_top = `${ height * 2 }px`;
break;
}
case 3: { // weapon_temp
css_top = `${ height * 3 }px`;
break;
}
case 4: { // weapon_fists
css_top = `${ height * 4 }px`;
break;
}
case 5: { // weapon_boots
css_top = `${ height * 5 }px`;
break;
}
}
}
const css_rule = ATTACK_HELPER_CSS.replace('CSSVAR', css_top).replace('CSSVAR', slot_height);
// `
// .wh-move-btn #attacker div[class^="modal___"]{display: block;width: 0;top: ${ css_top };left:0;height:0;}
// .wh-move-btn #attacker div[class^="dialog___"]{border:0;width:80px;height:${ slot_height };}
// .wh-move-btn #attacker div[class^="colored___"]{display:block;padding:0;}
// .wh-move-btn #attacker div[class^="title___"]{height:0;}
// .wh-move-btn #attacker button{width:100%;margin:0;height:63px;white-space:normal;}
// `;
CommonUtils.addStyle(css_rule);
document.body.classList.toggle('wh-move-btn');
btn.onclick = () => {
if (WuhuConfig.get('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 (WuhuConfig.get('quickFinishAtt') === 3) return;
const user_btn_select = ['leave', 'mug', 'hosp'][WuhuConfig.get('quickFinishAtt')];
// const wrap = document.querySelector('#react-root');
Log.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);
Log.info('按钮内容:', btn.innerText, ',是否包含选中:', flag);
if (!flag) btn.style.display = 'none';
});
}
// 盯梢模式
private watchTarget(): void {
Log.info('获取目标id');
let targetId = window.location.href.split('user2ID=')[1];
if (!CommonUtils.getInstance().isValidUid(targetId)) {
Log.error('目标id获取错误', targetId);
throw new Error('目标id获取错误:' + targetId);
}
let loop = new LoopHelper(async () => {
let userProfile;
try {
userProfile = await FetchUtils.getInstance().getProfile(targetId);
} catch {
Log.error('盯梢模式无法获取目标id');
throw new Error('盯梢模式无法获取目标id');
}
await CommonUtils.getInstance().sleep(MathUtils.getInstance().getRandomInt(20, 50));
if ((userProfile.userStatus.status === 'ok' && CommonUtils.getInstance().getTravelStage() === TRAVEL_STATE.IN_TORN) ||
(userProfile.userStatus.status === 'abroad' && CommonUtils.getInstance().getTravelStage() === TRAVEL_STATE.ABROAD)) {
watchSwitch.getInput().checked = false;
window.setTimeout(async () => {
new Alert('目标已落地/出院/出狱!', { timeout: 10, force: true, sysNotify: true });
await CommonUtils.getInstance().audioPlay();
await CommonUtils.getInstance().sleep(300);
await CommonUtils.getInstance().audioPlay();
await CommonUtils.getInstance().sleep(300);
await CommonUtils.getInstance().audioPlay();
await CommonUtils.getInstance().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 (CommonUtils.getInstance().getTravelStage() === TRAVEL_STATE.FLYING) {
new Alert('失败!已取消');
watchSwitch.getInput().checked = false;
return;
}
Log.info('盯梢开启, 目标id' + targetId);
loop.start(parseInt(WuhuConfig.get('WatchTargetFreq')));
},
cancel: () => watchSwitch.getInput().checked = false
});
} else {
loop.stop();
Log.info('盯梢关闭');
}
});
}
}

View File

@ -5,6 +5,7 @@ import MathUtils from "../utils/MathUtils";
import CommonUtils from "../utils/CommonUtils"; import CommonUtils from "../utils/CommonUtils";
import TornStyleBlock from "../utils/TornStyleBlock"; import TornStyleBlock from "../utils/TornStyleBlock";
import Timer from "../utils/Timer"; import Timer from "../utils/Timer";
import FetchUtils from "../utils/FetchUtils";
export default class LotteryHelper extends WuhuBase { export default class LotteryHelper extends WuhuBase {
className = 'LotteryHelper'; className = 'LotteryHelper';
@ -132,7 +133,7 @@ export default class LotteryHelper extends WuhuBase {
rsMsg = `终止操作,已完成${ i }/${ inputNumber }`; rsMsg = `终止操作,已完成${ i }/${ inputNumber }`;
break; break;
} }
await CommonUtils.ajaxFetch({ await FetchUtils.getInstance().ajaxFetch({
url: window.addRFC('https://www.torn.com/loader.php?sid=lotteryPlay&step=buyTicket&lotteryID=' + lotteryType), url: window.addRFC('https://www.torn.com/loader.php?sid=lotteryPlay&step=buyTicket&lotteryID=' + lotteryType),
method: 'GET', method: 'GET',
referrer: '/loader.php?sid=lottery', referrer: '/loader.php?sid=lottery',

View File

@ -4,6 +4,7 @@ import WuhuConfig from "../WuhuConfig";
import CommonUtils from "../utils/CommonUtils"; import CommonUtils from "../utils/CommonUtils";
import TornStyleBlock from "../utils/TornStyleBlock"; import TornStyleBlock from "../utils/TornStyleBlock";
import TornStyleSwitch from "../utils/TornStyleSwitch"; import TornStyleSwitch from "../utils/TornStyleSwitch";
import FetchUtils from "../utils/FetchUtils";
export default class ProfileHelper extends WuhuBase { export default class ProfileHelper extends WuhuBase {
className = 'ProfileHelper'; className = 'ProfileHelper';
@ -13,7 +14,7 @@ export default class ProfileHelper extends WuhuBase {
CommonUtils.addStyle('body.wh-hide_profile_img .profile-image a.profile-image-wrapper .img-wrap img{display:none;}'); 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 = document.querySelector('link[rel="canonical"]').getAttribute('href').split('=')[1];
// id获取格式判断 // id获取格式判断
if (!/^[0-9]{1,7}$/.test(id)) { if (!CommonUtils.getInstance().isValidUid(id)) {
Log.error('[ProfileHelper] id格式错误'); Log.error('[ProfileHelper] id格式错误');
} }
if (WuhuConfig.get('HideProfileImg')) { if (WuhuConfig.get('HideProfileImg')) {
@ -34,18 +35,13 @@ export default class ProfileHelper extends WuhuBase {
nameHistoryNode = document.createElement('p'); nameHistoryNode = document.createElement('p');
nameHistoryNode.innerHTML = '曾用名:'; nameHistoryNode.innerHTML = '曾用名:';
block.append(nameHistoryNode); block.append(nameHistoryNode);
CommonUtils.ajaxFetch({ FetchUtils.getInstance().getProfile(id).then((res) => {
url: window.addRFC('https://www.torn.com/profiles.php?step=getProfileData&XID=' + id), if (res.userInformation.previousAliases.length > 0) {
method: 'GET' res.userInformation.previousAliases.forEach(item => nameHistoryNode.innerHTML += item + ' ');
}).then((o) => { } else {
o.json().then((res) => { nameHistoryNode.innerHTML += '暂无';
if (res.userInformation.previousAliases.length > 0) { }
res.userInformation.previousAliases.forEach(item => nameHistoryNode.innerHTML += item + ' '); });
} else {
nameHistoryNode.innerHTML += '暂无';
}
}).catch(e => Log.error('[ProfileHelper] 错误: ', e.message, '错误堆栈: ', e.stack));
}).catch(e => Log.error('[ProfileHelper] 错误: ', e.message, '错误堆栈: ', e.stack));
} }
} }
} }

View File

@ -1,11 +1,11 @@
import WuhuBase from "../WuhuBase"; import WuhuBase from "../WuhuBase";
import XUNZHAOMUZHUANG_HTML from "../../static/html/xunzhaomuzhuang/index.html"; import XUNZHAOMUZHUANG_HTML from "../../static/html/xunzhaomuzhuang/index.html";
import * as MUZHUANG_ID_LIST_JSON from "../../static/json/muzhuang_id_list.json"; import * as MUZHUANG_ID_LIST_JSON from "../../static/json/muzhuang_id_list.json";
import Log from "../Log";
import CommonUtils from "../utils/CommonUtils"; import CommonUtils from "../utils/CommonUtils";
import XUNZHAOMUZHUANG_CSS from "../../static/css/xunzhaomuzhuang.css"; import XUNZHAOMUZHUANG_CSS from "../../static/css/xunzhaomuzhuang.css";
import TornStyleBlock from "../utils/TornStyleBlock"; import TornStyleBlock from "../utils/TornStyleBlock";
import MathUtils from "../utils/MathUtils"; import MathUtils from "../utils/MathUtils";
import FetchUtils from "../utils/FetchUtils";
/** /**
* *
@ -61,23 +61,15 @@ export default class XZMZ extends WuhuBase {
} }
private async SearchDeadman(id) { private async SearchDeadman(id) {
CommonUtils.ajaxFetch({ FetchUtils.getInstance().getProfile(id).then((res) => {
url: window.addRFC('https://www.torn.com/profiles.php?step=getProfileData&XID=' + id), if (res.userStatus.status.type === 'ok') {
method: 'GET' this.addRow({
}).then((o) => { player_id: res.user.userID,
this.counterHandler(); name: res.userInformation.name,
o.json().then((res) => { level: res.userInformation.level
if (res.userStatus.status.type === 'ok') { });
this.addRow({ }
player_id: res.user.userID, });
name: res.userInformation.name,
level: res.userInformation.level
});
}
}).catch(e => {
Log.error('[XZMZ] [CommonUtils.ajaxFetch]错误: ', e.message, '错误堆栈: ', e.stack);
});
})
await CommonUtils.getInstance().sleep(MathUtils.getInstance().getRandomInt(100, 200)); await CommonUtils.getInstance().sleep(MathUtils.getInstance().getRandomInt(100, 200));
} }

View File

@ -1,6 +1,7 @@
import WuhuBase from "../WuhuBase"; import WuhuBase from "../WuhuBase";
import Popup from "../utils/Popup"; import Popup from "../utils/Popup";
import Alert from "../utils/Alert"; import Alert from "../utils/Alert";
import DialogMsgBox from "../utils/DialogMsgBox";
export default class AdditionalSettingsHandler extends WuhuBase { export default class AdditionalSettingsHandler extends WuhuBase {
className = 'AdditionalSettingsHandler'; className = 'AdditionalSettingsHandler';
@ -11,13 +12,17 @@ export default class AdditionalSettingsHandler extends WuhuBase {
pop.getElement().insertAdjacentHTML('beforeend', insertHtml); pop.getElement().insertAdjacentHTML('beforeend', insertHtml);
let [btn1, btn2, btn3] = Array.from(pop.getElement().querySelectorAll('button')); let [btn1, btn2, btn3] = Array.from(pop.getElement().querySelectorAll('button'));
btn1.addEventListener('click', () => { btn1.addEventListener('click', () => {
localStorage.removeItem('wh_trv_alarm'); new DialogMsgBox('将清空所有芜湖助手相关设置并刷新页面,确定?', {
localStorage.removeItem('wh_trans_settings'); callback: () => {
localStorage.removeItem('whuuid'); localStorage.removeItem('wh_trv_alarm');
localStorage.removeItem('wh-gs-storage'); localStorage.removeItem('wh_trans_settings');
localStorage.removeItem('WHTEST'); localStorage.removeItem('whuuid');
new Alert('已清空,刷新页面'); localStorage.removeItem('wh-gs-storage');
window.location.reload(); localStorage.removeItem('WHTEST');
new Alert('已清空,刷新页面');
window.location.reload();
}
});
}); });
btn2.addEventListener('click', () => { btn2.addEventListener('click', () => {
}); });

View File

@ -6,7 +6,6 @@ import BuyBeerHelper from "../action/BuyBeerHelper";
import UpdateTranslateDict from "./UpdateTranslateDict"; import UpdateTranslateDict from "./UpdateTranslateDict";
import landedRedirect from "../../func/module/landedRedirect"; import landedRedirect from "../../func/module/landedRedirect";
import Alert from "../utils/Alert"; import Alert from "../utils/Alert";
import WuhuConfig from "../WuhuConfig";
import ViewLogsHandler from "./ViewLogsHandler"; import ViewLogsHandler from "./ViewLogsHandler";
import AdditionalSettingsHandler from "./AdditionalSettingsHandler"; import AdditionalSettingsHandler from "./AdditionalSettingsHandler";
import Popup from "../utils/Popup"; import Popup from "../utils/Popup";
@ -26,16 +25,18 @@ export default class SettingsHandler extends WuhuBase {
let startTime = new Timer(); let startTime = new Timer();
Log.info('构造设置开始'); Log.info('构造设置开始');
let pop = new Popup(CommonUtils.loading_gif_html(), '芜湖助手设置'); let pop = new Popup(CommonUtils.loading_gif_html(), '芜湖助手设置');
let tmp = document.createElement('div'); window.setTimeout(() => {
tmp.classList.add('gSetting'); let tmp = document.createElement('div');
this.list.forEach(set => CommonUtils.getInstance().elemGenerator(set, tmp)); tmp.classList.add('gSetting');
pop.getElement().innerHTML = ''; this.list.forEach(set => CommonUtils.getInstance().elemGenerator(set, tmp));
pop.getElement().appendChild(tmp); // 本日不提醒
// 本日不提醒 tmp.querySelector('#wh-qua-alarm-check-btn')
pop.getElement().querySelector('#wh-qua-alarm-check-btn') .addEventListener('click', () => BuyBeerHelper.getInstance().skip_today());
.addEventListener('click', () => BuyBeerHelper.getInstance().skip_today()); pop.getElement().innerHTML = '';
(window.initializeTooltip) && (window.initializeTooltip('#wh-popup-cont', 'white-tooltip')); pop.getElement().appendChild(tmp);
Log.info('构造设置结束 ' + startTime.getTimeMs()); (window.initializeTooltip) && (window.initializeTooltip('#wh-popup-cont', 'white-tooltip'));
Log.info('构造设置结束 ' + startTime.getTimeMs());
}, 0)
} }
// 设置 // 设置
@ -95,11 +96,11 @@ export default class SettingsHandler extends WuhuBase {
clickFunc: () => UpdateTranslateDict.getInstance().handle() clickFunc: () => UpdateTranslateDict.getInstance().handle()
}); });
// 战斗优化 // 战斗
list.push({ list.push({
domType: 'plain', domType: 'plain',
domId: '', domId: '',
domHTML: '战斗优化', domHTML: '战斗',
tagName: 'h4', tagName: 'h4',
}); });
// 光速拔刀 // 光速拔刀
@ -138,7 +139,6 @@ export default class SettingsHandler extends WuhuBase {
}, },
], ],
dictName: 'quickAttIndex', dictName: 'quickAttIndex',
isHide: true,
tip: '将Start Fight按钮移动到指定格子上', tip: '将Start Fight按钮移动到指定格子上',
}); });
// 光速跑路 // 光速跑路
@ -165,8 +165,7 @@ export default class SettingsHandler extends WuhuBase {
}, },
], ],
dictName: 'quickFinishAtt', dictName: 'quickFinishAtt',
isHide: true, tip: '将结束后指定按钮移动到上面指定的格子上',
tip: '<del>将结束后指定按钮移动到上面指定的格子上</del>暂时关闭',
}); });
// 攻击链接转跳 // 攻击链接转跳
list.push({ list.push({
@ -174,63 +173,75 @@ export default class SettingsHandler extends WuhuBase {
domId: 'wh-attack-relocate', domId: 'wh-attack-relocate',
domText: ' 真·攻击界面转跳', domText: ' 真·攻击界面转跳',
dictName: 'attRelocate', dictName: 'attRelocate',
tip: '在无法打开攻击界面的情况下依然可以转跳到正确的攻击页面', tip: '在无法打开攻击界面的情况下依然可以转跳到正确的攻击页面失效Ched疑似已移除此转跳',
isHide: true,
}); });
// 盯梢模式强度
list.push({
domType: 'select',
domId: '',
domText: '盯梢模式强度 ',
domSelectOpt: [
{ domVal: '550', domText: '强' },
{ domVal: '950', domText: '标准' },
{ domVal: '1450', domText: '弱' }
],
dictName: 'WatchTargetFreq',
tip: '越强盯得越紧刷新越快越容易触发Torn大流量保护机制<br/>强 ~0.6s<br/>标准 ~1s<br/>弱 ~1.5s',
})
// 危险行为⚠️ // 危险行为⚠️
if (WuhuConfig.get('dangerZone') === true) { // if (WuhuConfig.get('dangerZone') === true) {
// 攻击界面自刷新 // // 攻击界面自刷新
list.push({ // list.push({
domType: 'select', // domType: 'select',
domId: 'wh-attack-reload', // domId: 'wh-attack-reload',
domText: '⚠️攻击界面自动刷新 ', // domText: '⚠️攻击界面自动刷新 ',
dictName: 'attReload', // dictName: 'attReload',
domSelectOpt: [ // domSelectOpt: [
{ // {
domVal: 'none', // domVal: 'none',
domText: '无间隔', // domText: '无间隔',
}, // },
{ // {
domVal: '1', // domVal: '1',
domText: '约1s', // domText: '约1s',
}, // },
{ // {
domVal: '2', // domVal: '2',
domText: '约2s', // domText: '约2s',
}, // },
{ // {
domVal: '3', // domVal: '3',
domText: '约3s', // domText: '约3s',
}, // },
{ // {
domVal: '4', // domVal: '4',
domText: '约4s', // domText: '约4s',
}, // },
{ // {
domVal: '5', // domVal: '5',
domText: '约5s', // domText: '约5s',
}, // },
{ // {
domVal: 'disabled', // domVal: 'disabled',
domText: '关闭', // domText: '关闭',
}, // },
], // ],
isHide: true, // isHide: true,
tip: '危险功能:接机时常用,将自动刷新页面直到目标落地', // tip: '危险功能:接机时常用,将自动刷新页面直到目标落地',
}); // });
// 自动开打和结束 // // 自动开打和结束
list.push({ // list.push({
domType: 'checkbox', // domType: 'checkbox',
domId: 'wh-auto-start-finish', // domId: 'wh-auto-start-finish',
domText: ' ⚠️自动开打和结束', // domText: ' ⚠️自动开打和结束',
dictName: 'autoStartFinish', // dictName: 'autoStartFinish',
tip: '脚本将会自动按下战斗和结束按钮', // tip: '脚本将会自动按下战斗和结束按钮',
isHide: true, // isHide: true,
}); // });
} else { // } else {
WuhuConfig.set('autoStartFinish', false) // WuhuConfig.set('autoStartFinish', false)
WuhuConfig.set('attReload', 6) // WuhuConfig.set('attReload', 6)
} // }
// 飞行 // 飞行
list.push({ list.push({

View File

@ -1,19 +1,47 @@
import WuhuBase from "../WuhuBase"; import WuhuBase from "../WuhuBase";
import Log from "../Log"; import Log from "../Log";
import Popup from "../utils/Popup"; import Popup from "../utils/Popup";
import CommonUtils from "../utils/CommonUtils";
import VIEW_LOGS_HANDLER_HTML from "../../static/html/view_logs_handler.html";
export default class ViewLogsHandler extends WuhuBase { export default class ViewLogsHandler extends WuhuBase {
className = 'ViewLogsHandler'; className = 'ViewLogsHandler';
public handle(): void { public handle(): void {
let logCounter = Log.getCounter(); let logCounter = Log.getCounter();
let pop = new Popup('<textarea readonly style="width:100%;height:340px;"></textarea>', '查看日志'); let pop = new Popup(VIEW_LOGS_HANDLER_HTML
let text = pop.getElement().querySelector('textarea'); .replace('{{}}', logCounter.info.toString())
text.innerHTML = Log.getLogs(); .replace('{{}}', logCounter.warning.toString())
text.onclick = () => text.select(); .replace('{{}}', logCounter.error.toString()), '查看日志');
pop.getElement().insertAdjacentHTML( window.setTimeout(() => {
'afterbegin', let container = pop.getElement().querySelector('div');
`<p>${ logCounter.info }信息 ${ logCounter.warning }警告 ${ logCounter.error }错误</p>` let text = document.createElement('div');
); let logs = Log.getLogs().split('\r\n');
logs.forEach(log => {
let p = document.createElement('p');
p.innerText = log;
if (log.includes('ERR')) {
p.style.backgroundColor = '#ff000080';
} else if (log.includes('WRN')) {
p.style.backgroundColor = '#ffff0080';
}
text.append(p);
});
pop.getElement().querySelector('button').addEventListener('click', () => window.setTimeout(() => {
CommonUtils.getInstance()
.exportTextFile(
'wuhu_log_' + Log.getTime()
.replace('[', '')
.replace(']', '')
.replace(' ', '')
.replace('.', '')
.replaceAll('-', '')
.replaceAll(':', '') + '.log',
[Log.getLogs()]
);
}, 0));
container.innerHTML = '';
container.append(text);
}, 0);
} }
} }

View File

@ -2,13 +2,13 @@ import UserScriptEngine from "../../enum/UserScriptEngine";
import WuhuBase from "../WuhuBase"; import WuhuBase from "../WuhuBase";
import Log from "../Log"; import Log from "../Log";
import Device from "../../enum/Device"; import Device from "../../enum/Device";
import AjaxFetchOption from "../../interface/AjaxFetchOption";
import LOADING_IMG_HTML from "../../static/html/loading_img.html"; import LOADING_IMG_HTML from "../../static/html/loading_img.html";
import Timer from "./Timer"; import Timer from "./Timer";
import FetchUtils from "./FetchUtils"; import FetchUtils from "./FetchUtils";
import TornStyleSwitch from "./TornStyleSwitch"; import TornStyleSwitch from "./TornStyleSwitch";
import WuhuConfig from "../WuhuConfig"; import WuhuConfig from "../WuhuConfig";
import { MenuItemConfig } from "../ZhongIcon"; import { MenuItemConfig } from "../ZhongIcon";
import TRAVEL_STATE from "../../enum/TravelState";
export default class CommonUtils extends WuhuBase { export default class CommonUtils extends WuhuBase {
className = 'CommonUtils'; className = 'CommonUtils';
@ -125,19 +125,19 @@ export default class CommonUtils extends WuhuBase {
} }
} }
public static ajaxFetch(opt: AjaxFetchOption) { // public static ajaxFetch(opt: AjaxFetchOption) {
let { url, referrer = '/', method, body = null } = opt; // let { url, referrer = '/', method, body = null } = opt;
let req_params: RequestInit = { // let req_params: RequestInit = {
headers: { 'X-Requested-With': 'XMLHttpRequest' }, // headers: { 'X-Requested-With': 'XMLHttpRequest' },
referrer, // referrer,
method, // method,
}; // };
if (method === 'POST') { // if (method === 'POST') {
req_params.headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8'; // req_params.headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
req_params.body = body; // req_params.body = body;
} // }
return window.fetch(url, req_params); // return window.fetch(url, req_params);
} // }
/** /**
* mutation.observe * mutation.observe
@ -221,7 +221,6 @@ export default class CommonUtils extends WuhuBase {
*/ */
public isNewDay(target: number | Date, offsetHours: number = 0): boolean { public isNewDay(target: number | Date, offsetHours: number = 0): boolean {
let tar: Date = typeof target === "number" ? new Date(target) : target; let tar: Date = typeof target === "number" ? new Date(target) : target;
Log.info(tar.toLocaleString());
let today = new Date(); let today = new Date();
let utcNewDay = new Date(Date.UTC(today.getUTCFullYear(), today.getUTCMonth(), today.getUTCDate())); let utcNewDay = new Date(Date.UTC(today.getUTCFullYear(), today.getUTCMonth(), today.getUTCDate()));
utcNewDay.setHours(utcNewDay.getHours() + offsetHours); utcNewDay.setHours(utcNewDay.getHours() + offsetHours);
@ -321,4 +320,36 @@ export default class CommonUtils extends WuhuBase {
// 移动节点 // 移动节点
return root_node.appendChild(new_node); return root_node.appendChild(new_node);
} }
public exportTextFile(filename, content) {
const tmp = document.createElement('a');
tmp.href = URL.createObjectURL(new Blob(content, { type: 'text/plain', endings: 'transparent' }));
tmp.download = filename;
tmp.click();
tmp.remove();
URL.revokeObjectURL(tmp.href);
}
public isValidUid(id: string | number): boolean {
if (typeof id === 'string') {
return /^[0-9]{1,7}$/.test(id);
} else {
return /^[0-9]{1,7}$/.test(id.toString());
}
}
public getTravelStage(): TRAVEL_STATE {
let global = CommonUtils.glob;
if (global.bodyAttrs["data-abroad"] === 'false') {
return TRAVEL_STATE.IN_TORN;
}
// 海外落地abroad
else if (global.bodyAttrs["data-traveling"] === 'false') {
return TRAVEL_STATE.ABROAD;
}
// 飞行中traveling+abroad
else {
return TRAVEL_STATE.FLYING;
}
}
} }

View File

@ -7,7 +7,7 @@ export default class DialogMsgBox {
constructor(msg: string, opt: DialogMsgBoxOptions) { constructor(msg: string, opt: DialogMsgBoxOptions) {
Log.info('创建DialogMsgBox', { msg, opt }); Log.info('创建DialogMsgBox', { msg, opt });
let { title = '提示', callback } = opt; let { title = '提示', callback, cancel } = opt;
if (!callback) { if (!callback) {
Log.error('无callback'); Log.error('无callback');
throw new Error('无callback'); throw new Error('无callback');
@ -19,12 +19,13 @@ export default class DialogMsgBox {
this.container = document.createElement('div'); this.container = document.createElement('div');
this.container.id = 'wh-dialog'; this.container.id = 'wh-dialog';
this.container.innerHTML = DIALOG_MSG_BOX_HTML.replace('{{}}', title).replace('{{}}', msg); this.container.innerHTML = DIALOG_MSG_BOX_HTML.replace('{{}}', title).replace('{{}}', msg);
let [confirm, cancel] = Array.from(this.container.querySelectorAll('button')); let [confirm, cancelBtn] = Array.from(this.container.querySelectorAll('button'));
confirm.addEventListener('click', () => { confirm.addEventListener('click', () => {
callback(this.container); callback(this.container);
this.destroy(); this.destroy();
}); });
cancel.addEventListener('click', () => { cancelBtn.addEventListener('click', () => {
cancel ? cancel() : null;
this.destroy(); this.destroy();
}); });
document.body.append(this.container); document.body.append(this.container);
@ -50,4 +51,5 @@ export default class DialogMsgBox {
interface DialogMsgBoxOptions { interface DialogMsgBoxOptions {
title?: string; title?: string;
callback: Function; callback: Function;
cancel?: Function;
} }

View File

@ -1,5 +1,7 @@
import WuhuBase from "../WuhuBase"; import WuhuBase from "../WuhuBase";
import Log from "../Log"; import Log from "../Log";
import AjaxFetchOption from "../../interface/AjaxFetchOption";
import IUserProfileData from "../../interface/IUserProfileData";
export default class FetchUtils extends WuhuBase { export default class FetchUtils extends WuhuBase {
className = 'FetchUtils'; className = 'FetchUtils';
@ -24,6 +26,20 @@ export default class FetchUtils extends WuhuBase {
}); });
} }
public ajaxFetch(opt: AjaxFetchOption) {
let { url, referrer = '/', method, body = null } = opt;
let req_params: RequestInit = {
headers: { 'X-Requested-With': 'XMLHttpRequest' },
referrer,
method,
};
if (method === 'POST') {
req_params.headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
req_params.body = body;
}
return window.fetch(url, req_params);
}
public fetchText(url: string, init: RequestInit = null): Promise<string> { public fetchText(url: string, init: RequestInit = null): Promise<string> {
return new Promise((resolve, reject) => return new Promise((resolve, reject) =>
window.fetch(url, init) window.fetch(url, init)
@ -35,4 +51,23 @@ export default class FetchUtils extends WuhuBase {
}) })
); );
} }
public getProfile(uid: string): Promise<IUserProfileData> {
return new Promise((resolve, reject) => {
this.ajaxFetch({
url: window.addRFC('https://www.torn.com/profiles.php?step=getProfileData&XID=' + uid),
method: 'GET'
}).then((o) => {
o.json().then((res) => {
resolve(res);
}).catch(e => {
Log.error('[ProfileHelper] JSON解析错误: ', e.message, '错误堆栈: ', e.stack);
reject(e);
});
}).catch(e => {
Log.error('[ProfileHelper] 网络错误: ', e.message, '错误堆栈: ', e.stack);
reject(e);
});
});
}
} }

View File

@ -3,6 +3,7 @@ import Alert from "./Alert";
import ISidebarData from "../../interface/ISidebarData"; import ISidebarData from "../../interface/ISidebarData";
import Log from "../Log"; import Log from "../Log";
import CommonUtils from "./CommonUtils"; import CommonUtils from "./CommonUtils";
import FetchUtils from "./FetchUtils";
export default class InfoUtils extends WuhuBase { export default class InfoUtils extends WuhuBase {
className = 'InfoUtils'; className = 'InfoUtils';
@ -37,7 +38,7 @@ export default class InfoUtils extends WuhuBase {
ret = JSON.parse(sessionStorage.getItem(field)); ret = JSON.parse(sessionStorage.getItem(field));
} else { } else {
Log.info('无法从sessionStorage获取数据') Log.info('无法从sessionStorage获取数据')
ret = await (await CommonUtils.ajaxFetch({ ret = await (await FetchUtils.getInstance().ajaxFetch({
url: window.addRFC('/sidebarAjaxAction.php?q=getSidebarData'), url: window.addRFC('/sidebarAjaxAction.php?q=getSidebarData'),
method: 'POST', method: 'POST',
})).json(); })).json();

View File

@ -0,0 +1,37 @@
import Log from "../Log";
import Timer from "./Timer";
export default class LoopHelper {
private intervalId: number = null;
private readonly handler: Function;
private timer: Timer;
constructor(callback: Function) {
this.handler = callback;
Log.info('[LoopHelper] 已创建, 方法: ', callback);
}
public start(loopGap: number = 1000): void {
Log.info('[LoopHelper] 已启动, 间隔' + loopGap);
this.timer = new Timer();
this.intervalId = window.setInterval(() => {
try {
this.handler();
} catch (e) {
Log.error(e.message, e.stack);
throw e;
}
}, loopGap);
}
public stop(): void {
// this.counter = 0;
Log.info('[LoopHelper] 已停止, 运行' + this.timer.getTimeMs());
window.clearInterval(this.intervalId);
this.intervalId = null;
}
public isRunning(): boolean {
return this.intervalId !== null;
}
}

7
src/enum/TravelState.ts Normal file
View File

@ -0,0 +1,7 @@
enum TRAVEL_STATE {
IN_TORN,
FLYING,
ABROAD
}
export default TRAVEL_STATE

View File

@ -1,306 +1,535 @@
import Device from "../../enum/Device"; // import Device from "../../enum/Device";
import WuhuBase from "../../class/WuhuBase"; // import WuhuBase from "../../class/WuhuBase";
import WuhuConfig from "../../class/WuhuConfig"; // import WuhuConfig from "../../class/WuhuConfig";
import CommonUtils from "../../class/utils/CommonUtils"; // import CommonUtils from "../../class/utils/CommonUtils";
import Log from "../../class/Log"; // import Log from "../../class/Log";
import Alert from "../../class/utils/Alert"; // import Alert from "../../class/utils/Alert";
import MathUtils from "../../class/utils/MathUtils"; // import MathUtils from "../../class/utils/MathUtils";
import ActionButtonUtils from "../../class/utils/ActionButtonUtils"; // import ActionButtonUtils from "../../class/utils/ActionButtonUtils";
import ATTACK_HELPER_CSS from "../../static/css/attack_helper.css"; // import ATTACK_HELPER_CSS from "../../static/css/attack_helper.css";
// import Global from "../../class/Global";
enum FIGHT_STAGE { // import TornStyleBlock from "../../class/utils/TornStyleBlock";
READY, // import TornStyleSwitch from "../../class/utils/TornStyleSwitch";
IN_PROGRESS_OR_ERROR, // import DialogMsgBox from "../../class/utils/DialogMsgBox";
FINISHED //
} // enum FIGHT_STAGE {
// READY,
enum DIALOG_BUTTON { // IN_PROGRESS_OR_ERROR,
START = 'start', // FINISHED,
JOIN = 'join', // END,
LEAVE = 'leave', // OTHER
MUG = 'mug', // }
// TODO //
HOST = 'hospitalize', // // enum DIALOG_BUTTON {
OTHER = 'other' // // START = 'start',
} // // JOIN = 'join',
// // LEAVE = 'leave',
/** // // MUG = 'mug',
* TODO class重构 // // HOSPITALIZE = 'hospitalize',
*/ // // OTHER = 'other'
export default async function attackHelper(): Promise<null> { // // }
let { href, device } = WuhuBase.glob; // let currentStage = FIGHT_STAGE.OTHER;
// 攻击页面URL判断 //
if (href.contains(/loader\.php\?sid=attack/)) { // /**
let stop_reload = false; // * TODO class重构、各功能联动
const quickAttIndex = WuhuConfig.get('quickAttIndex'); // */
const quickFinishAtt = WuhuConfig.get('quickFinishAtt'); // export default async function attackHelper(): Promise<null> {
const attReload = WuhuConfig.get('attReload'); // let { href, device } = WuhuBase.glob;
// // 攻击页面URL判断
// 光速刷新按钮 // if (href.contains(/loader\.php\?sid=attack/)) {
ActionButtonUtils.getInstance().add('光速刷新', doAttackReload); // let stop_reload = false;
// const attReload = WuhuConfig.get('attReload');
// 自刷新 //
let audio_played_flag; // // 光速刷新按钮
// @ts-ignore TODO // ActionButtonUtils.getInstance().add('光速刷新', doAttackReload);
if (attReload !== 6 && stop_reload !== true) { //
const selector_device_map = { // // 自刷新
'pc': '#defender div[class^="modal___"]', // let audio_played_flag;
'mobile': '#attacker div[class^="modal___"]', // // @ts-ignore TODO
'tablet': '', // if (attReload !== 6 && stop_reload !== true) {
}; // const selector_device_map = {
const selector = selector_device_map[device]; // 'pc': '#defender div[class^="modal___"]',
CommonUtils.elementReady(selector).then(elem => { // 'mobile': '#attacker div[class^="modal___"]',
if (!elem.querySelector('button')) { // 'tablet': '',
if (WuhuConfig.get('attReload') === 0 && stop_reload !== true) { // };
doAttackReload(); // const selector = selector_device_map[device];
} else { // CommonUtils.elementReady(selector).then(elem => {
let reload_flag; // if (!elem.querySelector('button')) {
const timeout = WuhuConfig.get('attReload') * 1000 + MathUtils.getInstance().getRandomInt(-500, 500); // if (WuhuConfig.get('attReload') === 0 && stop_reload !== true) {
Log.info(`[WH] ${ timeout / 1000 }s 后自动刷新`); // doAttackReload();
window.setInterval(() => { // } else {
if (reload_flag === undefined) { // let reload_flag;
reload_flag = true; // const timeout = WuhuConfig.get('attReload') * 1000 + MathUtils.getInstance().getRandomInt(-500, 500);
} else if (stop_reload !== true) { // Log.info(`[WH] ${ timeout / 1000 }s 后自动刷新`);
// window.location.reload(); // window.setInterval(() => {
doAttackReload(); // if (reload_flag === undefined) {
} // reload_flag = true;
}, timeout); // } else if (stop_reload !== true) {
} // // window.location.reload();
} else if (audio_played_flag === undefined) { // doAttackReload();
audio_played_flag = true; // }
let play_time = 0; // }, timeout);
const audio_play_id = window.setInterval(() => { // }
const $audio = document.createElement('audio'); // } else if (audio_played_flag === undefined) {
$audio.src = 'https://www.torn.com/js/chat/sounds/Warble_1.mp3'; // audio_played_flag = true;
$audio.play().then(); // let play_time = 0;
play_time++; // const audio_play_id = window.setInterval(() => {
if (play_time === 3) clearInterval(audio_play_id); // const $audio = document.createElement('audio');
}, 600); // $audio.src = 'https://www.torn.com/js/chat/sounds/Warble_1.mp3';
} // $audio.play().then();
}); // play_time++;
} // if (play_time === 3) clearInterval(audio_play_id);
// }, 600);
// await CommonUtils.querySelector('#react-root div[class^="players___"]'); // pc 可用 // }
let playersModelWrap = await CommonUtils.querySelector('#react-root div[class^="playersModelWrap___"]'); // });
let fightStage = document.querySelectorAll('div[class^="dialogButtons___"] button').length > 1; // }
Log.info('响应式内容已加载'); //
// 光速拔刀 // // await CommonUtils.querySelector('#react-root div[class^="players___"]'); // pc 可用
if (quickAttIndex !== 6) { // // await CommonUtils.querySelector('#react-root div[class^="playersModelWrap___"]');
/** // Log.info('响应式内容已加载');
* pc #defender // // 光速拔刀
* mobile #attacker // // if (quickAttIndex !== 6) {
*/ // // /**
const btn = <HTMLInputElement>(document.querySelector('#attacker button') || document.querySelector('#defender button')); // // * pc #defender
Log.info('操作按钮', { btn }); // // * mobile #attacker
if (!btn.innerText.toLowerCase().includes('fight')) { // // */
Log.info('未找到攻击按钮, 光速拔刀跳过'); // // const btn = <HTMLInputElement>(document.querySelector('#attacker button') || document.querySelector('#defender button'));
new Alert('未找到攻击按钮, 光速拔刀跳过'); // // Log.info('操作按钮', { btn });
} else { // // if (!btn.innerText.toLowerCase().includes('fight')) {
// 判断是否存在脚踢 // // Log.info('未找到攻击按钮, 光速拔刀跳过');
const hasKick = !!document.querySelector('#weapon_boots'); // // new Alert('未找到攻击按钮, 光速拔刀跳过');
// modal层 // // } else {
// const modal: HTMLElement = document.querySelector('div[class^="modal___"]'); // // // 判断是否存在脚踢
Log.info(`当前设备类型是${ device }`); // // const hasKick = !!document.querySelector('#weapon_boots');
// 区分设备 // // // modal层
switch (device) { // // // const modal: HTMLElement = document.querySelector('div[class^="modal___"]');
case Device.PC: { // // Log.info(`当前设备类型是${ device }`);
Log.info(`开始调整按钮位置`); // // // 区分设备
// 隐藏modal层 // // switch (device) {
// modal.style.display = 'none'; // // case Device.PC: {
// 根据选择的武器调整css // // Log.info(`开始调整按钮位置`);
let css_top = '0'; // // // 隐藏modal层
switch (WuhuConfig.get('quickAttIndex')) { // // // modal.style.display = 'none';
// weapon_second // // // 根据选择的武器调整css
case 1: { // // let css_top = '0';
css_top = '97px'; // // switch (WuhuConfig.get('quickAttIndex')) {
break; // // // weapon_second
} // // case 1: {
// weapon_melee // // css_top = '97px';
case 2: { // // break;
css_top = '194px'; // // }
break; // // // weapon_melee
} // // case 2: {
// weapon_temp // // css_top = '194px';
case 3: { // // break;
css_top = '291px'; // // }
break; // // // weapon_temp
} // // case 3: {
// weapon_fists // // css_top = '291px';
case 4: // // break;
// weapon_boots // // }
case 5: { // // // weapon_fists
css_top = '375px'; // // case 4:
break; // // // weapon_boots
} // // case 5: {
} // // css_top = '375px';
CommonUtils.addStyle(ATTACK_HELPER_CSS); // // break;
CommonUtils.addStyle(`.wh-move-btn #defender div[class^="modal___"]{top: ${ css_top };}`); // // }
document.body.classList.add('wh-move-btn'); // // }
// 绑定点击事件 联动【光速跑路】 // // CommonUtils.addStyle(ATTACK_HELPER_CSS);
btn.onclick = () => { // // CommonUtils.addStyle(`.wh-move-btn #defender div[class^="modal___"]{top: ${ css_top };}`);
if (quickFinishAtt !== 3) { // // document.body.classList.add('wh-move-btn');
btn.remove(); // // // 绑定点击事件 联动【光速跑路】
// 停止自动刷新 // // btn.onclick = () => {
stop_reload = true; // // if (quickFinishAtt !== 3) {
} else { // // btn.remove();
document.body.classList.remove('wh-move-btn'); // // // 停止自动刷新
} // // stop_reload = true;
}; // // } else {
break; // // document.body.classList.remove('wh-move-btn');
} // // }
case Device.MOBILE: { // // };
Log.info(`开始调整按钮位置`); // // break;
// 加入css // // }
let css_top = '0'; // // case Device.MOBILE: {
let slot_height = '76px'; // // Log.info(`开始调整按钮位置`);
// 判断有没有脚踢 // // // 加入css
if (hasKick) { // // let css_top = '0';
// 根据选择的武器调整 // // let slot_height = '76px';
switch (WuhuConfig.get('quickAttIndex')) { // // // 判断有没有脚踢
case 1: { // weapon_second // // if (hasKick) {
css_top = '76px'; // // // 根据选择的武器调整
break; // // switch (WuhuConfig.get('quickAttIndex')) {
} // // case 1: { // weapon_second
case 2: { // weapon_melee // // css_top = '76px';
css_top = '152px'; // // break;
break; // // }
} // // case 2: { // weapon_melee
case 3: { // weapon_temp // // css_top = '152px';
css_top = '228px'; // // break;
break; // // }
} // // case 3: { // weapon_temp
case 4: { // weapon_fists // // css_top = '228px';
css_top = '304px'; // // break;
break; // // }
} // // case 4: { // weapon_fists
case 5: { // weapon_boots // // css_top = '304px';
css_top = '380px'; // // break;
break; // // }
} // // case 5: { // weapon_boots
} // // css_top = '380px';
} else { // // break;
const slot = document.querySelector('#weapon_main') as HTMLElement; // // }
const height = slot.offsetHeight + 1; // // }
// TODO 待验证 // // } else {
slot_height = height + 'px'; // // const slot = document.querySelector('#weapon_main') as HTMLElement;
// 根据选择的武器调整 // // const height = slot.offsetHeight + 1;
switch (WuhuConfig.get('quickAttIndex')) { // // // TODO 待验证
case 1: { // weapon_second // // slot_height = height + 'px';
css_top = `${ height }px`; // // // 根据选择的武器调整
break; // // switch (WuhuConfig.get('quickAttIndex')) {
} // // case 1: { // weapon_second
case 2: { // weapon_melee // // css_top = `${ height }px`;
css_top = `${ height * 2 }px`; // // break;
break; // // }
} // // case 2: { // weapon_melee
case 3: { // weapon_temp // // css_top = `${ height * 2 }px`;
css_top = `${ height * 3 }px`; // // break;
break; // // }
} // // case 3: { // weapon_temp
case 4: { // weapon_fists // // css_top = `${ height * 3 }px`;
css_top = `${ height * 4 }px`; // // break;
break; // // }
} // // case 4: { // weapon_fists
case 5: { // weapon_boots // // css_top = `${ height * 4 }px`;
css_top = `${ height * 5 }px`; // // break;
break; // // }
} // // case 5: { // weapon_boots
} // // css_top = `${ height * 5 }px`;
} // // break;
const css_rule = ATTACK_HELPER_CSS.replace('CSSVAR', css_top).replace('CSSVAR', slot_height); // // }
// ` // // }
// .wh-move-btn #attacker div[class^="modal___"]{display: block;width: 0;top: ${ css_top };left:0;height:0;} // // }
// .wh-move-btn #attacker div[class^="dialog___"]{border:0;width:80px;height:${ slot_height };} // // const css_rule = ATTACK_HELPER_CSS.replace('CSSVAR', css_top).replace('CSSVAR', slot_height);
// .wh-move-btn #attacker div[class^="colored___"]{display:block;padding:0;} // // // `
// .wh-move-btn #attacker div[class^="title___"]{height:0;} // // // .wh-move-btn #attacker div[class^="modal___"]{display: block;width: 0;top: ${ css_top };left:0;height:0;}
// .wh-move-btn #attacker button{width:100%;margin:0;height:63px;white-space:normal;} // // // .wh-move-btn #attacker div[class^="dialog___"]{border:0;width:80px;height:${ slot_height };}
// `; // // // .wh-move-btn #attacker div[class^="colored___"]{display:block;padding:0;}
CommonUtils.addStyle(css_rule); // // // .wh-move-btn #attacker div[class^="title___"]{height:0;}
document.body.classList.toggle('wh-move-btn'); // // // .wh-move-btn #attacker button{width:100%;margin:0;height:63px;white-space:normal;}
btn.onclick = () => { // // // `;
if (WuhuConfig.get('quickFinishAtt') !== 3) { // // CommonUtils.addStyle(css_rule);
btn.remove(); // // document.body.classList.toggle('wh-move-btn');
// 停止自动刷新 // // btn.onclick = () => {
stop_reload = true; // // if (WuhuConfig.get('quickFinishAtt') !== 3) {
} else { // // btn.remove();
document.body.classList.toggle('wh-move-btn'); // // // 停止自动刷新
} // // stop_reload = true;
}; // // } else {
break; // // document.body.classList.toggle('wh-move-btn');
} // // }
case Device.TABLET: { // // };
break; // // break;
} // // }
} // // case Device.TABLET: {
// 自动开打 // // break;
if (WuhuConfig.get('autoStartFinish') === true) { // // }
if (btn.innerText.includes('(')) { // // }
let interval_id = window.setInterval(() => { // // // 自动开打
if (!btn) { // // if (WuhuConfig.get('autoStartFinish') === true) {
clearInterval(interval_id); // // if (btn.innerText.includes('(')) {
return; // // let interval_id = window.setInterval(() => {
} // // if (!btn) {
try { // // clearInterval(interval_id);
btn.click(); // // return;
} catch { // // }
} // // try {
}, 100); // // btn.click();
} else { // // } catch {
btn.click(); // // }
} // // }, 100);
} // // } else {
} // // btn.click();
} // // }
// // }
// 光速跑路 TODO 暂时关闭 // // }
if (quickFinishAtt !== 3) { // // }
const user_btn_select = ['leave', 'mug', 'hosp'][WuhuConfig.get('quickFinishAtt')]; //
const wrap = document.querySelector('#react-root'); // // 光速跑路 TODO 暂时关闭
Log.info('光速跑路选项选中:', user_btn_select); // // if (quickFinishAtt !== 3) {
new MutationObserver((mut, obs) => { // // const user_btn_select = ['leave', 'mug', 'hosp'][WuhuConfig.get('quickFinishAtt')];
const btn_arr: HTMLButtonElement[] = document.querySelectorAll('div[class^="dialogButtons___"] button') as unknown as HTMLButtonElement[]; // // const wrap = document.querySelector('#react-root');
if (btn_arr.length > 1) btn_arr.forEach(btn => { // // Log.info('光速跑路选项选中:', user_btn_select);
const flag = btn.innerText.toLowerCase().includes(user_btn_select); // // new MutationObserver((mut, obs) => {
Log.info('按钮内容:', btn.innerText, ',是否包含选中:', flag); // // const btn_arr: HTMLButtonElement[] = document.querySelectorAll('div[class^="dialogButtons___"] button') as unknown as HTMLButtonElement[];
if (!flag) btn.style.display = 'none'; // // if (btn_arr.length > 1) btn_arr.forEach(btn => {
// 自动结束 // // const flag = btn.innerText.toLowerCase().includes(user_btn_select);
else if (WuhuConfig.get('autoStartFinish')) { // // Log.info('按钮内容:', btn.innerText, ',是否包含选中:', flag);
try { // // if (!flag) btn.style.display = 'none';
btn.click(); // // // 自动结束
} catch { // // else if (WuhuConfig.get('autoStartFinish')) {
} // // try {
} // // btn.click();
}); // // } catch {
}).observe(wrap, { subtree: true, attributes: true, childList: true }); // // }
} // // }
return; // // });
} // // }).observe(wrap, { subtree: true, attributes: true, childList: true });
// // }
// 错误的攻击页面 //
if (WuhuConfig.get('attRelocate') && href.includes('loader2.php')) { // new MutationObserver((_, mut) => {
const spl = window.location.href.trim().split('='); // let btnList = document.querySelectorAll('div[class^="dialogButtons___"] button') as NodeListOf<HTMLButtonElement>;
const uid = spl[spl.length - 1]; // if (btnList.length === 0) {
if (!/^\d+$/.test(uid)) return; // // 错误或正在打
window.location.href = `https://www.torn.com/loader.php?sid=attack&user2ID=${ uid }`; // currentStage = FIGHT_STAGE.IN_PROGRESS_OR_ERROR;
return; // Log.info('[attackHelper] currentStage', currentStage);
} // return;
} // }
// btnList.forEach(btn => {
// 战斗页面快速刷新 // if (btn.innerText.toLowerCase().includes('start')) {
function doAttackReload() { // // 开始
if (!window.ReactDOM) { // quickStartFight();
new Alert('光速刷新失败未找到React对象'); // } else if (btn.innerText.toLowerCase().includes('continue')) {
return; // // 结束end
} // currentStage = FIGHT_STAGE.END;
let react_root = document.querySelector('#react-root'); // mut.disconnect();
if (!react_root.querySelector('#attacker')) return; // } else if (btn.innerText.toLowerCase().includes('leave')) {
let script = document.querySelector('script[src*="/builds/attack/"]'); // // 无意识状态FINISHED
let url = script.src; // quickFinishFight(btnList);
if (!url.contains('app.js')) return; // }
window.ReactDOM.unmountComponentAtNode(react_root); // Log.info('[attackHelper] currentStage', currentStage);
script.remove(); // })
let node = document.createElement('script'); // })
node.src = url; // .observe(document.querySelector('#react-root'), { childList: true, subtree: true });
node.type = 'text/javascript'; //
document.head.appendChild(node); // // 盯梢模式
} // 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: () => watchTarget(),
// cancel: () => watchSwitch.getInput().checked = false
// });
// } else {
// Log.info('guanbi');
// }
// });
//
// return;
// }
//
// // 错误的攻击页面
// if (WuhuConfig.get('attRelocate') && href.includes('loader2.php')) {
// const spl = window.location.href.trim().split('=');
// const uid = spl[spl.length - 1];
// if (!/^\d+$/.test(uid)) return;
// window.location.href = `https://www.torn.com/loader.php?sid=attack&user2ID=${ uid }`;
// return;
// }
// }
//
// // 战斗页面快速刷新
// function doAttackReload() {
// if (!window.ReactDOM) {
// new Alert('光速刷新失败未找到React对象');
// return;
// }
// let react_root = document.querySelector('#react-root');
// if (!react_root.querySelector('#attacker')) return;
// let script = document.querySelector('script[src*="/builds/attack/"]');
// let url = script.src;
// if (!url.contains('app.js')) return;
// window.ReactDOM.unmountComponentAtNode(react_root);
// script.remove();
// let node = document.createElement('script');
// node.src = url;
// node.type = 'text/javascript';
// document.head.appendChild(node);
// }
//
// // 光速拔刀
// function quickStartFight(): void {
// if (currentStage === FIGHT_STAGE.READY) {
// return;
// } else {
// currentStage = FIGHT_STAGE.READY;
// }
// if (WuhuConfig.get('quickAttIndex') === 6) return;
// /**
// * pc #defender
// * mobile #attacker
// */
// const btn = <HTMLInputElement>(document.querySelector('#attacker button') || document.querySelector('#defender button'));
// Log.info('操作按钮', { btn });
// if (!btn.innerText.toLowerCase().includes('fight')) {
// Log.info('未找到攻击按钮, 光速拔刀跳过');
// new Alert('未找到攻击按钮, 光速拔刀跳过');
// } else {
// // 判断是否存在脚踢
// const hasKick = !!document.querySelector('#weapon_boots');
// // modal层
// // const modal: HTMLElement = document.querySelector('div[class^="modal___"]');
// let device = Global.getInstance().device;
// Log.info(`当前设备类型是${ device }`);
// // 区分设备
// switch (device) {
// case Device.PC: {
// Log.info(`开始调整按钮位置`);
// // 隐藏modal层
// // modal.style.display = 'none';
// // 根据选择的武器调整css
// let css_top = '0';
// switch (WuhuConfig.get('quickAttIndex')) {
// // weapon_second
// case 1: {
// css_top = '97px';
// break;
// }
// // weapon_melee
// case 2: {
// css_top = '194px';
// break;
// }
// // weapon_temp
// case 3: {
// css_top = '291px';
// break;
// }
// // weapon_fists
// case 4:
// // weapon_boots
// case 5: {
// css_top = '375px';
// break;
// }
// }
// CommonUtils.addStyle(ATTACK_HELPER_CSS);
// CommonUtils.addStyle(`.wh-move-btn #defender div[class^="modal___"]{top: ${ css_top };}`);
// document.body.classList.add('wh-move-btn');
// break;
// }
// case Device.MOBILE: {
// Log.info(`开始调整按钮位置`);
// // 加入css
// let css_top = '0';
// let slot_height = '76px';
// // 判断有没有脚踢
// if (hasKick) {
// // 根据选择的武器调整
// switch (WuhuConfig.get('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 (WuhuConfig.get('quickAttIndex')) {
// case 1: { // weapon_second
// css_top = `${ height }px`;
// break;
// }
// case 2: { // weapon_melee
// css_top = `${ height * 2 }px`;
// break;
// }
// case 3: { // weapon_temp
// css_top = `${ height * 3 }px`;
// break;
// }
// case 4: { // weapon_fists
// css_top = `${ height * 4 }px`;
// break;
// }
// case 5: { // weapon_boots
// css_top = `${ height * 5 }px`;
// break;
// }
// }
// }
// const css_rule = ATTACK_HELPER_CSS.replace('CSSVAR', css_top).replace('CSSVAR', slot_height);
// // `
// // .wh-move-btn #attacker div[class^="modal___"]{display: block;width: 0;top: ${ css_top };left:0;height:0;}
// // .wh-move-btn #attacker div[class^="dialog___"]{border:0;width:80px;height:${ slot_height };}
// // .wh-move-btn #attacker div[class^="colored___"]{display:block;padding:0;}
// // .wh-move-btn #attacker div[class^="title___"]{height:0;}
// // .wh-move-btn #attacker button{width:100%;margin:0;height:63px;white-space:normal;}
// // `;
// CommonUtils.addStyle(css_rule);
// document.body.classList.toggle('wh-move-btn');
// btn.onclick = () => {
// if (WuhuConfig.get('quickFinishAtt') !== 3) {
// btn.remove();
// // 停止自动刷新
// // stop_reload = true;
// } else {
// document.body.classList.toggle('wh-move-btn');
// }
// };
// break;
// }
// case Device.TABLET: {
// break;
// }
// }
// }
// }
//
// // 光速跑路
// function quickFinishFight(btnList: NodeListOf<HTMLButtonElement>): void {
// if (currentStage === FIGHT_STAGE.FINISHED) {
// return;
// } else {
// currentStage = FIGHT_STAGE.FINISHED;
// }
// if (WuhuConfig.get('quickFinishAtt') === 3) return;
// const user_btn_select = ['leave', 'mug', 'hosp'][WuhuConfig.get('quickFinishAtt')];
// // const wrap = document.querySelector('#react-root');
// Log.info('光速跑路选项选中:', user_btn_select);
// // new MutationObserver((mut, obs) => {
// // 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);
// Log.info('按钮内容:', btn.innerText, ',是否包含选中:', flag);
// if (!flag) btn.style.display = 'none';
// // 自动结束
// // else if (WuhuConfig.get('autoStartFinish')) {
// // try {
// // btn.click();
// // } catch {
// // }
// // }
// });
// // }).observe(wrap, { subtree: true, attributes: true, childList: true });
// }
//
// function watchTarget(): void {
// Log.info('获取目标id');
// let targetId = window.location.href.split('user2ID=')[1];
// if (!CommonUtils.getInstance().isValidUid(targetId)) {
// Log.error('目标id获取错误', targetId);
// throw new Error('目标id获取错误:' + targetId);
// }
// }

View File

@ -89,7 +89,11 @@ export default function depoHelper() {
let getTraceMoney = async () => { let getTraceMoney = async () => {
if (typeof addRFC === 'function') { if (typeof addRFC === 'function') {
let url = addRFC('/trade.php?step=getFullMoney&ID=' + traceId); let url = addRFC('/trade.php?step=getFullMoney&ID=' + traceId);
return (await CommonUtils.ajaxFetch({ url: url, method: 'GET', referrer: 'trade.php' })).text(); return (await FetchUtils.getInstance().ajaxFetch({
url: url,
method: 'GET',
referrer: 'trade.php'
})).text();
} }
}; };
// 监听jquery ajax请求 // 监听jquery ajax请求
@ -148,7 +152,7 @@ export default function depoHelper() {
new Alert('无法定额取钱,原因:数不对'); new Alert('无法定额取钱,原因:数不对');
return; return;
} }
await CommonUtils.ajaxFetch({ await FetchUtils.getInstance().ajaxFetch({
url: addRFC('/trade.php'), url: addRFC('/trade.php'),
method: 'POST', method: 'POST',
referrer: 'trade.php', referrer: 'trade.php',
@ -160,7 +164,7 @@ export default function depoHelper() {
buttonDepositAll.addEventListener('click', async () => { buttonDepositAll.addEventListener('click', async () => {
let money = await getTraceMoney(); let money = await getTraceMoney();
if (money === '0') return; if (money === '0') return;
await CommonUtils.ajaxFetch({ await FetchUtils.getInstance().ajaxFetch({
url: addRFC('/trade.php'), url: addRFC('/trade.php'),
method: 'POST', method: 'POST',
referrer: 'trade.php', referrer: 'trade.php',
@ -170,7 +174,7 @@ export default function depoHelper() {
}); });
// 全取 // 全取
buttonWithdrawAll.addEventListener('click', async () => { buttonWithdrawAll.addEventListener('click', async () => {
await CommonUtils.ajaxFetch({ await FetchUtils.getInstance().ajaxFetch({
url: addRFC('/trade.php'), url: addRFC('/trade.php'),
method: 'POST', method: 'POST',
referrer: 'trade.php', referrer: 'trade.php',

View File

@ -10,241 +10,241 @@ import TRAVEL_ALARM_CSS from "../../static/css/travel_alarm.css";
import TRAVEL_ALARM_HTML from "../../static/html/travel_alarm.html"; import TRAVEL_ALARM_HTML from "../../static/html/travel_alarm.html";
import TornStyleBlock from "../../class/utils/TornStyleBlock"; import TornStyleBlock from "../../class/utils/TornStyleBlock";
import QuickFlyBtnHandler from "../../class/handler/QuickFlyBtnHandler"; import QuickFlyBtnHandler from "../../class/handler/QuickFlyBtnHandler";
import TRAVEL_STATE from "../../enum/TravelState";
export default async function travelHelper(): Promise<null> { export default async function travelHelper(): Promise<void> {
let { href, bodyAttrs, device } = WuhuBase.glob; let { href, bodyAttrs, device } = WuhuBase.glob;
// URL判断 + 人不在城内 if (href.includes('index.php')) {
if (href.includes('index.php') && bodyAttrs['data-abroad'] === 'true') { switch (CommonUtils.getInstance().getTravelStage()) {
// 飞行中 // 飞行中
if (bodyAttrs["data-traveling"] === 'true') { case TRAVEL_STATE.FLYING: {
// 飞行闹钟 // 飞行闹钟
if (device === Device.PC && WuhuConfig.get('trvAlarm')) { if (device === Device.PC && WuhuConfig.get('trvAlarm')) {
// 获取目的地 // 获取目的地
let dest_cn; let dest_cn;
let country = document.body.getAttribute('data-country'); let country = document.body.getAttribute('data-country');
if (country === 'torn') { if (country === 'torn') {
dest_cn = '回城'; dest_cn = '回城';
} else {
dest_cn = {
'uk': "英国", 'switzerland': "瑞士", 'mexico': '墨西哥', 'canada': '加拿大', 'cayman': '开曼',
'hawaii': '夏威夷', 'argentina': '阿根廷',
'japan': '日本', 'china': '中国', 'uae': 'UAE', 'south-africa': '南非',
}[country] || country;
}
// 剩余时间
const remaining_arr = document.querySelector('#countrTravel').getAttribute('data-to');
const wh_trv_alarm = localStorage.getItem('wh_trv_alarm')
? JSON.parse(localStorage.getItem('wh_trv_alarm'))
: { 'enable': true, 'alert_time': 30, 'node_pos': [240, 240] };
const save_trv_settings = () => localStorage.setItem('wh_trv_alarm', JSON.stringify(wh_trv_alarm));
const wh_trv_alarm_node = document.createElement('div');
wh_trv_alarm_node.id = 'wh-trv-alarm';
wh_trv_alarm_node.style.left = `${ wh_trv_alarm.node_pos[0] }px`;
wh_trv_alarm_node.style.top = `${ wh_trv_alarm.node_pos[1] }px`;
wh_trv_alarm_node.innerHTML = TRAVEL_ALARM_HTML
.replace('{{}}', dest_cn === '回城' ? dest_cn : '飞往' + dest_cn)
.replace('{{}}', wh_trv_alarm.enable ? 'checked ' : '')
.replace('{{}}', wh_trv_alarm.alert_time || 30);
CommonUtils.addStyle(TRAVEL_ALARM_CSS);
document.body.append(wh_trv_alarm_node);
// 报错dom
const error_node = wh_trv_alarm_node.querySelector('#wh-trv-error') as HTMLElement;
// jquery拖动
// @ts-ignore
$(wh_trv_alarm_node).draggable({
containment: "body",
distance: 5,
handle: "#wh-trv-alarm-title",
stop: () => {
wh_trv_alarm.node_pos = [parseInt(wh_trv_alarm_node.style.left), parseInt(wh_trv_alarm_node.style.top)];
save_trv_settings();
},
scroll: false,
});
// 剩余时间dom
const remaining_node = wh_trv_alarm_node.querySelector('#wh-trv-alarm-remaining');
// 设定闹钟响的按钮
const set_node = wh_trv_alarm_node.querySelectorAll('#wh-trv-alarm-cont button')[0] as HTMLButtonElement;
// 落地前响铃时长
const cd_time = wh_trv_alarm_node.querySelector('input[type="number"]') as HTMLInputElement;
let count_down_notify: MyHTMLElement | { close: Function } = {
close: () => {
}
};
set_node.onclick = () => {
try {
wh_trv_alarm.alert_time = parseInt(cd_time.value);
} catch {
wh_trv_alarm.alert_time = 30;
}
save_trv_settings();
set_node.value = wh_trv_alarm.alert_time;
count_down_notify.close();
count_down_notify = new Alert('设置已更新');
};
// 停止响铃按钮
const stop_node = wh_trv_alarm_node.querySelectorAll('#wh-trv-alarm-cont button')[1] as HTMLButtonElement;
stop_node.onclick = () => {
user_stop_alert = true;
stop_node.innerText = '本次已关闭';
stop_node.disabled = true;
}
// 开启闹钟勾选
const enable_node = wh_trv_alarm_node.querySelector('#wh-trv-alarm-cont input[type="checkbox"]') as HTMLInputElement;
let on_off_notify: MyHTMLElement | { close: Function } = {
close: () => {
}
};
enable_node.onchange = ev => {
wh_trv_alarm.enable = (<HTMLInputElement>ev.target).checked;
save_trv_settings();
on_off_notify.close();
on_off_notify = new Alert(wh_trv_alarm.enable ? '闹钟已开启' : '闹钟已关闭');
};
// 剩余时间 秒
const remaining_sec = parseInt(remaining_arr);
// 落地时timestamp
const land_timestamp = Date.now() + remaining_sec * 1000;
// 音频dom
const audio = document.createElement('audio');
audio.src = 'https://www.torn.com/js/chat/sounds/Warble_1.mp3';
audio.play()
.then(() => audio.pause())
.catch(() => {
error_node.style.display = 'table';
const func = () => {
error_node.remove();
document.body.removeEventListener('click', func);
};
document.body.addEventListener('click', func);
});
// 是否正在响铃
let audio_play_flag = false;
// 用户是否停止当前响铃
let user_stop_alert = false;
// 响铃循环id
let audio_play_id = null;
// 响铃的方法
let audio_play_handle = () => {
if (user_stop_alert) {
clearInterval(audio_play_id);
audio_play_id = null;
return;
}
if (!audio_play_flag || !wh_trv_alarm.enable) return;
audio.play().then();
};
// 飞机小动画字符
const flying_arr = [
'✈ ',
'&nbsp;&nbsp;✈ ',
'&nbsp;&nbsp;&nbsp;&nbsp;✈ ',
'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;✈ ',
'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;✈ ',
'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;✈ ',
'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;✈ ',
'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;✈ ',
'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;✈ ',
'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;✈ ',
];
// 飞行的状态dom
const flying_status = wh_trv_alarm_node.querySelector('#wh-trv-status');
// 飞机的小动画dom
const flying_ani = flying_status.nextElementSibling;
// 飞机的计数
let flying_index = 0;
const id = window.setInterval(() => {
const remaining_time = (land_timestamp - Date.now()) / 1000 | 0;
remaining_node.innerText = `${ remaining_time / 3600 | 0 }${ remaining_time % 3600 / 60 | 0 }${ remaining_time % 60 }`;
if (remaining_time < wh_trv_alarm.alert_time) {
// flying_status.innerHTML = `即将落地...`;
if (wh_trv_alarm.enable) {
// 播放提示音
audio_play_flag = true;
if (audio_play_id === null && !user_stop_alert) audio_play_id = window.setInterval(audio_play_handle, 750);
stop_node.parentElement.classList.remove('wh-trv-alarm-stop-hide');
}
} else { } else {
// flying_status.innerHTML = `飞行中...`; dest_cn = {
if (wh_trv_alarm.enable) { 'uk': "英国",
'switzerland': "瑞士",
'mexico': '墨西哥',
'canada': '加拿大',
'cayman': '开曼',
'hawaii': '夏威夷',
'argentina': '阿根廷',
'japan': '日本',
'china': '中国',
'uae': 'UAE',
'south-africa': '南非',
}[country] || country;
}
// 剩余时间
const remaining_arr = document.querySelector('#countrTravel').getAttribute('data-to');
const wh_trv_alarm = localStorage.getItem('wh_trv_alarm')
? JSON.parse(localStorage.getItem('wh_trv_alarm'))
: { 'enable': true, 'alert_time': 30, 'node_pos': [240, 240] };
const save_trv_settings = () => localStorage.setItem('wh_trv_alarm', JSON.stringify(wh_trv_alarm));
const wh_trv_alarm_node = document.createElement('div');
wh_trv_alarm_node.id = 'wh-trv-alarm';
wh_trv_alarm_node.style.left = `${ wh_trv_alarm.node_pos[0] }px`;
wh_trv_alarm_node.style.top = `${ wh_trv_alarm.node_pos[1] }px`;
wh_trv_alarm_node.innerHTML = TRAVEL_ALARM_HTML
.replace('{{}}', dest_cn === '回城' ? dest_cn : '飞往' + dest_cn)
.replace('{{}}', wh_trv_alarm.enable ? 'checked ' : '')
.replace('{{}}', wh_trv_alarm.alert_time || 30);
CommonUtils.addStyle(TRAVEL_ALARM_CSS);
document.body.append(wh_trv_alarm_node);
// 报错dom
const error_node = wh_trv_alarm_node.querySelector('#wh-trv-error') as HTMLElement;
// jquery拖动
// @ts-ignore
$(wh_trv_alarm_node).draggable({
containment: "body",
distance: 5,
handle: "#wh-trv-alarm-title",
stop: () => {
wh_trv_alarm.node_pos = [parseInt(wh_trv_alarm_node.style.left), parseInt(wh_trv_alarm_node.style.top)];
save_trv_settings();
},
scroll: false,
});
// 剩余时间dom
const remaining_node = wh_trv_alarm_node.querySelector('#wh-trv-alarm-remaining');
// 设定闹钟响的按钮
const set_node = wh_trv_alarm_node.querySelectorAll('#wh-trv-alarm-cont button')[0] as HTMLButtonElement;
// 落地前响铃时长
const cd_time = wh_trv_alarm_node.querySelector('input[type="number"]') as HTMLInputElement;
let count_down_notify: MyHTMLElement | { close: Function } = {
close: () => {
}
};
set_node.onclick = () => {
try {
wh_trv_alarm.alert_time = parseInt(cd_time.value);
} catch {
wh_trv_alarm.alert_time = 30;
}
save_trv_settings();
set_node.value = wh_trv_alarm.alert_time;
count_down_notify.close();
count_down_notify = new Alert('设置已更新');
};
// 停止响铃按钮
const stop_node = wh_trv_alarm_node.querySelectorAll('#wh-trv-alarm-cont button')[1] as HTMLButtonElement;
stop_node.onclick = () => {
user_stop_alert = true;
stop_node.innerText = '本次已关闭';
stop_node.disabled = true;
}
// 开启闹钟勾选
const enable_node = wh_trv_alarm_node.querySelector('#wh-trv-alarm-cont input[type="checkbox"]') as HTMLInputElement;
let on_off_notify: MyHTMLElement | { close: Function } = {
close: () => {
}
};
enable_node.onchange = ev => {
wh_trv_alarm.enable = (<HTMLInputElement>ev.target).checked;
save_trv_settings();
on_off_notify.close();
on_off_notify = new Alert(wh_trv_alarm.enable ? '闹钟已开启' : '闹钟已关闭');
};
// 剩余时间 秒
const remaining_sec = parseInt(remaining_arr);
// 落地时timestamp
const land_timestamp = Date.now() + remaining_sec * 1000;
// 音频dom
const audio = document.createElement('audio');
audio.src = 'https://www.torn.com/js/chat/sounds/Warble_1.mp3';
audio.play()
.then(() => audio.pause())
.catch(() => {
error_node.style.display = 'table';
const func = () => {
error_node.remove();
document.body.removeEventListener('click', func);
};
document.body.addEventListener('click', func);
});
// 是否正在响铃
let audio_play_flag = false;
// 用户是否停止当前响铃
let user_stop_alert = false;
// 响铃循环id
let audio_play_id = null;
// 响铃的方法
let audio_play_handle = () => {
if (user_stop_alert) {
clearInterval(audio_play_id); clearInterval(audio_play_id);
audio_play_id = null; audio_play_id = null;
stop_node.parentElement.classList.add('wh-trv-alarm-stop-hide'); return;
} }
} if (!audio_play_flag || !wh_trv_alarm.enable) return;
flying_ani.innerHTML = `${ flying_arr[flying_index] }`; audio.play().then();
flying_index = (flying_index + 1) % flying_arr.length; };
}, 1000); // 飞机小动画字符
} const flying_arr = [
'✈ ',
'&nbsp;&nbsp;✈ ',
'&nbsp;&nbsp;&nbsp;&nbsp;✈ ',
'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;✈ ',
'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;✈ ',
'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;✈ ',
'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;✈ ',
'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;✈ ',
'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;✈ ',
'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;✈ ',
];
// 飞行的状态dom
const flying_status = wh_trv_alarm_node.querySelector('#wh-trv-status');
// 飞机的小动画dom
const flying_ani = flying_status.nextElementSibling;
// 飞机的计数
let flying_index = 0;
const id = window.setInterval(() => {
const remaining_time = (land_timestamp - Date.now()) / 1000 | 0;
remaining_node.innerText = `${ remaining_time / 3600 | 0 }${ remaining_time % 3600 / 60 | 0 }${ remaining_time % 60 }`;
// 落地转跳 落地前事件 if (remaining_time < wh_trv_alarm.alert_time) {
if (WuhuConfig.get('landedRedirect') && document.querySelector('#tcLogo[title]') === null) { // flying_status.innerHTML = `即将落地...`;
window.addEventListener('beforeunload', () => { if (wh_trv_alarm.enable) {
let obj = { url: WuhuConfig.get('landedRedirect'), timestamp: Date.now() }; // 播放提示音
sessionStorage['wh-landed-redirect'] = JSON.stringify(obj); audio_play_flag = true;
}); if (audio_play_id === null && !user_stop_alert) audio_play_id = window.setInterval(audio_play_handle, 750);
stop_node.parentElement.classList.remove('wh-trv-alarm-stop-hide');
}
} else {
// flying_status.innerHTML = `飞行中...`;
if (wh_trv_alarm.enable) {
clearInterval(audio_play_id);
audio_play_id = null;
stop_node.parentElement.classList.add('wh-trv-alarm-stop-hide');
}
}
flying_ani.innerHTML = `${ flying_arr[flying_index] }`;
flying_index = (flying_index + 1) % flying_arr.length;
}, 1000);
}
// 落地转跳 落地前事件
if (WuhuConfig.get('landedRedirect') && document.querySelector('#tcLogo[title]') === null) {
window.addEventListener('beforeunload', () => {
let obj = { url: WuhuConfig.get('landedRedirect'), timestamp: Date.now() };
sessionStorage['wh-landed-redirect'] = JSON.stringify(obj);
});
}
break;
} }
} // 海外落地
// 不在飞行中 海外落地页面 case TRAVEL_STATE.ABROAD: {
else { // 一键回城
// 一键回城 ActionButtonUtils.getInstance().add('直接回城', travelBack);
ActionButtonUtils.getInstance().add('直接回城', travelBack); // 海外警告
// 海外警告 if (WuhuConfig.get('abroadWarning')) {
if (WuhuConfig.get('abroadWarning')) { let c = 1;
let c = 1; setInterval(() => new Alert(`警告:您已海外落地${ c++ * 30 }`, {
setInterval(() => new Alert(`警告:您已海外落地${ c++ * 30 }`, { timeout: 30,
timeout: 30, sysNotify: true
sysNotify: true }), 30000);
}), 30000); }
// 解毒提醒
if (bodyAttrs['data-country'] === 'switzerland') {
let block = new TornStyleBlock('解毒提醒');
block.setContent('<p><a href="/index.php?page=rehab">❤️ 点击前往解毒</a></p>');
document.querySelector('h4#skip-to-content').before(block.getBase());
}
break;
} }
// 解毒提醒 // 主页界面
if (bodyAttrs['data-country'] === 'switzerland') { case TRAVEL_STATE.IN_TORN: {
let block = new TornStyleBlock('解毒提醒'); // 落地转跳
block.setContent('<p><a href="/index.php?page=rehab">❤️ 点击前往解毒</a></p>'); if (sessionStorage['wh-landed-redirect']) {
document.querySelector('h4#skip-to-content').before(block.getBase()); let { url, timestamp } = JSON.parse(sessionStorage['wh-landed-redirect']);
// let page_title = document.querySelector('h4#skip-to-content'); if (Date.now() - timestamp < 30000) {
// let msg = document.createElement('div'); sessionStorage.removeItem('wh-landed-redirect');
// msg.innerHTML = `<div class="info-msg border-round"> location.href = url;
// <i class="info-icon"></i> }
// <div class="delimiter"> }
// <div class="msg right-round" tabindex="0" role="alert"> break;
// <p><a href="/index.php?page=rehab">❤️ 点击前往解毒</a></p>
// </div>
// </div>
// </div>`;
// msg.classList.add('info-msg-cont', 'green', 'border-round', 'm-bottom10');
// page_title.before(msg);
}
}
return;
}
// URL判断 + 人在城内
else if (href.includes('index.php') && bodyAttrs['data-abroad'] === 'false') {
// 落地转跳
if (sessionStorage['wh-landed-redirect']) {
let { url, timestamp } = JSON.parse(sessionStorage['wh-landed-redirect']);
if (Date.now() - timestamp < 30000) {
sessionStorage.removeItem('wh-landed-redirect');
location.href = url;
} }
} }
} }
// 起飞页面 // 起飞页面
if (href.contains(/travelagency\.php/)) { else if (href.contains(/travelagency\.php/)) {
// 起飞提醒 // 起飞提醒 TODO 去除jquery mutation
if (WuhuConfig.get('energyAlert')) { if (WuhuConfig.get('energyAlert')) {
const $$ = $('.content-wrapper'); const contentWrapper = document.querySelector('.content-wrapper');
const OB = new MutationObserver(() => { const OB = new MutationObserver(() => {
OB.disconnect(); OB.disconnect();
titleTrans(); titleTrans();
contentTitleLinksTrans(); contentTitleLinksTrans();
trans(); trans();
OB.observe($$.get(0), { OB.observe(contentWrapper, {
characterData: true, characterData: true,
attributes: true, attributes: true,
subtree: true, subtree: true,
@ -277,7 +277,7 @@ export default async function travelHelper(): Promise<null> {
}); });
}; };
trans(); trans();
OB.observe($$.get(0), { OB.observe(contentWrapper, {
characterData: true, characterData: true,
attributes: true, attributes: true,
subtree: true, subtree: true,

View File

@ -0,0 +1,46 @@
export default interface IUserProfileData {
user: {
playerName: string,
userID: number,
displayPersonalDetails: boolean,
isFriend: boolean,
isEnemy: boolean,
signUp: number,
role: string,
sendMoneyWarning: string
};
currentUser: {
"playerName": string,
"userID": number,
"money": number,
"canSendAnonymously": boolean,
"loggedIn": boolean
};
userInformation: {
"name": string,
"previousAliases": string[],
"level": number,
"rank": {
"userTitle": string,
"userRank": string
},
"age": number,
"honorTitle": string,
"image": unknown
};
profileButtons: unknown;
userStatus: {
"status": {
"type": "ok" | "traveling-from" | "abroad-hospital" | "abroad"
},
"trait": {
"loot": unknown
}
};
medalInformation: unknown;
basicInformation: unknown;
personalInformation: unknown;
competitionStatus: unknown;
staffTools: null;
profileSignature: null;
}

View File

@ -0,0 +1,16 @@
<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,18 +1,19 @@
import WuhuBase from "../class/WuhuBase"; import WuhuBase from "../class/WuhuBase";
import Log from "../class/Log"; import Log from "../class/Log";
import DialogMsgBox from "../class/utils/DialogMsgBox"; import CommonUtils from "../class/utils/CommonUtils";
import TornStyleBlock from "../class/utils/TornStyleBlock";
import Popup from "../class/utils/Popup";
export default class Test extends WuhuBase { export default class Test extends WuhuBase {
className = 'Test'; className = 'Test';
public test(): void { public test(): void {
// let popup = new Popup(''); let popup = new Popup(CommonUtils.getInstance().getTravelStage().toString());
// popup.getElement()['__POOL__'] = Test.getPool(); popup.getElement()['__POOL__'] = Test.getPool();
// this.case1() // this.case1()
// this.case2() // this.case2()
this.case3().then(); this.case3().then();
// window.fetch('/test').then(res=>res.text()).then(o=>Log.info(o))
} }
private case1() { private case1() {
@ -50,6 +51,6 @@ export default class Test extends WuhuBase {
} }
private async case3() { private async case3() {
new DialogMsgBox('123', { callback: () => alert(1) }) new TornStyleBlock('1').insert2Dom();
} }
} }