diff --git a/global.d.ts b/global.d.ts index f596659..3910e76 100644 --- a/global.d.ts +++ b/global.d.ts @@ -18,10 +18,14 @@ declare interface Window { // 插件运行标识 WHTRANS?: number; Vue?: Function; - /* 油猴脚本引擎自带 */ + /** + * 油猴脚本引擎自带 + */ unsafeWindow?: Window & typeof globalThis; - - GM: any; + /** + * google + */ + _gaUserPrefs?: unknown; GM_xmlhttpRequest(init: GM_RequestParams): void; @@ -29,26 +33,25 @@ declare interface Window { GM_setValue(k: string, v: any): void; - // google不跟踪标识 - _gaUserPrefs?: unknown; + /** + * TORN自带 + */ + ReactDOM?: any; dataLayer?: unknown; eval(exc: string): void; - /* TORN自带 */ - ReactDOM?: any; - addRFC(url: URL | string): string; - // initMiniProf(selector: string): void; - getAction(opt: TornGetActionParams): void; initializeTooltip(selector: string, elemId: string): void; renderMiniProfile(node: Element, props: any): never; - /* PDA自带 */ + /** + * PDA自带 + */ PDA_httpGet(url: URL | string): Promise; PDA_httpPost(url: URL | string, init: any, body: any): Promise; @@ -114,4 +117,6 @@ declare module "*.css" { export default value; } -declare function GM_xmlhttpRequest(init: any): void; \ No newline at end of file +declare function GM_xmlhttpRequest(init: any): void; + +declare var unsafeWindow: Window & typeof globalThis; \ No newline at end of file diff --git a/src/class/Global.ts b/src/class/Global.ts index cffc3a7..89e00c7 100644 --- a/src/class/Global.ts +++ b/src/class/Global.ts @@ -10,12 +10,14 @@ import BuyBeerHelper from "./action/BuyBeerHelper"; */ export default class Global extends WuhuBase implements IGlobal { className = 'Global'; - GM_xmlhttpRequest: Function = null; + GM_xmlhttpRequest: Function = null; href: string = window.location.href; // 弹窗 popup_node: MyHTMLElement = null; - // 啤酒助手 + /** + * @deprecated 使用getInstance替代 + */ beer = null; // 留存的通知 notifies: NotifyWrapper = null; @@ -45,11 +47,18 @@ export default class Global extends WuhuBase implements IGlobal { constructor() { Log.info('WH脚本参数[Global]初始化'); super(); - this.unsafeWindow = window.unsafeWindow || null; - try { - // 上层调用如果使用eval此处GM_xmlhttpRequest可能不存在与window中 + if (typeof unsafeWindow !== 'undefined') { + Log.info('存在unsafeWindow, 引入'); + this.unsafeWindow = unsafeWindow || null; + window.addRFC = this.unsafeWindow.addRFC; + window.getAction = this.unsafeWindow.getAction; + window.initializeTooltip = this.unsafeWindow.initializeTooltip; + window.renderMiniProfile = this.unsafeWindow.renderMiniProfile; + window.ReactDOM = this.unsafeWindow.ReactDOM; + } + if (typeof GM_xmlhttpRequest === 'function') { + // 上层调用如果使用eval此处GM_xmlhttpRequest可能不存在于window中 this.GM_xmlhttpRequest = window.GM_xmlhttpRequest || GM_xmlhttpRequest || null; - } catch { } this.version = '$$WUHU_DEV_VERSION$$'; this.PDA_APIKey = '###PDA-APIKEY###'; @@ -62,15 +71,6 @@ export default class Global extends WuhuBase implements IGlobal { this.href = window.location.href; this.bodyAttrs = {}; - if (this.unsafeWindow) { - Log.info('存在unsafeWindow, 引入部分torn公共方法'); - 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; - } - for (let i = 0; i < document.body.attributes.length; i++) { let item = document.body.attributes.item(i); this.bodyAttrs[item.name] = item.value; diff --git a/src/class/Log.ts b/src/class/Log.ts index 7925146..4c9ef54 100644 --- a/src/class/Log.ts +++ b/src/class/Log.ts @@ -61,7 +61,7 @@ export default class Log { if (typeof item === 'string') this.logs += item; else if (item !== null && item !== undefined) { let json = '{}'; - let name = 'UNKNOWN_OBJECT' + let name = item.toString ? item.toString() : 'UNKNOWN_OBJECT'; try { json = JSON.stringify(item); name = Object.getPrototypeOf(item).constructor.name; diff --git a/src/class/UrlMatch.ts b/src/class/UrlMatch.ts index b7216a9..93aea45 100644 --- a/src/class/UrlMatch.ts +++ b/src/class/UrlMatch.ts @@ -63,11 +63,9 @@ export default class UrlPattern extends WuhuBase { beer.innerHTML = SHOP_BEER_STATIC_ITEM_HTML; if (clear_node) clear_node.before(beer); else node.append(beer); - // (e.target).remove(); (e.target).disabled = true; msg_node.innerHTML = '添加成功'; }); - // }); // 监听啤酒购买 $(document).ajaxComplete((_, xhr, settings) => { @@ -76,7 +74,6 @@ export default class UrlPattern extends WuhuBase { let response = JSON.parse(responseText); if (data.includes('step=buyShopItem') && data.includes('ID=180') && response['success']) { new Alert('已检测成功购买啤酒'); - // Global.getInstance().beer.skip_today(); BuyBeerHelper.getInstance().skip_today(); } }); @@ -84,6 +81,7 @@ export default class UrlPattern extends WuhuBase { // 快速crime TODO 重构、与翻译解藕 if (href.contains(/crimes\.php/) && WuhuConfig.get('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'); @@ -112,13 +110,14 @@ export default class UrlPattern extends WuhuBase { }); const trans = () => { const dom = QUICK_CRIMES_HTML; - const is_wh_translate = element.querySelector('.wh-translate') !== null; - const is_captcha = element.querySelector('div#tab-menu.captcha') !== null; - const $title = $('div.content-title'); - const $info = $('.info-msg-cont'); - if (!is_wh_translate && !is_captcha) { - if ($title.length > 0) $title.before(dom); - else if ($info.length > 0) $info.before(dom); + 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(); @@ -132,13 +131,13 @@ export default class UrlPattern extends WuhuBase { // 任务助手 TODO 重构、与翻译解藕 if (href.contains(/loader\.php\?sid=missions/) && WuhuConfig.get('missionHint')) { - const $$ = $('.content-wrapper'); + const anchor = document.querySelector('.content-wrapper'); const OB = new MutationObserver(() => { OB.disconnect(); // titleTrans(); // contentTitleLinksTrans(); trans(); - OB.observe($$.get(0), { + OB.observe(anchor, { characterData: true, attributes: true, subtree: true, @@ -148,16 +147,18 @@ export default class UrlPattern extends WuhuBase { const taskList = {}; const trans = () => { $('ul#giver-tabs a.ui-tabs-anchor').each((i, e) => { - if ($(e).children().hasClass('mission-complete-icon')) { + 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(); + taskList[i] = $e.clone().children().remove().end().text().trim(); } }); // 助手注入 $('div.max-height-fix.info').each((i, e) => { - if ($(e).find('.wh-translated').length !== 0) return; - $(e).append(`
任务助手

${ getTaskHint(taskList[i]) }

`); + let $e = $(e); + if ($e.find('.wh-translated').length !== 0) return; + $e.append(`
任务助手

${ getTaskHint(taskList[i]) }

`); }); // 任务目标 $('ul.tasks-list span.title-wrap').contents().each((i, e) => { @@ -169,7 +170,7 @@ export default class UrlPattern extends WuhuBase { }); }; trans(); - OB.observe($$.get(0), { + OB.observe(anchor, { characterData: true, attributes: true, subtree: true, diff --git a/src/class/WuhuTornHelper.ts b/src/class/WuhuTornHelper.ts index 759d365..0a25f91 100644 --- a/src/class/WuhuTornHelper.ts +++ b/src/class/WuhuTornHelper.ts @@ -38,8 +38,8 @@ export default class WuHuTornHelper extends WuhuBase { }; // 监听fetch - const ori_fetch = window.fetch; - window.fetch = (url: string, init: RequestInit) => { + let ori_fetch = window.fetch; + let fetchHandle: (string, RequestInit) => Promise = (url: string, init: RequestInit) => { let startTime = performance.now(); Log.info('FETCH调用:[' + url + '], init:', init); return new Promise(resolve => { @@ -66,6 +66,10 @@ export default class WuHuTornHelper extends WuhuBase { .catch(error => Log.error('监听到fetch获取错误', error)); }) }; + if (Global.getInstance().unsafeWindow) { + Global.getInstance().unsafeWindow.fetch = fetchHandle; + } + window.fetch = fetchHandle; CommonUtils.addStyle(COMMON_CSS.replace('{{}}', performance.now().toString())); diff --git a/src/class/ZhongIcon.ts b/src/class/ZhongIcon.ts index 7ab51e7..c79f53f 100644 --- a/src/class/ZhongIcon.ts +++ b/src/class/ZhongIcon.ts @@ -1,9 +1,6 @@ -import doQuickFly from "../func/module/doQuickFly"; import loadGS from "../func/module/loadGS"; import adHelper from "../func/module/adHelper"; import safeKeeper from "../func/module/safeKeeper"; -import updateTransDict from "../func/translate/updateTransDict"; -import landedRedirect from "../func/module/landedRedirect"; import initMiniProf from "../func/utils/initMiniProf"; import WuhuBase from "./WuhuBase"; import Log from "./Log"; @@ -14,137 +11,72 @@ import * as EVENTS from "../static/json/event.json"; import * as FEST from "../static/json/fest.json"; import Popup from "./utils/Popup"; import TravelItem from "./action/TravelItem"; -import QUICK_FLY_HTML from "../static/html/quick_fly.html"; -import NNB_INFO_HTML from "../static/html/nnb_info.html"; -import PRICE_WATCHER_HTML from "../static/html/price_watcher.html"; -import DANGER_ZONE_HTML from "../static/html/danger_zone.html"; import ZHONG_MENU_HTML from "../static/html/zhong/zhong_menu.html"; import ZHONG_UPDATE_HTML from "../static/html/zhong/zhong_update.html"; import ZHONG_LOOT_HTML from "../static/html/zhong/zhong_loot.html"; -import QUICK_CRIMES_HTML from "../static/html/quick_crimes.html"; -import QUICK_FLY_CSS from "../static/css/quick_fly.css"; -import QUICK_LINK_CSS from "../static/css/quick_link.css"; -import MDUtils from "./utils/MDUtils"; import Test from "../test/Test"; import TornStyleSwitch from "./utils/TornStyleSwitch"; import Global from "./Global"; -import BuyBeerHelper from "./action/BuyBeerHelper"; import Timer from "./utils/Timer"; +import DialogMsgBox from "./utils/DialogMsgBox"; +import QuickFlyBtnHandler from "./handler/QuickFlyBtnHandler"; +import NNB from "./handler/NNB"; +import QuickLinksHandler from "./handler/QuickLinksHandler"; +import ItemPriceWatcherHandler from "./handler/ItemPriceWatcherHandler"; +import IFrameCrimeHandler from "./handler/IFrameCrimeHandler"; +import ChangeLogHandler from "./handler/ChangeLogHandler"; +import SettingsHandler from "./handler/SettingsHandler"; export default class ZhongIcon extends WuhuBase { className = 'ZhongIcon'; public static ZhongNode: MyHTMLElement = null; private menuItemList: MenuItemConfig[] = null; - private settingItemList: MenuItemConfig[] = null; + + // private settingItemList: MenuItemConfig[] = null; public constructor() { Log.info('ZhongIcon初始化, 设置图标开始'); super(); - this.constructWuhuSettingList() + this + // .constructWuhuSettingList() .constructMenuList() .insert2Dom(); Log.info('设置图标结束, ZhongIcon初始化结束'); } - private elemGenerator(setting: MenuItemConfig, root_node: Element): HTMLElement { - let { tip, domType } = setting; - let new_node = null; - switch (domType) { - case 'checkbox': { - new_node = document.createElement('div'); - let { domId, dictName, domText, changeEv } = setting; - - let switcher = new TornStyleSwitch(domText); - let _input = switcher.getInput(); - switcher.getBase().id = domId; - (tip) && (switcher.getBase().setAttribute('title', tip)); - _input.checked = WuhuConfig.get(dictName); - _input.onchange = e => { - WuhuConfig.set(dictName, _input.checked, true); - if (changeEv) changeEv(e); - }; - new_node.appendChild(switcher.getBase()); - break; - } - case 'button': { - new_node = document.createElement('div'); - let { domId, domText, clickFunc } = setting; - let btn = document.createElement('button'); - (tip) && (btn.setAttribute('title', tip)); - btn.id = domId; - btn.innerHTML = domText; - btn.addEventListener('click', clickFunc); - new_node.appendChild(btn); - break; - } - case 'select': { - new_node = document.createElement('div'); - let { domSelectOpt, dictName, domId, domText } = setting; - let label = document.createElement('label'); - (tip) && (label.setAttribute('title', tip)); - let text = document.createTextNode(domText); - let select = document.createElement('select'); - select.id = domId; - domSelectOpt.forEach((opt, i) => { - let { domVal, domText } = opt; - let option = document.createElement('option'); - option.value = domVal; - option.innerHTML = domText; - option.selected = i === WuhuConfig.get(dictName); - option.innerHTML = domText; - select.appendChild(option); - }); - select.onchange = e => WuhuConfig.set(dictName, (e.target).selectedIndex); - label.appendChild(text); - label.appendChild(select); - new_node.appendChild(label); - break; - } - case 'plain': { - let tag = setting.tagName || 'div'; - new_node = document.createElement(tag); - if (setting.domId) new_node.id = setting.domId; - new_node.innerHTML += setting['domHTML']; - break; - } - } - // 移动节点 - // Log.info('创建node', new_node); - return root_node.appendChild(new_node); - } - /** * 添加左侧图标 */ private insert2Dom() { - let zhong_node: MyHTMLElement = document.querySelector('div#wh-trans-icon'); + ZhongIcon.ZhongNode = document.querySelector('div#wh-trans-icon'); + let zhongNode = ZhongIcon.ZhongNode; let settings = this.menuItemList; let { version } = WuhuBase.glob; - if ((self !== top) || !!zhong_node) return null; - zhong_node = document.createElement('div'); - zhong_node.id = 'wh-trans-icon'; - zhong_node.classList.add('cont-gray'); - zhong_node.innerHTML = ZHONG_MENU_HTML.replace('{{}}', version.slice(-1) === '$' ? 'DEV' : version); + if ((self !== top) || !!zhongNode) return null; + zhongNode = document.createElement('div'); + zhongNode.id = 'wh-trans-icon'; + zhongNode.classList.add('cont-gray'); + zhongNode.innerHTML = ZHONG_MENU_HTML.replace('{{}}', version.slice(-1) === '$' ? 'DEV' : version); // 助手菜单 - const menu_cont = zhong_node.querySelector('#wh-gSettings'); + const menu_cont = zhongNode.querySelector('#wh-gSettings'); // 遍历菜单node设置、生成node、插入dom - this.menuItemList.forEach(setting => this.elemGenerator(setting, menu_cont)); + this.menuItemList.forEach(setting => CommonUtils.getInstance().elemGenerator(setting, menu_cont)); Log.info('生成元素插入完成'); // 计时node - zhong_node.initTimer = zhong_node.querySelector('#wh-inittimer'); + zhongNode.initTimer = zhongNode.querySelector('#wh-inittimer'); // 芜湖助手图标点击事件 - (zhong_node.querySelector('#wh-trans-icon-btn')).onclick = () => { - zhong_node.classList.toggle('wh-icon-expanded'); + (zhongNode.querySelector('#wh-trans-icon-btn')).onclick = () => { + zhongNode.classList.toggle('wh-icon-expanded'); const click_func = e => { Log.info(e.target); - if (e.target === zhong_node.querySelector('#wh-trans-icon-btn')) return; - if (!zhong_node.contains(e.target)) { + if (e.target === zhongNode.querySelector('#wh-trans-icon-btn')) return; + if (!zhongNode.contains(e.target)) { Log.info('移除事件监听器'); document.body.removeEventListener('click', click_func); - zhong_node.classList.remove('wh-icon-expanded'); + zhongNode.classList.remove('wh-icon-expanded'); } }; - if (zhong_node.classList.contains('wh-icon-expanded')) { + if (zhongNode.classList.contains('wh-icon-expanded')) { Log.info('添加事件监听器'); document.body.addEventListener('click', click_func); } else { @@ -153,7 +85,7 @@ export default class ZhongIcon extends WuhuBase { } }; // 更新按钮点击事件 - (zhong_node.querySelector('#wh-update-btn')).onclick = e => { + (zhongNode.querySelector('#wh-update-btn')).onclick = e => { (e.target).blur(); const innerHtml = ZHONG_UPDATE_HTML; // 直接复制的按钮 @@ -179,7 +111,7 @@ export default class ZhongIcon extends WuhuBase { }; }; // 节日 - zhong_node.querySelectorAll('#wh-trans-fest-date button').forEach((el, i) => i === 0 + zhongNode.querySelectorAll('#wh-trans-fest-date button').forEach((el, i) => i === 0 ? el.addEventListener('click', () => { let html = ''; settings.fest_date_list.sort().forEach(date => @@ -189,7 +121,7 @@ export default class ZhongIcon extends WuhuBase { }) : el.addEventListener('click', null)); // 活动 - zhong_node.querySelectorAll('#wh-trans-event-cont button').forEach((el, i) => i === 0 + zhongNode.querySelectorAll('#wh-trans-event-cont button').forEach((el, i) => i === 0 ? el.addEventListener('click', () => { let html = '
'; settings.events.forEach(el => @@ -197,7 +129,7 @@ export default class ZhongIcon extends WuhuBase { new Popup(html += '

更多信息请关注群聊和公众号

', '活动'); }) : el.addEventListener('click', null)); - document.body.append(zhong_node); + document.body.append(zhongNode); // 引入torn自带浮动提示 Log.info('引入torn自带浮动提示'); (window.initializeTooltip) && (window.initializeTooltip('.wh-container', 'white-tooltip')); @@ -214,7 +146,6 @@ export default class ZhongIcon extends WuhuBase { }, 1000), counter: 0 }; - ZhongIcon.ZhongNode = zhong_node; Log.info('图标加入文档树完成'); } @@ -323,80 +254,21 @@ export default class ZhongIcon extends WuhuBase { domType: 'button', domId: 'wh-foreign-stock-btn', domText: '🌸 飞花库存', - clickFunc: async function (e) { - e.target.blur(); - // forStock().then(); - TravelItem.getInstance().clickHandler().then(); - }, + clickFunc: () => TravelItem.getInstance().clickHandler().then(), }); // 一键起飞 list.push({ domType: 'button', domId: 'wh-quick-fly-btn', domText: '✈️ 一键起飞', - clickFunc: async function () { - if (window.hasWHQuickFlyOpt) return; - window.hasWHQuickFlyOpt = true; - // TODO - CommonUtils.addStyle(QUICK_FLY_CSS); - const node = document.createElement('div'); - node.id = 'wh-quick-fly-opt'; - node.innerHTML = QUICK_FLY_HTML; - const [dest_node, type_node] = node.querySelectorAll('select') as any as HTMLSelectElement[]; - node.querySelector('button').addEventListener('click', () => { - sessionStorage['wh-quick-fly'] = `${ dest_node.selectedIndex } ${ type_node.selectedIndex } ${ new Date().getTime() }`; - if (!glob.href.contains('travelagency.php')) { - new Alert('正在转跳'); - location.href = 'https://www.torn.com/travelagency.php'; - } else { - doQuickFly(); - } - }); - node.querySelector('a').addEventListener('click', (e) => { - e.preventDefault(); - // forStock(); - TravelItem.getInstance().clickHandler(); - }); - node.querySelector('input').addEventListener('click', (e) => { - node.classList.toggle('wh-quick-fly-opt-hide'); - const el = e.target as HTMLInputElement; - el.value = el.value === ' - ' ? ' + ' : ' - '; - }); - const info_node = node.querySelector('info'); - const time_predict = document.createElement('p'); - const yaoCD = document.createElement('p'); - info_node.append(time_predict); - info_node.append(yaoCD); - const predict = [ - ['~54分', '~36分', '~26分', '~16分',], - ['~1时10分', '~50分', '~36分', '~22分',], - ['~1时22分', '~58分', '~40分', '~24分',], - ['~4时28分', '~3时8分', '~2时14分', '~1时20分',], - ['~5时18分', '~3时42分', '~2时40分', '~1时36分',], - ['~5时34分', '~3时54分', '~2时46分', '~1时40分',], - ['~5时50分', '~4时6分', '~2时56分', '~1时46分',], - ['~7时30分', '~5时16分', '~3时46分', '~2时16分',], - ['~8时4分', '~5时38分', '~4时2分', '~2时24分',], - ['~9时2分', '~6时20分', '~4时30分', '~2时42分',], - ['~9时54分', '~6时56分', '~4时58分', '~2时58分',], - ]; - const showTime = function () { - time_predict.innerHTML = `往返时间:${ predict[dest_node.selectedIndex][type_node.selectedIndex] }`; - } - dest_node.addEventListener('change', showTime); - type_node.addEventListener('change', showTime); - document.body.append(node); - showTime(); - yaoCD.innerHTML = `药CD剩余:${ CommonUtils.getYaoCD() }`; - }, + clickFunc: () => QuickFlyBtnHandler.getInstance().handle(), }); // NPC LOOT list.push({ domType: 'button', domId: 'wh-npc-loot-btn', domText: '🔫 LOOT', - clickFunc: function (e) { - e.target.blur(); + clickFunc: () => { const insert = ZHONG_LOOT_HTML.replace('{{}}', performance.now().toString()); new Popup(insert, 'NPC LOOT'); }, @@ -407,152 +279,21 @@ export default class ZhongIcon extends WuhuBase { domType: 'button', domId: 'wh-nnb-info', domText: '👮‍ 查看NNB', - clickFunc: function (e) { - e.target.blur(); - const insert = NNB_INFO_HTML - .replace('{{}}', localStorage.getItem('APIKey') || '不可用') - .replace('{{}}', glob.isPDA ? glob.PDA_APIKey : '不可用'); - const popup = new Popup(insert, '查看NNB').getElement(); - const select = popup.querySelector('input'); - const node = popup.querySelector('p'); - popup.querySelector('button').addEventListener('click', ev => { - let target = ev.target as HTMLInputElement; - target.style.display = 'none'; - node.innerHTML = '加载中'; - // API 计算 - if (select.checked) { - const api_key = glob.isPDA ? glob.PDA_APIKey : window.localStorage.getItem('APIKey'); - window.fetch(`https://api.torn.com/user/?selections=bars,perks&key=${ api_key }`) - .then(res => res.json()) - .then(data => { - if (data['error']) { - node.innerHTML = `出错了 ${ JSON.stringify(data['error']) }`; - target.style.display = null; - return; - } - let nb = data['nerve']['maximum']; - let perks = 0; - Object.values(data).forEach(val => { - (val instanceof Array) && val.forEach(s => { - s = s.toLowerCase(); - s.includes('maximum nerve') && (perks += (new RegExp('[0-9].').exec(s))[0] | 0) - }) - }); - node.innerHTML = `NNB: ${ nb - perks }`; - target.style.display = null; - }); - } - // 主页计算 - else { - if (window.location.href.includes('index.php') && document.title.includes('Home')) { - let nb = (document.querySelector('#barNerve p[class^="bar-value___"]').innerText.split('/')[1]) | 0; - let perks = 0; - document.querySelectorAll('#personal-perks li').forEach(elem => { - const str = elem.innerText.toLowerCase(); - str.includes('maximum nerve') && (perks += (/[0-9]./.exec(str) as any)[0] | 0) - }); - node.innerHTML = `NNB: ${ nb - perks }`; - target.style.display = null; - return; - } - node.innerHTML = '不在主页面,点击前往'; - target.style.display = null; - } - }); - }, + clickFunc: () => NNB.getInstance().handle(), }); // 常用链接 list.push({ domType: 'button', domId: 'wh-link-collection', domText: '🔗 常用链接', - clickFunc: function (e) { - if (!this.styleAdded) { - CommonUtils.addStyle(QUICK_LINK_CSS); - this.styleAdded = true; - } - e.target.blur(); - const quick_link_dict = []; - // 生存手册 - quick_link_dict.push({ - name: '生存手册', - url: 'https://docs.qq.com/doc/DTVpmV2ZaRnB0RG56', - new_tab: true, - img: 'https://www.torn.com/images/items/293/medium.png', - }); - // 买啤酒 - quick_link_dict.push({ - name: '抢啤酒', - url: 'https://www.torn.com/shops.php?step=bitsnbobs', - new_tab: true, - img: 'https://www.torn.com/images/items/180/medium.png', - }); - // 买XAN - quick_link_dict.push({ - name: '买XAN', - url: 'https://www.torn.com/imarket.php#/p=shop&step=shop&type=&searchname=Xanax', - new_tab: true, - img: 'https://www.torn.com/images/items/206/medium.png', - }); - // 起飞 - quick_link_dict.push({ - name: '起飞', - url: 'https://www.torn.com/travelagency.php', - new_tab: true, - img: 'https://www.torn.com/images/items/396/medium.png', - }); - // 买PT - quick_link_dict.push({ - name: '买PT', - url: 'https://www.torn.com/pmarket.php', - new_tab: true, - img: 'https://www.torn.com/images/items/722/medium.png', - }); - // 租PI - quick_link_dict.push({ - name: '租PI', - url: 'https://www.torn.com/properties.php?step=rentalmarket#/property=13', - new_tab: false, - img: 'https://www.torn.com/images/v2/properties/350x230/350x230_default_private_island.png', - }); - // 找工作 - quick_link_dict.push({ - name: '找工作', - url: 'https://www.torn.com/joblist.php#!p=main', - new_tab: false, - img: 'https://www.torn.com/images/items/421/medium.png', - }); - // 下悬赏 - quick_link_dict.push({ - name: '下悬赏', - url: 'https://www.torn.com/bounties.php#/p=add', - new_tab: false, - img: 'https://www.torn.com/images/items/431/medium.png', - }); - let insert = '

'; - quick_link_dict.forEach(el => { - insert += `${ el.name }`; - }); - insert += '

' - let popup = new Popup(insert, '常用链接'); - popup.getElement().classList.add('wh-link-collection-cont'); - popup.getElement().addEventListener('click', ev => { - let target = ev.target as HTMLElement; - if (target.tagName.toLowerCase() === 'a' || target.tagName.toLowerCase() === 'span') { - popup.close(); - } - }); - }, + clickFunc: () => QuickLinksHandler.getInstance().handle() }); // 飞贼 list.push({ domType: 'button', domId: 'wh-gs-btn', domText: '🐏 飞贼小助手', - clickFunc: function (e) { - e.target.blur(); - loadGS(CommonUtils.getScriptEngine()); - }, + clickFunc: () => loadGS(CommonUtils.getScriptEngine()), tip: '加载从PC端移植的伞佬的油猴版飞贼小助手', }); // 物品价格监视 @@ -560,133 +301,32 @@ export default class ZhongIcon extends WuhuBase { domType: 'button', domId: 'wh-price-watcher-btn', domText: '💊 价格监视', - clickFunc: function () { - const watcher_conf = WuhuConfig.get('priceWatcher'); - const pre_str = JSON.stringify(watcher_conf); - const html = PRICE_WATCHER_HTML - .replace('{{}}', localStorage.getItem('APIKey') || '不可用') - .replace('{{}}', glob.isPDA ? glob.PDA_APIKey : '不可用') - .replace('{{}}', watcher_conf['pt'] || -1) - .replace('{{}}', watcher_conf['xan'] || -1); - const popup = new Popup(html, '价格监视设置'); - popup.getElement().querySelector('button').onclick = () => { - const [pt_node, xan_node] = Array.from(>popup.getElement().querySelectorAll('input[type="number"]')); - watcher_conf.pt = (pt_node.value as any) | 0; - watcher_conf.xan = (xan_node.value as any) | 0; - if (JSON.stringify(watcher_conf) !== pre_str) WuhuConfig.set('priceWatcher', watcher_conf); - popup.close(); - }; - } + clickFunc: () => ItemPriceWatcherHandler.getInstance().handle() }); // 小窗犯罪 list.push({ domType: 'button', domId: 'wh-crime-iframe-btn', domText: '🤑 小窗犯罪', - clickFunc: function () { - // 弹出小窗口 - const ifHTML = ``; - const popup_insert = `

加载中请稍后${ CommonUtils.loading_gif_html() }

`; - const $popup = new Popup(popup_insert, '小窗快速犯罪').getElement(); - // 运行状态node - let loading_node = $popup.querySelector('p:first-of-type'); - // if容器 - const if_cont = $popup.querySelector('#wh-quick-crime-if-container'); - if_cont.innerHTML = ifHTML; - - // if内未加载脚本时插入的快捷crime node - const mobile_prepend_node = document.createElement('div'); - mobile_prepend_node.classList.add('wh-translate'); - mobile_prepend_node.innerHTML = QUICK_CRIMES_HTML; - - // if对象加载后运行 - let cIframe = $popup.querySelector('iframe'); - - // 加载状态 - const if_onload_func = () => { - // if内部文档对象 - const ifDocu = cIframe.contentWindow.document; - // 内部插件运行flag - const ifWH = cIframe.contentWindow.WHTRANS; - // 文档加载完成后移除 - if (!!loading_node) loading_node.remove(); - // 文档加载完成后才显示if - cIframe.style.display = 'block'; - // 验证码flag - const isValidate = ifDocu.querySelector('h4#skip-to-content').innerText.toLowerCase().includes('validate'); - // 如果iframe内部未运行脚本 - if (ifWH === undefined) { - // 隐藏顶部 - CommonUtils.elementReady('#header-root', ifDocu).then(e => e.style.display = 'none'); - // 隐藏4条 - CommonUtils.elementReady('#sidebarroot', ifDocu).then(e => e.style.display = 'none'); - // 隐藏聊天 - CommonUtils.elementReady('#chatRoot', ifDocu).then(e => e.style.display = 'none'); - // 非验证码页面隐藏滚动条 - if (!isValidate) ifDocu.body.style.overflow = 'hidden'; - // 调整容器位置 - CommonUtils.elementReady('.content-wrapper', ifDocu).then(elem => { - // 加入 - elem.prepend(mobile_prepend_node); - elem.style.margin = '0px'; - elem.style.position = 'absolute'; - elem.style.top = '-35px'; - new MutationObserver((m, o) => { - o.disconnect(); - if (!elem.querySelector('.wh-translate')) elem.prepend(mobile_prepend_node); - o.observe(elem, { childList: true, subtree: true }); - }) - .observe(elem, { childList: true, subtree: true }); - }); - // 隐藏返回顶部按钮 - CommonUtils.elementReady('#go-to-top-btn button', ifDocu).then(e => e.style.display = 'none'); - } - }; - cIframe.onload = if_onload_func; - - // 超时判断 - let time_counter = 0; - let time_out_id = window.setInterval(() => { - loading_node = $popup.querySelector('p:first-of-type'); - if (!loading_node) { - clearInterval(time_out_id); - time_out_id = undefined; - return; - } - time_counter++; - if (time_counter > 0 && !loading_node.querySelector('button')) { - const reload_btn = document.createElement('button'); - reload_btn.innerHTML = '重新加载'; - reload_btn.onclick = () => { - reload_btn.remove(); - time_counter = 0; - if_cont.innerHTML = null; - if_cont.innerHTML = ifHTML; - cIframe = $popup.querySelector('iframe'); - cIframe.onload = if_onload_func; - }; - loading_node.append(reload_btn); - } - }, 1000); - } + clickFunc: () => IFrameCrimeHandler.getInstance().handle() }); // 危险行为开关⚠️ list.push({ domType: 'button', domId: 'wh-danger-zone', domText: '⚠️ 危险功能', - clickFunc: function (e) { - e.target.blur(); - const insert = DANGER_ZONE_HTML.replace('{{}}', WuhuConfig.get('dangerZone') ? 'checked ' : ' '); - const popup = new Popup(insert, '⚠️警告'); - const warning_check = popup.getElement().querySelector('input'); - const ok_btn = popup.getElement().querySelector('button'); - warning_check.onchange = () => ok_btn.disabled = false; - ok_btn.onclick = () => { - WuhuConfig.set('dangerZone', warning_check.checked); - popup.close(); - window.location.reload(); - }; + clickFunc: () => { + new DialogMsgBox( + `打开危险功能,使用这些功能可能会造成账号封禁
${ new TornStyleSwitch('知道了,开启', WuhuConfig.get('dangerZone')).getHtml() }`, + { + callback(dom) { + let before = WuhuConfig.get('dangerZone'); + let checked = dom.querySelector('input').checked + WuhuConfig.set('dangerZone', checked, true); + if (!before && checked) window.location.reload(); + } + } + ) }, }); // 传单助手 @@ -714,65 +354,17 @@ export default class ZhongIcon extends WuhuBase { }); // 更新历史 list.push({ - domType: 'button', domId: '', domText: '🐞 更新历史', clickFunc: async () => { - let popup = new Popup( - '更新历史:
https://gitlab.com/JJins/wuhu-torn-helper/-/blob/dev/CHANGELOG.md
', - '更新历史' - ).getElement(); - popup.classList.add('wh-changeLog'); - let progressBar = document.createElement('div'); - progressBar.style.height = '2px'; - progressBar.style.width = '1%'; - progressBar.style.backgroundColor = 'red'; - let progressText = document.createElement('p'); - progressText.innerText = '加载更新文件……'; - progressText.style.textAlign = 'center'; - let style = document.createElement('style'); - style.innerHTML = `.wh-changeLog h2,.wh-changeLog h3,.wh-changeLog h4 {margin:8px 0;}.wh-changeLog li{list-style: inside;}`; - - popup.append(progressBar, progressText, style); - let update = await CommonUtils.COFetch('https://gitlab.com/JJins/wuhu-torn-helper/-/raw/dev/CHANGELOG.md?' + Date.now()); - progressBar.style.width = '60%'; - progressText.innerText = '解析中……'; - let md = MDUtils.getInstance().parse(update); - popup.append(md); - progressBar.style.width = '100%'; - progressText.innerText = '加载完成'; - - setTimeout(() => { - progressBar.remove(); - progressText.remove() - }, 3000); - }, + domType: 'button', + domId: '', + domText: '🐞 更新历史', + clickFunc: async () => ChangeLogHandler.getInstance().handle() }); // 助手设置 list.push({ - domType: 'button', domId: '', domText: '⚙️ 助手设置', clickFunc: () => { - let startTime = performance.now(); - Log.info('构造设置开始'); - let pop = new Popup(CommonUtils.loading_gif_html(), '芜湖助手设置'); - let tmp = document.createElement('div'); - tmp.classList.add('gSetting'); - this.settingItemList.forEach(set => this.elemGenerator(set, tmp)); - pop.getElement().innerHTML = ''; - pop.getElement().appendChild(tmp); - // 本日不提醒 - pop.getElement().querySelector('#wh-qua-alarm-check-btn').addEventListener('click', () => Global.getInstance().beer.skip_today()); - // 开发详情按钮 - // if (Log.debug()) $zhongNode.setting_root.querySelector('button#wh-devInfo').onclick = () => { - // const date = new Date(); - // let os = '未知'; - // try { - // os = window.navigator.userAgentData.platform || window.navigator.platform - // } catch { - // } - // - // pop.close(); - // new Popup(DEV_DETAILS_HTML, '开发者详情'); - // }; - (window.initializeTooltip) && (window.initializeTooltip('#wh-popup-cont', 'white-tooltip')); - Log.info('构造设置结束,' + ((performance.now() - startTime) | 0) + 'ms'); - }, + domType: 'button', + domId: '', + domText: '⚙️ 助手设置', + clickFunc: () => SettingsHandler.getInstance().handler(), }); // 测试 if (Log.debug()) list.push({ @@ -796,462 +388,9 @@ export default class ZhongIcon extends WuhuBase { Log.info('构造展开菜单列表结束' + timer.getTimeMs()); return this; } - - // 设置 - private constructWuhuSettingList(): ZhongIcon { - Log.info('构造设置列表开始'); - let timer = new Timer(); - const date = new Date(); - - let beer = BuyBeerHelper.getInstance(); - - let list: MenuItemConfig[] = []; - - // 12月时加入圣诞小镇选项 - if (date.getMonth() === 11) { - list.push({ - domType: 'plain', - domId: '', - domHTML: '圣诞小镇', - tagName: 'h4', - }) - list.push({ - domType: 'checkbox', - domId: 'wh-xmastown-wt', - domText: ' 圣诞小镇攻略', - dictName: 'xmasTownWT', - isHide: true, - }); - list.push({ - domType: 'checkbox', - domId: 'wh-xmastown-notify', - domText: ' 圣诞小镇物品提示', - dictName: 'xmasTownNotify', - isHide: true, - }); - } - - // 翻译 - list.push({ - domType: 'plain', - domId: '', - domHTML: '翻译', - tagName: 'h4', - }); - // 开启翻译 - list.push({ - domType: 'checkbox', - domId: 'wh-trans-enable', - domText: ' 开启翻译', - dictName: 'transEnable', - isHide: true, - }); - // 更新翻译词库 - list.push({ - domType: 'button', - domId: '', - domText: '更新翻译词库', - clickFunc: updateTransDict - }); - - // 战斗优化 - list.push({ - domType: 'plain', - domId: '', - domHTML: '战斗优化', - tagName: 'h4', - }); - // 光速拔刀 - list.push({ - domType: 'select', - domId: 'wh-quick-attack-index', - domText: '光速拔刀 ', - domSelectOpt: [ - { - domVal: 'pri', - domText: '主手', - }, - { - domVal: 'sec', - domText: '副手', - }, - { - domVal: 'wea', - domText: '近战', - }, - { - domVal: 'gre', - domText: '手雷', - }, - { - domVal: 'fis', - domText: '拳头', - }, - { - domVal: 'kic', - domText: '脚踢', - }, - { - domVal: 'none', - domText: '关闭', - }, - ], - dictName: 'quickAttIndex', - isHide: true, - tip: '将Start Fight按钮移动到指定格子上', - }); - // 光速跑路 - list.push({ - domType: 'select', - domId: 'wh-quick-mug', - domText: '光速跑路 ', - domSelectOpt: [ - { - domVal: 'leave', - domText: '跑路(LEAVE)', - }, - { - domVal: 'mug', - domText: '打劫(MUG)', - }, - { - domVal: 'hosp', - domText: '住院(HOSP)', - }, - { - domVal: 'none', - domText: '关闭', - }, - ], - dictName: 'quickFinishAtt', - isHide: true, - tip: '将结束后指定按钮移动到上面指定的格子上暂时关闭', - }); - // 攻击链接转跳 - list.push({ - domType: 'checkbox', - domId: 'wh-attack-relocate', - domText: ' 真·攻击界面转跳', - dictName: 'attRelocate', - tip: '在无法打开攻击界面的情况下依然可以转跳到正确的攻击页面', - isHide: true, - }); - - // 飞行 - list.push({ - domType: 'plain', - domId: '', - domHTML: '飞行', - tagName: 'h4', - }); - // 起飞警告 - list.push({ - domType: 'checkbox', - domId: 'wh-energy-alert', - domText: ' 起飞爆E警告', - dictName: 'energyAlert', - tip: '起飞前计算来回是否会爆体,红字警告', - isHide: true, - }); - // 飞行闹钟 - list.push({ - domType: 'checkbox', - domId: 'wh-trv-alarm-check', - domText: ' 飞行闹钟', - dictName: 'trvAlarm', - tip: '(仅PC) 飞行页面将显示一个内建的闹钟,落地前声音提醒,需要打开浏览器声音权限', - isHide: true, - }); - // 海外警告 - list.push({ - domType: 'checkbox', - domId: '', - domText: ' 海外警告', - dictName: 'abroadWarning', - tip: '海外落地后每30秒通知警告', - }); - // 落地转跳 - list.push({ domType: 'button', domId: '', domText: '落地转跳', clickFunc: landedRedirect }); - - // 公司 - list.push({ - domType: 'plain', - domId: '', - domHTML: '公司', - tagName: 'h4', - }); - // 浮动存钱框 - list.push({ - domType: 'checkbox', - domId: '', - domText: ' 浮动存钱框', - dictName: 'floatDepo', - tip: '打开公司或帮派的存钱页面后存钱框将浮动显示', - }); - // 公司转跳存钱 - list.push({ - domType: 'checkbox', - domId: '', - domText: ' 公司转跳存钱', - dictName: 'companyRedirect', - tip: '打开公司页面时自动打开存钱选项卡', - }); - // 收起公司冰蛙效率表 - list.push({ - domType: 'checkbox', - domId: '', - domText: ' 收起公司冰蛙效率表', - dictName: 'companyBWCollapse', - tip: '开启后可手动显示隐藏冰蛙公司表格', - }); - // 任何位置一键存钱 - list.push({ - domType: 'checkbox', - domId: '', - domText: ' 任何位置一键存钱', - dictName: 'companyDepositAnywhere', - tip: '在所有页面显示一键存钱按钮,Torn OK状态下可用,此功能未完全测试无害,使用请慎重', - }); - // 火车检测开关 - list.push({ - domType: 'checkbox', - domId: null, - domText: '火车检测', - dictName: 'CHTrainsDetectSwitch', - tip: '检测明日火车是否会超出上限,需要系统通知权限' - }); - - // 啤酒 - list.push({ - domType: 'plain', - domId: '', - domHTML: '啤酒', - tagName: 'h4', - }); - // 啤酒提醒 - list.push({ - domType: 'checkbox', - domId: 'wh-qua-alarm-check', - domText: ' 啤酒提醒 ', - dictName: '_15Alarm', - tip: '每小时的整15分钟的倍数时通知提醒抢啤酒或者血包', - isHide: true, - changeEv: function (ev) { - ev.target.checked ? beer.start() : beer.stop(); - }, - }); - // 啤酒提醒状态 - list.push({ - domType: 'button', - domId: '', - domText: '啤酒提醒状态', - clickFunc: function () { - new Alert(`啤酒提醒${ beer.status() }`); - } - }); - // 啤酒提醒时间 - list.push({ - domType: 'button', - domId: '', - domText: '啤酒提醒时间设定', - // tip: '通知提前时间', - clickFunc: function () { - let popup = new Popup(`

区间为 1 ~ 60,默认 50

`, '啤酒提醒时间设定'); - let confirm = document.createElement('button'); - confirm.innerHTML = '确定'; - confirm.style.float = 'right'; - confirm.addEventListener('click', () => { - let input: HTMLInputElement = popup.getElement().querySelector('input'); - let num = (input.value as any) | 0; - if (num === WuhuConfig.get('_15AlarmTime')) return; - if (num < 1 || num > 60) num = 50; - input.value = num.toString(); - WuhuConfig.set('_15AlarmTime', num); - beer.set_time(num); - // 之前的运行状态 - if (beer.is_running()) beer.start(); - popup.close(); - }); - popup.getElement().appendChild(confirm); - }, - }); - - // 其他 - list.push({ - domType: 'plain', - domId: '', - domHTML: '其他', - tagName: 'h4', - }); - // 任务助手 - list.push({ - domType: 'checkbox', - domId: 'wh-mission-lint', - domText: ' 任务助手', - dictName: 'missionHint', - tip: 'Duke任务的一些中文小提示', - isHide: true, - }); - // 捡垃圾助手 - list.push({ - domType: 'checkbox', - domId: 'wh-city-finder', - domText: ' 捡垃圾助手', - dictName: 'cityFinder', - tip: '城市地图中放大显示物品并且估计价值', - isHide: true, - }); - // 快速crime - list.push({ - domType: 'checkbox', - domId: 'wh-quick-crime', - domText: ' 快速犯罪', - dictName: 'quickCrime', - tip: '显示快捷操作按钮,目前不支持自定义', - isHide: true, - }); - // 叠E保护 - list.push({ - domType: 'checkbox', - domId: 'wh-SEProtect-check', - domText: ' 叠E保护', - dictName: 'SEProtect', - tip: '隐藏健身房的锻炼按钮,防止误操作', - isHide: true, - }); - // PT一键购买 - list.push({ - domType: 'checkbox', - domId: 'wh-ptQuickBuy-check', - domText: ' PT一键购买', - dictName: 'ptQuickBuy', - tip: 'PT市场页面购买时跳过确认', - isHide: true, - }); - // 4条转跳 - list.push({ - domType: 'checkbox', - domId: '', - domText: ' 4条转跳', - dictName: 'barsRedirect', - tip: '点击4条时转跳对应页面', - }); - // 清除多余的脚本 - list.push({ - domType: 'checkbox', - domId: '', - domText: ' 清除多余的脚本', - dictName: 'removeScripts', - tip: '清除Google相关脚本、顶部横幅等', - }); - // 危险行为⚠️ - if (WuhuConfig.get('dangerZone') === true) { - // 攻击界面自刷新 - list.push({ - domType: 'select', - domId: 'wh-attack-reload', - domText: '⚠️攻击界面自动刷新 ', - dictName: 'attReload', - domSelectOpt: [ - { - domVal: 'none', - domText: '无间隔', - }, - { - domVal: '1', - domText: '约1s', - }, - { - domVal: '2', - domText: '约2s', - }, - { - domVal: '3', - domText: '约3s', - }, - { - domVal: '4', - domText: '约4s', - }, - { - domVal: '5', - domText: '约5s', - }, - { - domVal: 'disabled', - domText: '关闭', - }, - ], - isHide: true, - tip: '危险功能:接机时常用,将自动刷新页面直到目标落地', - }); - // 自动开打和结束 - list.push({ - domType: 'checkbox', - domId: 'wh-auto-start-finish', - domText: ' ⚠️自动开打和结束', - dictName: 'autoStartFinish', - tip: '脚本将会自动按下战斗和结束按钮', - isHide: true, - }); - } else { - WuhuConfig.set('autoStartFinish', false) - WuhuConfig.set('attReload', 6) - } - // dev - list.push({ - domType: 'checkbox', - domId: 'wh-dev-mode', - domText: '开发模式', - dictName: 'isDev', - isHide: true, - }); - // 查看logs - list.push({ - domType: 'button', - domId: null, - domText: '查看日志', - clickFunc: () => { - let logCounter = Log.getCounter(); - let pop = new Popup('', '查看日志'); - let text = pop.getElement().querySelector('textarea'); - text.innerHTML = Log.getLogs(); - text.onclick = () => text.select(); - pop.getElement().insertAdjacentHTML('afterbegin', `

${ logCounter.info }信息 ${ logCounter.warning }警告 ${ logCounter.error }错误

`) - } - }); - // 更多设定 - list.push({ - domType: 'button', domId: 'wh-otherBtn', domText: '更多设定', - clickFunc: () => { - let pop = new Popup('', '更多设定'); - let insertHtml = '

'; - pop.getElement().insertAdjacentHTML('beforeend', insertHtml); - let [btn1, btn2, btn3] = Array.from(pop.getElement().querySelectorAll('button')); - btn1.addEventListener('click', () => { - localStorage.removeItem('wh_trv_alarm'); - localStorage.removeItem('wh_trans_settings'); - localStorage.removeItem('whuuid'); - localStorage.removeItem('wh-gs-storage'); - localStorage.removeItem('WHTEST'); - new Alert('已清空,刷新页面'); - window.location.reload(); - }); - btn2.addEventListener('click', () => { - }); - btn3.addEventListener('click', () => { - }); - }, - // isHide: true, - }); - - this.settingItemList = list; - Log.info('构造设置列表结束' + timer.getTimeMs()); - return this; - } } -interface MenuItemConfig { +export interface MenuItemConfig { domType: 'button' | 'plain' | 'checkbox' | 'select'; tagName?: string; domId?: string; @@ -1283,4 +422,4 @@ interface Event { end: number[]; name: string; eff: string; -} \ No newline at end of file +} diff --git a/src/class/action/BuyBeerHelper.ts b/src/class/action/BuyBeerHelper.ts index 11609b2..ac61e2e 100644 --- a/src/class/action/BuyBeerHelper.ts +++ b/src/class/action/BuyBeerHelper.ts @@ -6,6 +6,7 @@ import Alert from "../utils/Alert"; import MathUtils from "../utils/MathUtils"; import NOTIFY_HTML from "../../static/html/buyBeer/notify.html"; import CommonUtils from "../utils/CommonUtils"; +import Popup from "../utils/Popup"; export default class BuyBeerHelper extends WuhuBase implements BeerMonitorLoop { className = 'BuyBeerHelper'; @@ -98,6 +99,26 @@ export default class BuyBeerHelper extends WuhuBase implements BeerMonitorLoop { // 通知中的取消按钮 notify.getElement().querySelector('.wh-notify-msg button').addEventListener('click', () => WuhuConfig.set('_15_alarm_ignore', undefined, true)); } + + public setTimeHandler(): void { + let popup = new Popup(`

区间为 1 ~ 60,默认 50

`, '啤酒提醒时间设定'); + let confirm = document.createElement('button'); + confirm.innerHTML = '确定'; + confirm.style.float = 'right'; + confirm.addEventListener('click', () => { + let input: HTMLInputElement = popup.getElement().querySelector('input'); + let num = (input.value as any) | 0; + if (num === WuhuConfig.get('_15AlarmTime')) return; + if (num < 1 || num > 60) num = 50; + input.value = num.toString(); + WuhuConfig.set('_15AlarmTime', num); + this.set_time(num); + // 之前的运行状态 + if (this.is_running()) this.start(); + popup.close(); + }); + popup.getElement().appendChild(confirm); + } } export interface BeerMonitorLoop { diff --git a/src/class/action/LotteryHelper.ts b/src/class/action/LotteryHelper.ts index 7f99956..3922d45 100644 --- a/src/class/action/LotteryHelper.ts +++ b/src/class/action/LotteryHelper.ts @@ -4,6 +4,7 @@ import InfoUtils from "../utils/InfoUtils"; import MathUtils from "../utils/MathUtils"; import CommonUtils from "../utils/CommonUtils"; import TornStyleBlock from "../utils/TornStyleBlock"; +import Timer from "../utils/Timer"; export default class LotteryHelper extends WuhuBase { className = 'LotteryHelper'; @@ -22,7 +23,7 @@ export default class LotteryHelper extends WuhuBase { private readonly mathUtils = MathUtils.getInstance(); public init() { - let startTime = performance.now(); + let startTime = new Timer(); Log.info('彩票助手初始化开始'); let radioLabelDaily = document.createElement('label'); @@ -99,11 +100,11 @@ export default class LotteryHelper extends WuhuBase { progressBarBg, progressBar, status, desc).insert2Dom(); // document.querySelector('#websocketConnectionData').after(container); - Log.info('彩票助手初始化结束,耗时:' + (performance.now() - startTime) + 'ms'); + Log.info('彩票助手初始化结束,耗时:' + startTime.getTimeMs()); } private async start() { - let startTime = performance.now(); + let startTime = new Timer(); this.loopFlag = true; this.stopBtn.disabled = false; this.startBtn.disabled = true; @@ -151,7 +152,7 @@ export default class LotteryHelper extends WuhuBase { rsMsg = '输入有误'; } - this.desc.innerHTML = '结束: ' + (rsMsg ? rsMsg + `
耗时:${ (performance.now() - startTime) | 0 }ms` : '出错了'); + this.desc.innerHTML = '结束: ' + (rsMsg ? rsMsg + '
耗时:' + startTime.getTimeMs() : '出错了'); this.stopBtn.disabled = true; this.startBtn.disabled = false; diff --git a/src/class/handler/AdditionalSettingsHandler.ts b/src/class/handler/AdditionalSettingsHandler.ts new file mode 100644 index 0000000..1f11420 --- /dev/null +++ b/src/class/handler/AdditionalSettingsHandler.ts @@ -0,0 +1,27 @@ +import WuhuBase from "../WuhuBase"; +import Popup from "../utils/Popup"; +import Alert from "../utils/Alert"; + +export default class AdditionalSettingsHandler extends WuhuBase { + className = 'AdditionalSettingsHandler'; + + public handle(): void { + let pop = new Popup('', '更多设定'); + let insertHtml = '

'; + pop.getElement().insertAdjacentHTML('beforeend', insertHtml); + let [btn1, btn2, btn3] = Array.from(pop.getElement().querySelectorAll('button')); + btn1.addEventListener('click', () => { + localStorage.removeItem('wh_trv_alarm'); + localStorage.removeItem('wh_trans_settings'); + localStorage.removeItem('whuuid'); + localStorage.removeItem('wh-gs-storage'); + localStorage.removeItem('WHTEST'); + new Alert('已清空,刷新页面'); + window.location.reload(); + }); + btn2.addEventListener('click', () => { + }); + btn3.addEventListener('click', () => { + }); + } +} \ No newline at end of file diff --git a/src/class/handler/ChangeLogHandler.ts b/src/class/handler/ChangeLogHandler.ts new file mode 100644 index 0000000..050f53b --- /dev/null +++ b/src/class/handler/ChangeLogHandler.ts @@ -0,0 +1,49 @@ +import WuhuBase from "../WuhuBase"; +import Popup from "../utils/Popup"; +import CommonUtils from "../utils/CommonUtils"; +import MDUtils from "../utils/MDUtils"; +import Log from "../Log"; + +export default class ChangeLogHandler extends WuhuBase { + className = 'ChangeLogHandler'; + + public handle(): void { + let popup = new Popup( + '更新历史:
https://gitlab.com/JJins/wuhu-torn-helper/-/blob/dev/CHANGELOG.md
', + '更新历史' + ).getElement(); + popup.classList.add('wh-changeLog'); + let progressBar = document.createElement('div'); + progressBar.style.height = '2px'; + progressBar.style.width = '1%'; + progressBar.style.backgroundColor = 'red'; + let progressText = document.createElement('p'); + progressText.innerText = '加载更新文件……'; + progressText.style.textAlign = 'center'; + let style = document.createElement('style'); + style.innerHTML = `.wh-changeLog h2,.wh-changeLog h3,.wh-changeLog h4 {margin:8px 0;}.wh-changeLog li{list-style: inside;}`; + + popup.append(progressBar, progressText, style); + + CommonUtils + .COFetch('https://gitlab.com/JJins/wuhu-torn-helper/-/raw/dev/CHANGELOG.md?' + performance.now()) + .then(update => { + progressBar.style.width = '60%'; + progressText.innerText = '解析中……'; + let md = MDUtils.getInstance().parse(update); + popup.append(md); + progressBar.style.width = '100%'; + progressText.innerText = '加载完成'; + + window.setTimeout(() => { + progressBar.remove(); + progressText.remove() + }, 3000); + }) + .catch(e => { + Log.error(e); + progressBar.remove(); + progressText.innerText = '无法加载'; + }); + } +} \ No newline at end of file diff --git a/src/class/handler/IFrameCrimeHandler.ts b/src/class/handler/IFrameCrimeHandler.ts new file mode 100644 index 0000000..3c579ca --- /dev/null +++ b/src/class/handler/IFrameCrimeHandler.ts @@ -0,0 +1,95 @@ +import WuhuBase from "../WuhuBase"; +import CommonUtils from "../utils/CommonUtils"; +import Popup from "../utils/Popup"; +import QUICK_CRIMES_HTML from "../../static/html/quick_crimes.html"; + +export default class IFrameCrimeHandler extends WuhuBase { + className = 'IFrameCrimeHandler'; + + public handle(): void { + // 弹出小窗口 + const ifHTML = ``; + const popup_insert = `

加载中请稍后${ CommonUtils.loading_gif_html() }

`; + const $popup = new Popup(popup_insert, '小窗快速犯罪').getElement(); + // 运行状态node + let loading_node = $popup.querySelector('p:first-of-type'); + // if容器 + const if_cont = $popup.querySelector('#wh-quick-crime-if-container'); + if_cont.innerHTML = ifHTML; + + // if内未加载脚本时插入的快捷crime node + const mobile_prepend_node = document.createElement('div'); + mobile_prepend_node.classList.add('wh-translate'); + mobile_prepend_node.innerHTML = QUICK_CRIMES_HTML; + + // if对象加载后运行 + let cIframe = $popup.querySelector('iframe'); + + // 加载状态 + const if_onload_func = () => { + // if内部文档对象 + const ifDocu = cIframe.contentWindow.document; + // 内部插件运行flag + const ifWH = cIframe.contentWindow.WHTRANS; + // 文档加载完成后移除 + if (!!loading_node) loading_node.remove(); + // 文档加载完成后才显示if + cIframe.style.display = 'block'; + // 验证码flag + const isValidate = ifDocu.querySelector('h4#skip-to-content').innerText.toLowerCase().includes('validate'); + // 如果iframe内部未运行脚本 + if (ifWH === undefined) { + // 隐藏顶部 + CommonUtils.elementReady('#header-root', ifDocu).then(e => e.style.display = 'none'); + // 隐藏4条 + CommonUtils.elementReady('#sidebarroot', ifDocu).then(e => e.style.display = 'none'); + // 隐藏聊天 + CommonUtils.elementReady('#chatRoot', ifDocu).then(e => e.style.display = 'none'); + // 非验证码页面隐藏滚动条 + if (!isValidate) ifDocu.body.style.overflow = 'hidden'; + // 调整容器位置 + CommonUtils.elementReady('.content-wrapper', ifDocu).then(elem => { + // 加入 + elem.prepend(mobile_prepend_node); + elem.style.margin = '0px'; + elem.style.position = 'absolute'; + elem.style.top = '-35px'; + new MutationObserver((m, o) => { + o.disconnect(); + if (!elem.querySelector('.wh-translate')) elem.prepend(mobile_prepend_node); + o.observe(elem, { childList: true, subtree: true }); + }) + .observe(elem, { childList: true, subtree: true }); + }); + // 隐藏返回顶部按钮 + CommonUtils.elementReady('#go-to-top-btn button', ifDocu).then(e => e.style.display = 'none'); + } + }; + cIframe.onload = if_onload_func; + + // 超时判断 + let time_counter = 0; + let time_out_id = window.setInterval(() => { + loading_node = $popup.querySelector('p:first-of-type'); + if (!loading_node) { + clearInterval(time_out_id); + time_out_id = undefined; + return; + } + time_counter++; + if (time_counter > 0 && !loading_node.querySelector('button')) { + const reload_btn = document.createElement('button'); + reload_btn.innerHTML = '重新加载'; + reload_btn.onclick = () => { + reload_btn.remove(); + time_counter = 0; + if_cont.innerHTML = null; + if_cont.innerHTML = ifHTML; + cIframe = $popup.querySelector('iframe'); + cIframe.onload = if_onload_func; + }; + loading_node.append(reload_btn); + } + }, 1000); + } +} \ No newline at end of file diff --git a/src/class/handler/ItemPriceWatcherHandler.ts b/src/class/handler/ItemPriceWatcherHandler.ts new file mode 100644 index 0000000..890044a --- /dev/null +++ b/src/class/handler/ItemPriceWatcherHandler.ts @@ -0,0 +1,27 @@ +import WuhuBase from "../WuhuBase"; +import WuhuConfig from "../WuhuConfig"; +import PRICE_WATCHER_HTML from "../../static/html/price_watcher.html"; +import Popup from "../utils/Popup"; +import Global from "../Global"; + +export default class ItemPriceWatcherHandler extends WuhuBase { + className = 'ItemPriceWatcherHandler'; + + public handle(): void { + const watcher_conf = WuhuConfig.get('priceWatcher'); + const pre_str = JSON.stringify(watcher_conf); + const html = PRICE_WATCHER_HTML + .replace('{{}}', localStorage.getItem('APIKey') || '不可用') + .replace('{{}}', Global.getInstance().isPDA ? Global.getInstance().PDA_APIKey : '不可用') + .replace('{{}}', watcher_conf['pt'] || -1) + .replace('{{}}', watcher_conf['xan'] || -1); + const popup = new Popup(html, '价格监视设置'); + popup.getElement().querySelector('button').onclick = () => { + const [pt_node, xan_node] = Array.from(>popup.getElement().querySelectorAll('input[type="number"]')); + watcher_conf.pt = (pt_node.value as any) | 0; + watcher_conf.xan = (xan_node.value as any) | 0; + if (JSON.stringify(watcher_conf) !== pre_str) WuhuConfig.set('priceWatcher', watcher_conf); + popup.close(); + }; + } +} \ No newline at end of file diff --git a/src/class/handler/NNB.ts b/src/class/handler/NNB.ts new file mode 100644 index 0000000..676168d --- /dev/null +++ b/src/class/handler/NNB.ts @@ -0,0 +1,62 @@ +import WuhuBase from "../WuhuBase"; +import NNB_INFO_HTML from "../../static/html/nnb_info.html"; +import Popup from "../utils/Popup"; +import Global from "../Global"; + +export default class NNB extends WuhuBase { + className = 'NNB'; + + public handle(): void { + let { isPDA, PDA_APIKey } = Global.getInstance(); + const insert = NNB_INFO_HTML + .replace('{{}}', localStorage.getItem('APIKey') || '不可用') + .replace('{{}}', isPDA ? PDA_APIKey : '不可用'); + const popup = new Popup(insert, '查看NNB').getElement(); + const select = popup.querySelector('input'); + const node = popup.querySelector('p'); + popup.querySelector('button').addEventListener('click', ev => { + let target = ev.target as HTMLInputElement; + target.style.display = 'none'; + node.innerHTML = '加载中'; + // API 计算 + if (select.checked) { + const api_key = isPDA ? PDA_APIKey : window.localStorage.getItem('APIKey'); + window.fetch(`https://api.torn.com/user/?selections=bars,perks&key=${ api_key }`) + .then(res => res.json()) + .then(data => { + if (data['error']) { + node.innerHTML = `出错了 ${ JSON.stringify(data['error']) }`; + target.style.display = null; + return; + } + let nb = data['nerve']['maximum']; + let perks = 0; + Object.values(data).forEach(val => { + (val instanceof Array) && val.forEach(s => { + s = s.toLowerCase(); + s.includes('maximum nerve') && (perks += (new RegExp('[0-9].').exec(s))[0] | 0) + }) + }); + node.innerHTML = `NNB: ${ nb - perks }`; + target.style.display = null; + }); + } + // 主页计算 + else { + if (window.location.href.includes('index.php') && document.title.includes('Home')) { + let nb = (document.querySelector('#barNerve p[class^="bar-value___"]').innerText.split('/')[1]) | 0; + let perks = 0; + document.querySelectorAll('#personal-perks li').forEach(elem => { + const str = elem.innerText.toLowerCase(); + str.includes('maximum nerve') && (perks += (/[0-9]./.exec(str) as any)[0] | 0) + }); + node.innerHTML = `NNB: ${ nb - perks }`; + target.style.display = null; + return; + } + node.innerHTML = '不在主页面,点击前往'; + target.style.display = null; + } + }); + } +} \ No newline at end of file diff --git a/src/class/handler/QuickFlyBtnHandler.ts b/src/class/handler/QuickFlyBtnHandler.ts new file mode 100644 index 0000000..4ff8b2e --- /dev/null +++ b/src/class/handler/QuickFlyBtnHandler.ts @@ -0,0 +1,107 @@ +import WuhuBase from "../WuhuBase"; +import CommonUtils from "../utils/CommonUtils"; +import QUICK_FLY_CSS from "../../static/css/quick_fly.css"; +import QUICK_FLY_HTML from "../../static/html/quick_fly.html"; +import Alert from "../utils/Alert"; +import TravelItem from "../action/TravelItem"; + +export default class QuickFlyBtnHandler extends WuhuBase { + className = 'QuickFlyBtnHandler'; + + public static doQuickFly(): void { + // [id: dest, _type: (1...4), ts: timestamp] + const [_id, _type, ts] = sessionStorage['wh-quick-fly'].trim().split(' '); + if (new Date().getTime() - ts > 20000) { + new Alert('超时,一键起飞计划已取消'); + return; + } + const keyNode = document.querySelector('div[data-id][data-key]'); + if (!keyNode) { + new Alert('出错了,无法起飞,已取消'); + return; + } + const _key = keyNode.getAttribute('data-key'); + window.getAction({ + type: 'post', + data: { + step: 'travel', + id: QuickFlyBtnHandler.getDestId(_id), + key: _key, + type: ['standard', 'airstrip', 'private', 'business'][_type] + }, + success: function (str) { + new Alert(str) + if (str.includes('err')) { + new Alert('起飞出错了'); + return; + } + window.location.href = 'https://www.torn.com/index.php' + }, + before: function () { + } + }); + delete sessionStorage['wh-quick-fly']; + } + + // 起飞目的地id + private static getDestId(dest): number { + // 墨、开、加、夏、英、阿、瑞s、立本、祖、迪、南 + return [2, 12, 9, 3, 10, 7, 8, 5, 6, 11, 4][dest]; + } + + public handle(): void { + if (window.hasWHQuickFlyOpt) return; + window.hasWHQuickFlyOpt = true; + // TODO + CommonUtils.addStyle(QUICK_FLY_CSS); + const node = document.createElement('div'); + node.id = 'wh-quick-fly-opt'; + node.innerHTML = QUICK_FLY_HTML; + const [dest_node, type_node] = node.querySelectorAll('select') as any as HTMLSelectElement[]; + node.querySelector('button').addEventListener('click', () => { + sessionStorage['wh-quick-fly'] = `${ dest_node.selectedIndex } ${ type_node.selectedIndex } ${ new Date().getTime() }`; + if (!window.location.href.contains('travelagency.php')) { + new Alert('正在转跳'); + location.href = 'https://www.torn.com/travelagency.php'; + } else { + QuickFlyBtnHandler.doQuickFly(); + } + }); + node.querySelector('a').addEventListener('click', (e) => { + e.preventDefault(); + // forStock(); + TravelItem.getInstance().clickHandler(); + }); + node.querySelector('input').addEventListener('click', (e) => { + node.classList.toggle('wh-quick-fly-opt-hide'); + const el = e.target as HTMLInputElement; + el.value = el.value === ' - ' ? ' + ' : ' - '; + }); + const info_node = node.querySelector('info'); + const time_predict = document.createElement('p'); + const yaoCD = document.createElement('p'); + info_node.append(time_predict); + info_node.append(yaoCD); + const predict = [ + ['~54分', '~36分', '~26分', '~16分',], + ['~1时10分', '~50分', '~36分', '~22分',], + ['~1时22分', '~58分', '~40分', '~24分',], + ['~4时28分', '~3时8分', '~2时14分', '~1时20分',], + ['~5时18分', '~3时42分', '~2时40分', '~1时36分',], + ['~5时34分', '~3时54分', '~2时46分', '~1时40分',], + ['~5时50分', '~4时6分', '~2时56分', '~1时46分',], + ['~7时30分', '~5时16分', '~3时46分', '~2时16分',], + ['~8时4分', '~5时38分', '~4时2分', '~2时24分',], + ['~9时2分', '~6时20分', '~4时30分', '~2时42分',], + ['~9时54分', '~6时56分', '~4时58分', '~2时58分',], + ]; + const showTime = function () { + time_predict.innerHTML = `往返时间:${ predict[dest_node.selectedIndex][type_node.selectedIndex] }`; + } + dest_node.addEventListener('change', showTime); + type_node.addEventListener('change', showTime); + document.body.append(node); + showTime(); + yaoCD.innerHTML = `药CD剩余:${ CommonUtils.getYaoCD() }`; + } +} \ No newline at end of file diff --git a/src/class/handler/QuickLinksHandler.ts b/src/class/handler/QuickLinksHandler.ts new file mode 100644 index 0000000..aa08db2 --- /dev/null +++ b/src/class/handler/QuickLinksHandler.ts @@ -0,0 +1,93 @@ +import WuhuBase from "../WuhuBase"; +import CommonUtils from "../utils/CommonUtils"; +import QUICK_LINK_CSS from "../../static/css/quick_link.css"; +import Popup from "../utils/Popup"; + +export default class QuickLinksHandler extends WuhuBase { + className = 'QuickLinksHandler'; + + private styleAdded: boolean = false; + private list = []; + + constructor() { + super(); + let list = this.list; + // 生存手册 + list.push({ + name: '生存手册', + url: 'https://docs.qq.com/doc/DTVpmV2ZaRnB0RG56', + new_tab: true, + img: 'https://www.torn.com/images/items/293/medium.png', + }); + // 买啤酒 + list.push({ + name: '抢啤酒', + url: 'https://www.torn.com/shops.php?step=bitsnbobs', + new_tab: true, + img: 'https://www.torn.com/images/items/180/medium.png', + }); + // 买XAN + list.push({ + name: '买XAN', + url: 'https://www.torn.com/imarket.php#/p=shop&step=shop&type=&searchname=Xanax', + new_tab: true, + img: 'https://www.torn.com/images/items/206/medium.png', + }); + // 起飞 + list.push({ + name: '起飞', + url: 'https://www.torn.com/travelagency.php', + new_tab: true, + img: 'https://www.torn.com/images/items/396/medium.png', + }); + // 买PT + list.push({ + name: '买PT', + url: 'https://www.torn.com/pmarket.php', + new_tab: true, + img: 'https://www.torn.com/images/items/722/medium.png', + }); + // 租PI + list.push({ + name: '租PI', + url: 'https://www.torn.com/properties.php?step=rentalmarket#/property=13', + new_tab: false, + img: 'https://www.torn.com/images/v2/properties/350x230/350x230_default_private_island.png', + }); + // 找工作 + list.push({ + name: '找工作', + url: 'https://www.torn.com/joblist.php#!p=main', + new_tab: false, + img: 'https://www.torn.com/images/items/421/medium.png', + }); + // 下悬赏 + list.push({ + name: '下悬赏', + url: 'https://www.torn.com/bounties.php#/p=add', + new_tab: false, + img: 'https://www.torn.com/images/items/431/medium.png', + }); + } + + public handle(): void { + if (!this.styleAdded) { + CommonUtils.addStyle(QUICK_LINK_CSS); + this.styleAdded = true; + } + const list = this.list; + let insert = '

'; + list.forEach(el => { + insert += `${ el.name }`; + }); + insert += '

' + let popup = new Popup(insert, '常用链接'); + popup.getElement().classList.add('wh-link-collection-cont'); + popup.getElement().addEventListener('click', ev => { + let target = ev.target as HTMLElement; + if (target.tagName.toLowerCase() === 'a' || target.tagName.toLowerCase() === 'span') { + popup.close(); + } + }); + } +} \ No newline at end of file diff --git a/src/class/handler/SettingsHandler.ts b/src/class/handler/SettingsHandler.ts new file mode 100644 index 0000000..9c0e8c7 --- /dev/null +++ b/src/class/handler/SettingsHandler.ts @@ -0,0 +1,448 @@ +import WuhuBase from "../WuhuBase"; +import { MenuItemConfig } from "../ZhongIcon"; +import Log from "../Log"; +import Timer from "../utils/Timer"; +import BuyBeerHelper from "../action/BuyBeerHelper"; +import UpdateTranslateDict from "./UpdateTranslateDict"; +import landedRedirect from "../../func/module/landedRedirect"; +import Alert from "../utils/Alert"; +import WuhuConfig from "../WuhuConfig"; +import ViewLogsHandler from "./ViewLogsHandler"; +import AdditionalSettingsHandler from "./AdditionalSettingsHandler"; +import Popup from "../utils/Popup"; +import CommonUtils from "../utils/CommonUtils"; + +export default class SettingsHandler extends WuhuBase { + className = 'SettingsHandler'; + + private list: MenuItemConfig[] = []; + + constructor() { + super(); + this.constructWuhuSettingList(); + } + + public handler(): void { + let startTime = new Timer(); + Log.info('构造设置开始'); + let pop = new Popup(CommonUtils.loading_gif_html(), '芜湖助手设置'); + let tmp = document.createElement('div'); + tmp.classList.add('gSetting'); + this.list.forEach(set => CommonUtils.getInstance().elemGenerator(set, tmp)); + pop.getElement().innerHTML = ''; + pop.getElement().appendChild(tmp); + // 本日不提醒 + pop.getElement().querySelector('#wh-qua-alarm-check-btn') + .addEventListener('click', () => BuyBeerHelper.getInstance().skip_today()); + (window.initializeTooltip) && (window.initializeTooltip('#wh-popup-cont', 'white-tooltip')); + Log.info('构造设置结束 ' + startTime.getTimeMs()); + } + + // 设置 + private constructWuhuSettingList(): SettingsHandler { + let timer = new Timer(); + Log.info('构造设置列表开始'); + const date = new Date(); + + let beer = BuyBeerHelper.getInstance(); + + let list = this.list; + + // 12月时加入圣诞小镇选项 + if (date.getMonth() === 11) { + list.push({ + domType: 'plain', + domId: '', + domHTML: '圣诞小镇', + tagName: 'h4', + }) + list.push({ + domType: 'checkbox', + domId: 'wh-xmastown-wt', + domText: ' 圣诞小镇攻略', + dictName: 'xmasTownWT', + isHide: true, + }); + list.push({ + domType: 'checkbox', + domId: 'wh-xmastown-notify', + domText: ' 圣诞小镇物品提示', + dictName: 'xmasTownNotify', + isHide: true, + }); + } + + // 翻译 + list.push({ + domType: 'plain', + domId: '', + domHTML: '翻译', + tagName: 'h4', + }); + // 开启翻译 + list.push({ + domType: 'checkbox', + domId: 'wh-trans-enable', + domText: ' 开启翻译', + dictName: 'transEnable', + isHide: true, + }); + // 更新翻译词库 + list.push({ + domType: 'button', + domId: '', + domText: '更新翻译词库', + clickFunc: () => UpdateTranslateDict.getInstance().handle() + }); + + // 战斗优化 + list.push({ + domType: 'plain', + domId: '', + domHTML: '战斗优化', + tagName: 'h4', + }); + // 光速拔刀 + list.push({ + domType: 'select', + domId: 'wh-quick-attack-index', + domText: '光速拔刀 ', + domSelectOpt: [ + { + domVal: 'pri', + domText: '主手', + }, + { + domVal: 'sec', + domText: '副手', + }, + { + domVal: 'wea', + domText: '近战', + }, + { + domVal: 'gre', + domText: '手雷', + }, + { + domVal: 'fis', + domText: '拳头', + }, + { + domVal: 'kic', + domText: '脚踢', + }, + { + domVal: 'none', + domText: '关闭', + }, + ], + dictName: 'quickAttIndex', + isHide: true, + tip: '将Start Fight按钮移动到指定格子上', + }); + // 光速跑路 + list.push({ + domType: 'select', + domId: 'wh-quick-mug', + domText: '光速跑路 ', + domSelectOpt: [ + { + domVal: 'leave', + domText: '跑路(LEAVE)', + }, + { + domVal: 'mug', + domText: '打劫(MUG)', + }, + { + domVal: 'hosp', + domText: '住院(HOSP)', + }, + { + domVal: 'none', + domText: '关闭', + }, + ], + dictName: 'quickFinishAtt', + isHide: true, + tip: '将结束后指定按钮移动到上面指定的格子上暂时关闭', + }); + // 攻击链接转跳 + list.push({ + domType: 'checkbox', + domId: 'wh-attack-relocate', + domText: ' 真·攻击界面转跳', + dictName: 'attRelocate', + tip: '在无法打开攻击界面的情况下依然可以转跳到正确的攻击页面', + isHide: true, + }); + // 危险行为⚠️ + if (WuhuConfig.get('dangerZone') === true) { + // 攻击界面自刷新 + list.push({ + domType: 'select', + domId: 'wh-attack-reload', + domText: '⚠️攻击界面自动刷新 ', + dictName: 'attReload', + domSelectOpt: [ + { + domVal: 'none', + domText: '无间隔', + }, + { + domVal: '1', + domText: '约1s', + }, + { + domVal: '2', + domText: '约2s', + }, + { + domVal: '3', + domText: '约3s', + }, + { + domVal: '4', + domText: '约4s', + }, + { + domVal: '5', + domText: '约5s', + }, + { + domVal: 'disabled', + domText: '关闭', + }, + ], + isHide: true, + tip: '危险功能:接机时常用,将自动刷新页面直到目标落地', + }); + // 自动开打和结束 + list.push({ + domType: 'checkbox', + domId: 'wh-auto-start-finish', + domText: ' ⚠️自动开打和结束', + dictName: 'autoStartFinish', + tip: '脚本将会自动按下战斗和结束按钮', + isHide: true, + }); + } else { + WuhuConfig.set('autoStartFinish', false) + WuhuConfig.set('attReload', 6) + } + + // 飞行 + list.push({ + domType: 'plain', + domId: '', + domHTML: '飞行', + tagName: 'h4', + }); + // 起飞警告 + list.push({ + domType: 'checkbox', + domId: 'wh-energy-alert', + domText: ' 起飞爆E警告', + dictName: 'energyAlert', + tip: '起飞前计算来回是否会爆体,红字警告', + isHide: true, + }); + // 飞行闹钟 + list.push({ + domType: 'checkbox', + domId: 'wh-trv-alarm-check', + domText: ' 飞行闹钟', + dictName: 'trvAlarm', + tip: '(仅PC) 飞行页面将显示一个内建的闹钟,落地前声音提醒,需要打开浏览器声音权限', + isHide: true, + }); + // 海外警告 + list.push({ + domType: 'checkbox', + domId: '', + domText: ' 海外警告', + dictName: 'abroadWarning', + tip: '海外落地后每30秒通知警告', + }); + // 落地转跳 + list.push({ domType: 'button', domId: '', domText: '落地转跳', clickFunc: landedRedirect }); + + // 公司 + list.push({ + domType: 'plain', + domId: '', + domHTML: '公司', + tagName: 'h4', + }); + // 浮动存钱框 + list.push({ + domType: 'checkbox', + domId: '', + domText: ' 浮动存钱框', + dictName: 'floatDepo', + tip: '打开公司或帮派的存钱页面后存钱框将浮动显示', + }); + // 公司转跳存钱 + list.push({ + domType: 'checkbox', + domId: '', + domText: ' 公司转跳存钱', + dictName: 'companyRedirect', + tip: '打开公司页面时自动打开存钱选项卡', + }); + // 收起公司冰蛙效率表 + list.push({ + domType: 'checkbox', + domId: '', + domText: ' 收起公司冰蛙效率表', + dictName: 'companyBWCollapse', + tip: '开启后可手动显示隐藏冰蛙公司表格', + }); + // 任何位置一键存钱 + list.push({ + domType: 'checkbox', + domId: '', + domText: ' 任何位置一键存钱', + dictName: 'companyDepositAnywhere', + tip: '在所有页面显示一键存钱按钮,Torn OK状态下可用,此功能未完全测试无害,使用请慎重', + }); + // 火车检测开关 + list.push({ + domType: 'checkbox', + domId: null, + domText: '火车检测', + dictName: 'CHTrainsDetectSwitch', + tip: '检测明日火车是否会超出上限,需要系统通知权限' + }); + + // 啤酒 + list.push({ + domType: 'plain', + domId: '', + domHTML: '啤酒', + tagName: 'h4', + }); + // 啤酒提醒 + list.push({ + domType: 'checkbox', + domId: 'wh-qua-alarm-check', + domText: ' 啤酒提醒 ', + dictName: '_15Alarm', + tip: '每小时的整15分钟的倍数时通知提醒抢啤酒或者血包', + isHide: true, + changeEv: function (ev) { + ev.target.checked ? beer.start() : beer.stop(); + }, + }); + // 啤酒提醒状态 + list.push({ + domType: 'button', + domId: '', + domText: '啤酒提醒状态', + clickFunc: function () { + new Alert(`啤酒提醒${ beer.status() }`); + } + }); + // 啤酒提醒时间 + list.push({ + domType: 'button', + domId: '', + domText: '啤酒提醒时间设定', + // tip: '通知提前时间', + clickFunc: () => BuyBeerHelper.getInstance().setTimeHandler() + }); + + // 其他 + list.push({ + domType: 'plain', + domId: '', + domHTML: '其他', + tagName: 'h4', + }); + // 任务助手 + list.push({ + domType: 'checkbox', + domId: 'wh-mission-lint', + domText: ' 任务助手', + dictName: 'missionHint', + tip: 'Duke任务的一些中文小提示', + isHide: true, + }); + // 捡垃圾助手 + list.push({ + domType: 'checkbox', + domId: 'wh-city-finder', + domText: ' 捡垃圾助手', + dictName: 'cityFinder', + tip: '城市地图中放大显示物品并且估计价值', + isHide: true, + }); + // 快速crime + list.push({ + domType: 'checkbox', + domId: 'wh-quick-crime', + domText: ' 快速犯罪', + dictName: 'quickCrime', + tip: '显示快捷操作按钮,目前不支持自定义', + isHide: true, + }); + // 叠E保护 + list.push({ + domType: 'checkbox', + domId: 'wh-SEProtect-check', + domText: ' 叠E保护', + dictName: 'SEProtect', + tip: '隐藏健身房的锻炼按钮,防止误操作', + isHide: true, + }); + // PT一键购买 + list.push({ + domType: 'checkbox', + domId: 'wh-ptQuickBuy-check', + domText: ' PT一键购买', + dictName: 'ptQuickBuy', + tip: 'PT市场页面购买时跳过确认', + isHide: true, + }); + // 4条转跳 + list.push({ + domType: 'checkbox', + domId: '', + domText: ' 4条转跳', + dictName: 'barsRedirect', + tip: '点击4条时转跳对应页面', + }); + // 清除多余的脚本 + list.push({ + domType: 'checkbox', + domId: '', + domText: ' 清除多余的脚本', + dictName: 'removeScripts', + tip: '清除Google相关脚本、顶部横幅等', + }); + // dev + list.push({ + domType: 'checkbox', + domId: 'wh-dev-mode', + domText: '开发模式', + dictName: 'isDev', + isHide: true, + }); + // 查看logs + list.push({ + domType: 'button', + domId: null, + domText: '查看日志', + clickFunc: () => ViewLogsHandler.getInstance().handle() + }); + // 更多设定 + list.push({ + domType: 'button', domId: 'wh-otherBtn', domText: '更多设定', + clickFunc: () => AdditionalSettingsHandler.getInstance().handle() + }); + + Log.info('构造设置列表结束' + timer.getTimeMs()); + return this; + } +} \ No newline at end of file diff --git a/src/class/handler/UpdateTranslateDict.ts b/src/class/handler/UpdateTranslateDict.ts new file mode 100644 index 0000000..b26f76b --- /dev/null +++ b/src/class/handler/UpdateTranslateDict.ts @@ -0,0 +1,10 @@ +import WuhuBase from "../WuhuBase"; +import Alert from "../utils/Alert"; + +export default class UpdateTranslateDict extends WuhuBase { + className = 'UpdateTranslateDict'; + + public handle(): void { + new Alert('计划中'); + } +} \ No newline at end of file diff --git a/src/class/handler/ViewLogsHandler.ts b/src/class/handler/ViewLogsHandler.ts new file mode 100644 index 0000000..4d9de04 --- /dev/null +++ b/src/class/handler/ViewLogsHandler.ts @@ -0,0 +1,19 @@ +import WuhuBase from "../WuhuBase"; +import Log from "../Log"; +import Popup from "../utils/Popup"; + +export default class ViewLogsHandler extends WuhuBase { + className = 'ViewLogsHandler'; + + public handle(): void { + let logCounter = Log.getCounter(); + let pop = new Popup('', '查看日志'); + let text = pop.getElement().querySelector('textarea'); + text.innerHTML = Log.getLogs(); + text.onclick = () => text.select(); + pop.getElement().insertAdjacentHTML( + 'afterbegin', + `

${ logCounter.info }信息 ${ logCounter.warning }警告 ${ logCounter.error }错误

` + ); + } +} diff --git a/src/class/utils/CommonUtils.ts b/src/class/utils/CommonUtils.ts index 31880ba..86c959d 100644 --- a/src/class/utils/CommonUtils.ts +++ b/src/class/utils/CommonUtils.ts @@ -3,10 +3,12 @@ import WuhuBase from "../WuhuBase"; import Log from "../Log"; import Device from "../../enum/Device"; import AjaxFetchOption from "../../interface/AjaxFetchOption"; -import Alert from "./Alert"; import LOADING_IMG_HTML from "../../static/html/loading_img.html"; import Timer from "./Timer"; import FetchUtils from "./FetchUtils"; +import TornStyleSwitch from "./TornStyleSwitch"; +import WuhuConfig from "../WuhuConfig"; +import { MenuItemConfig } from "../ZhongIcon"; export default class CommonUtils extends WuhuBase { className = 'CommonUtils'; @@ -84,22 +86,22 @@ export default class CommonUtils extends WuhuBase { }); } - /** - * 返回玩家信息的对象 { playername: string, userID: number } - * @return {PlayerInfo} rs - */ - static getPlayerInfo(): PlayerInfo { - const node = document.querySelector('script[uid]'); - if (node) { - return { - playername: node.getAttribute('name'), - userID: node.getAttribute('uid') as unknown as number, - } - } else { - new Alert('严重错误:芜湖助手无法获取用户数据,已退出'); - throw '芜湖助手无法获取用户数据'; - } - } + // /** + // * 返回玩家信息的对象 { playername: string, userID: number } + // * @return {PlayerInfo} rs + // */ + // static getPlayerInfo(): PlayerInfo { + // const node = document.querySelector('script[uid]'); + // if (node) { + // return { + // playername: node.getAttribute('name'), + // userID: node.getAttribute('uid') as unknown as number, + // } + // } else { + // new Alert('严重错误:芜湖助手无法获取用户数据,已退出'); + // throw '芜湖助手无法获取用户数据'; + // } + // } // 用户设备类型 对应PC MOBILE TABLET public static getDeviceType(): Device { @@ -171,6 +173,12 @@ export default class CommonUtils extends WuhuBase { }); } + /** + * 通过 mutation.observe 方法异步返回元素 + * @param selectors + * @param content + * @param timeout + */ public static querySelector(selectors: string, content: Document = document, timeout: number = 30000): Promise { return CommonUtils.elementReady(selectors, content, timeout); } @@ -247,4 +255,70 @@ export default class CommonUtils extends WuhuBase { let time = Math.max(ms, 10); return new Promise(resolve => setTimeout(() => resolve(null), time)); } -} \ No newline at end of file + + public elemGenerator(setting: MenuItemConfig, root_node: Element): HTMLElement { + let { tip, domType } = setting; + let new_node = null; + switch (domType) { + case 'checkbox': { + new_node = document.createElement('div'); + let { domId, dictName, domText, changeEv } = setting; + + let switcher = new TornStyleSwitch(domText); + let _input = switcher.getInput(); + switcher.getBase().id = domId; + (tip) && (switcher.getBase().setAttribute('title', tip)); + _input.checked = WuhuConfig.get(dictName); + _input.onchange = e => { + WuhuConfig.set(dictName, _input.checked, true); + if (changeEv) changeEv(e); + }; + new_node.appendChild(switcher.getBase()); + break; + } + case 'button': { + new_node = document.createElement('div'); + let { domId, domText, clickFunc } = setting; + let btn = document.createElement('button'); + (tip) && (btn.setAttribute('title', tip)); + btn.id = domId; + btn.innerHTML = domText; + btn.addEventListener('click', clickFunc); + new_node.appendChild(btn); + break; + } + case 'select': { + new_node = document.createElement('div'); + let { domSelectOpt, dictName, domId, domText } = setting; + let label = document.createElement('label'); + (tip) && (label.setAttribute('title', tip)); + let text = document.createTextNode(domText); + let select = document.createElement('select'); + select.id = domId; + domSelectOpt.forEach((opt, i) => { + let { domVal, domText } = opt; + let option = document.createElement('option'); + option.value = domVal; + option.innerHTML = domText; + option.selected = i === WuhuConfig.get(dictName); + option.innerHTML = domText; + select.appendChild(option); + }); + select.onchange = e => WuhuConfig.set(dictName, (e.target).selectedIndex); + label.appendChild(text); + label.appendChild(select); + new_node.appendChild(label); + break; + } + case 'plain': { + let tag = setting.tagName || 'div'; + new_node = document.createElement(tag); + if (setting.domId) new_node.id = setting.domId; + new_node.innerHTML += setting['domHTML']; + break; + } + } + // 移动节点 + return root_node.appendChild(new_node); + } +} diff --git a/src/class/utils/DialogMsgBox.ts b/src/class/utils/DialogMsgBox.ts new file mode 100644 index 0000000..8aa90c4 --- /dev/null +++ b/src/class/utils/DialogMsgBox.ts @@ -0,0 +1,53 @@ +import Log from "../Log"; +import DIALOG_MSG_BOX_HTML from "../../static/html/dialog_msg_box.html"; + +export default class DialogMsgBox { + private static existed = false; + private readonly container: HTMLElement; + + constructor(msg: string, opt: DialogMsgBoxOptions) { + Log.info('创建DialogMsgBox', { msg, opt }); + let { title = '提示', callback } = opt; + if (!callback) { + Log.error('无callback'); + throw new Error('无callback'); + } + if (DialogMsgBox.existed) { + Log.error('无法创建DialogMsgBox:已存在'); + throw new Error('无法创建DialogMsgBox:已存在'); + } + this.container = document.createElement('div'); + this.container.id = 'wh-dialog'; + this.container.innerHTML = DIALOG_MSG_BOX_HTML.replace('{{}}', title).replace('{{}}', msg); + let [confirm, cancel] = Array.from(this.container.querySelectorAll('button')); + confirm.addEventListener('click', () => { + callback(this.container); + this.destroy(); + }); + cancel.addEventListener('click', () => { + this.destroy(); + }); + document.body.append(this.container); + // this.hideChat(); + DialogMsgBox.existed = true; + } + + // private hideChat() { + // document.querySelector('#chatRoot').classList.add('wh-hide'); + // } + // + // private showChat() { + // document.querySelector('#chatRoot').classList.remove('wh-hide'); + // } + + private destroy() { + this.container.remove(); + // this.showChat(); + DialogMsgBox.existed = false; + } +} + +interface DialogMsgBoxOptions { + title?: string; + callback: Function; +} \ No newline at end of file diff --git a/src/class/utils/Timer.ts b/src/class/utils/Timer.ts index 8cd66a5..39011c1 100644 --- a/src/class/utils/Timer.ts +++ b/src/class/utils/Timer.ts @@ -1,5 +1,5 @@ export default class Timer { - private startTime: number; + private readonly startTime: number; constructor() { this.startTime = performance.now(); diff --git a/src/class/utils/TornStyleSwitch.ts b/src/class/utils/TornStyleSwitch.ts index 1d22727..a17b4f9 100644 --- a/src/class/utils/TornStyleSwitch.ts +++ b/src/class/utils/TornStyleSwitch.ts @@ -4,11 +4,11 @@ export default class TornStyleSwitch { private readonly baseElement; private readonly randomId; - constructor(label: string) { + constructor(label: string, checked: boolean = false) { this.randomId = MathUtils.getInstance().getRandomInt(100, 2000); this.baseElement = document.createElement('span'); this.baseElement.id = 'WHSwitch' + this.randomId; - this.baseElement.innerHTML = ` + this.baseElement.innerHTML = ` `; } @@ -19,4 +19,8 @@ export default class TornStyleSwitch { public getInput(): HTMLInputElement { return this.baseElement.querySelector('input'); } + + public getHtml(): string { + return this.baseElement.innerHTML; + } } \ No newline at end of file diff --git a/src/func/module/doQuickFly.ts b/src/func/module/doQuickFly.ts index 7ed0038..9e237bb 100644 --- a/src/func/module/doQuickFly.ts +++ b/src/func/module/doQuickFly.ts @@ -1,43 +1,43 @@ -import Alert from "../../class/utils/Alert"; - -// 一键起飞 -export default function doQuickFly() { - // [id: dest, _type: (1...4), ts: timestamp] - const [_id, _type, ts] = sessionStorage['wh-quick-fly'].trim().split(' '); - if (new Date().getTime() - ts > 20000) { - new Alert('超时,一键起飞计划已取消'); - return; - } - const keynode = document.querySelector('div[data-id][data-key]'); - if (!keynode) { - new Alert('出错了,无法起飞,已取消'); - return; - } - const _key = keynode.getAttribute('data-key'); - window.getAction({ - type: 'post', - data: { - step: 'travel', - id: getDestId(_id), - key: _key, - type: ['standard', 'airstrip', 'private', 'business'][_type] - }, - success: function (str) { - new Alert(str) - if (str.includes('err')) { - new Alert('起飞出错了'); - return; - } - window.location.href = 'https://www.torn.com/index.php' - }, - before: function () { - } - }); - delete sessionStorage['wh-quick-fly']; -} - -// 起飞目的地id -function getDestId(dest) { - // 墨、开、加、夏、英、阿、瑞s、立本、祖、迪、南 - return [2, 12, 9, 3, 10, 7, 8, 5, 6, 11, 4][dest]; -} +// import Alert from "../../class/utils/Alert"; +// +// // 一键起飞 +// export default function doQuickFly() { +// // [id: dest, _type: (1...4), ts: timestamp] +// const [_id, _type, ts] = sessionStorage['wh-quick-fly'].trim().split(' '); +// if (new Date().getTime() - ts > 20000) { +// new Alert('超时,一键起飞计划已取消'); +// return; +// } +// const keynode = document.querySelector('div[data-id][data-key]'); +// if (!keynode) { +// new Alert('出错了,无法起飞,已取消'); +// return; +// } +// const _key = keynode.getAttribute('data-key'); +// window.getAction({ +// type: 'post', +// data: { +// step: 'travel', +// id: getDestId(_id), +// key: _key, +// type: ['standard', 'airstrip', 'private', 'business'][_type] +// }, +// success: function (str) { +// new Alert(str) +// if (str.includes('err')) { +// new Alert('起飞出错了'); +// return; +// } +// window.location.href = 'https://www.torn.com/index.php' +// }, +// before: function () { +// } +// }); +// delete sessionStorage['wh-quick-fly']; +// } +// +// // 起飞目的地id +// function getDestId(dest) { +// // 墨、开、加、夏、英、阿、瑞s、立本、祖、迪、南 +// return [2, 12, 9, 3, 10, 7, 8, 5, 6, 11, 4][dest]; +// } diff --git a/src/func/module/priceWatcherHandle.ts b/src/func/module/priceWatcherHandle.ts index a42a356..1a34f83 100644 --- a/src/func/module/priceWatcherHandle.ts +++ b/src/func/module/priceWatcherHandle.ts @@ -1,5 +1,3 @@ -import getWhSettingObj from "../utils/@deprecated/getWhSettingObj"; -import log from "../utils/@deprecated/log"; import toThousands from "../utils/toThousands"; import Log from "../../class/Log"; import Alert from "../../class/utils/Alert"; @@ -12,7 +10,7 @@ export default function priceWatcherHandle(isPDA: boolean, PDA_APIKey: string) { const price_conf = WuhuConfig.get('priceWatcher'); const apikey = isPDA ? PDA_APIKey : localStorage.getItem('APIKey'); if (!apikey || (price_conf['pt'] === -1 && price_conf['xan'] === -1)) { - Log.error('价格监视失败,无apikey'); + Log.warn('价格监视关闭,无apikey或设置未打开'); window.clearInterval(intervalId); return; } diff --git a/src/func/module/travelHelper.ts b/src/func/module/travelHelper.ts index 697ad5d..34144a6 100644 --- a/src/func/module/travelHelper.ts +++ b/src/func/module/travelHelper.ts @@ -1,7 +1,6 @@ import titleTrans from "../translate/titleTrans"; import contentTitleLinksTrans from "../translate/contentTitleLinksTrans"; import Device from "../../enum/Device"; -import doQuickFly from "./doQuickFly"; import WuhuBase from "../../class/WuhuBase"; import Alert from "../../class/utils/Alert"; import ActionButtonUtils from "../../class/utils/ActionButtonUtils"; @@ -10,6 +9,7 @@ import CommonUtils from "../../class/utils/CommonUtils"; import TRAVEL_ALARM_CSS from "../../static/css/travel_alarm.css"; import TRAVEL_ALARM_HTML from "../../static/html/travel_alarm.html"; import TornStyleBlock from "../../class/utils/TornStyleBlock"; +import QuickFlyBtnHandler from "../../class/handler/QuickFlyBtnHandler"; export default async function travelHelper(): Promise { let { href, bodyAttrs, device } = WuhuBase.glob; @@ -29,7 +29,7 @@ export default async function travelHelper(): Promise { dest_cn = { 'uk': "英国", 'switzerland': "瑞士", 'mexico': '墨西哥', 'canada': '加拿大', 'cayman': '开曼', 'hawaii': '夏威夷', 'argentina': '阿根廷', - 'japan': '日本', 'china': '中国', 'uae': 'UAE', 'sa': '南非', + 'japan': '日本', 'china': '中国', 'uae': 'UAE', 'south-africa': '南非', }[country] || country; } @@ -286,7 +286,7 @@ export default async function travelHelper(): Promise { } // 一键起飞 if (sessionStorage['wh-quick-fly']) { - doQuickFly(); + QuickFlyBtnHandler.doQuickFly(); } } } diff --git a/src/func/translate/translateMain.ts b/src/func/translate/translateMain.ts index be821b6..fdfed09 100644 --- a/src/func/translate/translateMain.ts +++ b/src/func/translate/translateMain.ts @@ -37,6 +37,7 @@ import showItemInfoTrans from "./showItemInfoTrans"; import log from "../utils/@deprecated/log"; import contentTitleLinksTransReact from "./contentTitleLinksTransReact"; import titleTransReact from "./titleTransReact"; +import Log from "../../class/Log"; export default function translateMain(href: string): void { // 时分秒转换 @@ -123,12 +124,14 @@ export default function translateMain(href: string): void { const headerTrans = function headerTrans() { // 搜索内容下拉框中的文字 已选中 - if (headerDict[$('div.find button.toggler.down').text()]) - $('div.find button.toggler.down').text(headerDict[$('div.find button.toggler.down').text()]); + let $toggle = $('div.find button.toggler.down'); + if (headerDict[$toggle.text()]) + $toggle.text(headerDict[$toggle.text()]); // pc端 搜索下拉框点击后的搜索类型文字 $('div.find li.item').each((i, e) => { - if (headerDict[$(e).text()]) - $(e).text(headerDict[$(e).text()]); + let $e = $(e); + if (headerDict[$e.text()]) + $e.text(headerDict[$e.text()]); }); // 手机端 搜索下拉框点击后的搜索类型文字 $('li[class^="search-type-"] label').each((i, e) => { @@ -136,46 +139,54 @@ export default function translateMain(href: string): void { $(e).text(headerDict[$(e).text()]); }); // 搜索框placeholder - if (headerDict[$('input[class^="searchInput"]').attr('placeholder')]) - $('input[class^="searchInput"]').attr('placeholder', - headerDict[$('input[class^="searchInput"]').attr('placeholder')]); + let $searchInput = $('input[class^="searchInput"]'); + if (headerDict[$searchInput.attr('placeholder')]) + $searchInput.attr('placeholder', + headerDict[$searchInput.attr('placeholder')]); // 高级搜索框 search by - if (headerDict[document.querySelector('div#header-root legend.title').innerText]) - $('div#header-root legend.title').text(headerDict[$('div#header-root legend.title').text()]); + if (headerDict[document.querySelector('div#header-root legend.title').innerText]) { + let $title = $('div#header-root legend.title'); + $title.text(headerDict[$title.text()]); + } // 高级搜索框的条件 左 键 $('ul.advancedSearchFormBody label.label').each((i, e) => { - if (headerDict[$(e).text()]) - $(e).text(headerDict[$(e).text()]); + let $e = $(e); + if (headerDict[$e.text()]) + $e.text(headerDict[$e.text()]); }); // 高级搜索框的已选中 $('ul.advancedSearchFormBody div.select-wrapper button.toggler.down').each((i, e) => { - // log($(e).text()) - if (headerDict[$(e).text().trim()]) - $(e).text(headerDict[$(e).text().trim()]); - else if (propertyDict[$(e).text().trim()]) - $(e).text(propertyDict[$(e).text().trim()]); + let $e = $(e); + if (headerDict[$e.text().trim()]) + $e.text(headerDict[$e.text().trim()]); + else if (propertyDict[$e.text().trim()]) + $e.text(propertyDict[$e.text().trim()]); }); // 高级搜索的下拉选项 $('ul.advancedSearchFormBody li.item').each((i, e) => { - if (headerDict[$(e).text()]) - $(e).text(headerDict[$(e).text()]); - else if (propertyDict[$(e).text()]) - $(e).text(propertyDict[$(e).text()]); + let $e = $(e); + if (headerDict[$e.text()]) + $e.text(headerDict[$e.text()]); + else if (propertyDict[$e.text()]) + $e.text(propertyDict[$e.text()]); }); // 高级搜索的"Not" $('ul.advancedSearchFormBody label.search-condition-not').each((i, e) => { - if (headerDict[$(e).text()]) - $(e).text(headerDict[$(e).text()]); + let $e = $(e); + if (headerDict[$e.text()]) + $e.text(headerDict[$e.text()]); }); // 高级搜索的"to" $('ul.advancedSearchFormBody label[for*="To"]').each((i, e) => { - if (headerDict[$(e).text()]) - $(e).text(headerDict[$(e).text()]); + let $e = $(e); + if (headerDict[$e.text()]) + $e.text(headerDict[$e.text()]); }); // 高级搜索的reset search按钮 $('form.form-search-extend div.bottom button').each((i, e) => { - if (headerDict[$(e).text()]) - $(e).text(headerDict[$(e).text()]); + let $e = $(e); + if (headerDict[$e.text()]) + $e.text(headerDict[$e.text()]); }); // log按钮“view log” const $view_log = $('div.recentHistory a[class^="link"] span[class^="text"]') @@ -184,8 +195,9 @@ export default function translateMain(href: string): void { .text(headerDict[$view_log.text().trim()]); // 点击头像打开的菜单 $('ul.settings-menu span').each((i, e) => { - if (headerDict[$(e).text()] && e.childNodes.length === 1) - $(e).text(headerDict[$(e).text()]); + let $e = $(e); + if (headerDict[$e.text()] && e.childNodes.length === 1) + $e.text(headerDict[$e.text()]); else if (e.childNodes.length === 3) if (headerDict[e.firstChild.nodeValue]) e.firstChild.nodeValue = headerDict[e.firstChild.nodeValue]; @@ -205,20 +217,22 @@ export default function translateMain(href: string): void { const chatTrans = function chatTrans() { // 聊天框的标题 $('div#chatRoot div[class^="chat-box-title"] span[class^="name"]').each((i, e) => { - if (chatDict[$(e).text().trim()]) - $(e).text(chatDict[$(e).text().trim()]); + let $e = $(e); + if (chatDict[$e.text().trim()]) + $e.text(chatDict[$e.text().trim()]); }); // 聊天设置的左边label $('div[class^="chat-settings-opts"] div[class*="label"]').each((i, e) => { - if ($(e).next().children('div.rc-slider').length > 0) { + let $e = $(e); + if ($e.next().children('div.rc-slider').length > 0) { // 高度和宽度有响应式的% - if (chatDict[$(e).text().split(' ')[0]]) { - $(e).text($(e).text().replace($(e).text().split(' ')[0], chatDict[$(e).text().split(' ')[0]])); + if (chatDict[$e.text().split(' ')[0]]) { + $e.text($e.text().replace($e.text().split(' ')[0], chatDict[$e.text().split(' ')[0]])); } return; } - if (chatDict[$(e).text().trim()]) - $(e).text(chatDict[$(e).text().trim()]); + if (chatDict[$e.text().trim()]) + $e.text(chatDict[$e.text().trim()]); }); // 选项下拉栏 $('div[class^="dropdown-root"]').find('*').contents().each((i, e) => { @@ -228,29 +242,30 @@ export default function translateMain(href: string): void { }); // 设置的两个选项 $('label[class^="privacy-label"]').each((i, e) => { - if (chatDict[$(e).text().trim()]) - $(e).text(chatDict[$(e).text().trim()]); + let $e = $(e); + if (chatDict[$e.text().trim()]) + $e.text(chatDict[$e.text().trim()]); }); // people中的5个分类 faction friend... $('ul[class^="type-list"] li a').each((i, e) => { - if (chatDict[$(e).text().trim()]) - $(e).text(chatDict[$(e).text().trim()]); + let $e = $(e); + if (chatDict[$e.text().trim()]) + $e.text(chatDict[$e.text().trim()]); }); // people中的列表添加框placeholder $('div.ac-wrapper input.ac-search').each((i, e) => { - if (chatDict[$(e).attr('placeholder')]) - $(e).attr('placeholder', chatDict[$(e).attr('placeholder')]); + let $e = $(e); + if (chatDict[$e.attr('placeholder')]) + $e.attr('placeholder', chatDict[$e.attr('placeholder')]); }); // - if (eventsDict[$('div#chatRoot div[class^="overview"] > div > div:nth-child(2)').text().trim()]) { - $('div#chatRoot div[class^="overview"] > div > div:nth-child(2)') - .text( - eventsDict[document.querySelector('div#chatRoot div[class^="overview"] > div > div:nth-child(2)').innerText.trim()] - ); + let $chatRootOverview = document.querySelector('div#chatRoot div[class^="overview"] > div > div:nth-child(2)'); + if (eventsDict[$chatRootOverview.innerText.trim()]) { + $chatRootOverview.innerText = eventsDict[$chatRootOverview.innerText.trim()]; } }; chatTrans(); - chatOB.observe($('div#chatRoot').get(0), { childList: true, subtree: true, attributes: true }); + chatOB.observe(document.querySelector('div#chatRoot'), { childList: true, subtree: true, attributes: true }); } // 搜索玩家的4个分类按钮 @@ -327,18 +342,18 @@ export default function translateMain(href: string): void { // 翻译最近5个攻击 else if (e.firstChild.nodeValue === 'Latest Attacks') { $(e).parent().next().find('span').each(function () { - let nodes = $(this)[0].childNodes; + let $this = $(this); + let nodes = $this[0].childNodes; nodes.forEach((v, i) => { if (v.nodeValue !== null) { - let waitToTsf = v.nodeValue.toString().indexOf(" "); + // let waitToTsf = v.nodeValue.toString().indexOf(" "); let words = v.nodeValue.replace("\n", "").toString().split(" "); words.forEach((word, j) => { if (attackDict.hasOwnProperty(word)) { if (word === "Someone") { - $(this)[0].childNodes[i].nodeValue = $(this)[0].childNodes[i].nodeValue.replace(" ", ""); + $this[0].childNodes[i].nodeValue = $(this)[0].childNodes[i].nodeValue.replace(" ", ""); } - let change = $(this)[0].childNodes[i].nodeValue.replace(word, attackDict[word]); - $(this)[0].childNodes[i].nodeValue = change; + $this[0].childNodes[i].nodeValue = $this[0].childNodes[i].nodeValue.replace(word, attackDict[word]); } }) @@ -373,13 +388,13 @@ export default function translateMain(href: string): void { }); // 标志建筑 标题 - if (cityDict[$('div.title-black').text()]) - $('div.title-black').text(cityDict[$('div.title-black').text()]); + let $divTitleBlack = document.querySelector('div.title-black'); + if (cityDict[$divTitleBlack.innerText]) + $divTitleBlack.innerText = cityDict[$divTitleBlack.innerText]; // 标志建筑 6个分类 $('ul.map-symbols span').each((i, e) => { - if (cityDict[$(e).text()]) - $(e).text(cityDict[$(e).text()]); + if (cityDict[e.innerText]) e.innerText = cityDict[e.innerText]; }); // 地图显示模式 @@ -388,13 +403,13 @@ export default function translateMain(href: string): void { // 完全显示 文字 $('span.active-mode').text(cityDict['active-mode']); // 开关 - $('div.on-label').text('已开启'); - $('div.off-label').text('已关闭'); + document.querySelector('div.on-label').innerText = '已开启'; + document.querySelector('div.off-label').innerText = '已关闭'; // 快速链接中的分类标题 $('li.title').each((i, e) => { - if (cityDict[$(e).text()]) - $(e).text(cityDict[$(e).text()]); + if (cityDict[e.innerText]) + e.innerText = cityDict[e.innerText]; }); // 快速链接中的区域 @@ -1235,9 +1250,10 @@ export default function translateMain(href: string): void { let newspaperTrans = function newspaperTrans() { titleTrans(); contentTitleLinksTrans(); - if ($('a.newspaper-link').length === 0) return; + let $newspaperLink = $('a.newspaper-link'); + if ($newspaperLink.length === 0) return; // 导航菜单 - $('a.newspaper-link').contents().each((i, e) => { + $newspaperLink.contents().each((i, e) => { if (newspaperDict[e.nodeValue]) e.nodeValue = newspaperDict[e.nodeValue]; }); @@ -1284,8 +1300,9 @@ export default function translateMain(href: string): void { }); // 底部链接 // Why not visit our sponsor? - if (newspaperDict[$('div.link-left').text().trim()]) - $('div.link-left').text(newspaperDict[$('div.link-left').text().trim()]); + let $linkLeft = document.querySelector('div.link-left'); + if (newspaperDict[$linkLeft.innerText.trim()]) + $linkLeft.innerText = newspaperDict[$linkLeft.innerText.trim()]; // View all | Advertise here $('div.link-right a').contents().each((i, e) => { if (newspaperDict[e.nodeValue.trim()]) @@ -1306,8 +1323,9 @@ export default function translateMain(href: string): void { } // 漫画 if (window.location.href.contains(/freebies/)) { - if (newspaperDict[$('div.bonus-wrap a').text().trim()]) - $('div.bonus-wrap a').text(newspaperDict[$('div.bonus-wrap a').text().trim()]); + let $bonusWrapA = document.querySelector('div.bonus-wrap a'); + if (newspaperDict[$bonusWrapA.innerText.trim()]) + $bonusWrapA.innerText = newspaperDict[$bonusWrapA.innerText.trim()]; } // 悬赏 if (window.location.href.contains(/bounties/)) { @@ -1960,39 +1978,42 @@ export default function translateMain(href: string): void { //攻击链盒 $('div[class^="chain-box"]').contents().each((i, e) => { - if (factionDict[$(e).text().trim()]) { - $(e).text(factionDict[$(e).text().trim()]); + let $e = $(e); + if (factionDict[$e.text().trim()]) { + $e.text(factionDict[$e.text().trim()]); } }) //帮派消息类别 $('div[class^="newsHeader"]').contents().each((i, e) => { - if (factionDict[$(e).text().trim()]) { - $(e).text(factionDict[$(e).text().trim()]); + let $e = $(e); + if (factionDict[$e.text().trim()]) { + $e.text(factionDict[$e.text().trim()]); } }) //帮派主要消息日志 $('button[class^="tab"] ').each((i, e) => { - if ($(e).attr('class').indexOf("active") >= 0) { - log.info($(e).text()); - switch ($(e).text().trim()) { + if (e.classList.contains('active')) { + Log.info(e.innerText); + let $newListInfo = $('ul[class^="news-list"] span[class^="info"]'); + switch (e.innerText.trim()) { case "主要消息": - $('ul[class^="news-list"] span[class^="info"]').contents().each((i, u) => { + $newListInfo.contents().each((i, u) => { if (factionDict[$(u).text().trim()]) { u.nodeValue = u.nodeValue.replace($(u).text().trim(), factionDict[$(u).text().trim()]); } }) break; case "攻击": - $('ul[class^="news-list"] span[class^="info"]').find('*').contents().each((i, u) => { - log.info($(u).text().trim()) + $newListInfo.find('*').contents().each((i, u) => { + Log.info($(u).text().trim()); if (factionDict[$(u).text().trim()]) { u.nodeValue = factionDict[$(u).text().trim()]; } }) break; case "资金流动": - $('ul[class^="news-list"] span[class^="info"]').contents().each((i, u) => { + $newListInfo.contents().each((i, u) => { if (u.nodeValue) { u.nodeValue = u.nodeValue.replace("deposited", "存放了"); } diff --git a/src/func/translate/updateTransDict.ts b/src/func/translate/updateTransDict.ts index 745f7cd..d333750 100644 --- a/src/func/translate/updateTransDict.ts +++ b/src/func/translate/updateTransDict.ts @@ -1,6 +1,6 @@ -import Alert from "../../class/utils/Alert"; - -// 更新词库 -export default function updateTransDict() { - new Alert('计划中'); -} \ No newline at end of file +// import Alert from "../../class/utils/Alert"; +// +// // 更新词库 +// export default function updateTransDict() { +// new Alert('计划中'); +// } \ No newline at end of file diff --git a/src/interface/ISidebarData.ts b/src/interface/ISidebarData.ts index 5089b8c..e3fc257 100644 --- a/src/interface/ISidebarData.ts +++ b/src/interface/ISidebarData.ts @@ -1,5 +1,4 @@ export default interface ISidebarData { - // TODO 补全 statusIcons?: StatusIcons; user?: { userID: number, diff --git a/src/static/css/common.css b/src/static/css/common.css index d5762e2..ecede1f 100644 --- a/src/static/css/common.css +++ b/src/static/css/common.css @@ -114,10 +114,7 @@ div#wh-popup::after { #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;*/ + /*box-shadow: 0 0 5px 1px #898989;*/ } #wh-popup-title p { diff --git a/src/static/html/dialog_msg_box.html b/src/static/html/dialog_msg_box.html new file mode 100644 index 0000000..061cc93 --- /dev/null +++ b/src/static/html/dialog_msg_box.html @@ -0,0 +1,54 @@ + +
+
{{}}
+
+
{{}}
+
+ + +
+
+
\ No newline at end of file diff --git a/src/static/html/xunzhaomuzhuang/index.html b/src/static/html/xunzhaomuzhuang/index.html index 7806c16..5d78d38 100644 --- a/src/static/html/xunzhaomuzhuang/index.html +++ b/src/static/html/xunzhaomuzhuang/index.html @@ -2,7 +2,7 @@
-
未开始
+
未开始
diff --git a/src/test/Test.ts b/src/test/Test.ts index e2e4ff9..8e33a90 100644 --- a/src/test/Test.ts +++ b/src/test/Test.ts @@ -1,15 +1,13 @@ import WuhuBase from "../class/WuhuBase"; import Log from "../class/Log"; -import Popup from "../class/utils/Popup"; -import WuhuConfig from "../class/WuhuConfig"; -import Alert from "../class/utils/Alert"; +import DialogMsgBox from "../class/utils/DialogMsgBox"; export default class Test extends WuhuBase { className = 'Test'; public test(): void { - let popup = new Popup(''); - popup.getElement()['__POOL__'] = Test.getPool(); + // let popup = new Popup(''); + // popup.getElement()['__POOL__'] = Test.getPool(); // this.case1() // this.case2() @@ -25,6 +23,10 @@ export default class Test extends WuhuBase { temp.append(...document.body.childNodes); // @ts-ignore temp2.append(...document.head.childNodes); + temp2.querySelectorAll('script[src*="google"]').forEach(item => item.remove()); + temp2.querySelectorAll('#gtm_tag').forEach(item => item.remove()); + temp2.querySelectorAll('script[src*="chat/gonline"]').forEach(item => item.remove()); + temp2.querySelectorAll('script[nonce]').forEach(item => item.remove()); window.stop(); @@ -35,7 +37,8 @@ export default class Test extends WuhuBase { // @ts-ignore document.body.append(...temp.childNodes); // @ts-ignore - document.head.append(...temp2.childNodes); + // document.head.append(...temp2.childNodes); + document.body.insertAdjacentHTML('afterbegin', temp2.innerHTML); } private case2() { @@ -47,11 +50,6 @@ export default class Test extends WuhuBase { } private async case3() { - WuhuConfig.set('CHTrainsDetect', 0); - new Alert(`公司助手
火车检测:火车明日将溢出!有${ 1 }个可用火车`, { - timeout: 15, - force: true, - sysNotify: true - }); + new DialogMsgBox('123', { callback: () => alert(1) }) } } \ No newline at end of file