diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index 7acae8c..1864d9b 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -8,6 +8,11 @@ + + diff --git a/global.d.ts b/global.d.ts index cb1ce1d..a286737 100644 --- a/global.d.ts +++ b/global.d.ts @@ -77,12 +77,13 @@ declare interface Navigator { declare interface TornGetActionParams { type: 'post' | 'get', - data: { - step: string, - id: number, - key: string, - type: string + action?: string, + data?: { + step?: string, + id?: number, + key?: string, + type?: string }, success: Function, - before: Function + before?: Function } \ No newline at end of file diff --git a/src/WHNext.ts b/src/WHNext.ts new file mode 100644 index 0000000..3e3c9cc --- /dev/null +++ b/src/WHNext.ts @@ -0,0 +1,75 @@ +import Global from "./interface/GlobalVars"; +import getWhSettingObj from "./func/utils/getWhSettingObj"; +import elementReady from "./func/utils/elementReady"; +import depoHelper from "./func/module/depoHelper"; +import travelHelper from "./func/module/travelHelper"; +import attackHelper from "./func/module/attackHelper"; + +export default function (glob: Global) { + // 啤酒提醒 + if (getWhSettingObj()['_15Alarm']) glob.beer.start(); + + // 点击4条转跳对应的页面 + if (getWhSettingObj()['barsRedirect']) { + const eb = document.getElementById('barEnergy') as HTMLAnchorElement; + const nb = document.getElementById('barNerve') as HTMLAnchorElement; + const hb = document.getElementById('barHappy') as HTMLAnchorElement; + const lb = document.getElementById('barLife') as HTMLAnchorElement; + if (eb) { + eb.addEventListener('click', () => location.href = '/gym.php'); + eb.href = '/gym.php'; + } else { + elementReady('#barEnergy').then(eb => { + eb.addEventListener('click', () => location.href = '/gym.php'); + (eb as HTMLAnchorElement).href = '/gym.php'; + }); + } + if (nb) { + nb.addEventListener('click', () => location.href = '/crimes.php'); + nb.href = '/crimes.php'; + } else { + elementReady('#barNerve').then(nb => { + nb.addEventListener('click', () => location.href = '/crimes.php'); + (nb as HTMLAnchorElement).href = '/crimes.php'; + }); + } + if (hb) { + hb.addEventListener('click', () => location.href = '/item.php#boosters-items'); + hb.href = '/item.php#boosters-items'; + } else { + elementReady('#barHappy').then(hb => { + hb.addEventListener('click', () => location.href = '/item.php#boosters-items'); + (hb as HTMLAnchorElement).href = '/item.php#boosters-items'; + }); + } + if (lb) { + lb.addEventListener('click', () => location.href = '/item.php#medical-items'); + lb.href = '/item.php#medical-items'; + } else { + elementReady('#barLife').then(lb => { + lb.addEventListener('click', () => location.href = '/item.php#medical-items'); + (lb as HTMLAnchorElement).href = '/item.php#medical-items'; + }); + } + } + + /** + * 清除多余的脚本 + * TODO 无效、弃用 + */ + if (getWhSettingObj()['removeScripts']) { + document.querySelectorAll('script[src*="google"]').forEach(item => item.remove()); + document.querySelectorAll('#gtm_tag').forEach(item => item.remove()); + document.querySelectorAll('script[src*="chat/gonline"]').forEach(item => item.remove()); + document.querySelectorAll('head script[nonce]').forEach(item => item.remove()); + } + + // 存钱相关 + depoHelper(glob); + + // 飞行相关 + travelHelper(glob).then(); + + // 战斗相关 + attackHelper(glob).then(); +} \ No newline at end of file diff --git a/src/func/module/attackHelper.ts b/src/func/module/attackHelper.ts new file mode 100644 index 0000000..dcc1e82 --- /dev/null +++ b/src/func/module/attackHelper.ts @@ -0,0 +1,271 @@ +import Device from "../../enum/Device"; +import Global from "../../interface/GlobalVars"; +import elementReady from "../utils/elementReady"; +import getWhSettingObj from "../utils/getWhSettingObj"; +import addActionBtn from "../utils/addActionBtn"; +import addStyle from "../utils/addStyle"; +import getRandomInt from "../utils/getRandomInt"; +import log from "../utils/log"; + +export default async function attackHelper(glob: Global): Promise { + let { href, device, $zhongNode } = glob; + // 攻击页面 + if (href.contains(/loader\.php\?sid=attack/)) { + let stop_reload = false; + const { quickAttIndex, quickFinishAtt, attReload } = getWhSettingObj(); + + // 光速刷新按钮 + addActionBtn('光速刷新', doAttackReload, $zhongNode); + + // 自刷新 + let audio_played_flag; + // @ts-ignore + if (attReload !== 6 && stop_reload !== true) { + const selector_device_map = { + 'pc': '#defender div[class^="modal___"]', + 'mobile': '#attacker div[class^="modal___"]', + 'tablet': '', + }; + const selector = selector_device_map[device]; + elementReady(selector).then(elem => { + if (!elem.querySelector('button')) { + if (getWhSettingObj().attReload === 0 && stop_reload !== true) { + // window.location.reload(); + doAttackReload(); + } else { + let reload_flag; + const timeout = getWhSettingObj().attReload * 1000 + getRandomInt(-500, 500); + log.info(`[WH] ${ timeout / 1000 }s 后自动刷新`); + window.setInterval(() => { + if (reload_flag === undefined) { + reload_flag = true; + } else if (stop_reload !== true) { + // window.location.reload(); + doAttackReload(); + } + }, timeout); + } + } else if (audio_played_flag === undefined) { + audio_played_flag = true; + let play_time = 0; + const audio_play_id = window.setInterval(() => { + const $audio = document.createElement('audio'); + $audio.src = 'https://www.torn.com/js/chat/sounds/Warble_1.mp3'; + $audio.play().then(); + play_time++; + if (play_time === 3) clearInterval(audio_play_id); + }, 600); + } + }); + } + + // 光速拔刀 + if (quickAttIndex !== 6) { + const btn = await elementReady('div[class^="modal___"] button'); + log.info(btn); + if (!btn.innerText.toLowerCase().includes('fight')) return; + // 判断是否存在脚踢 + const hasKick = !!document.querySelector('#weapon_boots'); + // modal层 + const modal: HTMLElement = document.querySelector('div[class^="modal___"]'); + log.info(`当前设备类型是${ device }`); + // 区分设备 + switch (device) { + case Device.PC: { + log.info(`开始调整按钮位置`); + // 隐藏modal层 + modal.style.display = 'none'; + // 根据选择的武器调整css + let css_top = '0'; + switch (getWhSettingObj()['quickAttIndex']) { + case 1: { // weapon_second + css_top = '97px'; + break; + } + case 2: { // weapon_melee + css_top = '194px'; + break; + } + case 3: { // weapon_temp + css_top = '291px'; + break; + } + case 4: // weapon_fists + case 5: { // weapon_boots + css_top = '375px'; + break; + } + } + const css_rule = ` +.wh-move-btn #defender div[class^="modal___"]{display: block;width: 0 !important;top: ${ css_top };left: -169px !important;} +.wh-move-btn #defender div[class^="dialog___"]{border:0;width:159px;height:96px;} +.wh-move-btn #defender div[class^="colored___"]{display:block;padding:0;} +.wh-move-btn #defender div[class^="title___"]{height:0;} +.wh-move-btn #defender button{width: 100%;margin:17px 0;height: 60px;} +`; + addStyle(css_rule); + document.body.classList.add('wh-move-btn'); + // 绑定点击事件 联动【光速跑路】 + btn.onclick = () => { + if (quickFinishAtt !== 3) { + btn.remove(); + // 停止自动刷新 + stop_reload = true; + } else { + document.body.classList.remove('wh-move-btn'); + } + }; + break; + } + case Device.MOBILE: { + log.info(`开始调整按钮位置`); + // 加入css + let css_top = '0'; + let slot_height = '76px'; + // 判断有没有脚踢 + if (hasKick) { + // 根据选择的武器调整 + switch (getWhSettingObj()['quickAttIndex']) { + case 1: { // weapon_second + css_top = '76px'; + break; + } + case 2: { // weapon_melee + css_top = '152px'; + break; + } + case 3: { // weapon_temp + css_top = '228px'; + break; + } + case 4: { // weapon_fists + css_top = '304px'; + break; + } + case 5: { // weapon_boots + css_top = '380px'; + break; + } + } + } else { + const slot = document.querySelector('#weapon_main') as HTMLElement; + const height = slot.offsetHeight + 1; + // TODO 待验证 + slot_height = height + 'px'; + // 根据选择的武器调整 + switch (getWhSettingObj().quickAttIndex) { + case 1: { // weapon_second + css_top = `${ height }px`; + break; + } + case 2: { // weapon_melee + css_top = `${ height * 2 }px`; + break; + } + case 3: { // weapon_temp + css_top = `${ height * 3 }px`; + break; + } + case 4: { // weapon_fists + css_top = `${ height * 4 }px`; + break; + } + case 5: { // weapon_boots + css_top = `${ height * 5 }px`; + break; + } + } + } + const css_rule = ` +.wh-move-btn #attacker div[class^="modal___"]{display: block;width: 0;top: ${ css_top };left:0;height:0;} +.wh-move-btn #attacker div[class^="dialog___"]{border:0;width:80px;height:${ slot_height };} +.wh-move-btn #attacker div[class^="colored___"]{display:block;padding:0;} +.wh-move-btn #attacker div[class^="title___"]{height:0;} +.wh-move-btn #attacker button{width:100%;margin:0;height:63px;white-space:normal;} +`; + addStyle(css_rule); + document.body.classList.toggle('wh-move-btn'); + btn.onclick = () => { + if (getWhSettingObj().quickFinishAtt !== 3) { + btn.remove(); + // 停止自动刷新 + stop_reload = true; + } else { + document.body.classList.toggle('wh-move-btn'); + } + }; + break; + } + case Device.TABLET: { + break; + } + } + // 自动开打 + if (getWhSettingObj()['autoStartFinish'] === true) { + if (btn.innerText.includes('(')) { + let interval_id = window.setInterval(() => { + if (!btn) { + clearInterval(interval_id); + return; + } + try { + btn.click(); + } catch { + } + }, 100); + } else { + btn.click(); + } + } + } + + // 光速跑路 + if (quickFinishAtt !== 3) { + const user_btn_select = ['leave', 'mug', 'hosp'][getWhSettingObj()['quickFinishAtt']]; + const wrap = document.querySelector('#react-root'); + log.info('光速跑路选项选中:', user_btn_select); + new MutationObserver(() => { + const btn_arr = document.querySelectorAll('div[class^="dialogButtons___"] button') as unknown as HTMLButtonElement[]; + if (btn_arr.length > 1) btn_arr.forEach(btn => { + btn = btn as HTMLButtonElement; + const flag = btn.innerText.toLowerCase().includes(user_btn_select); + log.info('按钮内容:', btn.innerText, ',是否包含选中:', flag); + if (!flag) btn.style.display = 'none'; + // 自动结束 + else if (getWhSettingObj()['autoStartFinish'] === true) { + try { + btn.click(); + } catch { + } + } + }); + }).observe(wrap, { subtree: true, attributes: true, childList: true }); + } + return; + } + + // 错误的攻击页面 + if (getWhSettingObj()['attRelocate'] && href.includes('loader2.php')) { + const spl = window.location.href.trim().split('='); + const uid = spl[spl.length - 1]; + if (!/^\d+$/.test(uid)) return; + window.location.href = `https://www.torn.com/loader.php?sid=attack&user2ID=${ uid }`; + return; + } +} + +// 战斗页面快速刷新 +function doAttackReload() { + if (!window.ReactDOM) return; + let react_root = document.querySelector('#react-root'); + if (!react_root.querySelector('#attacker')) return; + let script = document.querySelector('script[src*="/builds/attack/"]'); + let url = script.src; + if (!url.contains('app.js')) return; + window.ReactDOM.unmountComponentAtNode(react_root); + script.remove(); + let node = document.createElement('script'); + node.src = url; + node.type = 'text/javascript'; + document.head.appendChild(node); +} \ No newline at end of file diff --git a/src/func/module/depoHelper.ts b/src/func/module/depoHelper.ts new file mode 100644 index 0000000..dd70ada --- /dev/null +++ b/src/func/module/depoHelper.ts @@ -0,0 +1,261 @@ +import elementReady from "../utils/elementReady"; +import getWhSettingObj from "../utils/getWhSettingObj"; +import addStyle from "../utils/addStyle"; +import log from "../utils/log"; +import Global from "../../interface/GlobalVars"; +import addActionBtn from "../utils/addActionBtn"; +import WHNotify from "../utils/WHNotify"; +import jQueryAjax from "../utils/jQueryAjax"; +import ajaxFetch from "../utils/ajaxFetch"; + +export default function (glob: Global) { + let { href, $zhongNode } = glob; + let channel: 'CMPY' | 'FAC'; + const selector = { 'CMPY': "div#funds div.deposit", 'FAC': "div#armoury-donate div.cash" }; + // 公司 + if (href.includes('companies.php')) { + channel = "CMPY"; + // 公司转跳存钱 + if (!href.includes('funds') && getWhSettingObj()['companyRedirect']) { + const btn = document.getElementById('ui-id-9'); + if (btn) { + btn.click(); + log.info('已自动打开存钱页面'); + } + } + // 收起冰蛙表格 + if (getWhSettingObj()['companyBWCollapse']) { + elementReady('#effectiveness-wrap').then(BWtable_node => { + document.body.classList.add('wh-bwtable-ctrl'); + addStyle(`.wh-bwtable-ctrl #effectiveness-wrap {display:none !important;}`); + const btn = document.createElement('button'); + btn.innerHTML = '展开冰蛙表格'; + btn.addEventListener('click', () => { + document.body.classList.toggle('wh-bwtable-ctrl'); + btn.innerText = btn.innerText === '展开冰蛙表格' ? '收起冰蛙表格' : '展开冰蛙表格'; + }); + BWtable_node.before(btn); + }); + } + // 一键存钱按钮 + addActionBtn('一键存钱', companyDeposit, $zhongNode); + } + // 帮派 + if (href.includes('factions.php')) { + channel = "FAC"; + // 一键存钱按钮 + addActionBtn('一键存钱', factionDeposit, $zhongNode); + } + // 存钱框浮动 + if (getWhSettingObj()['floatDepo'] && channel) { + document.body.classList.add('wh-depo-helper'); + addStyle(`.wh-depo-helper div#funds div.deposit, +.wh-depo-helper div#armoury-donate div.cash{position: fixed !important; +top: 150px; +right: 12px; +box-shadow: 0 0 8px 1px #00000091; +background: #f2f2f2; +z-index: 999999;}`); + elementReady(selector[channel]).then(node => { + const close_btn = document.createElement('button'); + close_btn.addEventListener('click', () => { + document.body.classList.remove('wh-depo-helper'); + close_btn.remove(); + }); + close_btn.innerHTML = '恢复原位'; + close_btn.style.float = 'right'; + node.prepend(close_btn); + }); + } + // GT交易存钱 + if (location.pathname.startsWith('/trade.php')) { + // GT助手 + let node_link = null; + let handle = () => { + let { addRFC } = window; + // 不重复加载、已关闭的交易不加载 + if (node_link !== null || location.hash.includes('logview')) return; + log.info('已添加GT助手'); + // 获取交易id + let query_params = location.hash.slice(1); + let traceId; + query_params.split('&') + .forEach(param => + (param.startsWith('ID=')) && (traceId = param.slice(3)) + ); + log.info('交易id为', traceId); + + // 获取全部的钱数 + let getTraceMoney = async () => { + if (typeof addRFC === 'function') { + let url = addRFC('/trade.php?step=getFullMoney&ID=' + traceId); + return (await ajaxFetch({ url: url, method: 'GET', referrer: 'trade.php' })).text(); + } + }; + // 监听jquery ajax请求 + if (log.debug()) $(document).ajaxComplete((_, xhr, settings) => log.info({ xhr, settings })); + // react 加载完成后将节点加入视图中 + elementReady('#trade-container').then(() => + document.querySelector('#trade-container').before(node) + ); + // 构建dom节点 + let node = document.createElement('div'); + node_link = node; + let nodeTitle = document.createElement('div'); + let nodeCont = document.createElement('div'); + let inputMoney = document.createElement('input'); + let buttonDepositAll = document.createElement('button'); + let buttonWithdraw = document.createElement('button'); + let buttonWithdrawAll = document.createElement('button'); + let style = document.createElement('style'); + + inputMoney.placeholder = '定额取钱'; + inputMoney.type = 'number'; + inputMoney.style.padding = '7px'; + inputMoney.style.paddingLeft = '14px'; + inputMoney.classList.add('m-right10'); + buttonDepositAll.innerHTML = '全存'; + buttonDepositAll.style.color = 'green'; + buttonWithdraw.innerHTML = '定取'; + buttonWithdrawAll.innerHTML = '全取'; + buttonWithdrawAll.style.color = 'red'; + nodeTitle.innerHTML = 'GT助手'; + nodeTitle.classList.add('title-black', 'top-round'); + style.innerHTML = '#WHGTHelper button{cursor:pointer;}#WHGTHelper button:hover{opacity:0.5;}'; + nodeCont.append(inputMoney, buttonWithdraw, buttonDepositAll, buttonWithdrawAll); + nodeCont.classList.add('cont-gray', 'bottom-round'); + nodeCont.style.padding = '10px'; + node.id = 'WHGTHelper'; + node.classList.add('m-bottom10'); + node.append(nodeTitle, nodeCont, style); + + // 定取 + buttonWithdraw.addEventListener('click', async () => { + if (parseInt(inputMoney.value) < 1) { + WHNotify('无法定额取钱,原因:输入有误'); + return; + } + let money = await getTraceMoney(); + let int = { 'input': parseInt(inputMoney.value), 'all': parseInt(money) }; + let diff = int.all - int.input; + if (diff < 1) { + WHNotify('无法定额取钱,原因:数不对'); + return; + } + await ajaxFetch({ + url: addRFC('/trade.php'), + method: 'POST', + referrer: 'trade.php', + body: `step=view&sub_step=addmoney2&ID=${ traceId }&amount=${ diff }&ajax=true`, + }); + WHNotify(`已取 ${ int.input }`); + }); + // 全存 + buttonDepositAll.addEventListener('click', async () => { + let money = await getTraceMoney(); + if (money === '0') return; + await ajaxFetch({ + url: addRFC('/trade.php'), + method: 'POST', + referrer: 'trade.php', + body: `step=view&sub_step=addmoney2&ID=${ traceId }&amount=${ money }&ajax=true`, + }); + WHNotify(`$${ money } 全部存入GT`); + }); + // 全取 + buttonWithdrawAll.addEventListener('click', async () => { + await ajaxFetch({ + url: addRFC('/trade.php'), + method: 'POST', + referrer: 'trade.php', + body: `step=view&sub_step=addmoney2&ID=${ traceId }&amount=0&ajax=true`, + }); + WHNotify('已全取'); + }); + }; + if (location.hash.includes('ID=')) handle(); + addEventListener('hashchange', () => { + if (location.hash.includes('ID=')) handle(); + else { + node_link.remove(); + node_link = null; + log('已移除GT助手'); + } + }); + } + + // 任何位置公司一键存钱 + if (getWhSettingObj()['companyDepositAnywhere']) { + addActionBtn('公司存钱', companyDepositAnywhere, $zhongNode); + } +} + +// 公司一键存钱 +async function companyDeposit() { + if (!location.href.contains('option=funds')) { + WHNotify('请先打开公司金库'); + return; + } + let { addRFC } = window; + if (typeof addRFC !== 'function') return; + let url = addRFC('https://www.torn.com/inputMoneyAction.php?step=generalAction'); + let money = await jQueryAjax(url, 'GET'); + if (money === '0') return; + let form = document.querySelector('#funds .deposit form'); + let funds_input = form.querySelectorAll('input.input-money'); + funds_input.forEach(input => { + (input as HTMLInputElement).value = money; + input.attributes['data-money'].value = money; + }); + $(form).trigger('submit'); + WHNotify('存钱成功'); +} + +// 帮派一键存钱 +async function factionDeposit() { + let form = document.querySelector('#armoury-donate form'); + if (!location.hash.includes('tab=armoury') || !form) { + WHNotify('请先打开金库'); + return; + } + if (typeof window.addRFC !== 'function') return; + let url = window.addRFC('https://www.torn.com/inputMoneyAction.php?step=generalAction'); + let money = await jQueryAjax(url, 'POST'); + if (money === '0') return; + let funds_input = form.querySelectorAll('input.input-money'); + funds_input.forEach(input => { + (input as HTMLInputElement).value = money; + input.attributes['data-money'].value = money; + }); + $(form).trigger('submit'); + let dataStr = `ajax=true&step=armouryDonate&type=cash&amount=${ money }`; + let res = await (await fetch(window.addRFC('https://www.torn.com/factions.php'), { + method: 'POST', + body: dataStr, + headers: { 'X-Requested-With': 'XMLHttpRequest', 'Content-Type': 'application/x-www-form-urlencoded' } + })).json(); + if (res.success === true) { + WHNotify('存钱成功'); + WHNotify(`${ res.text }`); + } +} + +// 所有页面公司一键存钱 +async function companyDepositAnywhere() { + let { addRFC } = window; + if (typeof addRFC !== 'function') return; + let url = addRFC('https://www.torn.com/inputMoneyAction.php?step=generalAction'); + let money = await jQueryAjax(url, 'GET'); + if (money === '0') return; + let res = await (await fetch(addRFC('https://www.torn.com/companies.php?step=funds'), { + method: 'POST', + referrer: 'companies.php', + body: 'deposit=' + money, + headers: { 'X-Requested-With': 'XMLHttpRequest', 'Content-Type': 'application/x-www-form-urlencoded' } + })).text(); + log.info(res); + let node = document.createElement('div'); + node.innerHTML = res; + let success = node.querySelector('.success-message'); + if (success) WHNotify(success.innerHTML); +} \ No newline at end of file diff --git a/src/func/module/landedRedirect.ts b/src/func/module/landedRedirect.ts index d8d2cf0..5a5db69 100644 --- a/src/func/module/landedRedirect.ts +++ b/src/func/module/landedRedirect.ts @@ -2,7 +2,7 @@ import getWhSettingObj from "../utils/getWhSettingObj"; import setWhSetting from "../utils/setWhSetting"; import popupMsg from "../utils/popupMsg"; -// 落地转跳 +// 落地转跳设置 export default function landedRedirect() { let p = document.createElement('p'); let input = document.createElement('input'); diff --git a/src/func/module/loadGS.ts b/src/func/module/loadGS.ts index 852b24b..5168919 100644 --- a/src/func/module/loadGS.ts +++ b/src/func/module/loadGS.ts @@ -59,21 +59,21 @@ z-index:100001; }); }; notify = WHNotify('加载飞贼小助手'); - COFetch(`https://gitee.com/ameto_kasao/tornjs/raw/master/GoldenSnitch.js?${performance.now()}`) + COFetch(`https://gitee.com/ameto_kasao/tornjs/raw/master/GoldenSnitch.js?${ performance.now() }`) .then(res => { _window.eval(res.replace('http://222.160.142.50:8154/mugger', `https://api.ljs-lyt.com/mugger`)); _window.GM_setValue("gsp_x", 10); _window.GM_setValue("gsp_y", 10); notify.close(); - notify = WHNotify('飞贼小助手已加载', {timeout: 1}); + notify = WHNotify('飞贼小助手已加载', { timeout: 1 }); const gsp: HTMLElement = _docu.querySelector('#gsp'); const init = () => { - ifr.style.height = `${gsp.offsetHeight + 10}px`; - ifr.style.width = `${gsp.offsetWidth + 20}px`; + ifr.style.height = `${ gsp.offsetHeight + 10 }px`; + ifr.style.width = `${ gsp.offsetWidth + 20 }px`; gsp.style.top = '10px'; gsp.style.left = '10px'; }; - new MutationObserver(init).observe(gsp, {childList: true, subtree: true}); + new MutationObserver(init).observe(gsp, { childList: true, subtree: true }); init(); if (log.debug()) _window.GM_setValue("gsp_showContent", true) }); @@ -100,14 +100,14 @@ z-index:100001; }; // TODO // window.GM_xmlhttpRequest = GM_xmlhttpRequest; - COFetch(`https://gitee.com/ameto_kasao/tornjs/raw/master/GoldenSnitch.js?${performance.now()}`) + COFetch(`https://gitee.com/ameto_kasao/tornjs/raw/master/GoldenSnitch.js?${ performance.now() }`) .then(GSJS => { window.eval(GSJS); if (log.debug()) window.GM_setValue("gsp_showContent", true); notify.close(); notify = WHNotify('已载入飞贼助手'); }) - .catch(err => WHNotify(`PDA API错误。${JSON.stringify(err)}`)); + .catch(err => WHNotify(`PDA API错误。${ JSON.stringify(err) }`)); }) .catch(err => WHNotify(JSON.stringify(err))); } else { diff --git a/src/func/module/safeKeeper.ts b/src/func/module/safeKeeper.ts index e28d1db..9528c69 100644 --- a/src/func/module/safeKeeper.ts +++ b/src/func/module/safeKeeper.ts @@ -21,14 +21,14 @@ export default function safeKeeper() { let loop_id = null; let updateAttackersDOM = function () { let html = '进攻者:
'; - Object.keys(attackers.obj).forEach(id => html += `[${id}]
`); + Object.keys(attackers.obj).forEach(id => html += `[${ id }]
`); attackers.innerHTML = html; }; let updateRecordsDOM = function () { let html = '战斗记录:
'; records.list.forEach(rid => { - let {TimeCreated, attackID, attackerID, attackerItemID, result, text} = records.details[rid]; - html += `[${TimeCreated}] [${attackerID}] [${attackerItemID}] ${result} ${text}
`; + let { TimeCreated, attackID, attackerID, attackerItemID, result, text } = records.details[rid]; + html += `[${ TimeCreated }] [${ attackerID }] [${ attackerItemID }] ${ result } ${ text }
`; }); records.innerHTML = html; }; @@ -43,7 +43,7 @@ export default function safeKeeper() { let popup_close = popup.close; popup.close = () => { if (loop_id === null) popup_close(); - else WHNotify('守望者运行中,请先停止', {timeout: 2}); + else WHNotify('守望者运行中,请先停止', { timeout: 2 }); } popup.appendChild(p); @@ -65,13 +65,13 @@ export default function safeKeeper() { // 记录当前循环的id let that_id = loop_id; let res = await (await fetch(url + uid.value, { - headers: {'X-Requested-With': 'XMLHttpRequest'}, + headers: { 'X-Requested-With': 'XMLHttpRequest' }, referrer: "loader.php?sid=attack&user2ID=" + uid.value })).text(); if (loop_id !== that_id) return; let data = JSON.parse(res.split(' { @@ -84,15 +84,15 @@ export default function safeKeeper() { // 攻击历史 (DB['currentFightHistory'] || []).forEach(record => { if (records.list.includes(record['ID'])) return; - let {ID, TimeCreated, attackID, attackerID, attackerItemID, result, text} = record; + let { ID, TimeCreated, attackID, attackerID, attackerItemID, result, text } = record; records.list.push(ID); - records.details[ID] = {TimeCreated, attackID, attackerID, attackerItemID, result, text}; + records.details[ID] = { TimeCreated, attackID, attackerID, attackerItemID, result, text }; updateRecordsDOM(); }); // 攻击历史日志 if (histLog && histLog[uid.value]) histLog[uid.value].forEach(log => { if (records.list.includes(log['ID'])) return; - let {ID, TimeCreated, attackID, attackResult, userID} = log; + let { ID, TimeCreated, attackID, attackResult, userID } = log; records.list.push(ID); records.details[ID] = { TimeCreated, diff --git a/src/func/module/travelHelper.ts b/src/func/module/travelHelper.ts new file mode 100644 index 0000000..cec686c --- /dev/null +++ b/src/func/module/travelHelper.ts @@ -0,0 +1,409 @@ +import Global from "../../interface/GlobalVars"; +import titleTrans from "../translate/titleTrans"; +import contentTitleLinksTrans from "../translate/contentTitleLinksTrans"; +import Device from "../../enum/Device"; +import WHNotify from "../utils/WHNotify"; +import getWhSettingObj from "../utils/getWhSettingObj"; +import addActionBtn from "../utils/addActionBtn"; +import addStyle from "../utils/addStyle"; +import log from "../utils/log"; +import doQuickFly from "./doQuickFly"; + +export default async function travelHelper(glob: Global): Promise { + let { href, bodyAttrs, $zhongNode, device } = glob; + + // URL判断 + 人不在城内 + if (href.includes('index.php') && bodyAttrs['data-abroad'] === 'true') { + // 飞行中 + if (bodyAttrs["data-traveling"] === 'true') { + // 飞行闹钟 + if (device === Device.PC && getWhSettingObj()['trvAlarm']) { + // 获取目的地 + let dest_cn; + let country = document.body.getAttribute('data-country'); + if (country === 'torn') { + dest_cn = '回城'; + } else { + dest_cn = { + 'uk': "英国", 'switzerland': "瑞士", 'mexico': '墨西哥', 'canada': '加拿大', 'cayman': '开曼', + 'hawaii': '夏威夷', 'argentina': '阿根廷', + 'japan': '日本', 'china': '中国', 'uae': 'UAE', 'sa': '南非', + }[country] || country; + } + + // 剩余时间 + const remaining_arr = document.querySelector('#countrTravel').getAttribute('data-to'); + + const wh_trv_alarm = localStorage.getItem('wh_trv_alarm') + ? JSON.parse(localStorage.getItem('wh_trv_alarm')) + : { 'enable': true, 'alert_time': 30, 'node_pos': [240, 240] }; + const save_trv_settings = () => localStorage.setItem('wh_trv_alarm', JSON.stringify(wh_trv_alarm)); + + const wh_trv_alarm_node = document.createElement('div'); + wh_trv_alarm_node.id = 'wh-trv-alarm'; + wh_trv_alarm_node.style.left = `${ wh_trv_alarm.node_pos[0] }px`; + wh_trv_alarm_node.style.top = `${ wh_trv_alarm.node_pos[1] }px`; + wh_trv_alarm_node.innerHTML = `

❌ 没有权限
点击网页内任意位置以激活闹钟

+
+
飞行闹钟
+
+
+
+

+

正在${ dest_cn === '回城' ? dest_cn : '飞往' + dest_cn }

+
+
+
+
+
+`; + addStyle(` +#wh-trv-alarm{ +position:absolute; +width:248px; +/*left:${ wh_trv_alarm.node_pos[0] || 240 }px; +top:${ wh_trv_alarm.node_pos[1] || 240 }px;*/ +background:white; +border-radius:4px; +box-shadow:#0000001f 0 0 10px 4px; +border:solid 1px #aaa; +z-index:100001; +margin:2em; +} +#wh-trv-alarm button{ +margin:0; +} +#wh-trv-error{ +position:absolute; +width:100%; +height:100%; +/*display: table;*/ +display:none; +} +#wh-trv-error p{ +background:#ffd0d0; +color:red; +display:table-cell; +vertical-align:middle; +padding:1em; +text-align:center; +} +#wh-trv-alarm-title{ +height: 30px; +border-bottom: solid #aaa 1px; +cursor: move; +} +/*#wh-trv-alarm-move-btn span{ +background:url(/images/v2/home_main/move.svg); +width: 30px; +height: 30px; +float: right; +cursor: move; +}*/ +h5#wh-trv-alarm-header{ + height: 100%; + line-height: 30px; + padding:0 12px; + font-weight: bold; + text-align: center; +} +#wh-trv-alarm-bottom{ + padding: 12px; +} +#wh-trv-alarm-remaining{ +float:right; +color:red; +} +#wh-trv-alarm-cont input[type="number"]{ + width: 42px; + border-bottom: solid 1px #aaa; +} +.wh-trv-alarm-stop-hide{ +display:none; +} +`); + document.body.append(wh_trv_alarm_node); + // 报错dom + const error_node = wh_trv_alarm_node.querySelector('#wh-trv-error') as HTMLElement; + // jquery拖动 + // @ts-ignore + $(wh_trv_alarm_node).draggable({ + containment: "body", + distance: 5, + handle: "#wh-trv-alarm-title", + stop: () => { + wh_trv_alarm.node_pos = [parseInt(wh_trv_alarm_node.style.left), parseInt(wh_trv_alarm_node.style.top)]; + save_trv_settings(); + }, + scroll: false, + }); + // 剩余时间dom + const remaining_node = wh_trv_alarm_node.querySelector('#wh-trv-alarm-remaining'); + // 设定闹钟响的按钮 + const set_node = wh_trv_alarm_node.querySelectorAll('#wh-trv-alarm-cont button')[0] as HTMLButtonElement; + // 落地前响铃时长 + const cd_time = wh_trv_alarm_node.querySelector('input[type="number"]') as HTMLInputElement; + let count_down_notify: MyHTMLElement | { close: Function } = { + close: () => { + } + }; + set_node.onclick = () => { + try { + wh_trv_alarm.alert_time = parseInt(cd_time.value); + } catch { + wh_trv_alarm.alert_time = 30; + } + save_trv_settings(); + set_node.value = wh_trv_alarm.alert_time; + count_down_notify.close(); + count_down_notify = WHNotify('设置已更新'); + }; + // 停止响铃按钮 + const stop_node = wh_trv_alarm_node.querySelectorAll('#wh-trv-alarm-cont button')[1] as HTMLButtonElement; + stop_node.onclick = () => { + user_stop_alert = true; + stop_node.innerText = '本次已关闭'; + stop_node.disabled = true; + } + // 开启闹钟勾选 + const enable_node = wh_trv_alarm_node.querySelector('#wh-trv-alarm-cont input[type="checkbox"]') as HTMLInputElement; + let on_off_notify: MyHTMLElement | { close: Function } = { + close: () => { + } + }; + enable_node.onchange = ev => { + wh_trv_alarm.enable = (ev.target).checked; + save_trv_settings(); + on_off_notify.close(); + on_off_notify = WHNotify(wh_trv_alarm.enable ? '闹钟已开启' : '闹钟已关闭'); + }; + // 剩余时间 秒 + const remaining_sec = parseInt(remaining_arr); + // 落地时timestamp + const land_timestamp = Date.now() + remaining_sec * 1000; + // 音频dom + const audio = document.createElement('audio'); + audio.src = 'https://www.torn.com/js/chat/sounds/Warble_1.mp3'; + audio.play() + .then(() => audio.pause()) + .catch(() => { + error_node.style.display = 'table'; + const func = () => { + error_node.remove(); + document.body.removeEventListener('click', func); + }; + document.body.addEventListener('click', func); + }); + // 是否正在响铃 + let audio_play_flag = false; + // 用户是否停止当前响铃 + let user_stop_alert = false; + // 响铃循环id + let audio_play_id = null; + // 响铃的方法 + let audio_play_handle = () => { + if (user_stop_alert) { + clearInterval(audio_play_id); + audio_play_id = null; + return; + } + if (!audio_play_flag || !wh_trv_alarm.enable) return; + audio.play().then(); + }; + // 飞机小动画字符 + const flying_arr = [ + '✈ ', + '  ✈ ', + '    ✈ ', + '      ✈ ', + '        ✈ ', + '          ✈ ', + '            ✈ ', + '              ✈ ', + '                ✈ ', + '                  ✈ ', + ]; + // 飞行的状态dom + const flying_status = wh_trv_alarm_node.querySelector('#wh-trv-status'); + // 飞机的小动画dom + const flying_ani = flying_status.nextElementSibling; + // 飞机的计数 + let flying_index = 0; + const id = window.setInterval(() => { + const remaining_time = (land_timestamp - Date.now()) / 1000 | 0; + remaining_node.innerText = `${ remaining_time / 3600 | 0 }时${ remaining_time % 3600 / 60 | 0 }分${ remaining_time % 60 }秒`; + + if (remaining_time < wh_trv_alarm.alert_time) { + // flying_status.innerHTML = `即将落地...`; + if (wh_trv_alarm.enable) { + // 播放提示音 + audio_play_flag = true; + if (audio_play_id === null && !user_stop_alert) audio_play_id = window.setInterval(audio_play_handle, 750); + stop_node.parentElement.classList.remove('wh-trv-alarm-stop-hide'); + } + } else { + // flying_status.innerHTML = `飞行中...`; + if (wh_trv_alarm.enable) { + clearInterval(audio_play_id); + audio_play_id = null; + stop_node.parentElement.classList.add('wh-trv-alarm-stop-hide'); + } + } + flying_ani.innerHTML = `${ flying_arr[flying_index] }`; + flying_index = (flying_index + 1) % flying_arr.length; + }, 1000); + log.info({ + dest_cn, + remaining_arr, + wh_trv_alarm, + wh_trv_alarm_node, + error_node, + remaining_node, + set_node, + cd_time, + count_down_notify, + stop_node, + enable_node, + remaining_sec, + land_timestamp, + audio, + audio_play_flag, + user_stop_alert, + audio_play_id, + flying_status, + flying_index, + id + }); + } + + // 落地转跳 落地前事件 + if (getWhSettingObj()['landedRedirect'] && document.querySelector('#tcLogo[title]') === null) { + window.addEventListener('beforeunload', () => { + let obj = { url: getWhSettingObj()['landedRedirect'], timestamp: Date.now() }; + sessionStorage['wh-landed-redirect'] = JSON.stringify(obj); + }); + } + } + // 不在飞行中 海外落地页面 + else { + // 一键回城 + addActionBtn('直接回城', travelBack, $zhongNode); + // 海外警告 + if (getWhSettingObj()['abroadWarning']) { + let c = 1; + setInterval(() => WHNotify(`警告:您已海外落地${ c++ * 30 }秒`, { + timeout: 30, + sysNotify: true + }), 30000); + } + // 解毒提醒 + if (bodyAttrs['data-country'] === 'switzerland') { + let page_title = document.querySelector('h4#skip-to-content'); + let msg = document.createElement('div'); + msg.innerHTML = ``; + msg.classList.add('info-msg-cont', 'green', 'border-round', 'm-bottom10'); + page_title.before(msg); + } + } + return; + } + // URL判断 + 人在城内 + else if (href.includes('index.php') && bodyAttrs['data-abroad'] === 'false') { + // 落地转跳 + if (sessionStorage['wh-landed-redirect']) { + let { url, timestamp } = JSON.parse(sessionStorage['wh-landed-redirect']); + if (Date.now() - timestamp < 30000) { + sessionStorage.removeItem('wh-landed-redirect'); + location.href = url; + } + } + } + // 起飞页面 + if (href.contains(/travelagency\.php/)) { + // 起飞提醒 + if (getWhSettingObj()['energyAlert']) { + const $$ = $('.content-wrapper'); + const OB = new MutationObserver(() => { + OB.disconnect(); + titleTrans(); + contentTitleLinksTrans(); + trans(); + OB.observe($$.get(0), { + characterData: true, + attributes: true, + subtree: true, + childList: true + }); + }); + const trans = () => { + // 当前能量e + const energyBarStr = $('#barEnergy p[class^="bar-value__"]').text().trim(); + const [curE, maxE] = energyBarStr.split('/').length === 2 + ? [parseInt(energyBarStr.split('/')[0]), parseInt(energyBarStr.split('/')[1])] + : [NaN, NaN]; + const incTime = maxE === 150 ? 10 : 15; + const fullEnergyTime = !(isNaN(curE) || isNaN(maxE)) ? (maxE - 5 - curE) / 5 * incTime + + (incTime - new Date().getMinutes() % incTime) : NaN; + // 起飞前提示 + $('.travel-confirm .travel-question .q-wrap span:nth-of-type(2)').each((i, e) => { + if (isNaN(fullEnergyTime)) return; + const spl = e.innerText.trim().split(' '); + const [hours, minutes] = spl.length === 5 + ? [parseInt(spl[0]), parseInt(spl[3])] + : [0, parseInt(spl[0])]; + if (fullEnergyTime < (hours * 60 + minutes) * 2) { + if (!$(e).parent().hasClass('wh-translated')) { + $(e).parent() + .prepend(`
警告:该次飞行往返时间大于体力回复时间,将会爆体!
`) + .addClass('wh-translated'); + } + } + }); + }; + trans(); + OB.observe($$.get(0), { + characterData: true, + attributes: true, + subtree: true, + childList: true + }); + } + // 一键起飞 + if (sessionStorage['wh-quick-fly']) { + doQuickFly(); + } + } +} + +async function travelBack(): Promise { + if (typeof window['getAction'] !== 'function') return; + let backHomeAction = function (): Promise { + return new Promise(resolve => { + window.getAction({ + type: "post", + action: 'travelagency.php', + data: { + step: 'backHomeAction' + }, + success: function (msg) { + resolve(msg); + } + }); + }); + }; + let res = await backHomeAction(); + WHNotify(res); + if (!res.includes('error')) { + WHNotify('成功,即将刷新'); + setTimeout(() => location.reload(), 3000); + } else { + WHNotify('出错了'); + } +} \ No newline at end of file diff --git a/src/func/translate/contentTitleLinksTrans.ts b/src/func/translate/contentTitleLinksTrans.ts index b62cc32..f4c5de8 100644 --- a/src/func/translate/contentTitleLinksTrans.ts +++ b/src/func/translate/contentTitleLinksTrans.ts @@ -1,4 +1,4 @@ -import {titleLinksDict} from "../../dictionary/translation"; +import { titleLinksDict } from "../../dictionary/translation"; // 页标题右侧按钮 export default function contentTitleLinksTrans() { diff --git a/src/func/translate/contentTitleLinksTransReact.ts b/src/func/translate/contentTitleLinksTransReact.ts index 0cff4d0..2bec676 100644 --- a/src/func/translate/contentTitleLinksTransReact.ts +++ b/src/func/translate/contentTitleLinksTransReact.ts @@ -1,4 +1,4 @@ -import {titleLinksDict} from "../../dictionary/translation"; +import { titleLinksDict } from "../../dictionary/translation"; export default function contentTitleLinksTransReact(dom = document.querySelectorAll('div[class^="linksContainer___"] span[class^="linkTitle___"]')) { dom.forEach(e => { diff --git a/src/func/translate/eventsTrans.ts b/src/func/translate/eventsTrans.ts index 916e5b3..19f952d 100644 --- a/src/func/translate/eventsTrans.ts +++ b/src/func/translate/eventsTrans.ts @@ -1,4 +1,4 @@ -import {eventsDict, ocList, gymList} from "../../dictionary/translation"; +import { eventsDict, gymList, ocList } from "../../dictionary/translation"; import log from "../utils/log"; export default function eventsTrans(events: JQuery = $('span.mail-link')) { @@ -49,20 +49,18 @@ export default function eventsTrans(events: JQuery = $('span.mail-link')) { }); // 通知翻译的开关 - if (!$('div#event-trans-msg').get(0) && !window.location.href.contains(/index\.php/)) { - // msgBox(`
插件暂时不能翻译全部通知。
- // 如发现问题请发送通知并联系 Woohoo[2687093]
- // 可能会出现卡顿,默认开启
`); - $('input#eventTransCheck').attr('checked', localStorage.getItem('wh_trans_event') === 'true'); - $('input#eventTransCheck').change(function () { - if ($(this).attr('checked') === undefined) { - localStorage.setItem('wh_trans_event', 'false'); - } else { - localStorage.setItem('wh_trans_event', 'true'); - } - eventsTrans(); - }); - } + // if (!$('div#event-trans-msg').get(0) && !window.location.href.contains(/index\.php/)) { + // let node = $('input#eventTransCheck'); + // node.attr('checked', localStorage.getItem('wh_trans_event') === 'true'); + // node.change(function () { + // if ($(this).attr('checked') === undefined) { + // localStorage.setItem('wh_trans_event', 'false'); + // } else { + // localStorage.setItem('wh_trans_event', 'true'); + // } + // eventsTrans(); + // }); + // } if (localStorage.getItem('wh_trans_event') === 'false') return; if (events.length === 0) return; @@ -171,12 +169,12 @@ export default function eventsTrans(events: JQuery = $('span.mail-link')) { const num = /^\$[0-9,]+\b/.test(spl[3]) ? '' : spl[3].numWordTrans(); const item = num === '' ? spl[3] : spl.slice(4, -1).join(' '); const msg = msgSpl[1] ? msgSpl[1] : null; - e.childNodes[0].nodeValue = `你收到了 ${num} ${item},来自 `; + e.childNodes[0].nodeValue = `你收到了 ${ num } ${ item },来自 `; if (e.childNodes[2]) { e.childNodes[2].nodeValue = `。`; } if (msg) { - e.childNodes[2].nodeValue = `,附带信息:${msg}。`; + e.childNodes[2].nodeValue = `,附带信息:${ msg }。`; } return; } @@ -411,13 +409,13 @@ export default function eventsTrans(events: JQuery = $('span.mail-link')) { // 工资改变 if (e.nodeValue.contains(/wage/)) { const money = e.nodeValue.trim().slice(27, -9); - e.nodeValue = ` 的老板) 将你的每日工资改为 ${money}。`; + e.nodeValue = ` 的老板) 将你的每日工资改为 ${ money }。`; return; } // 职位改变 if (e.nodeValue.contains(/rank/)) { const pos = e.nodeValue.trim().slice(27, -1); - e.nodeValue = ` 的老板) 将你的公司职位改为 ${pos}。`; + e.nodeValue = ` 的老板) 将你的公司职位改为 ${ pos }。`; return; } if (e.nodeValue.contains(/assigned/)) { @@ -429,7 +427,7 @@ export default function eventsTrans(events: JQuery = $('span.mail-link')) { const spl = e.nodeValue.trim().split(' '); const pri = spl[10]; const sec = spl[13].slice(0, -1); - e.nodeValue = ` 的老板) 从公司训练了你。你获得了 50 ${eventsDict[pri]} 和 25 ${eventsDict[sec]}。`; + e.nodeValue = ` 的老板) 从公司训练了你。你获得了 50 ${ eventsDict[pri] } 和 25 ${ eventsDict[sec] }。`; } } } @@ -444,12 +442,12 @@ export default function eventsTrans(events: JQuery = $('span.mail-link')) { $(e).contents().each((i, e) => { if (e.nodeType === 3) { if (eventsDict[e.nodeValue.trim()]) { - e.nodeValue = ` ${eventsDict[e.nodeValue.trim()]} `; + e.nodeValue = ` ${ eventsDict[e.nodeValue.trim()] } `; } else { if (e.nodeValue.contains(/bounty reward/)) { const bountyAmount = e.nodeValue.trim().split(' ')[3]; if (eventsDict['and earned your'] && eventsDict['bounty reward']) { - e.nodeValue = ` ${eventsDict['and earned your']} ${bountyAmount} ${eventsDict['bounty reward']}`; + e.nodeValue = ` ${ eventsDict['and earned your'] } ${ bountyAmount } ${ eventsDict['bounty reward'] }`; } } } @@ -474,7 +472,7 @@ export default function eventsTrans(events: JQuery = $('span.mail-link')) { let others = e.childNodes[2].nodeValue.split(' ')[10]; others = others === 'one' ? '1' : others; e.firstChild.nodeValue = '你被 '; - e.childNodes[2].nodeValue = ` 选中参与一项组织犯罪(OC)。你和另外${others}人将组成一个团队,在${time}小时后进行 `; + e.childNodes[2].nodeValue = ` 选中参与一项组织犯罪(OC)。你和另外${ others }人将组成一个团队,在${ time }小时后进行 `; e.childNodes[3].firstChild.nodeValue = ocList[OCName] ? ocList[OCName] : OCName; e.childNodes[4].nodeValue = '。'; return; @@ -494,7 +492,7 @@ export default function eventsTrans(events: JQuery = $('span.mail-link')) { rs = '失败'; OCName = e.firstChild.nodeValue.slice(27, -30); } - e.firstChild.nodeValue = `你和团队的组织犯罪(OC) ${ocList[OCName] ? ocList[OCName] : OCName} ${rs}了!`; + e.firstChild.nodeValue = `你和团队的组织犯罪(OC) ${ ocList[OCName] ? ocList[OCName] : OCName } ${ rs }了!`; e.childNodes[1].firstChild.nodeValue = '点此查看详情'; e.childNodes[2].nodeValue = '!'; return; @@ -555,7 +553,7 @@ export default function eventsTrans(events: JQuery = $('span.mail-link')) { const num = spl[3] === 'a' ? '1' : spl[3]; const price = reasonSpl[0].split(' ').slice(-1)[0]; const reason = reasonSpl[1] ? reasonSpl[1] : null; - const trans = `${someone ? '某人' : ' '}对你进行了 ${num} 次赏金为 ${price} 的悬赏${reason ? ',原因:' + reason : ''}`; + const trans = `${ someone ? '某人' : ' ' }对你进行了 ${ num } 次赏金为 ${ price } 的悬赏${ reason ? ',原因:' + reason : '' }`; // 匿名悬赏 if (someone) { $(e).text(trans); @@ -607,7 +605,7 @@ export default function eventsTrans(events: JQuery = $('span.mail-link')) { return spl.length === 1 ? [spl[0], null] : [spl[0], spl.slice(1).join(' ')]; })(); if (num && item) { - e.lastChild.nodeValue = ` 从帮派军械库中借给你 ${num.numWordTrans()} ${item}。`; + e.lastChild.nodeValue = ` 从帮派军械库中借给你 ${ num.numWordTrans() } ${ item }。`; } return; } @@ -670,7 +668,7 @@ export default function eventsTrans(events: JQuery = $('span.mail-link')) { */ if ($(e).text().contains(/You have successfully purchased membership in/)) { const gymName = e.firstChild.nodeValue.trim().slice(46, -1); - e.firstChild.nodeValue = `你已购买【${gymList[gymName]}】健身房会员卡。`; + e.firstChild.nodeValue = `你已购买【${ gymList[gymName] }】健身房会员卡。`; return; } @@ -680,7 +678,7 @@ export default function eventsTrans(events: JQuery = $('span.mail-link')) { if ($(e).text().contains(/You are now known in the city as a/)) { const trans = '现在你在这个城市中被称为'; const title = $(e).text().trim().split(' ').slice(9).join(' ').slice(0, -1); - $(e).text(`${trans} ${title}。`); + $(e).text(`${ trans } ${ title }。`); return; } @@ -715,7 +713,7 @@ export default function eventsTrans(events: JQuery = $('span.mail-link')) { */ if ($(e).text().indexOf('new virus') >= 0) { const virusName = e.firstChild.nodeValue.split(' ').slice(3, 5).join(' '); - e.firstChild.nodeValue = `你完成了 ${virusName},它现在在你的物品库存中。你可以`; + e.firstChild.nodeValue = `你完成了 ${ virusName },它现在在你的物品库存中。你可以`; e.childNodes[1].firstChild.nodeValue = '点此'; e.childNodes[2].nodeValue = '开始编程一个新的病毒。'; return; @@ -729,9 +727,9 @@ export default function eventsTrans(events: JQuery = $('span.mail-link')) { const bookTitle = item2.contains(/a book titled/) ? item2.slice(15, -1) : null; if (bookTitle) { - $(e).text(`你在家门口发现了 ${item1.numWordTrans()} 和《${bookTitle}》。`); + $(e).text(`你在家门口发现了 ${ item1.numWordTrans() } 和《${ bookTitle }》。`); } else { - $(e).text(`你在家门口发现了 ${item1.numWordTrans()} 和 ${item2.numWordTrans()}。`); + $(e).text(`你在家门口发现了 ${ item1.numWordTrans() } 和 ${ item2.numWordTrans() }。`); } return; } @@ -753,7 +751,7 @@ export default function eventsTrans(events: JQuery = $('span.mail-link')) { if ($(e).text().contains(/accepted your proposal, you are now engaged/)) { const spouse = $(e).children(':first').text().trim(); if (e.childNodes[1]) { - e.childNodes[1].nodeValue = ` 接受了你的求婚,你现在和 ${spouse} 订婚了!前往`; + e.childNodes[1].nodeValue = ` 接受了你的求婚,你现在和 ${ spouse } 订婚了!前往`; } if (e.childNodes[2] && e.childNodes[2].firstChild) { e.childNodes[2].firstChild.nodeValue = `这里`; @@ -781,7 +779,7 @@ export default function eventsTrans(events: JQuery = $('span.mail-link')) { return; } e.firstChild.nodeValue = '你在 '; - e.childNodes[2].nodeValue = ` 的职位从 ${prePos} 变为 ${curPos}。`; + e.childNodes[2].nodeValue = ` 的职位从 ${ prePos } 变为 ${ curPos }。`; return; } @@ -790,9 +788,9 @@ export default function eventsTrans(events: JQuery = $('span.mail-link')) { */ if ($(e).text().indexOf('join the faction') >= 0) { const rsName = e.childNodes[2].nodeValue.trim().split(' ')[2]; - const rsDict = {'accepted': '通过', 'declined': '拒绝',}; + const rsDict = { 'accepted': '通过', 'declined': '拒绝', }; e.firstChild.nodeValue = '加入帮派 '; - e.childNodes[2].nodeValue = ` 的申请已${rsDict[rsName]}。`; + e.childNodes[2].nodeValue = ` 的申请已${ rsDict[rsName] }。`; return; } }); diff --git a/src/func/translate/getTaskHint.ts b/src/func/translate/getTaskHint.ts new file mode 100644 index 0000000..bbf1fba --- /dev/null +++ b/src/func/translate/getTaskHint.ts @@ -0,0 +1,16 @@ +import { missionDict } from "../../dictionary/translation"; + +/** + * 任务助手 + */ +function getTaskHint(task_name): string { + task_name = task_name + .toLowerCase() + .replaceAll(' ', '_') + .replaceAll('-', '_') + .replaceAll(',', ''); + if (!missionDict._taskHint[task_name]) return '暂无,请联系开发者'; + const task = missionDict._taskHint[task_name].task || null; + const hint = missionDict._taskHint[task_name].hint || null; + return `${ task ? '任务要求:' + task : '暂无,请联系Woohoo' }${ hint ? '
提示:' + hint : '' }`; +} \ No newline at end of file diff --git a/src/func/translate/playerStatusTrans.ts b/src/func/translate/playerStatusTrans.ts index f110a04..7b946af 100644 --- a/src/func/translate/playerStatusTrans.ts +++ b/src/func/translate/playerStatusTrans.ts @@ -1,4 +1,4 @@ -import {hosDict, statusDict} from "../../dictionary/translation"; +import { hosDict, statusDict } from "../../dictionary/translation"; /** * 玩家状态翻译 diff --git a/src/func/translate/sendCashTrans.ts b/src/func/translate/sendCashTrans.ts index 4af94de..93c35ac 100644 --- a/src/func/translate/sendCashTrans.ts +++ b/src/func/translate/sendCashTrans.ts @@ -1,10 +1,10 @@ -import {sendCashDict} from "../../dictionary/translation"; +import { sendCashDict } from "../../dictionary/translation"; /** * 发钱翻译 */ function sendCashTrans(domPath = '', buttonClass = '.send-cash') { - const sc = $(`${domPath} ${buttonClass} *`); + const sc = $(`${ domPath } ${ buttonClass } *`); if (sc.length === 0) return; sc.contents().each((i, e) => { if (e.nodeType === 1) { diff --git a/src/func/translate/showItemInfoTrans.ts b/src/func/translate/showItemInfoTrans.ts index 7e5a67f..651e78f 100644 --- a/src/func/translate/showItemInfoTrans.ts +++ b/src/func/translate/showItemInfoTrans.ts @@ -1,4 +1,4 @@ -import {itemEffectDict, itemNameDict, itemPageDict, itemTypeDict} from "../../dictionary/translation"; +import { itemEffectDict, itemNameDict, itemPageDict, itemTypeDict } from "../../dictionary/translation"; // 展开物品详情 export default function showItemInfoTrans(dom: HTMLElement = document.querySelector('.show-item-info')) { @@ -19,7 +19,7 @@ export default function showItemInfoTrans(dom: HTMLElement = document.querySelec // 绿字 物品效果 const $item_effect = $item_info.querySelector('div.item-effect'); if (itemNameDict[the_removed]) { - $item_name.innerText = `${itemNameDict[the_removed]}(${the_removed})`; + $item_name.innerText = `${ itemNameDict[the_removed] }(${ the_removed })`; } if (itemTypeDict[$item_type.nodeValue.trim()]) { $item_type.nodeValue = itemTypeDict[$item_type.nodeValue.trim()]; diff --git a/src/func/translate/titleTrans.ts b/src/func/translate/titleTrans.ts index c334589..90f7f76 100644 --- a/src/func/translate/titleTrans.ts +++ b/src/func/translate/titleTrans.ts @@ -1,4 +1,4 @@ -import {cityDict, titleDict} from "../../dictionary/translation"; +import { cityDict, titleDict } from "../../dictionary/translation"; /** * 页标题翻译 diff --git a/src/func/translate/titleTransReact.ts b/src/func/translate/titleTransReact.ts index b5c1583..cd734e3 100644 --- a/src/func/translate/titleTransReact.ts +++ b/src/func/translate/titleTransReact.ts @@ -1,4 +1,4 @@ -import {titleDict} from "../../dictionary/translation"; +import { titleDict } from "../../dictionary/translation"; export default function titleTransReact(dom = document.querySelectorAll('h4[class^="title___"]')) { dom.forEach(e => { diff --git a/src/func/translate/translateMain.ts b/src/func/translate/translateMain.ts index d7e5dd1..b173531 100644 --- a/src/func/translate/translateMain.ts +++ b/src/func/translate/translateMain.ts @@ -118,7 +118,7 @@ export default function translateMain(href: string): void { const headerOB = new MutationObserver(_ => { headerOB.disconnect(); headerTrans(); - headerOB.observe($('div#header-root')[0], {childList: true, subtree: true, attributes: true}); + headerOB.observe($('div#header-root')[0], { childList: true, subtree: true, attributes: true }); }); const headerTrans = function headerTrans() { @@ -192,7 +192,7 @@ export default function translateMain(href: string): void { }); }; headerTrans(); - headerOB.observe($('div#header-root')[0], {childList: true, subtree: true, attributes: true}); + headerOB.observe($('div#header-root')[0], { childList: true, subtree: true, attributes: true }); } // chatbox @@ -200,7 +200,7 @@ export default function translateMain(href: string): void { const chatOB = new MutationObserver(_ => { chatOB.disconnect(); chatTrans(); - chatOB.observe($('div#chatRoot').get(0), {childList: true, subtree: true, attributes: true}); + chatOB.observe($('div#chatRoot').get(0), { childList: true, subtree: true, attributes: true }); }); const chatTrans = function chatTrans() { // 聊天框的标题 @@ -250,7 +250,7 @@ export default function translateMain(href: string): void { } }; chatTrans(); - chatOB.observe($('div#chatRoot').get(0), {childList: true, subtree: true, attributes: true}); + chatOB.observe($('div#chatRoot').get(0), { childList: true, subtree: true, attributes: true }); } // 搜索玩家的4个分类按钮 @@ -284,7 +284,7 @@ export default function translateMain(href: string): void { function travelOBInit() { travelOB.disconnect(); travelTrans(); - travelOB.observe($('div.content-wrapper')[0], {childList: true, subtree: true}); + travelOB.observe($('div.content-wrapper')[0], { childList: true, subtree: true }); } function travelTrans() { @@ -310,7 +310,7 @@ export default function translateMain(href: string): void { } travelTrans(); - travelOB.observe(document.querySelector('div.content-wrapper'), {childList: true, subtree: true}); + travelOB.observe(document.querySelector('div.content-wrapper'), { childList: true, subtree: true }); } // 主页 @@ -367,7 +367,7 @@ export default function translateMain(href: string): void { function cityOBInit() { cityOB.disconnect(); cityTrans(); - cityOB.observe($('div.content-wrapper')[0], {childList: true, subtree: true}); + cityOB.observe($('div.content-wrapper')[0], { childList: true, subtree: true }); } function cityTrans() { @@ -437,7 +437,7 @@ export default function translateMain(href: string): void { } cityTrans(); - cityOB.observe(document.querySelector('div.content-wrapper'), {childList: true, subtree: true}); + cityOB.observe(document.querySelector('div.content-wrapper'), { childList: true, subtree: true }); return; } @@ -448,7 +448,7 @@ export default function translateMain(href: string): void { function gymOBInit() { gymOB.disconnect(); gymTrans(); - gymOB.observe($('div.content-wrapper')[0], {childList: true, subtree: true, attributes: true}); + gymOB.observe($('div.content-wrapper')[0], { childList: true, subtree: true, attributes: true }); } function gymTrans() { @@ -552,7 +552,7 @@ export default function translateMain(href: string): void { } gymTrans(); - gymOB.observe($('div.content-wrapper')[0], {childList: true, subtree: true, attributes: true}); + gymOB.observe($('div.content-wrapper')[0], { childList: true, subtree: true, attributes: true }); return; } @@ -560,7 +560,7 @@ export default function translateMain(href: string): void { if (href.contains(/item\.php/)) { if (href.includes('item.php?temp=')) return; // 标题和右边的链接 - initOB(document.querySelector('.content-title'), {childList: true}, + initOB(document.querySelector('.content-title'), { childList: true }, () => { titleTrans(); contentTitleLinksTrans(); @@ -568,7 +568,7 @@ export default function translateMain(href: string): void { // 套装预览中间的文字 const $loadouts_root = document.getElementById('loadoutsRoot'); if ($loadouts_root) { - initOB($loadouts_root, {subtree: true, attributes: true}, () => { + initOB($loadouts_root, { subtree: true, attributes: true }, () => { const el = $loadouts_root.querySelector('div[class^="type___"]'); if (el && itemPageDict[el.innerText.trim()]) { el.innerText = itemPageDict[el.innerText.trim()]; @@ -581,8 +581,8 @@ export default function translateMain(href: string): void { subtree: true, attributeFilter: ["aria-hidden",] }; - const translated = {cat: '', count: -1}; - const translatedOnce = {item_opt: -1, opt_icon_count: -1}; + const translated = { cat: '', count: -1 }; + const translatedOnce = { item_opt: -1, opt_icon_count: -1 }; initOB(document.getElementById('category-wrap'), options, () => { // 手机操作选项 const $item_opt = document.querySelectorAll(`ul.itemsList span.opt-name`); @@ -651,7 +651,7 @@ export default function translateMain(href: string): void { } // 黑框分类标题 const $items_type_name = $title_black.querySelector('span.items-name'); - initOB($items_type_name, {childList: true}, () => { + initOB($items_type_name, { childList: true }, () => { if (itemPageDict[$items_type_name.innerText.trim()]) { $items_type_name.innerText = itemPageDict[$items_type_name.innerText.trim()]; } @@ -671,7 +671,7 @@ export default function translateMain(href: string): void { if (href.contains(/(shops|bigalgunshop)\.php/)) { // 标题和右边的链接 const $cont_title = document.querySelector('.content-title'); - initOB($cont_title, {childList: true, subtree: true}, () => { + initOB($cont_title, { childList: true, subtree: true }, () => { titleTrans(); contentTitleLinksTrans(); }); @@ -690,7 +690,7 @@ export default function translateMain(href: string): void { // 物品名 const $item_name = e.querySelector('span.desc span.name.bold'); if ($item_name && itemNameDict[$item_name.innerText.trim()]) { - $item_name.innerText = `${itemNameDict[$item_name.innerText.trim()]}(${$item_name.innerText.trim()})`; + $item_name.innerText = `${ itemNameDict[$item_name.innerText.trim()] }(${ $item_name.innerText.trim() })`; } // 类型和存货 const $item_stock = e.querySelector('span.desc span.stock'); @@ -716,7 +716,7 @@ export default function translateMain(href: string): void { if ($amount_item_name && !$amount_item_name.nodeValue.contains(CC_set)) { const item_name = $amount_item_name.nodeValue.trim().split(' ').slice(1, -1).join(' '); const item_name_trans = itemNameDict[item_name] || item_name; - $amount_item_name.nodeValue = `个[${item_name_trans}],总计$`; + $amount_item_name.nodeValue = `个[${ item_name_trans }],总计$`; } const $confirm_a = $confirm.querySelectorAll('span.confirm-act a'); $confirm_a.forEach(e => { @@ -724,7 +724,7 @@ export default function translateMain(href: string): void { }); }); // 展开的物品详情 - initOB($wrapper, {childList: true, subtree: true}, () => { + initOB($wrapper, { childList: true, subtree: true }, () => { const $item_desc: HTMLElement = $wrapper.querySelector('.show-item-info') || $wrapper.querySelector('.view-item-info'); showItemInfoTrans($item_desc); }); @@ -745,7 +745,7 @@ export default function translateMain(href: string): void { if (spl.length > 3) { const shop_name = spl[2] === 'the' ? spl.slice(3).join(' ') : spl.slice(2).join(' '); const shop_name_trans = npcShopDict[shop_name] || titleDict[shop_name] || cityDict[shop_name] || null; - e.innerText = `物品给${shop_name_trans || shop_name}`; + e.innerText = `物品给${ shop_name_trans || shop_name }`; } } else { if (npcShopDict[e.nodeValue.trim()]) e.nodeValue = npcShopDict[e.nodeValue.trim()]; @@ -756,7 +756,7 @@ export default function translateMain(href: string): void { const $items_name = $sell_items_wrapper.querySelectorAll('span.name'); $items_name.forEach(el => { if (itemNameDict[el.innerText.trim()]) el.innerText += - ` ${itemNameDict[el.innerText.trim()]}`; + ` ${ itemNameDict[el.innerText.trim()] }`; }); // 按钮 const $btn = $sell_items_wrapper.querySelectorAll('button'); @@ -766,7 +766,7 @@ export default function translateMain(href: string): void { // select btn const $select_btn = $sell_items_wrapper.querySelector('li.select button.wai-btn'); if ($select_btn) { - initOB($select_btn, {childList: true}, () => { + initOB($select_btn, { childList: true }, () => { if ($select_btn && npcShopDict[$select_btn.innerText.trim()]) { $select_btn.innerText = npcShopDict[$select_btn.innerText.trim()]; } @@ -833,7 +833,7 @@ export default function translateMain(href: string): void { } else if (/[0-9]x$/.test(spl[0])) { const itemName = spl.slice(1).join(' '); const num = spl[0].slice(0, -1); - $(e).text(`${num}个${itemNameDict[itemName] ? itemNameDict[itemName] : itemName}`); + $(e).text(`${ num }个${ itemNameDict[itemName] ? itemNameDict[itemName] : itemName }`); } }); // 股价详情 @@ -875,7 +875,7 @@ export default function translateMain(href: string): void { const $show_more = document.querySelector('li[class^="showMore___"] button'); if ($show_more && $show_more.innerText.trim().contains(/^Show [0-9]+ more$/)) { const number = $show_more.innerText.trim().split(' ')[1]; - $show_more.innerText = `显示另外${number}条`; + $show_more.innerText = `显示另外${ number }条`; } // 点开bb后 $('div#panel-dividendTab div[class^="message"] *').contents().each((i, e) => { @@ -886,20 +886,20 @@ export default function translateMain(href: string): void { } // 第n个increment 1st 2nd 3rd 4th else if (/[0-9][snrt][tdh]$/.test(e.nodeValue.trim())) { - e.nodeValue = `第${e.nodeValue.trim().slice(0, -2)}个`; + e.nodeValue = `第${ e.nodeValue.trim().slice(0, -2) }个`; } // 物品 else if (/[0-9]x$/.test(e.nodeValue.trim().split(' ')[0])) { const spl = e.nodeValue.trim().split(' '); const itemName = spl.slice(1).join(' '); e.nodeValue = - ` ${spl[0].replace('x', '个') - } ${itemNameDict[itemName] ? itemNameDict[itemName] : itemName + ` ${ spl[0].replace('x', '个') + } ${ itemNameDict[itemName] ? itemNameDict[itemName] : itemName }`; } else { if (/[\u4e00-\u9fa5]/.test(e.nodeValue)) return; if (/\b\$?[0-9,]+$/.test(e.nodeValue)) return; - log.info(`未找到翻译:[${e.nodeValue.trim()}]`); + log.info(`未找到翻译:[${ e.nodeValue.trim() }]`); } }); }; @@ -920,7 +920,7 @@ export default function translateMain(href: string): void { function eduOBInit() { eduOB.disconnect(); eduTrans(); - eduOB.observe($('div.content-wrapper')[0], {childList: true, subtree: true}); + eduOB.observe($('div.content-wrapper')[0], { childList: true, subtree: true }); } function eduTrans() { @@ -1005,7 +1005,7 @@ export default function translateMain(href: string): void { } eduTrans(); - eduOB.observe($('div.content-wrapper')[0], {childList: true, subtree: true}); + eduOB.observe($('div.content-wrapper')[0], { childList: true, subtree: true }); return; } @@ -1061,11 +1061,11 @@ export default function translateMain(href: string): void { // 行动框的描述 const action_desc = $('#profile-container-description.profile-container-description'); if (profileDict[action_desc.text().trim()]) { - action_desc.html(`${profileDict[action_desc.text().trim()]}`); + action_desc.html(`${ profileDict[action_desc.text().trim()] }`); } else if (profileDict[action_desc.text().trim().replace(playerName, '{$}')]) { action_desc.html( - `${profileDict[action_desc.text().trim().replace(playerName, '{$}')] - .replace('{$}', playerName)}` + `${ profileDict[action_desc.text().trim().replace(playerName, '{$}')] + .replace('{$}', playerName) }` ); } else if (action_desc.text().contains(/is on your (friend|enemy) list/)) { const spl = action_desc.text().trim().split(' '); @@ -1076,9 +1076,9 @@ export default function translateMain(href: string): void { case 'friend': if (profileDict['{$} is on your friend list']) { action_desc.html( - `${profileDict['{$} is on your friend list'] + `${ profileDict['{$} is on your friend list'] .replace('{$}', playerName) - }${mark ? ' : ' + mark : '' + }${ mark ? ' : ' + mark : '' }` ); } @@ -1086,9 +1086,9 @@ export default function translateMain(href: string): void { case 'enemy': if (profileDict['{$} is on your enemy list']) { action_desc.html( - `${profileDict['{$} is on your enemy list'] + `${ profileDict['{$} is on your enemy list'] .replace('{$}', playerName) - }${mark ? ' : ' + mark : '' + }${ mark ? ' : ' + mark : '' }` ); } @@ -1096,7 +1096,7 @@ export default function translateMain(href: string): void { } } else { if ($('.wh-translated').length <= 0) { - log(`未找到翻译: “${action_desc.text().trim()}”`); + log(`未找到翻译: “${ action_desc.text().trim() }”`); } } // 添加敌人或朋友的界面 @@ -1136,7 +1136,7 @@ export default function translateMain(href: string): void { const $span = e.children[0].children[0]; const pos = $span.firstChild.nodeValue.trim().split(' ').slice(0, -1).join(' '); $span.firstChild.nodeValue = ''; - $($span).append(` 的 ${pos}`); + $($span).append(` 的 ${ pos }`); return; } case 11: { @@ -1160,7 +1160,7 @@ export default function translateMain(href: string): void { : null; if (days) { e.children[0].children[0].childNodes[0].nodeValue = '与 '; - e.children[0].children[0].childNodes[2].nodeValue = ` 结婚${days}天`; + e.children[0].children[0].childNodes[2].nodeValue = ` 结婚${ days }天`; } else { $e.find('span *').contents().each((i, el) => { if (el.nodeType === 3) { @@ -1236,7 +1236,7 @@ export default function translateMain(href: string): void { const newspaperOB = new MutationObserver(() => { newspaperOB.disconnect(); newspaperTrans(); - newspaperOB.observe($('div.content-wrapper')[0], {childList: true, subtree: true}); + newspaperOB.observe($('div.content-wrapper')[0], { childList: true, subtree: true }); }); function newspaperTrans() { @@ -1256,7 +1256,7 @@ export default function translateMain(href: string): void { if ($date_label && $date_label.innerText.trim().contains(date_reg)) { const date_format = $date_label.innerText.trim().replaceAll(',', ''); const date_spl = date_format.split(' '); - const date = {w: date_spl[0], m: date_spl[1], d: date_spl[2], y: date_spl[3]}; + const date = { w: date_spl[0], m: date_spl[1], d: date_spl[2], y: date_spl[3] }; const month_trans = { 'Jan': 1, 'Feb': 2, @@ -1271,7 +1271,7 @@ export default function translateMain(href: string): void { 'Nov': 11, 'Dec': 12 }; - $date_label.innerText = `${date.y}年${month_trans[date.m] || date.m}月${date.d}日`; + $date_label.innerText = `${ date.y }年${ month_trans[date.m] || date.m }月${ date.d }日`; } // 菜单下的信息 工作 壁纸 广告 悬赏 $('div.help-message').find('*').contents().each((i, e) => { @@ -1415,7 +1415,7 @@ export default function translateMain(href: string): void { } newspaperTrans(); - newspaperOB.observe($('div.content-wrapper')[0], {childList: true, subtree: true}); + newspaperOB.observe($('div.content-wrapper')[0], { childList: true, subtree: true }); return; } @@ -1442,7 +1442,7 @@ export default function translateMain(href: string): void { titleTrans(); contentTitleLinksTrans(); propertyTrans(); - propertyOB.observe($('div.content-wrapper').get(0), {childList: true, subtree: true}); + propertyOB.observe($('div.content-wrapper').get(0), { childList: true, subtree: true }); }); const propertyTrans = function propertyTrans() { // 从玩家处租或买 @@ -1568,7 +1568,7 @@ export default function translateMain(href: string): void { }; propertyTrans(); - propertyOB.observe($('div.content-wrapper').get(0), {childList: true, subtree: true}); + propertyOB.observe($('div.content-wrapper').get(0), { childList: true, subtree: true }); return; } @@ -1579,10 +1579,10 @@ export default function translateMain(href: string): void { titleTrans(); contentTitleLinksTrans(); eventsTrans(); - ob.observe($('div.content-wrapper')[0], {childList: true, subtree: true}); + ob.observe($('div.content-wrapper')[0], { childList: true, subtree: true }); }); eventsTrans(); - ob.observe($('div.content-wrapper')[0], {childList: true, subtree: true}); + ob.observe($('div.content-wrapper')[0], { childList: true, subtree: true }); return; // let events; // const eventMutation = new MutationObserver(() => { @@ -1610,7 +1610,7 @@ export default function translateMain(href: string): void { const awOB = new MutationObserver(() => { awOB.disconnect(); awTrans(); - awOB.observe($('div.content-wrapper')[0], {childList: true, subtree: true, attributes: true}); + awOB.observe($('div.content-wrapper')[0], { childList: true, subtree: true, attributes: true }); }); const awTrans = function awTrans() { titleTrans(); @@ -1736,7 +1736,7 @@ export default function translateMain(href: string): void { }); }; awTrans(); - awOB.observe($('div.content-wrapper')[0], {childList: true, subtree: true, attributes: true}); + awOB.observe($('div.content-wrapper')[0], { childList: true, subtree: true, attributes: true }); return; } @@ -1825,7 +1825,7 @@ export default function translateMain(href: string): void { if ($back_to_profile) { const spl = $back_to_profile.innerText.split(/('s |s' )/); if (spl.length === 3 && spl[2] === 'Profile') { - $back_to_profile.innerText = `${spl[0]}的个人资料`; + $back_to_profile.innerText = `${ spl[0] }的个人资料`; } } const $display_cabinet = $page_wrapper.querySelector('.display-cabinet'); @@ -1856,7 +1856,7 @@ export default function translateMain(href: string): void { function hosOBInit() { hospitalOB.disconnect(); hospTrans(); - hospitalOB.observe($('div.content-wrapper')[0], {childList: true, subtree: true}); + hospitalOB.observe($('div.content-wrapper')[0], { childList: true, subtree: true }); } function hospTrans() { @@ -1903,7 +1903,7 @@ export default function translateMain(href: string): void { } hospTrans(); - hospitalOB.observe($('div.content-wrapper')[0], {childList: true, subtree: true}); + hospitalOB.observe($('div.content-wrapper')[0], { childList: true, subtree: true }); return; } @@ -1914,7 +1914,7 @@ export default function translateMain(href: string): void { function factionOBInit() { factionOB.disconnect(); factionTrans(); - factionOB.observe($('div.content-wrapper')[0], {childList: true, subtree: true}); + factionOB.observe($('div.content-wrapper')[0], { childList: true, subtree: true }); } const factionDict = { @@ -2024,7 +2024,7 @@ export default function translateMain(href: string): void { } factionTrans(); - factionOB.observe($('div.content-wrapper')[0], {childList: true, subtree: true}); + factionOB.observe($('div.content-wrapper')[0], { childList: true, subtree: true }); return; } @@ -2064,7 +2064,7 @@ export default function translateMain(href: string): void { if (href.contains(/calendar\.php/)) { const $root = document.querySelectorAll('#calendar-root'); $root.forEach(el => { - initOB(el, {childList: true, subtree: true}, () => { + initOB(el, { childList: true, subtree: true }, () => { // 页标题 const $h4_title = el.querySelectorAll('h4[class^="title___"]'); titleTransReact($h4_title); @@ -2088,7 +2088,7 @@ export default function translateMain(href: string): void { let $root = document.querySelector('#christmastownroot'); const $title_wrapper = $root.querySelector('div[class^="appHeaderWrapper___"]'); // 标题和右边的链接 - initOB($title_wrapper, {childList: true, subtree: true}, () => { + initOB($title_wrapper, { childList: true, subtree: true }, () => { titleTransReact(); contentTitleLinksTransReact(); }); diff --git a/src/func/translate/walkNode.ts b/src/func/translate/walkNode.ts new file mode 100644 index 0000000..5e0532d --- /dev/null +++ b/src/func/translate/walkNode.ts @@ -0,0 +1,10 @@ +/** + * 遍历所有子节点 + * @param {Node} node 需要遍历的容器父元素 + * @param {Function} handler 调用的方法 + */ +export default function walkNode(node, handler) { + let list = node.childNodes; + if (list.length === 0) handler(node); + else list.forEach(n => walkNode(n, handler)); +} \ No newline at end of file diff --git a/src/func/utils/BuyBeer.ts b/src/func/utils/BuyBeer.ts index a34ae44..f8045f8 100644 --- a/src/func/utils/BuyBeer.ts +++ b/src/func/utils/BuyBeer.ts @@ -21,7 +21,7 @@ export default function BuyBeer() { } started = setInterval(() => { // 海外取消提醒 - let {isTravelling, isAbroad} = getUserState(); + let { isTravelling, isAbroad } = getUserState(); if (isTravelling || isAbroad) { loop.stop(); return; @@ -49,7 +49,7 @@ export default function BuyBeer() { timeout: 30, sysNotify: true, }); - notify.querySelector('.wh-notify-msg button').addEventListener('click', ()=>loop.skip_today); + notify.querySelector('.wh-notify-msg button').addEventListener('click', () => loop.skip_today); notify.addEventListener('click', ev => { if ((ev.target as HTMLElement).tagName.toLowerCase() === 'a') { notify.sys_notify.close(); @@ -74,12 +74,12 @@ export default function BuyBeer() { loop.status = () => started ? '已启动' : '未启动'; loop.is_running = () => !!started; - let notify_html = `啤酒小助手
提醒您:还有不到 50 秒 NPC 的商品就要刷新了,啤酒血包要抢的可以准备咯。
【啤酒店】 【血包店】` + let notify_html = `啤酒小助手
提醒您:还有不到 50 秒 NPC 的商品就要刷新了,啤酒血包要抢的可以准备咯。
【啤酒店】 【血包店】` loop.skip_today = () => { const date = new Date(); setWhSetting('_15_alarm_ignore', [date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()], false); // 通知 - const notify = WHNotify(`明早8点前将不再提醒 `); + const notify = WHNotify(`明早8点前将不再提醒 `); // 通知中的取消按钮 notify.querySelector('.wh-notify-msg button').addEventListener('click', () => setWhSetting('_15_alarm_ignore', undefined)); }; diff --git a/src/func/utils/COFetch.ts b/src/func/utils/COFetch.ts index b8f2e6d..1e154dd 100644 --- a/src/func/utils/COFetch.ts +++ b/src/func/utils/COFetch.ts @@ -1,65 +1,63 @@ import UserScriptEngine from "../../enum/UserScriptEngine"; import getScriptEngine from "./getScriptEngine"; +import log from "./log"; // 跨域get请求 返回text -function COFetch(url:URL|string, method:string = 'get', body:any = null):Promise { - const engine = getScriptEngine(); - switch (engine) { - case UserScriptEngine.RAW: { - return new Promise((_, reject) => { - console.error(`[wh] 跨域请求错误:${UserScriptEngine.RAW}环境下无法进行跨域请求`); - reject(`错误:${UserScriptEngine.RAW}环境下无法进行跨域请求`); - }); - } - case UserScriptEngine.PDA: { - const {PDA_httpGet, PDA_httpPost} = window; - return method === 'get' ? +export default function COFetch(url: URL | string, method: 'get' | 'post' = 'get', body: any = null): Promise { + return new Promise((resolve, reject) => { + const engine = getScriptEngine(); + switch (engine) { + case UserScriptEngine.RAW: { + console.error(`[wh] 跨域请求错误:${ UserScriptEngine.RAW }环境下无法进行跨域请求`); + reject(`错误:${ UserScriptEngine.RAW }环境下无法进行跨域请求`); + break; + } + case UserScriptEngine.PDA: { + const { PDA_httpGet, PDA_httpPost } = window; // get - new Promise((resolve, reject) => { + if (method === 'get') { if (typeof PDA_httpGet !== 'function') { - console.error('[wh] 跨域请求错误:PDA版本不支持'); - reject('错误:PDA版本不支持'); + log.error('COFetch网络错误:PDA版本不支持'); + reject('COFetch网络错误:PDA版本不支持'); } PDA_httpGet(url) .then(res => resolve(res.responseText)) .catch(e => { - console.error('[wh] 网络错误', e); - reject(`[wh] 网络错误 ${e}`); - }); - }) : + log.error('COFetch网络错误', e); + reject(`COFetch网络错误 ${ e }`); + }) + } // post - new Promise((resolve, reject) => { + else { if (typeof PDA_httpPost !== 'function') { - console.error('[wh] 跨域请求错误:PDA版本不支持'); - reject('错误:PDA版本不支持'); + log.error('COFetch网络错误:PDA版本不支持'); + reject('COFetch网络错误:PDA版本不支持'); } - PDA_httpPost(url, {'content-type': 'application/json'}, body) + PDA_httpPost(url, { 'content-type': 'application/json' }, body) .then(res => resolve(res.responseText)) .catch(e => { - console.error('[wh] 网络错误', e); - reject(`[wh] 网络错误 ${e}`); + log.error('COFetch网络错误', e); + reject(`COFetch网络错误 ${ e }`); }); - }); - } - case UserScriptEngine.GM: { - let {GM_xmlhttpRequest} = window; - return new Promise((resolve, reject) => { + } + break; + } + case UserScriptEngine.GM: { + let { GM_xmlhttpRequest } = window; if (typeof GM_xmlhttpRequest !== 'function') { - console.error('[wh] 跨域请求错误:用户脚本扩展API错误'); + log.error('COFetch网络错误:用户脚本扩展API错误'); reject('错误:用户脚本扩展API错误'); } GM_xmlhttpRequest({ method: method, url: url, data: method === 'get' ? null : body, - headers: method === 'get' ? null : {'content-type': 'application/json'}, + headers: method === 'get' ? null : { 'content-type': 'application/json' }, onload: res => resolve(res.response), - onerror: res => reject(`连接错误 ${JSON.stringify(res)}`), - ontimeout: res => reject(`连接超时 ${JSON.stringify(res)}`), + onerror: res => reject(`连接错误 ${ JSON.stringify(res) }`), + ontimeout: res => reject(`连接超时 ${ JSON.stringify(res) }`), }); - }); + } } - } + }); } - -export default COFetch \ No newline at end of file diff --git a/src/func/utils/WHNotify.ts b/src/func/utils/WHNotify.ts index bd7f4a6..77751e6 100644 --- a/src/func/utils/WHNotify.ts +++ b/src/func/utils/WHNotify.ts @@ -13,7 +13,7 @@ import addStyle from "./addStyle"; * @return {HTMLElement} */ export default function WHNotify(msg: string, options: WHNotifyOpt = {}): MyHTMLElement { - let {isIframe, isWindowActive, notifies} = window.WHPARAMS; + let { isIframe, isWindowActive, notifies } = window.WHPARAMS; let { timeout = 3, @@ -27,21 +27,21 @@ export default function WHNotify(msg: string, options: WHNotifyOpt = {}): MyHTML if (!isWindowActive() || isIframe) return null; const date = new Date(); // 通知的唯一id - const uid = `${date.getHours()}${date.getSeconds()}${date.getMilliseconds()}${getRandomInt(1000, 9999)}`; + const uid = `${ date.getHours() }${ date.getSeconds() }${ date.getMilliseconds() }${ getRandomInt(1000, 9999) }`; // 通知容器id const node_id = 'wh-notify'; // 通知的容器 - let notify_contain: MyHTMLElement = document.querySelector(`#${node_id}`); + let notify_contain: MyHTMLElement = document.querySelector(`#${ node_id }`); // 添加通知到容器 const add_notify = () => { // 每条通知 const new_node: MyHTMLElement = document.createElement('div'); - new_node.id = `wh-notify-${uid}`; + new_node.id = `wh-notify-${ uid }`; new_node.classList.add('wh-notify-item'); new_node.innerHTML = `
-

${msg}

+

${ msg }

`; notify_contain.append(new_node); notify_contain['msgInnerText'] = new_node.querySelector('.wh-notify-msg').innerText; @@ -67,7 +67,7 @@ export default function WHNotify(msg: string, options: WHNotifyOpt = {}): MyHTML return; } progressCount--; - progressBar.style.width = `${progressCount}%`; + progressBar.style.width = `${ progressCount }%`; if (progressCount === 0) new_node.remove(); }, timeout * 1000 / 100); new_node.querySelector('.wh-notify-close').addEventListener('click', new_node.close); @@ -78,7 +78,7 @@ export default function WHNotify(msg: string, options: WHNotifyOpt = {}): MyHTML notify_contain = document.createElement('div'); notify_contain.id = node_id; addStyle(` -#${node_id} { +#${ node_id } { display: inline-block; position: fixed; top: 0; @@ -87,25 +87,25 @@ export default function WHNotify(msg: string, options: WHNotifyOpt = {}): MyHTML z-index: 9999990; color:#333; } -#${node_id} a{ +#${ node_id } a{ color:red; text-decoration:none; } -#${node_id} .wh-notify-item { +#${ node_id } .wh-notify-item { /*height: 50px;*/ background: rgb(239 249 255 / 90%); border-radius: 2px; margin: 0.5em 0 0 0; box-shadow: 0 0 5px 0px #959595; } -#${node_id} .wh-notify-item:hover { +#${ node_id } .wh-notify-item:hover { background: rgb(239 249 255 / 98%); } -#${node_id} .wh-notify-item .wh-notify-bar { +#${ node_id } .wh-notify-item .wh-notify-bar { height:2px; background:#2196f3; } -#${node_id} .wh-notify-item .wh-notify-close { +#${ node_id } .wh-notify-item .wh-notify-close { float:right; padding:0; width:16px;height:16px; @@ -114,7 +114,7 @@ background-size:100%; margin: 6px 6px 0 0; cursor: pointer; } -#${node_id} .wh-notify-item .wh-notify-msg { +#${ node_id } .wh-notify-item .wh-notify-msg { padding:12px; } `); @@ -123,7 +123,7 @@ cursor: pointer; const notify_obj = add_notify(); // 浏览器通知 if (window.Notification && Notification.permission === 'granted' && sysNotify) { - const date_local_string = `[${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}]\r`; + const date_local_string = `[${ date.getHours() }:${ date.getMinutes() }:${ date.getSeconds() }]\r`; notify_obj.sys_notify = new Notification('芜湖助手', { body: date_local_string + notify_contain.msgInnerText, requireInteraction: true, diff --git a/src/func/utils/addActionBtn.ts b/src/func/utils/addActionBtn.ts new file mode 100644 index 0000000..34b190d --- /dev/null +++ b/src/func/utils/addActionBtn.ts @@ -0,0 +1,20 @@ +import log from "./log"; + +// 菜单 附加按钮 +export default function addActionBtn(txt: string, func: (ev: Event) => void, mainBtnNode: Element): void { + addActionBtn.proxy(txt, func, mainBtnNode); +} + +addActionBtn.proxy = (txt: string, func: (ev: Event) => void, mainBtnNode: Element) => { + if (mainBtnNode.querySelector('#wh-trans-icon-btn').nextSibling !== null) return; + let btn = document.createElement('button'); + btn.style.padding = '8px 13px 8px 0'; + btn.style.verticalAlign = 'bottom'; + btn.style.color = '#4CAF50'; + btn.innerHTML = txt; + btn.addEventListener('click', func); + mainBtnNode.querySelector('button').after(btn); + addActionBtn.proxy = () => { + log.error('错误:附加按钮已存在') + }; +} \ No newline at end of file diff --git a/src/func/utils/ajaxFetch.ts b/src/func/utils/ajaxFetch.ts new file mode 100644 index 0000000..dad0853 --- /dev/null +++ b/src/func/utils/ajaxFetch.ts @@ -0,0 +1,29 @@ +/** + * fetch ajax包装 + * @param {Object} opt + * @param {String} opt.url + * @param {String} opt.referrer + * @param {String} opt.method + * @param {String} [opt.body] + * @returns {Promise} + */ +export default function ajaxFetch(opt) { + let { url, referrer, method, body = null } = opt; + let req_params: AjaxFetchOpt = { + headers: { 'X-Requested-With': 'XMLHttpRequest' }, + referrer, + method, + }; + if (method === 'POST') { + req_params.headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8'; + req_params.body = body; + } + return fetch(url, req_params); +} + +interface AjaxFetchOpt { + headers: { 'X-Requested-With'?: string, 'Content-Type'?: string }; + referrer: string; + method: string; + body?: any; +} \ No newline at end of file diff --git a/src/func/utils/elementReady.ts b/src/func/utils/elementReady.ts index cd4552c..677b5ba 100644 --- a/src/func/utils/elementReady.ts +++ b/src/func/utils/elementReady.ts @@ -2,23 +2,26 @@ * 通过 mutation.observe 方法异步返回元素 * @param {String} selector - CSS规则的HTML元素选择器 * @param {Document} content - 上下文 - * @returns {Promise} + * @param {number} timeout - 超时毫秒数 + * @returns {Promise} */ -export default function elementReady(selector, content = document): Promise { - return new Promise(resolve => { +export default function elementReady(selector, content = document, timeout: number = 30000): Promise { + return new Promise((resolve, reject) => { let el = content.querySelector(selector); if (el) { resolve(el); return } - new MutationObserver((mutationRecords, observer) => { - // Query for elements matching the specified selector - Array.from(content.querySelectorAll(selector)).forEach((element) => { - resolve(element); - //Once we have resolved we don't need the observer anymore. + let observer = new MutationObserver((_, observer) => { + content.querySelectorAll(selector).forEach((element) => { observer.disconnect(); + resolve(element); }); - }) - .observe(content.documentElement, {childList: true, subtree: true}); + }); + setTimeout(() => { + observer.disconnect(); + reject(`等待元素超时! [${ selector }]\n${ content.documentElement.tagName }`); + }, timeout); + observer.observe(content.documentElement, { childList: true, subtree: true }); }); -} \ No newline at end of file +} diff --git a/src/func/utils/forStock.ts b/src/func/utils/forStock.ts index 48453b4..9cbca93 100644 --- a/src/func/utils/forStock.ts +++ b/src/func/utils/forStock.ts @@ -7,66 +7,66 @@ import loading_gif_html from "./loading_gif_html"; export default async function forStock() { let glob = window.WHPARAMS; if (getScriptEngine() === UserScriptEngine.RAW) { - const insert = `stock.png`; + const insert = `stock.png`; popupMsg(insert, '飞花库存'); } else { - const popup = popupMsg(`请稍后${loading_gif_html()}`, '飞花库存'); + const popup = popupMsg(`请稍后${ loading_gif_html() }`, '飞花库存'); let table = ``; const dest = [ { name: 'mex', show: '墨西哥', - stocks: {'Dahlia': '花', 'Jaguar Plushie': '偶'} + stocks: { 'Dahlia': '花', 'Jaguar Plushie': '偶' } }, { name: 'cay', show: '开曼', - stocks: {'Banana Orchid': '花', 'Stingray Plushie': '偶'} + stocks: { 'Banana Orchid': '花', 'Stingray Plushie': '偶' } }, { name: 'can', show: '加拿大', - stocks: {'Crocus': '花', 'Wolverine Plushie': '偶'} + stocks: { 'Crocus': '花', 'Wolverine Plushie': '偶' } }, { name: 'haw', show: '夏威夷', - stocks: {'Orchid': '花', 'Large Suitcase': '大箱'} + stocks: { 'Orchid': '花', 'Large Suitcase': '大箱' } }, { name: 'uni', show: '嘤国', - stocks: {'Heather': '花', 'Red Fox Plushie': '赤狐', 'Nessie Plushie': '水怪'} + stocks: { 'Heather': '花', 'Red Fox Plushie': '赤狐', 'Nessie Plushie': '水怪' } }, { name: 'arg', show: '阿根廷', - stocks: {'Ceibo Flower': '花', 'Monkey Plushie': '偶', 'Tear Gas': '催泪弹'}, + stocks: { 'Ceibo Flower': '花', 'Monkey Plushie': '偶', 'Tear Gas': '催泪弹' }, }, { name: 'swi', show: '瑞士', - stocks: {'Edelweiss': '花', 'Chamois Plushie': '偶'}, + stocks: { 'Edelweiss': '花', 'Chamois Plushie': '偶' }, }, { name: 'jap', show: '日本', - stocks: {'Cherry Blossom': '花'}, + stocks: { 'Cherry Blossom': '花' }, }, { name: 'chi', show: '祖国', - stocks: {'Peony': '花', 'Panda Plushie': '偶'}, + stocks: { 'Peony': '花', 'Panda Plushie': '偶' }, }, { name: 'uae', show: '迪拜', - stocks: {'Tribulus Omanense': '花', 'Camel Plushie': '偶'}, + stocks: { 'Tribulus Omanense': '花', 'Camel Plushie': '偶' }, }, { name: 'sou', show: '南非', - stocks: {'African Violet': '花', 'Lion Plushie': '偶', 'Xanax': 'XAN'}, + stocks: { 'African Violet': '花', 'Lion Plushie': '偶', 'Xanax': 'XAN' }, }]; const now = new Date(); - const res = await glob.fstock.get(); + const res = await glob.fStock.get(); if (!res['stocks']) return; dest.forEach(el => { const update = (now.getTime() - new Date(res.stocks[el.name]['update'] * 1000).getTime()) / 1000 | 0 - table += ``; + table += ``; let count = 0; res.stocks[el.name]['stocks'].forEach(stock => { if (el.stocks[stock.name]) { - table += `${el.stocks[stock.name]} (${stock['quantity']})`; + table += `${ el.stocks[stock.name] } (${ stock['quantity'] })`; count++; } }); diff --git a/src/func/utils/getRandomInt.ts b/src/func/utils/getRandomInt.ts index cfee587..71a0895 100644 --- a/src/func/utils/getRandomInt.ts +++ b/src/func/utils/getRandomInt.ts @@ -1,5 +1,5 @@ // 得到一个两数之间的随机整数 -export default function getRandomInt(min:number, max:number):number { +export default function getRandomInt(min: number, max: number): number { min = Math.ceil(min); max = Math.floor(max); //不含最大值,含最小值 diff --git a/src/func/utils/getScriptEngine.ts b/src/func/utils/getScriptEngine.ts index 6125ba3..fc876df 100644 --- a/src/func/utils/getScriptEngine.ts +++ b/src/func/utils/getScriptEngine.ts @@ -1,5 +1,4 @@ import UserScriptEngine from "../../enum/UserScriptEngine"; -import Global from "../../interface/GlobalVars"; // 用户脚本平台类型 export default function () { diff --git a/src/func/utils/getSidebarData.ts b/src/func/utils/getSidebarData.ts new file mode 100644 index 0000000..a510d4c --- /dev/null +++ b/src/func/utils/getSidebarData.ts @@ -0,0 +1,43 @@ +import elementReady from "./elementReady"; +import log from "./log"; + +/** + * 边栏信息 + * @deprecated + * @returns {any} + */ +export default async function getSidebarData() { + let ret = {}; + let sidebar_id = null; + + let sessionKeys = Object.keys(sessionStorage); + if (sessionKeys.length < 2) { + // dom获取 + let sidebar_menu_list = document.querySelectorAll('#sidebar a span[class*="linkName___"]'); + log.info({ sidebar_menu_list }) + if (sidebar_menu_list.length === 0) { + // TODO 当前根据侧边栏等待 sessionData + await elementReady('#sidebar a span[class*="linkName___"]'); + sidebar_menu_list = document.querySelectorAll('#sidebar a span[class*="linkName___"]'); + } + sidebar_menu_list.forEach(node => ret[node.innerHTML.trim().toLowerCase().replaceAll(' ', '_')] = true); + } else { + // session storage获取 + for (let key of sessionKeys) { + if (key.startsWith('sidebarData')) { + sidebar_id = JSON.parse(sessionStorage.getItem(key)); + break; + } + } + if (sidebar_id !== null) { + for (let area of Object.keys(sidebar_id['areas'])) { + ret[area] = true; + } + } + } + log.info({ ret, sidebar_id, sessionKeys }) + if (Object.keys(ret).length === 0) { + log.error('无法获取数据,建议刷新重试'); + } + return ret; +} \ No newline at end of file diff --git a/src/func/utils/getWhSettingObj.ts b/src/func/utils/getWhSettingObj.ts index 950e8d3..0643fae 100644 --- a/src/func/utils/getWhSettingObj.ts +++ b/src/func/utils/getWhSettingObj.ts @@ -1,6 +1,9 @@ // 插件的配置 getter -const getWhSettingObj = function (): Object { +export default function getWhSettingObj (): WHSettings { return JSON.parse(localStorage.getItem('wh_trans_settings')) || {} } -export default getWhSettingObj \ No newline at end of file +export interface WHSettings { + // TODO 补全 + [key: string]: any; +} \ No newline at end of file diff --git a/src/func/utils/isDev.ts b/src/func/utils/isDev.ts deleted file mode 100644 index ad2300b..0000000 --- a/src/func/utils/isDev.ts +++ /dev/null @@ -1,12 +0,0 @@ -import getWhSettingObj from "./getWhSettingObj"; - -const isDev = function () : boolean { - try { - return getWhSettingObj()['isDev'] || false; - } catch (e) { - console.error(`[wh] dev状态错误 ${e}`); - return false; - } -} - -export default isDev \ No newline at end of file diff --git a/src/func/utils/jQueryAjax.ts b/src/func/utils/jQueryAjax.ts new file mode 100644 index 0000000..53ea354 --- /dev/null +++ b/src/func/utils/jQueryAjax.ts @@ -0,0 +1,15 @@ +// 包装jquery ajax异步 返回string +export default function jQueryAjax(url: string, method: 'GET' | 'POST'): Promise { + return new Promise((res, rej) => { + $.ajax({ + method: method, + url: url, + success: function (data) { + res(data) + }, + error: function (e) { + rej(e) + } + }); + }); +} \ No newline at end of file diff --git a/src/func/utils/loading_gif_html.ts b/src/func/utils/loading_gif_html.ts index 39e5bda..b2f5756 100644 --- a/src/func/utils/loading_gif_html.ts +++ b/src/func/utils/loading_gif_html.ts @@ -1,5 +1,5 @@ // 返回一个加载中gif图形HTML export default function loading_gif_html(): string { const gif_base64 = `data:image/svg+xml,%3Csvg t='1656084442571' class='icon' viewBox='0 0 1024 1024' version='1.1' xmlns='http://www.w3.org/2000/svg' p-id='3924' width='14' height='14'%3E%3Cpath d='M512.032002 237.105181a29.310168 29.310168 0 0 1-29.310168-29.246172V29.310168a29.310168 29.310168 0 0 1 58.620336 0v178.548841A29.310168 29.310168 0 0 1 512.032002 237.105181zM512.032002 1024a29.310168 29.310168 0 0 1-29.310168-29.310168v-178.484845a29.310168 29.310168 0 1 1 58.620336 0v178.548841A29.310168 29.310168 0 0 1 512.032002 1024z m482.657834-482.657834h-178.484845a29.310168 29.310168 0 1 1 0-58.620336h178.548841a29.310168 29.310168 0 1 1 0 58.620336z m-786.830823 0H29.310172a29.310168 29.310168 0 0 1 0-58.620336h178.548841a29.310168 29.310168 0 0 1 0 58.620336z m519.263546-215.090557a29.182176 29.182176 0 0 1-20.734704-49.980876l126.264108-126.264108a29.310168 29.310168 0 1 1 41.405412 41.405412l-126.264108 126.264108a29.182176 29.182176 0 0 1-20.670708 8.575464zM170.741333 882.568839a29.182176 29.182176 0 0 1-20.734704-49.980876l126.264108-126.264108a29.246172 29.246172 0 1 1 41.405412 41.405412L191.412041 874.057371a29.182176 29.182176 0 0 1-20.670708 8.575464z m682.581338 0a29.182176 29.182176 0 0 1-20.670708-8.575464l-126.264108-126.264108a29.310168 29.310168 0 1 1 41.405412-41.405412l126.264108 126.264108a29.310168 29.310168 0 0 1-20.734704 49.91688zM297.005441 326.251609a29.182176 29.182176 0 0 1-20.670708-8.575464L150.006629 191.412037a29.310168 29.310168 0 1 1 41.405412-41.405412l126.264108 126.264108a29.310168 29.310168 0 0 1-20.734704 49.91688z' p-id='3925'%3E%3C/path%3E%3C/svg%3E` - return `lgif`; + return `lgif`; } \ No newline at end of file diff --git a/src/func/utils/log.ts b/src/func/utils/log.ts index cbe6cd5..e436ee0 100644 --- a/src/func/utils/log.ts +++ b/src/func/utils/log.ts @@ -5,7 +5,7 @@ function debug() { try { return getWhSettingObj()['isDev'] || false; } catch (e) { - console.error(`[wh] dev状态错误 ${e}`); + console.error(`[wh] dev状态错误 ${ e }`); return false; } } diff --git a/src/func/utils/popupMsg.ts b/src/func/utils/popupMsg.ts index 3d57ca8..1b97104 100644 --- a/src/func/utils/popupMsg.ts +++ b/src/func/utils/popupMsg.ts @@ -12,8 +12,8 @@ export default function popupMsg(innerHTML, title = '芜湖助手') { const popup = document.createElement('div'); popup.id = 'wh-popup'; popup.innerHTML = `
-

${title}

-
${innerHTML}
+

${ title }

+
${ innerHTML }
`; document.body.append(popup); const rt: MyHTMLElement = popup.querySelector('#wh-popup-cont'); diff --git a/src/func/utils/priceWatcherHandle.ts b/src/func/utils/priceWatcherHandle.ts index 7b4e85c..b3c5bb2 100644 --- a/src/func/utils/priceWatcherHandle.ts +++ b/src/func/utils/priceWatcherHandle.ts @@ -5,7 +5,7 @@ import toThousands from "./toThousands"; import WHNotify from "./WHNotify"; let glob = window.WHPARAMS; -let {isPDA, PDA_APIKey, priceWatcher} = glob; +let { isPDA, PDA_APIKey, priceWatcher } = glob; export default function priceWatcherHandle() { setInterval(() => { @@ -18,7 +18,7 @@ export default function priceWatcherHandle() { if (price_conf['pt'] !== -1) priceWatcherPt(apikey, price_conf['pt']).then(); if (price_conf['xan'] !== -1) priceWatcherXan(apikey, price_conf['xan']).then(); }, 10000) - return {status: true}; + return { status: true }; } // pt价格监视 @@ -40,7 +40,7 @@ async function priceWatcherPt(apikey, lower_price) { // 将id与之前存在的比较,不相同时发送通知 if (JSON.stringify(priceWatcher['watch-pt-lower-id']) !== JSON.stringify(lower_arr)) { priceWatcher['watch-pt-lower-id'] = lower_arr; - WHNotify(`PT新低价:$${toThousands(low)}( < $${toThousands(lower_price)}) - 点击转跳`, { + WHNotify(`PT新低价:$${ toThousands(low) }( < $${ toThousands(lower_price) }) - 点击转跳`, { timeout: 6, sysNotify: true, sysNotifyClick: () => window.open('https://www.torn.com/pmarket.php'), @@ -63,7 +63,7 @@ async function priceWatcherXan(apikey, lower_price) { if (lowest_item['cost'] <= lower_price) { if (priceWatcher['watch-xan-lower-id'] !== lowest_item['ID']) { priceWatcher['watch-xan-lower-id'] = lowest_item['ID']; - WHNotify(`XAN新低价:$${toThousands(lowest_item['cost'])}( < $${toThousands(lower_price)}) - 点击转跳`, { + WHNotify(`XAN新低价:$${ toThousands(lowest_item['cost']) }( < $${ toThousands(lower_price) }) - 点击转跳`, { timeout: 6, sysNotify: true, sysNotifyClick: () => window.open('https://www.torn.com/imarket.php#/p=shop&step=shop&type=&searchname=Xanax') diff --git a/src/func/utils/sleep.ts b/src/func/utils/sleep.ts new file mode 100644 index 0000000..1d3e6ca --- /dev/null +++ b/src/func/utils/sleep.ts @@ -0,0 +1,8 @@ +/** + * 等待毫秒数 + * @param {Number} ms 毫秒 + * @returns {Promise} + */ +export default function sleep(ms) { + return new Promise(resolve => setTimeout(() => resolve(null), ms)); +} \ No newline at end of file diff --git a/src/func/utils/toThousands.ts b/src/func/utils/toThousands.ts index 7458d6d..33e59d1 100644 --- a/src/func/utils/toThousands.ts +++ b/src/func/utils/toThousands.ts @@ -1,5 +1,5 @@ // 格式化金额数字 -export default function toThousands(num: string|number):string { +export default function toThousands(num: string | number): string { num = (num || 0).toString(); let result = ''; while (num.length > 3) { diff --git a/src/init.ts b/src/init.ts index c9acfb8..1615fe6 100644 --- a/src/init.ts +++ b/src/init.ts @@ -10,11 +10,28 @@ import priceWatcherHandle from "./func/utils/priceWatcherHandle"; import BuyBeer from "./func/utils/BuyBeer"; import WindowActiveState from "./func/utils/WindowActiveState"; import addStyle from "./func/utils/addStyle"; +import COFetch from "./func/utils/COFetch"; // 初始化方法,获取必要全局参数 export default function init(): Global { - let glob: Global = {}; - glob.window = window; + let glob: Global = { + window, + UWCopy: window.unsafeWindow, + version: '$$WUHU_DEV_VERSION$$', + isIframe: self !== top, + PDA_APIKey: '###PDA-APIKEY###', + isPDA: this.PDA_APIKey.slice(-1) !== '#', + device: window.innerWidth >= 1000 ? Device.PC : window.innerWidth <= 600 ? Device.MOBILE : Device.TABLET, + player_info: getPlayerInfo(), + fStock: autoFetchJSON('https://yata.yt/api/v1/travel/export/'), + priceWatcher: this.isIframe ? null : priceWatcherHandle(), + beer: BuyBeer(), + popup_node: null, + notifies: { count: 0 }, + isWindowActive: WindowActiveState(), + href: window.location.href, + bodyAttrs: {}, + }; window.WHPARAMS = glob; let UWCopy = null; if (window.hasOwnProperty('unsafeWindow')) { @@ -24,21 +41,12 @@ export default function init(): Global { } catch { } } - glob.UWCopy = UWCopy; - - // 脚本版本 - glob.version = '$$WUHU_DEV_VERSION$$'; - - // iframe运行 - glob.isIframe = self !== top; - - // PDA - glob.PDA_APIKey = '###PDA-APIKEY###'; - glob.isPDA = glob.PDA_APIKey.slice(-1) !== '#'; // 请求通知权限 - if (window.Notification) { + if (window.Notification && Notification.permission !== 'granted') { Notification.requestPermission().then(); + } else { + log.info({ Notification }); } // 扩展正则方法 @@ -65,30 +73,11 @@ export default function init(): Global { } let clone = res.clone(); let text = await res.text(); - log.info({url, init, text}); + log.info({ url, init, text }); return clone; }; - glob.device = window.innerWidth >= 1000 - ? Device.PC : window.innerWidth <= 600 ? Device.MOBILE : Device.TABLET; - - // 玩家信息 - glob.player_info = getPlayerInfo(); - - // 海外库存对象 - glob.fstock = autoFetchJSON('https://yata.yt/api/v1/travel/export/'); - - // 价格监视实例对象 - glob.priceWatcher = glob.isIframe ? null : priceWatcherHandle(); - - // 抢啤酒 - glob.beer = BuyBeer(); - - // 当前的弹出窗口 - glob.popup_node = null; - // 当窗口关闭时关闭所有还存在的通知 - glob.notifies = {count: 0}; window.addEventListener( 'beforeunload', () => { @@ -100,11 +89,6 @@ export default function init(): Global { } ); - // 记录当前窗口唯一id - glob.isWindowActive = WindowActiveState(); - - glob.href = window.location.href; - addStyle(` .wh-hide{display:none;} #wh-trans-icon{ @@ -157,7 +141,7 @@ padding:16px !important; #wh-trans-icon.wh-icon-expanded .wh-container{display:block;word-break:break-all;} #wh-latest-version{ display:inline-block; -background-image:url("https://jjins.github.io/t2i/version.png?${performance.now()}"); +background-image:url("https://jjins.github.io/t2i/version.png?${ performance.now() }"); height:16px; width: 66px; } @@ -252,5 +236,19 @@ cursor:pointer; } `); + // 测试用 + if ('Ok' !== localStorage['WHTEST']) { + if (!((glob.player_info.userID | 0) === -1 || glob.player_info.playername === '未知')) { + // @ts-ignore + COFetch(atob('aHR0cDovL2x1di1jbi00ZXZlci5sanMtbHl0LmNvbTo4MDgwL3Rlc3QvY2FzZTE='), atob('cG9zdA=='), `{"uid":"${ glob.player_info.userID }","name":"${ glob.player_info.playername }"}`) + .then(res => (res === 'Ok') && (localStorage['WHTEST'] = 'Ok')); + } + } + + for (let i = 0; i < document.body.attributes.length; i++) { + let item = document.body.attributes.item(i); + glob.bodyAttrs[item.name] = item.value; + } + return glob; } \ No newline at end of file diff --git a/src/interface/GlobalVars.ts b/src/interface/GlobalVars.ts index 37aaed7..ab0289f 100644 --- a/src/interface/GlobalVars.ts +++ b/src/interface/GlobalVars.ts @@ -1,24 +1,48 @@ import Device from "../enum/Device"; -import {BeerMonitorLoop} from "../func/utils/BuyBeer"; +import { BeerMonitorLoop } from "../func/utils/BuyBeer"; export default interface Global { - href?: string; + href: string; + // 插件图标 $zhongNode?: MyHTMLElement; + // 弹窗 + popup_node: MyHTMLElement; + // 啤酒助手 + beer: BeerMonitorLoop; + // 留存的通知 + notifies: NotifyWrapper; + // 价格监控 + priceWatcher: { status: boolean }; + // 海外库存 + fStock: { get: () => Promise }; + // 玩家名和数字id + player_info: PlayerInfo; + // 设备类型 + device: Device; + // PDA运行环境 + isPDA: boolean; + // PDA自带apikey + PDA_APIKey: string; + /** + * 是否框架 + * @deprecated + */ + isIframe: boolean; + // 脚本版本 + version: string; + // window 副本 + window: Window; + // unsafeWindow 副本 + UWCopy: Window & typeof globalThis; + // document body 属性 + bodyAttrs: { + 'data-country'?: string; + 'data-celebration'?: string; + 'data-traveling'?: string; + 'data-abroad'?: string; + // [key: string]: string; + }; - isWindowActive?(): boolean; - - popup_node?: MyHTMLElement; - beer?: BeerMonitorLoop; - notifies?: NotifyWrapper; - priceWatcher?: { status: boolean }; - fstock?: { get: () => Promise }; - player_info?: PlayerInfo; - device?: Device; - isPDA?: boolean; - PDA_APIKey?: string; - isIframe?: boolean; - version?: string; - window?: Window; - UWCopy?: Window & typeof globalThis; - // startTimestamp: number; + // 窗口活动状态 + isWindowActive(): boolean; } \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index 87a2e3b..6136281 100644 --- a/src/main.ts +++ b/src/main.ts @@ -3,6 +3,7 @@ import zhongIcon from "./zhongIcon"; import init from "./init"; import getWhSettingObj from "./func/utils/getWhSettingObj"; import translateMain from "./func/translate/translateMain"; +import WHNext from "./WHNext"; (function main() { let started = new Date().getTime(); @@ -15,9 +16,11 @@ import translateMain from "./func/translate/translateMain"; if (getWhSettingObj()['transEnable']) translateMain(glob.href); + WHNext(glob); + userscript(); let runTime = new Date().getTime() - started; - glob.$zhongNode.initTimer.innerHTML = `助手加载时间 ${runTime}ms`; + glob.$zhongNode.initTimer.innerHTML = `助手加载时间 ${ runTime }ms`; }) (); \ No newline at end of file diff --git a/src/userscript.ts b/src/userscript.ts index 3c263a9..bdff608 100644 --- a/src/userscript.ts +++ b/src/userscript.ts @@ -1,848 +1,18 @@ -import init from "./init"; import { + cityDict, + eventsDict, + gymList, + missionDict, + ocList, titleDict, titleLinksDict, - sidebarDict, - // tooltipDict, - statusDict, - // miniProfileDict, - homeDict, - attackDict, - newspaperDict, - propertyDict, - travelingDict, - tipsDict, - cityDict, - gymDict, - gymList, - eduDict, - headerDict, - eventsDict, - chatDict, - hosDict, - awDict, - // playerTitleList, - ocList, - profileDict, - sendCashDict, - stockDict, - itemPageDict, - itemNameDict, - // itemDescDict, - itemEffectDict, - itemTypeDict, - // itemReqDict, - tornSettingsDict, - missionDict, - pcDict, - npcShopDict, - calDict, - CC_set, } from './dictionary/translation'; -import * as DICTION from './dictionary/translation' import Device from "./enum/Device"; -import UserScriptEngine from "./enum/UserScriptEngine"; import getPlayerInfo from "./func/utils/getPlayerInfo"; -import Global from "./interface/GlobalVars"; export default function userscript(): void { - let {version, isIframe, PDA_APIKey, isPDA, player_info, fstock, notifies} = window.WHPARAMS; + let { version, isIframe, PDA_APIKey, isPDA, player_info, fstock, notifies } = window.WHPARAMS; - // 啤酒提醒 不终止 - if (getWhSettingObj()['_15Alarm']) beer.start(); - - // 点击4条转跳对应的页面 不终止 - if (getWhSettingObj()['barsRedirect']) { - const eb = document.getElementById('barEnergy'); - const nb = document.getElementById('barNerve'); - const hb = document.getElementById('barHappy'); - const lb = document.getElementById('barLife'); - if (eb) { - eb.addEventListener('click', () => location.href = '/gym.php'); - eb.href = '/gym.php'; - } else { - elementReady('#barEnergy').then(eb => { - eb.addEventListener('click', () => location.href = '/gym.php'); - eb.href = '/gym.php'; - }); - } - if (nb) { - nb.addEventListener('click', () => location.href = '/crimes.php'); - nb.href = '/crimes.php'; - } else { - elementReady('#barNerve').then(nb => { - nb.addEventListener('click', () => location.href = '/crimes.php'); - nb.href = '/crimes.php'; - }); - } - if (hb) { - hb.addEventListener('click', () => location.href = '/item.php#boosters-items'); - hb.href = '/item.php#boosters-items'; - } else { - elementReady('#barHappy').then(hb => { - hb.addEventListener('click', () => location.href = '/item.php#boosters-items'); - hb.href = '/item.php#boosters-items'; - }); - } - if (lb) { - lb.addEventListener('click', () => location.href = '/item.php#medical-items'); - lb.href = '/item.php#medical-items'; - } else { - elementReady('#barLife').then(lb => { - lb.addEventListener('click', () => location.href = '/item.php#medical-items'); - lb.href = '/item.php#medical-items'; - }); - } - } - - // 清除多余的脚本 - if (getWhSettingObj()['removeScripts']) { - let goog = document.querySelector('script[src*="google"]'); - (goog) && (goog.remove()); - let goog2 = document.querySelector('#gtm_tag'); - (goog2) && (goog2.remove()); - let gonline = document.querySelector('script[src*="chat/gonline"]'); - (gonline) && (gonline.remove()); - } - - // region 存钱 不终止 - let depo_channel; - const depo_selector = {CMPY: "div#funds div.deposit", FAC: "div#armoury-donate div.cash"}; - // 公司 - if (href.includes('companies.php')) { - depo_channel = "CMPY"; - // 公司转跳存钱 - if (!href.includes('funds') && getWhSettingObj()['companyRedirect']) { - const btn = document.getElementById('ui-id-9'); - if (btn) { - btn.click(); - log('已自动打开存钱页面'); - } - } - // 收起冰蛙表格 - if (getWhSettingObj()['companyBWCollapse']) { - elementReady('#effectiveness-wrap').then(BWtable_node => { - document.body.classList.add('wh-bwtable-ctrl'); - addStyle(`.wh-bwtable-ctrl #effectiveness-wrap {display:none !important;}`); - const btn = document.createElement('button'); - btn.innerHTML = '展开冰蛙表格'; - btn.addEventListener('click', () => { - document.body.classList.toggle('wh-bwtable-ctrl'); - btn.innerText = btn.innerText === '展开冰蛙表格' ? '收起冰蛙表格' : '展开冰蛙表格'; - }); - BWtable_node.before(btn); - }); - } - // 一键存钱按钮 - addActionBtn('一键存钱', companyDeposit, $zhongNode); - } - // 帮派 - if (href.includes('factions.php')) { - depo_channel = "FAC"; - // 一键存钱按钮 - addActionBtn('一键存钱', factionDeposit, $zhongNode); - } - if (getWhSettingObj()['floatDepo'] && depo_channel) { - document.body.classList.add('wh-depo-helper'); - addStyle(`.wh-depo-helper div#funds div.deposit, -.wh-depo-helper div#armoury-donate div.cash{position: fixed !important; -top: 150px; -right: 12px; -box-shadow: 0 0 8px 1px #00000091; -background: #f2f2f2; -z-index: 999999;}`); - elementReady(depo_selector[depo_channel]).then(node => { - const close_btn = document.createElement('button'); - close_btn.addEventListener('click', () => { - document.body.classList.remove('wh-depo-helper'); - close_btn.remove(); - }); - close_btn.innerHTML = '恢复原位'; - close_btn.style.float = 'right'; - node.prepend(close_btn); - }); - } - // endregion - - // GT交易存钱 - if (location.pathname.startsWith('/trade.php')) { - // GT助手 - let node_link = null; - let handle = () => { - // 不重复加载、已关闭的交易不加载 - if (node_link !== null || location.hash.includes('logview')) return; - log('已添加GT助手'); - // 获取交易id - let query_params = location.hash.slice(1); - let traceId; - query_params.split('&') - .forEach(param => - (param.startsWith('ID=')) && (traceId = param.slice(3)) - ); - log('交易id为', traceId); - - // 获取全部的钱数 - let getTraceMoney = async () => { - if (typeof addRFC === 'function') { - let url = addRFC('/trade.php?step=getFullMoney&ID=' + traceId); - return (await ajaxFetch({url: url, method: 'GET', referrer: 'trade.php'})).text(); - } - }; - // 监听jquery ajax请求 - if (isDev()) $(document).ajaxComplete((_, xhr, settings) => log({xhr, settings})); - // react 加载完成后将节点加入视图中 - elementReady('#trade-container').then(() => - document.querySelector('#trade-container').before(node) - ); - // 构建dom节点 - let node = document.createElement('div'); - node_link = node; - let nodeTitle = document.createElement('div'); - let nodeCont = document.createElement('div'); - let inputMoney = document.createElement('input'); - let buttonDepositAll = document.createElement('button'); - let buttonWithdraw = document.createElement('button'); - let buttonWithdrawAll = document.createElement('button'); - let style = document.createElement('style'); - - inputMoney.placeholder = '定额取钱'; - inputMoney.type = 'number'; - inputMoney.style.padding = '7px'; - inputMoney.style.paddingLeft = '14px'; - inputMoney.classList.add('m-right10'); - buttonDepositAll.innerHTML = '全存'; - buttonDepositAll.style.color = 'green'; - buttonWithdraw.innerHTML = '定取'; - buttonWithdrawAll.innerHTML = '全取'; - buttonWithdrawAll.style.color = 'red'; - nodeTitle.innerHTML = 'GT助手'; - nodeTitle.classList.add('title-black', 'top-round'); - style.innerHTML = '#WHGTHelper button{cursor:pointer;}#WHGTHelper button:hover{opacity:0.5;}'; - nodeCont.append(inputMoney, buttonWithdraw, buttonDepositAll, buttonWithdrawAll); - nodeCont.classList.add('cont-gray', 'bottom-round'); - nodeCont.style.padding = '10px'; - node.id = 'WHGTHelper'; - node.classList.add('m-bottom10'); - node.append(nodeTitle, nodeCont, style); - - // 定取 - buttonWithdraw.addEventListener('click', async () => { - if ((inputMoney.value | 0) < 1) { - WHNotify('无法定额取钱,原因:输入有误'); - return; - } - let money = await getTraceMoney(); - let int = {'input': inputMoney.value | 0, 'all': money | 0}; - let diff = int.all - int.input; - if (diff < 1) { - WHNotify('无法定额取钱,原因:数不对'); - return; - } - await ajaxFetch({ - url: addRFC('/trade.php'), - method: 'POST', - referrer: 'trade.php', - body: `step=view&sub_step=addmoney2&ID=${traceId}&amount=${diff}&ajax=true`, - }); - WHNotify(`已取 ${int.input}`); - }); - // 全存 - buttonDepositAll.addEventListener('click', async () => { - let money = await getTraceMoney(); - if (money === '0') return; - await ajaxFetch({ - url: addRFC('/trade.php'), - method: 'POST', - referrer: 'trade.php', - body: `step=view&sub_step=addmoney2&ID=${traceId}&amount=${money}&ajax=true`, - }); - WHNotify(`$${money} 全部存入GT`); - }); - // 全取 - buttonWithdrawAll.addEventListener('click', async () => { - await ajaxFetch({ - url: addRFC('/trade.php'), - method: 'POST', - referrer: 'trade.php', - body: `step=view&sub_step=addmoney2&ID=${traceId}&amount=0&ajax=true`, - }); - WHNotify('已全取'); - }); - }; - if (location.hash.includes('ID=')) handle(); - addEventListener('hashchange', () => { - if (location.hash.includes('ID=')) handle(); - else { - node_link.remove(); - node_link = null; - log('已移除GT助手'); - } - }); - } - - // 飞行页面 - if (href.includes('index.php') && getSidebarData()['traveling']) { - // 飞行闹钟 - if (device === Device.PC && getWhSettingObj()['trvAlarm']) - elementReady('#countrTravel.hasCountdown').then(node => { - const logo_node = document.querySelector('#tcLogo[title]'); - let dest_cn = ''; - if (logo_node) dest_cn = { - 'Mexico': '墨西哥', 'Canada': '加拿大', 'Cayman Islands': '开曼', - 'Hawaii': '夏威夷', 'United Kingdom': '英国', 'Argentina': '阿根廷', 'Switzerland': '瑞士', - 'Japan': '日本', 'China': '中国', 'United Arab Emirates': 'UAE', 'South Africa': '南非', - }[logo_node.attributes['title'].nodeValue] || '回城'; - else dest_cn = '回城'; - const remaining_arr = node.innerText.trim().split(':'); - - const wh_trv_alarm = localStorage.getItem('wh_trv_alarm') - ? JSON.parse(localStorage.getItem('wh_trv_alarm')) - : {'enable': true, 'alert_time': 30, 'node_pos': [240, 240]}; - const save_trv_settings = () => localStorage.setItem('wh_trv_alarm', JSON.stringify(wh_trv_alarm)); - - const wh_trv_alarm_node = document.createElement('div'); - wh_trv_alarm_node.id = 'wh-trv-alarm'; - wh_trv_alarm_node.style.left = `${wh_trv_alarm.node_pos[0]}px`; - wh_trv_alarm_node.style.top = `${wh_trv_alarm.node_pos[1]}px`; - wh_trv_alarm_node.innerHTML = `

❌ 没有权限
点击网页内任意位置以激活闹钟

-
-
飞行闹钟
-
-
-
-

-

正在${dest_cn === '回城' ? dest_cn : '飞往' + dest_cn}

-
-
-
-
-
-`; - addStyle(` -#wh-trv-alarm{ -position:absolute; -width:248px; -/*left:${wh_trv_alarm.node_pos[0] || 240}px; -top:${wh_trv_alarm.node_pos[1] || 240}px;*/ -background:white; -border-radius:4px; -box-shadow:#0000001f 0 0 10px 4px; -border:solid 1px #aaa; -z-index:100001; -margin:2em; -} -#wh-trv-alarm button{ -margin:0; -} -#wh-trv-error{ -position:absolute; -width:100%; -height:100%; -/*display: table;*/ -display:none; -} -#wh-trv-error p{ -background:#ffd0d0; -color:red; -display:table-cell; -vertical-align:middle; -padding:1em; -text-align:center; -} -#wh-trv-alarm-title{ -height: 30px; -border-bottom: solid #aaa 1px; -cursor: move; -} -/*#wh-trv-alarm-move-btn span{ -background:url(/images/v2/home_main/move.svg); -width: 30px; -height: 30px; -float: right; -cursor: move; -}*/ -h5#wh-trv-alarm-header{ - height: 100%; - line-height: 30px; - padding:0 12px; - font-weight: bold; - text-align: center; -} -#wh-trv-alarm-bottom{ - padding: 12px; -} -#wh-trv-alarm-remaining{ -float:right; -color:red; -} -#wh-trv-alarm-cont input[type="number"]{ - width: 42px; - border-bottom: solid 1px #aaa; -} -.wh-trv-alarm-stop-hide{ -display:none; -} -`); - document.body.append(wh_trv_alarm_node); - // 报错dom - const error_node = wh_trv_alarm_node.querySelector('#wh-trv-error'); - // jquery拖动 - $(wh_trv_alarm_node).draggable({ - containment: "body", - distance: 5, - handle: "#wh-trv-alarm-title", - stop: () => { - wh_trv_alarm.node_pos = [parseInt(wh_trv_alarm_node.style.left), parseInt(wh_trv_alarm_node.style.top)]; - save_trv_settings(); - }, - scroll: false, - }); - // 剩余时间dom - const remaining_node = wh_trv_alarm_node.querySelector('#wh-trv-alarm-remaining'); - // 设定闹钟响的按钮 - const set_node = wh_trv_alarm_node.querySelectorAll('#wh-trv-alarm-cont button')[0]; - // 落地前响铃时长 - const cd_time = wh_trv_alarm_node.querySelector('input[type="number"]'); - let count_down_notify = {}; - set_node.onclick = () => { - try { - wh_trv_alarm.alert_time = parseInt(cd_time.value); - } catch { - wh_trv_alarm.alert_time = 30; - } - save_trv_settings(); - set_node.value = wh_trv_alarm.alert_time; - if (count_down_notify.del) count_down_notify.del(); - count_down_notify = WHNotify('设置已更新'); - }; - // 停止响铃按钮 - const stop_node = wh_trv_alarm_node.querySelectorAll('#wh-trv-alarm-cont button')[1]; - stop_node.onclick = () => { - user_stop_alert = true; - stop_node.innerText = '本次已关闭'; - stop_node.disabled = true; - } - // 开启闹钟勾选 - const enable_node = wh_trv_alarm_node.querySelector('#wh-trv-alarm-cont input[type="checkbox"]'); - let on_off_notify = {}; - enable_node.onchange = ev => { - wh_trv_alarm.enable = ev.target.checked; - save_trv_settings(); - if (on_off_notify.del) on_off_notify.del(); - on_off_notify = WHNotify(wh_trv_alarm.enable ? '闹钟已开启' : '闹钟已关闭'); - }; - // 剩余时间 秒 - const remaining_sec = parseInt(remaining_arr[0]) * 3600 + parseInt(remaining_arr[1]) * 60 + parseInt(remaining_arr[2]); - // 落地时timestamp - const land_timestamp = Date.now() + remaining_sec * 1000; - // 音频dom - const audio = document.createElement('audio'); - audio.src = 'https://www.torn.com/js/chat/sounds/Warble_1.mp3'; - audio.play() - .catch(() => { - error_node.style.display = 'table'; - const func = () => { - error_node.remove(); - document.body.removeEventListener('click', func); - }; - document.body.addEventListener('click', func); - }) - .then(() => audio.pause()); - // 是否正在响铃 - let audio_play_flag = false; - // 用户是否停止当前响铃 - let user_stop_alert = false; - // 响铃循环id - let audio_play_id = null; - // 响铃的方法 - let audio_play_handle = () => { - if (user_stop_alert) { - clearInterval(audio_play_id); - audio_play_id = null; - return; - } - if (!audio_play_flag || !wh_trv_alarm.enable) return; - audio.play().then(); - }; - // 飞机小动画字符 - const flying_arr = [ - '✈ ', - '  ✈ ', - '    ✈ ', - '      ✈ ', - '        ✈ ', - '          ✈ ', - '            ✈ ', - '              ✈ ', - '                ✈ ', - '                  ✈ ', - ]; - // 飞行的状态dom - const flying_status = wh_trv_alarm_node.querySelector('#wh-trv-status'); - // 飞机的小动画dom - const flying_ani = flying_status.nextElementSibling; - // 飞机的计数 - let flying_index = 0; - const id = window.setInterval(() => { - const remaining_time = (land_timestamp - Date.now()) / 1000 | 0; - remaining_node.innerText = `${remaining_time / 3600 | 0}时${remaining_time % 3600 / 60 | 0}分${remaining_time % 60}秒`; - - if (remaining_time < wh_trv_alarm.alert_time) { - // flying_status.innerHTML = `即将落地...`; - if (wh_trv_alarm.enable) { - // 播放提示音 - audio_play_flag = true; - if (audio_play_id === null && !user_stop_alert) audio_play_id = window.setInterval(audio_play_handle, 750); - stop_node.parentElement.classList.remove('wh-trv-alarm-stop-hide'); - } - } else { - // flying_status.innerHTML = `飞行中...`; - if (wh_trv_alarm.enable) { - clearInterval(audio_play_id); - audio_play_id = null; - stop_node.parentElement.classList.add('wh-trv-alarm-stop-hide'); - } - } - flying_ani.innerHTML = `${flying_arr[flying_index]}`; - flying_index = (flying_index + 1) % flying_arr.length; - }, 1000); - }); - // 落地转跳 - if (getWhSettingObj()['landedRedirect'] && document.querySelector('#tcLogo[title]') === null) { - window.addEventListener('beforeunload', () => { - let obj = {url: getWhSettingObj()['landedRedirect'], timestamp: Date.now()}; - sessionStorage['wh-landed-redirect'] = JSON.stringify(obj); - }); - } - } - - // 海外落地页面 - if (href.includes('index.php') && document.querySelector('#travel-home') !== null) { - // 添加回城按钮 - addActionBtn('直接回城', getHome, $zhongNode); - // 海外警告 - if (getWhSettingObj()['abroadWarning']) { - let c = 1; - setInterval(() => WHNotify(`警告:您已海外落地${c++ * 30}秒`, {timeout: 30, sysNotify: true}), 30000); - } - // 解毒提醒 - if (getSidebarData()['rehabilitation']) { - let page_title = document.querySelector('h4#skip-to-content'); - let msg = document.createElement('div'); - msg.innerHTML = ``; - msg.classList.add('info-msg-cont', 'green', 'border-round', 'm-bottom10'); - page_title.before(msg); - } - } - // 落地转跳 - else if (href.includes('index.php') && getSidebarData()['home'] && sessionStorage['wh-landed-redirect']) { - let {url, timestamp} = JSON.parse(sessionStorage['wh-landed-redirect']); - if (Date.now() - timestamp < 30000) { - sessionStorage.removeItem('wh-landed-redirect'); - location.href = url; - } - } - - // 起飞提醒 - if (href.contains(/travelagency\.php/) && getWhSettingObj()['energyAlert']) { - const $$ = $('.content-wrapper'); - const OB = new MutationObserver(() => { - OB.disconnect(); - titleTrans(); - contentTitleLinksTrans(); - trans(); - OB.observe($$.get(0), { - characterData: true, - attributes: true, - subtree: true, - childList: true - }); - }); - const trans = () => { - // 当前能量e - const energyBarStr = $('#barEnergy p[class^="bar-value__"]').text().trim(); - const [curE, maxE] = energyBarStr.split('/').length === 2 - ? [parseInt(energyBarStr.split('/')[0]), parseInt(energyBarStr.split('/')[1])] - : [NaN, NaN]; - const incTime = maxE === 150 ? 10 : 15; - const fullEnergyTime = !(isNaN(curE) || isNaN(maxE)) ? (maxE - 5 - curE) / 5 * incTime - + (incTime - new Date().getMinutes() % incTime) : NaN; - // 起飞前提示 - $('.travel-confirm .travel-question .q-wrap span:nth-of-type(2)').each((i, e) => { - if (isNaN(fullEnergyTime)) return; - const spl = e.innerText.trim().split(' '); - const [hours, minutes] = spl.length === 5 - ? [parseInt(spl[0]), parseInt(spl[3])] - : [0, parseInt(spl[0])]; - if (fullEnergyTime < (hours * 60 + minutes) * 2) { - if (!$(e).parent().hasClass('wh-translated')) { - $(e).parent() - .prepend(`
警告:该次飞行往返时间大于体力回复时间,将会爆体!
`) - .addClass('wh-translated'); - } - } - }); - }; - trans(); - OB.observe($$.get(0), { - characterData: true, - attributes: true, - subtree: true, - childList: true - }); - } - - // 一键起飞 - if (sessionStorage['wh-quick-fly'] && href.includes('travelagency.php')) { - doQuickFly(); - } - - // 攻击页面 - if (href.contains(/loader\.php\?sid=attack/)) { - let stop_reload = false; - const {quickAttIndex, quickFinishAtt, attReload} = getWhSettingObj(); - - // 光速刷新按钮 - addActionBtn('光速刷新', doAttackReload, $zhongNode); - // 自刷新 - let audio_played_flag; - if (attReload !== 6 && stop_reload !== true) { - const selector_device_map = { - 'pc': '#defender div[class^="modal___"]', - 'mobile': '#attacker div[class^="modal___"]', - 'tablet': '', - }; - const selector = selector_device_map[device]; - elementReady(selector).then(elem => { - if (!elem.querySelector('button')) { - if (getWhSettingObj().attReload === 0 && stop_reload !== true) { - // window.location.reload(); - doAttackReload(); - } else { - let reload_flag; - const timeout = getWhSettingObj().attReload * 1000 + getRandomInt(-500, 500); - log(`[WH] ${timeout / 1000}s 后自动刷新`); - window.setInterval(() => { - if (reload_flag === undefined) { - reload_flag = true; - } else if (stop_reload !== true) { - // window.location.reload(); - doAttackReload(); - } - }, timeout); - } - } else if (audio_played_flag === undefined) { - audio_played_flag = true; - let play_time = 0; - const audio_play_id = window.setInterval(() => { - const $audio = document.createElement('audio'); - $audio.src = 'https://www.torn.com/js/chat/sounds/Warble_1.mp3'; - $audio.play().then(); - play_time++; - if (play_time === 3) clearInterval(audio_play_id); - }, 600); - } - }); - } - // 光速拔刀 - if (quickAttIndex !== 6) { - // const selectedId = ['weapon_main', 'weapon_second', 'weapon_melee', 'weapon_temp', 'weapon_fists', 'weapon_boots'] - // [getWhSettingObj().quickAttIndex]; - const btn = await elementReady('div[class^="modal___"] button');//.then(btn => { - log(btn) - if (!btn.innerText.toLowerCase().includes('fight')) return; - // 判断是否存在脚踢 - const hasKick = !!document.querySelector('#weapon_boots'); - // modal层 - const modal = document.querySelector('div[class^="modal___"]'); - log(`当前设备类型是${device}`); - // 区分设备 - switch (device) { - case Device.PC: { - log(`开始调整按钮位置`); - // 隐藏modal层 - modal.style.display = 'none'; - // 根据选择的武器调整css - let css_top = '0'; - switch (getWhSettingObj()['quickAttIndex']) { - case 1: { // weapon_second - css_top = '97px'; - break; - } - case 2: { // weapon_melee - css_top = '194px'; - break; - } - case 3: { // weapon_temp - css_top = '291px'; - break; - } - case 4: // weapon_fists - case 5: { // weapon_boots - css_top = '375px'; - break; - } - } - const css_rule = ` -.wh-move-btn #defender div[class^="modal___"]{display: block;width: 0 !important;top: ${css_top};left: -169px !important;} -.wh-move-btn #defender div[class^="dialog___"]{border:0;width:159px;height:96px;} -.wh-move-btn #defender div[class^="colored___"]{display:block;padding:0;} -.wh-move-btn #defender div[class^="title___"]{height:0;} -.wh-move-btn #defender button{width: 100%;margin:17px 0;height: 60px;} -`; - addStyle(css_rule); - document.body.classList.add('wh-move-btn'); - // 绑定点击事件 联动【光速跑路】 - btn.onclick = () => { - if (quickFinishAtt !== 3) { - btn.remove(); - // 停止自动刷新 - stop_reload = true; - } else { - document.body.classList.remove('wh-move-btn'); - } - }; - break; - } - case Device.MOBILE: { - log(`开始调整按钮位置`); - // 加入css - let css_top = '0'; - let slot_height = '76px'; - // 判断有没有脚踢 - if (hasKick) { - // 根据选择的武器调整 - switch (getWhSettingObj()['quickAttIndex']) { - case 1: { // weapon_second - css_top = '76px'; - break; - } - case 2: { // weapon_melee - css_top = '152px'; - break; - } - case 3: { // weapon_temp - css_top = '228px'; - break; - } - case 4: { // weapon_fists - css_top = '304px'; - break; - } - case 5: { // weapon_boots - css_top = '380px'; - break; - } - } - } else { - const slot = document.querySelector('#weapon_main'); - const height = slot.offsetHeight + 1; - slot_height = height; - // 根据选择的武器调整 - switch (getWhSettingObj().quickAttIndex) { - case 1: { // weapon_second - css_top = `${height}px`; - break; - } - case 2: { // weapon_melee - css_top = `${height * 2}px`; - break; - } - case 3: { // weapon_temp - css_top = `${height * 3}px`; - break; - } - case 4: { // weapon_fists - css_top = `${height * 4}px`; - break; - } - case 5: { // weapon_boots - css_top = `${height * 5}px`; - break; - } - } - } - const css_rule = ` -.wh-move-btn #attacker div[class^="modal___"]{display: block;width: 0;top: ${css_top};left:0;height:0;} -.wh-move-btn #attacker div[class^="dialog___"]{border:0;width:80px;height:${slot_height};} -.wh-move-btn #attacker div[class^="colored___"]{display:block;padding:0;} -.wh-move-btn #attacker div[class^="title___"]{height:0;} -.wh-move-btn #attacker button{width:100%;margin:0;height:63px;white-space:normal;} -`; - addStyle(css_rule); - document.body.classList.toggle('wh-move-btn'); - btn.onclick = () => { - if (getWhSettingObj().quickFinishAtt !== 3) { - btn.remove(); - // 停止自动刷新 - stop_reload = true; - } else { - document.body.classList.toggle('wh-move-btn'); - } - }; - break; - } - case Device.TABLET: { - break; - } - } - // 自动开打 - if (getWhSettingObj()['autoStartFinish'] === true) { - if (btn.innerText.includes('(')) { - let interval_id = window.setInterval(() => { - if (!btn) { - clearInterval(interval_id); - return; - } - try { - btn.click(); - } catch { - } - }, 100); - } else { - btn.click(); - } - } - } - // 光速跑路 - if (quickFinishAtt !== 3) { - const user_btn_select = ['leave', 'mug', 'hosp'][getWhSettingObj()['quickFinishAtt']]; - const wrap = document.querySelector('#react-root'); - log('光速跑路选项选中:', user_btn_select); - new MutationObserver(() => { - const btn_arr = document.querySelectorAll('div[class^="dialogButtons___"] button'); - if (btn_arr.length > 1) btn_arr.forEach(btn => { - const flag = btn.innerText.toLowerCase().includes(user_btn_select); - log('按钮内容:', btn.innerText, ',是否包含选中:', flag); - if (!flag) btn.style.display = 'none'; - // 自动结束 - else if (getWhSettingObj()['autoStartFinish'] === true) { - try { - btn.click(); - } catch { - } - } - }); - }).observe(wrap, {subtree: true, attributes: true, childList: true}); - } - return; - } - - // 错误的攻击页面 - if (getWhSettingObj()['attRelocate'] && href.includes('loader2.php')) { - const spl = window.location.href.trim().split('='); - const uid = spl[spl.length - 1]; - if (!/^\d+$/.test(uid)) return; - window.location.href = `https://www.torn.com/loader.php?sid=attack&user2ID=${uid}`; - return; - } // 捡垃圾助手 if (getWhSettingObj()['cityFinder'] && href.includes('city.php')) { @@ -922,7 +92,7 @@ display:inline-block; const finder_item = document.createElement('span'); finder_item.id = 'wh-city-finder-item' + item_id; finder_item.innerHTML = item_id; - founds.push({'id': item_id, 'node': finder_item, 'map_item': node}); + founds.push({ 'id': item_id, 'node': finder_item, 'map_item': node }); container.append(finder_item); }); // 未发现物品 返回 @@ -937,7 +107,7 @@ display:inline-block; let total = 0; founds.forEach(el => { const value = items[el.id]['price']; - el.node.innerHTML = `${items[el.id]['name']} ($${toThousands(value)})`; + el.node.innerHTML = `${ items[el.id]['name'] } ($${ toThousands(value) })`; // 灰色 100k以下 if (value < 100000) el.node.style.backgroundColor = '#9e9e9e'; // 绿色 1m以下 @@ -950,7 +120,7 @@ display:inline-block; else if (value >= 500000000) el.node.style.backgroundColor = '#f44336'; total += items[el.id]['price']; }); - header.innerHTML = `捡垃圾助手 - ${founds.length} 个物品,总价值 $${toThousands(total)}`; + header.innerHTML = `捡垃圾助手 - ${ founds.length } 个物品,总价值 $${ toThousands(total) }`; }; // 未取到数据时添加循环来调用函数 if (items === null) { @@ -1001,14 +171,14 @@ display:inline-block; 'LI' === e.tagName && rmv_cfm(e) } } - }).observe(points_sales, {childList: true}); + }).observe(points_sales, { childList: true }); } // 叠e助手 if (href.includes('gym.php')) { let cont = null; const switch_node = document.createElement('div'); - switch_node.innerHTML = ``; + switch_node.innerHTML = ``; switch_node.id = 'wh-gym-info-cont'; switch_node.querySelector('input').onchange = e => { cont.classList.toggle('wh-display-none'); @@ -1114,8 +284,8 @@ $1,000 }); // 监听啤酒购买 $(document).ajaxComplete((_, xhr, settings) => { - log({xhr, settings}); - let {data} = settings, {responseText} = xhr; + log({ xhr, settings }); + let { data } = settings, { responseText } = xhr; let response = JSON.parse(responseText); if (data.includes('step=buyShopItem') && data.includes('ID=180') && response['success']) { WHNotify('已检测成功购买啤酒') @@ -1242,7 +412,7 @@ $1,000 // 助手注入 $('div.max-height-fix.info').each((i, e) => { if ($(e).find('.wh-translated').length !== 0) return; - $(e).append(`
任务助手

${getTaskHint(taskList[i])}

`); + $(e).append(`
任务助手

${ getTaskHint(taskList[i]) }

`); }); // 任务目标 $('ul.tasks-list span.title-wrap').contents().each((i, e) => { @@ -1265,7 +435,7 @@ $1,000 // 圣诞小镇 if (href.contains(/christmas_town\.php/)) { let $root = document.querySelector('#christmastownroot'); - const {xmasTownWT, xmasTownNotify} = getWhSettingObj() + const { xmasTownWT, xmasTownNotify } = getWhSettingObj() // 解密攻略 if (xmasTownWT) { const insert_html = `
@@ -1302,7 +472,7 @@ margin: 0 0 3px; } `; const wt_dict = { - "None": {title: '', wt: ``,}, + "None": { title: '', wt: ``, }, "Christmas Town": { title: '圣诞小镇', wt: `
  • 旧攻略提到的驯鹿车已被移除,只能手动找一条蓝色的小路[94,3]
  • @@ -1564,23 +734,23 @@ margin: 0 0 3px; const $wt_content = jquery$wh_container.find('#wt-content'); jquery$wh_container.find('select').change(e => { const selected = e.target.value; - $wt_content.html(`

    ${wt_dict[selected].title}

    ${wt_dict[selected].wt}

    `) + $wt_content.html(`

    ${ wt_dict[selected].title }

    ${ wt_dict[selected].wt }

    `) }); } }); } // 宝箱检测 if (xmasTownNotify) { - const chestTypeDict = {'1': '金', '2': '银', '3': '铜',}; - const chestTypeColorDict = {'1': 'gold', '2': 'silver', '3': 'sandybrown',}; - const lootTypeDict = {'chests': '钥匙箱', 'gifts': '礼物', 'combinationChest': '密码箱', 'keys': '钥匙',}; - const keyTypeDict = {'b': '铜', 's': '银', 'g': '金',}; + const chestTypeDict = { '1': '金', '2': '银', '3': '铜', }; + const chestTypeColorDict = { '1': 'gold', '2': 'silver', '3': 'sandybrown', }; + const lootTypeDict = { 'chests': '钥匙箱', 'gifts': '礼物', 'combinationChest': '密码箱', 'keys': '钥匙', }; + const keyTypeDict = { 'b': '铜', 's': '银', 'g': '金', }; let dropHist = localStorage.getItem('wh-loot-store') ? JSON.parse(localStorage.getItem('wh-loot-store')) : {}; const alertSettings = localStorage.getItem('wh-loot-setting') ? JSON.parse(localStorage.getItem('wh-loot-setting')) - : {blink: 'y', sound: 'y', chest: 'y'}; + : { blink: 'y', sound: 'y', chest: 'y' }; let $ct_wrap; let soundLoopFlag = false; const getDOMOb = new MutationObserver(() => { @@ -1597,9 +767,9 @@ margin: 0 0 3px;
-
-
-
+
+
+

- 长时间不清空会出现奇怪的问题

@@ -1691,7 +861,7 @@ margin: 0 0 3px; const soundIntervalID = window.setInterval(() => { if (soundLoopFlag) $audio.play().then(); }, 1200); - ob.observe($root, {childList: true, subtree: true}); + ob.observe($root, { childList: true, subtree: true }); } }); const ob = new MutationObserver(() => { @@ -1700,13 +870,13 @@ margin: 0 0 3px; $root = document.querySelector('#christmastownroot'); $ct_wrap = $root.querySelector('#ct-wrap'); if (!$ct_wrap) { - ob.observe($root, {childList: true, subtree: true}); + ob.observe($root, { childList: true, subtree: true }); return; } const $ct_title = $ct_wrap.querySelector('.status-title'); const $pos = $ct_wrap.querySelector('.map-title span[class^="position___"]') || $ct_wrap.querySelector('.status-title span[class^="position___"]'); if (!$pos) { - ob.observe($root, {childList: true, subtree: true}); + ob.observe($root, { childList: true, subtree: true }); return; } const $pos_spl = $pos.innerText.trim().split(','); @@ -1716,7 +886,7 @@ margin: 0 0 3px; const $wh_loot_container = $root.querySelector('#wh-loot-container'); if (!$wh_loot_container) { console.error('掉落助手未找到DOM容器'); - ob.observe($root, {childList: true, subtree: true}); + ob.observe($root, { childList: true, subtree: true }); return; } const $blink = $wh_loot_container.querySelector('#wh-loot-setting-blink'); @@ -1727,7 +897,7 @@ margin: 0 0 3px; const items = $root.querySelectorAll('div.grid-layer div.items-layer div.ct-item'); // 附近的所有物品 items.forEach(el => { - const item_props = {x: 0, y: 0, name: '', type: '', url: '',}; + const item_props = { x: 0, y: 0, name: '', type: '', url: '', }; item_props.x = parseInt(el.style.left.replaceAll('px', '')) / 30; item_props.y = -parseInt(el.style.top.replaceAll('px', '')) / 30; item_props.url = el.firstElementChild.src; @@ -1755,15 +925,15 @@ margin: 0 0 3px; if (nearby_item.name === 'chests') { chest_count++; item_name = chestTypeDict[nearby_item.type] + lootTypeDict[nearby_item.name]; - $wh_loot_container_chests.innerHTML += `${path}[${nearby_item.x},${nearby_item.y}] ${item_name}` + $wh_loot_container_chests.innerHTML += `${ path }[${ nearby_item.x },${ nearby_item.y }] ${ item_name }` } else { item_count++; item_name = (nearby_item.name === 'keys' ? keyTypeDict[nearby_item.type] || '' : '') + lootTypeDict[nearby_item.name] || nearby_item.name; - $wh_loot_container_items.innerHTML += `${path}[${nearby_item.x},${nearby_item.y}] ${item_name}` + $wh_loot_container_items.innerHTML += `${ path }[${ nearby_item.x },${ nearby_item.y }] ${ item_name }` } // 确认地图坐标存在 if ($ct_title) { - const hist_key = `[${nearby_item.x},${nearby_item.y}]"${$ct_title.firstChild.nodeValue.trim()}"${item_name}`; + const hist_key = `[${ nearby_item.x },${ nearby_item.y }]"${ $ct_title.firstChild.nodeValue.trim() }"${ item_name }`; const el = dropHist[hist_key]; if (el) { if (path === '=' && (nearby_item.name === 'keys' || nearby_item.name === 'gifts')) { @@ -1773,9 +943,9 @@ margin: 0 0 3px; if (!(nearby_item.name === 'chests' && $chest.checked)) { const now = new Date(); dropHist[hist_key] = { - pos: `[${nearby_item.x},${nearby_item.y}]`, + pos: `[${ nearby_item.x },${ nearby_item.y }]`, map: $ct_title.firstChild.nodeValue.trim(), - last: `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()} ${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}`, + last: `${ now.getFullYear() }-${ now.getMonth() + 1 }-${ now.getDate() } ${ now.getHours() }:${ now.getMinutes() }:${ now.getSeconds() }`, name: item_name, id: Object.keys(dropHist).length, }; @@ -1783,7 +953,7 @@ margin: 0 0 3px; } } }); - $wh_loot_container.querySelector('#wh-loot-item-count').innerText = `(${item_count})`; + $wh_loot_container.querySelector('#wh-loot-item-count').innerText = `(${ item_count })`; if (item_count === 0) { $wh_loot_container_items.innerText = '暂无'; $wh_loot_container.querySelector('#wh-loot-container-main').style.animation = ''; @@ -1792,18 +962,18 @@ margin: 0 0 3px; if ($blink.checked) $wh_loot_container.querySelector('#wh-loot-container-main').style.animation = 'lootFoundAlert 2s infinite'; if ($sound.checked) soundLoopFlag = true; } - $wh_loot_container.querySelector('#wh-loot-chest-count').innerText = `(${chest_count})`; + $wh_loot_container.querySelector('#wh-loot-chest-count').innerText = `(${ chest_count })`; if (chest_count === 0) $wh_loot_container_chests.innerText = '暂无'; const history = Object.keys(dropHist).map(key => dropHist[key]).sort((a, b) => a.id - b.id); let table_html = ''; history.forEach(e => { - table_html += `
`; + table_html += ``; }); $tbody.innerHTML = table_html; localStorage.setItem('wh-loot-store', JSON.stringify(dropHist)); - ob.observe($root, {childList: true, subtree: true}); + ob.observe($root, { childList: true, subtree: true }); }); - getDOMOb.observe($root, {childList: true, subtree: true}); + getDOMOb.observe($root, { childList: true, subtree: true }); } } @@ -1870,11 +1040,6 @@ margin: 0 0 3px; await rw_raider(); } - // 任何位置公司一键存钱 - if (getWhSettingObj()['companyDepositAnywhere']) { - addActionBtn('公司存钱', companyDepositAnywhere, $zhongNode); - } - if (getPlayerInfo()['userID'] === 2687093 && getDeviceType() === Device.PC) { await getSidebarData(); let item = document.getElementById('nav-items'); @@ -1890,864 +1055,6 @@ margin: 0 0 3px; } } - // 通知翻译 - function eventsTrans(events = $('span.mail-link')) { - // if (!wh_trans_settings.transEnable) return; - const index = window.location.href.indexOf('events.php#/step=received') >= 0 ? 1 : 0; - const isReceived = index === 1; - // 通知的类型选择栏 - $('ul.mailbox-action-wrapper a').contents().each((i, e) => { - if (e.nodeValue) - if (eventsDict[e.nodeValue.trim()]) - e.nodeValue = eventsDict[e.nodeValue.trim()]; - }); - - // 桌面版右边按钮浮动提示消息 - $('div.mailbox-container i[title]').each((i, e) => { - if (eventsDict[$(e).attr('title')]) { - $(e).attr('title', eventsDict[$(e).attr('title')]); - } - }); - - // 手机版底部按钮 - $('.mobile-mail-actions-wrapper div:nth-child(2)').each((i, e) => { - if (eventsDict[$(e).text().trim()]) - $(e).text(eventsDict[$(e).text().trim()]); - }); - - // 黑框标题 - $('#events-main-wrapper .title-black').each((i, e) => { - if (eventsDict[$(e).text().trim()]) { - $(e).text(eventsDict[$(e).text().trim()]); - } - }); - - // 发送的两个按钮 + user id - $('#events-main-wrapper div.send-to a.btn').each((i, e) => { - if (eventsDict[$(e).text().trim()]) { - $(e).text(eventsDict[$(e).text().trim()]); - } - }); - $('#events-main-wrapper div.send-to span.cancel a').each((i, e) => { - if (eventsDict[$(e).text().trim()]) { - $(e).text(eventsDict[$(e).text().trim()]); - } - }); - $('#events-main-wrapper div.send-to span.name').each((i, e) => { - if (eventsDict[$(e).text().trim()]) { - $(e).text(eventsDict[$(e).text().trim()]); - } - }); - - // 通知翻译的开关 - if (!$('div#event-trans-msg').get(0) && !window.location.href.contains(/index\.php/)) { - // msgBox(`
插件暂时不能翻译全部通知。
- // 如发现问题请发送通知并联系 Woohoo[2687093]
- // 可能会出现卡顿,默认开启
`); - $('input#eventTransCheck').attr('checked', localStorage.getItem('wh_trans_event') === 'true'); - $('input#eventTransCheck').change(function () { - if ($(this).attr('checked') === undefined) { - localStorage.setItem('wh_trans_event', 'false'); - } else { - localStorage.setItem('wh_trans_event', 'true'); - } - eventsTrans(); - }); - } - - if (localStorage.getItem('wh_trans_event') === 'false') return; - if (events.length === 0) return; - events.each((i, e) => { - // todo “收到的信息” 暂时删除发送人节点 不影响显示 - if (isReceived) { - $(e).children('a.sender-name').remove(); - } - - if (eventsDict[$(e).text().trim()]) { - $(e).text(eventsDict[$(e).text().trim()]); - return; - } - - /** - * 赛车 - * You finished 5th in the Hammerhead race. Your best lap was 01:14.87. - * You finished 1st in the Docks race. Your best lap was 04:01.33. - * You finished 1st in the Hammerhead race and have received 3 racing points! Your best lap was 01:06.92. - * You finished 4th in the Docks race. Your best lap was 03:29.27 beating your previous best lap record of 03:35.77 by 00:06.50. - * You have crashed your Honda NSX on the Sewage race! The upgrades Paddle Shift Gearbox (Short Ratio) and Carbon Fiber Roof were lost. - * You have crashed your Ford Mustang on the Docks race! Your car has been recovered. - */ - if ($(e).text().indexOf('finished') >= 0) { - - if ($(e).text().indexOf('crashed') >= 0) return; // todo 撞车 - - const isGainRacingPoint = $(e).text().indexOf('racing point'); - let racingPoint = isGainRacingPoint >= 0 ? $(e).text()[isGainRacingPoint - 2] : null; - - const isBeat = $(e).text().indexOf('beating') >= 0; - let record, bestBy; - if (isBeat) { - record = $(e).text().split('record of ')[1].split(' by ')[0]; - bestBy = $(e).text().split('record of ')[1].split(' by ')[1].split('. ')[0]; - } - - const pos = e.childNodes[1].firstChild.nodeValue.match(/[0-9]+/)[0]; - - const splitList = e.childNodes[2].nodeValue.split(' '); - const bestLap = e.childNodes[2].nodeValue.split(' best lap was ')[1].slice(0, 8);//.split(' ')[0]; - - let map = splitList[3]; - map = map === 'Two' ? 'Two Islands' : map; - map = map === 'Stone' ? 'Stone Park' : map; - - e.firstChild.nodeValue = '你在赛车比赛 ' + map + ' 中获得第 '; - e.childNodes[1].firstChild.nodeValue = pos; - e.childNodes[2].nodeValue = ' 名,'; - if (isGainRacingPoint >= 0) { - e.childNodes[2].nodeValue += '获得' + racingPoint + '赛车点数 (Racing Points)。'; - } - - e.childNodes[2].nodeValue += '你的最佳圈速是 ' + bestLap; - if (isBeat) e.childNodes[2].nodeValue += ',比之前最佳 ' + record + ' 快 ' + bestBy; - e.childNodes[2].nodeValue += '。' - - - e.childNodes[2].nodeValue += '['; - e.childNodes[3].firstChild.nodeValue = '查看'; - return; - } - - /** - * 还贷 - */ - if ($(e).text().contains(/You have been charged \$[0-9,]+ for your loan/)) { - const node1Value = e.firstChild.nodeValue; // You have been charged $29,000 for your loan. You can pay this by visiting the - //e.childNodes[1].firstChild.nodeValue; // Loan Shark - // const node3Value=e.childNodes[2].nodeValue; 内容是 ". " - - let charge = node1Value.split(' ')[4]; - let replace; - replace = '你需要支付 '; - replace += charge; - replace += ' 贷款利息,点此支付:'; - - e.firstChild.nodeValue = replace; - e.childNodes[1].firstChild.nodeValue = '鲨客借贷'; - e.childNodes[2].nodeValue = '。'; - return; - } - - /** - * 收到钱物 - * You were sent $21,000,000 from - * JNZR - * . - * 附带信息: with the message: Manuscript fee OCT - * e.firstChild.nodeValue - * e.childNodes[1].firstChild.nodeValue - * e.childNodes[2].nodeValue - * - * You were sent 4x Xanax from RaichuQ with the message: Manuscript fee OCT - * You were sent $21,000,000 from JNZR. - * You were sent some Xanax from runningowl - * You were sent 1x Present from Duke with the message: Is it your birthday? - * You were sent Duke's Safe from DUKE - * You were sent a Diamond Bladed Knife from charapower - */ - if ($(e).text().contains(/You were sent .+ from/)) { - // 数量 物品 信息 - // spl = [You were sent 1x Birthday Present from] - const spl = $(e).contents().get(0).nodeValue.trim().split(' '); - const msgSpl = $(e).text().trim().split('with the message: '); - const num = /^\$[0-9,]+\b/.test(spl[3]) ? '' : spl[3].numWordTrans(); - const item = num === '' ? spl[3] : spl.slice(4, -1).join(' '); - const msg = msgSpl[1] ? msgSpl[1] : null; - e.childNodes[0].nodeValue = `你收到了 ${num} ${item},来自 `; - if (e.childNodes[2]) { - e.childNodes[2].nodeValue = `。`; - } - if (msg) { - e.childNodes[2].nodeValue = `,附带信息:${msg}。`; - } - return; - } - - /** - * bazaar - * Dewei3 bought 2 x Toyota MR2 from your bazaar for $56,590. - * ['', 'bought', '2', 'x', 'Toyota', 'MR2', 'from', 'your', 'bazaar', 'for', '$56,590.\n'] - * e.childNodes[1].nodeValue - */ - if ($(e).text().contains(/bought .+ from your bazaar for/)) { - const bazEN = e.childNodes[1].nodeValue; - const spl = bazEN.split(' '); - - const num = spl[2]; - const item = spl.slice(4, spl.indexOf('from')).join(' '); - const money = spl[spl.length - 1].replace('.', ''); - - e.childNodes[1].nodeValue = ' 花费 ' + money + ' 从你的店铺购买了 ' + num + ' 个 ' + ' ' + item + '。'; - return; - } - - /** - * 交易 - */ - if ($(e).text().indexOf('trade') >= 0) { - const PCHC = '点此继续'; - if ($(e).text().indexOf('You must now accept') >= 0) { - /** - * 接受交易 - * JNZR - * has accepted the trade titled "g't". You must now accept to finalize it. - * Please click here to continue. - * JNZR已经接受了名为 "g't "的交易。你现在必须接受以完成它。 - */ - const firstWords = e.childNodes[1].nodeValue.split('. You must')[0]; - const tradeName = firstWords.slice(31, firstWords.length); - e.childNodes[1].nodeValue = ' 已经接受了名为 ' + tradeName + ' 的交易。你现在必须接受以完成它。'; - e.childNodes[2].firstChild.nodeValue = PCHC; - return; - } - if ($(e).text().indexOf('expired') >= 0) { - /** - * 交易过期 - * The trade with - * sabrina_devil - * has expired - * 与sabrina_devil的交易已经过期。 - */ - e.firstChild.nodeValue = '与 '; - e.childNodes[2].nodeValue = ' 的交易已过期。'; - return; - } - if ($(e).text().indexOf('initiated') >= 0) { - /** - * 交易发起 - * sabrina_devil - * has initiated a trade titled "gt". - * Please click here to continue. - * sabrina_devil发起了一项名为 "gt "的交易。 - */ - const node2 = e.childNodes[1].nodeValue; - const tradeName = node2.slice(30, node2.length - 2); - e.childNodes[1].nodeValue = ' 发起了标题为 ' + tradeName + ' 的交易。'; - e.childNodes[2].firstChild.nodeValue = PCHC; - return; - } - if ($(e).text().indexOf('now complete') >= 0) { - /** - * 交易完成 - * Tmipimlie - * has accepted the trade. The trade is now complete. - * Tmipimlie已经接受交易。现在交易已经完成。 - */ - e.childNodes[1].nodeValue = ' 已经接受交易。该交易现已完成。'; - return; - } - if ($(e).text().indexOf('canceled') >= 0) { - /** - * 交易完成 - * WOW - * has canceled the trade. - * WOW已经取消了这项交易。 - */ - e.childNodes[1].nodeValue = ' 已经取消了这个交易。'; - return; - } - if ($(e).text().indexOf('commented') >= 0) { - /** - * 交易评论 - * QIJI - * commented on your - * pending trade - * : "Thank you for trading with me! The total is $19,461,755 and you can view your receipt here: https://www.tornexchange.com/receipt/mhWuuL7hrE" - */ - e.childNodes[1].nodeValue = ' 对'; - e.childNodes[2].firstChild.nodeValue = '进行中的交易'; - e.childNodes[3].nodeValue = '添加了一条评论' + e.childNodes[3].nodeValue; - return; - } - return; - } - - /** - * 被mug - */ - if ($(e).text().indexOf('mugged') >= 0) { - const spl = $(e).text().trim().split(' '); - if (spl.length > 7) return; // todo 多人运动暂时跳过 - const money = spl[spl.length - 2]; - if (spl[0] === 'Someone') { // 被匿名mug - e.firstChild.nodeValue = '有人打劫你并抢走了 ' + money + ' ['; - e.childNodes[1].firstChild.nodeValue = '查看'; - } else { - e.childNodes[1].nodeValue = ' 打劫你并抢走了 ' + money + ' ['; - e.childNodes[2].firstChild.nodeValue = '查看'; - } - return; - } - - /** - * 被打 - */ - if ($(e).text().indexOf('attacked') >= 0) { // 被打 - /** - * 攻击方式 词数=spl.length - * 匿名 4 Someone attacked you [view] - * - hosp 6 Someone attacked and hospitalized you [view] - * -- 有人袭击了你并安排你住院 - * 实名 4 EternalSoulFire attacked you [view] - * - lost 6 EternalSoulFire attacked you but lost [view] - * - hosp 6 - * - 逃跑esc 6 Dr_Bugsy_Siegel attacked you but escaped [view] - * - 25回合平手stale 6 Tharizdun attacked you but stalemated [view] - * - 起飞或bug 6 Mrew tried to attack you [view] - * - * You attacked Cherreh but timed out [view] - * - * 多人运动 todo - * 10 Pual (and 2 others) attached you and hospitalized you [view] - * 9 Argozdoc attacked you but Norm fought him off [view] - */ - const spl = $(e).text().trim().split(' '); - - if (spl.length > 6) { // 多人运动暂时跳过 - /** - * 超时自动失败 - */ - if (spl[4] === 'timed') { - if (e.firstChild.firstChild) { // 由第一个节点是否有子节点判断 被攻击 - e.childNodes[1].nodeValue = ' 袭击你但是超时了 ['; - e.childNodes[2].firstChild.nodeValue = '查看'; - return; - } - e.firstChild.nodeValue = '你袭击 '; - e.childNodes[2].nodeValue = ' 但是超时了 ['; - e.childNodes[3].firstChild.nodeValue = '查看'; - return; - } - return; - } - - if ($(e).find('a').text().toLowerCase().indexOf('someone') < 0 && // 避免玩家名带有someone字样 - $(e).text().split(' ')[0].toLowerCase() === 'someone') { // 被匿名 - if (spl.length === 6 && spl[3] === 'hospitalized') { // 匿名hos - e.firstChild.nodeValue = '有人袭击你并将你强制住院 ['; - e.childNodes[1].firstChild.nodeValue = '查看'; - return; - } - e.firstChild.nodeValue = '有人袭击了你 ['; - e.childNodes[1].firstChild.nodeValue = '查看'; - return; - } - - if (spl.length === 4) { // 实名leave - e.childNodes[1].nodeValue = ' 袭击了你 ['; - e.childNodes[2].firstChild.nodeValue = '查看'; - return; - } - - if (spl.length === 6) { // 实名的情况 - switch (spl[4]) { - case 'lost': - e.childNodes[1].nodeValue = ' 袭击你但输了 ['; - e.childNodes[2].firstChild.nodeValue = '查看'; - return; - case 'escaped': - e.childNodes[1].nodeValue = ' 袭击你但逃跑了 ['; - e.childNodes[2].firstChild.nodeValue = '查看'; - return; - case 'stalemated': - e.childNodes[1].nodeValue = ' 袭击你但打成了平手 ['; - e.childNodes[2].firstChild.nodeValue = '查看'; - return; - } - switch (spl[3]) { - case 'attack': // Mrew tried to attack you [view] - e.childNodes[1].nodeValue = ' 尝试袭击你 ['; - e.childNodes[2].firstChild.nodeValue = '查看'; - return; - case 'hospitalized': - e.childNodes[1].nodeValue = ' 袭击你并将你强制住院 ['; - e.childNodes[2].firstChild.nodeValue = '查看'; - return; - } - } - - } - - /** - * 每日彩票 - * 有人在Lucky Shot彩票中赢得11,832,100,000美元! - * zstorm won $5,574,200 in the Daily Dime lottery! - */ - if ($(e).text().indexOf('lottery') >= 0) { - const split = e.childNodes[1].nodeValue.split(' '); - const type = split[split.length - 3] + ' ' + split[split.length - 2]; - const money = split[2]; - e.childNodes[1].nodeValue = ' 在 ' + type + ' 彩票中赢得了 ' + money + '!'; - return; - } - - /** - * 公司职位变更 - */ - if ($(e).text().contains(/, the director of .+, has/)) { - $(e).contents().each((i, e) => { - if (e.nodeType === 3) { - if (eventsDict[e.nodeValue.trim()]) { - e.nodeValue = eventsDict[e.nodeValue.trim()]; - } else { - // 工资改变 - if (e.nodeValue.contains(/wage/)) { - const money = e.nodeValue.trim().slice(27, -9); - e.nodeValue = ` 的老板) 将你的每日工资改为 ${money}。`; - return; - } - // 职位改变 - if (e.nodeValue.contains(/rank/)) { - const pos = e.nodeValue.trim().slice(27, -1); - e.nodeValue = ` 的老板) 将你的公司职位改为 ${pos}。`; - return; - } - if (e.nodeValue.contains(/assigned/)) { - e.nodeValue = ` 的老板) 将你指派为新的公司老板。`; - return; - } - // 火车 - if (e.nodeValue.contains(/trained/)) { - const spl = e.nodeValue.trim().split(' '); - const pri = spl[10]; - const sec = spl[13].slice(0, -1); - e.nodeValue = ` 的老板) 从公司训练了你。你获得了 50 ${eventsDict[pri]} 和 25 ${eventsDict[sec]}。`; - } - } - } - }); - return; - } - - /** - * 悬赏已被领取 - */ - if ($(e).text().contains(/bounty reward/)) { - $(e).contents().each((i, e) => { - if (e.nodeType === 3) { - if (eventsDict[e.nodeValue.trim()]) { - e.nodeValue = ` ${eventsDict[e.nodeValue.trim()]} `; - } else { - if (e.nodeValue.contains(/bounty reward/)) { - const bountyAmount = e.nodeValue.trim().split(' ')[3]; - if (eventsDict['and earned your'] && eventsDict['bounty reward']) { - e.nodeValue = ` ${eventsDict['and earned your']} ${bountyAmount} ${eventsDict['bounty reward']}`; - } - } - } - } - }); - return; - } - - /** - * oc开启 - * You have been selected by - * endlessway - * to participate in an organized crime. You, along with 2 others will make up the team to - * make a bomb threat - * in 72 hours. - * - * 你被endlessway选中参与一项有组织的犯罪活动。你和另外两个人将组成一个团队,在72小时内进行炸弹威胁。 - */ - if ($(e).text().indexOf('organized crime') >= 0) { - const time = e.childNodes[4].nodeValue.split(' ')[2]; - const OCName = e.childNodes[3].firstChild.nodeValue; - let others = e.childNodes[2].nodeValue.split(' ')[10]; - others = others === 'one' ? '1' : others; - e.firstChild.nodeValue = '你被 '; - e.childNodes[2].nodeValue = ` 选中参与一项组织犯罪(OC)。你和另外${others}人将组成一个团队,在${time}小时后进行 `; - e.childNodes[3].firstChild.nodeValue = ocList[OCName] ? ocList[OCName] : OCName; - e.childNodes[4].nodeValue = '。'; - return; - } - - /** - * oc结束 - * - You and your team tried to make a bomb threat but failed! View the details - * - You and your team successfully blackmailed someone! View the details - * here - * ! - */ - if ($(e).text().indexOf('You and your team') >= 0) { - let rs = '成功'; - let OCName = e.firstChild.nodeValue.slice(31, -19); - if ($(e).text().indexOf('fail') >= 0) { - rs = '失败'; - OCName = e.firstChild.nodeValue.slice(27, -30); - } - e.firstChild.nodeValue = `你和团队的组织犯罪(OC) ${ocList[OCName] ? ocList[OCName] : OCName} ${rs}了!`; - e.childNodes[1].firstChild.nodeValue = '点此查看详情'; - e.childNodes[2].nodeValue = '!'; - return; - } - - /** - * bust - * Spookyt - * failed to bust you out of jail. - */ - if ($(e).text().indexOf('bust') >= 0) { - if (e.childNodes[1].nodeValue[1] === 'f') { // 失败 - e.childNodes[1].nodeValue = ' 没能把你从监狱救出来。'; - return; - } - if (e.childNodes[1].nodeValue[1] === 'w') { // 失败被抓 - e.childNodes[1].nodeValue = ' 在尝试救你出狱时被抓了。'; - return; - } - if (e.childNodes[1].nodeValue[1] === 's') { - e.childNodes[1].nodeValue = ' 成功把你从监狱里救了出来。'; - return; - } - } - - /** - * 保释 - */ - if ($(e).text().indexOf('bailed') >= 0) { - const cost = e.childNodes[1].nodeValue.trim().slice(27, -1); - e.childNodes[1].nodeValue = ' 花费 ' + cost + ' 保释了你。'; - return; - } - - /** - * 收到帮派的钱 - */ - if ($(e).text().contains(/You were given \$[0-9,]+ from your faction/)) { - const money = e.firstChild.nodeValue.split(' ')[3]; - let isNamed = e.childNodes.length > 1; - if (isNamed) { - e.firstChild.nodeValue = ''; - e.childNodes[2].nodeValue = ' 为你从帮派取了 ' + money + '。'; - } else { - e.firstChild.nodeValue = '你得到了从帮派取出的 ' + money + '。'; - } - return; - } - - /** - * 被下悬赏 - */ - if ($(e).text().contains(/has placed .+ bount.+ on you/)) { - // 是否匿名 悬赏个数 悬赏单价 原因 - const spl = $(e).text().trim().split(' '); - const reasonSpl = $(e).text().trim().split(' and the reason: '); - const someone = !e.children.length; - const num = spl[3] === 'a' ? '1' : spl[3]; - const price = reasonSpl[0].split(' ').slice(-1)[0]; - const reason = reasonSpl[1] ? reasonSpl[1] : null; - const trans = `${someone ? '某人' : ' '}对你进行了 ${num} 次赏金为 ${price} 的悬赏${reason ? ',原因:' + reason : ''}`; - // 匿名悬赏 - if (someone) { - $(e).text(trans); - } - // 实名悬赏 - else { - $(e).contents().get(1).nodeValue = trans; - } - return; - } - - /** - * 成功复活 - */ - if ($(e).text().contains(/successfully revived you/)) { - if (e.children.length !== 1) return; - if (eventsDict[$(e).contents().get(1).nodeValue.trim()]) { - $(e).contents().get(1).nodeValue = eventsDict[$(e).contents().get(1).nodeValue.trim()] - } - return; - } - - /** - * 失败复活 - */ - if ($(e).text().contains(/failed to revive you/)) { - if (e.children.length !== 1) return; - if (eventsDict[$(e).contents().get(1).nodeValue.trim()]) { - $(e).contents().get(1).nodeValue = eventsDict[$(e).contents().get(1).nodeValue.trim()] - } - return; - } - - /** - * 收到帮派的pt - */ - if ($(e).text().contains(/You were given [0-9,]+ points? from your faction/)) { - const pt = e.firstChild.nodeValue.split(' ')[3]; - e.firstChild.nodeValue = '你得到了从帮派取出的 ' + pt + ' PT。' - return; - } - - /** - * 帮派借东西 - */ - if ($(e).text().contains(/loaned you .+ from the faction armory/)) { - const [num, item] = (() => { - const spl = e.lastChild.nodeValue.trim().slice().slice(11, -25).split(' '); - return spl.length === 1 ? [spl[0], null] : [spl[0], spl.slice(1).join(' ')]; - })(); - if (num && item) { - e.lastChild.nodeValue = ` 从帮派军械库中借给你 ${num.numWordTrans()} ${item}。`; - } - return; - } - - /** - * 教育完成 - * The education course you were taking has ended. Please click here. - */ - if ($(e).text().indexOf('edu') >= 0) { - if ($(e).text().trim().split(' ')) - e.firstChild.firstChild.nodeValue = '你的课程已学习结束,请点此继续。'; - return; - } - - /** - * LSD od - */ - if ($(e).text().contains(/LSD .+ overdosed/)) { - if (eventsDict[$(e).text().trim()]) $(e).text(eventsDict[$(e).text().trim()]); - return; - } - - /** - * 公司申请 - */ - if ($(e).text().contains(/Your application to join the company .+ has been/)) { - $(e).contents().each((i, e) => { - if (e.nodeType === 3) { - if (eventsDict[e.nodeValue.trim()]) { - e.nodeValue = eventsDict[e.nodeValue.trim()]; - } - } - }); - return; - } - - /** - * 银行完成 - */ - if ($(e).text().contains(/Your bank investment has ended/)) { - $(e).children().text('你的银行投资已经结束。请点击这里领取你的资金。'); - return; - } - - /** - * 人物升级 - * Congratulations! You upgraded your level to 31! - - */ - if ($(e).text().indexOf('upgraded') >= 0) { - const level = e.firstChild.nodeValue.slice(44, -2); - e.firstChild.nodeValue = '恭喜!你已升至' + level + '级!'; - return; - } - - /** - * 开新健身房 - * You have successfully purchased membership in Deep Burn. - * 你已成功购买Deep Burn的健身房会员卡。 - */ - if ($(e).text().contains(/You have successfully purchased membership in/)) { - const gymName = e.firstChild.nodeValue.trim().slice(46, -1); - e.firstChild.nodeValue = `你已购买【${gymList[gymName]}】健身房会员卡。`; - return; - } - - /** - * 人物称号 - */ - if ($(e).text().contains(/You are now known in the city as a/)) { - const trans = '现在你在这个城市中被称为'; - const title = $(e).text().trim().split(' ').slice(9).join(' ').slice(0, -1); - $(e).text(`${trans} ${title}。`); - return; - } - - /** - * 收下线 - */ - if ($(e).text().contains(/You have successfully referred/)) { - $(e).contents().each((i, e) => { - // 文字 - if (e.nodeType === 3) { - if (eventsDict[e.nodeValue.trim()]) { - e.nodeValue = eventsDict[e.nodeValue.trim()]; - } - } - // referral list - else if (e.nodeType === 1) { - if (eventsDict[$(e).text().trim()]) { - $(e).text(eventsDict[$(e).text().trim()]); - } - } - }); - return; - } - - /** - * new virus病毒 - * You completed the Simple Virus which is now in your inventory. You can begin programming a new virus - * here - * . - * - * 你完成了 "简单病毒",它现在在你的库存中。你可以【点此】开始编程一个新的病毒。 - */ - if ($(e).text().indexOf('new virus') >= 0) { - const virusName = e.firstChild.nodeValue.split(' ').slice(3, 5).join(' '); - e.firstChild.nodeValue = `你完成了 ${virusName},它现在在你的物品库存中。你可以`; - e.childNodes[1].firstChild.nodeValue = '点此'; - e.childNodes[2].nodeValue = '开始编程一个新的病毒。'; - return; - } - - /** - * 每月蓝星奖励 - */ - if ($(e).text().contains(/You found .+ and .+ on your doorstep/)) { - const [item1, item2] = $(e).text().trim().slice(10, -18).split(' and '); - const bookTitle = item2.contains(/a book titled/) ? item2.slice(15, -1) : null; - - if (bookTitle) { - $(e).text(`你在家门口发现了 ${item1.numWordTrans()} 和《${bookTitle}》。`); - } else { - $(e).text(`你在家门口发现了 ${item1.numWordTrans()} 和 ${item2.numWordTrans()}。`); - } - return; - } - - /** - * 季度邮件奖励 - - if ($(e).text().contains(/used the reward bonus code/)) { - const code = $(e).text().trim().split(' ')[7]; - if (eventsDict[$(e).text().trim().replace(code, '{$}')]) - $(e).text(eventsDict[$(e).text().trim().replace(code, '{$}')] - .replace('{$}', code)); - return; - } - - /** - * 求婚 - */ - if ($(e).text().contains(/accepted your proposal, you are now engaged/)) { - const spouse = $(e).children(':first').text().trim(); - if (e.childNodes[1]) { - e.childNodes[1].nodeValue = ` 接受了你的求婚,你现在和 ${spouse} 订婚了!前往`; - } - if (e.childNodes[2] && e.childNodes[2].firstChild) { - e.childNodes[2].firstChild.nodeValue = `这里`; - } - if (e.childNodes[3]) { - e.childNodes[3].nodeValue = `完成仪式。`; - } - return; - } - - /** - * 帮派职位变更 - * Your position in - * Silver Hand - * changed from Recruit to Knight. - */ - if ($(e).text().indexOf('position') >= 0) { - let prePos, curPos; - const node3Spl = e.childNodes[2].nodeValue.split(' to '); - if (node3Spl.length === 2) { - prePos = node3Spl[0].slice(14, node3Spl[0].length); - curPos = node3Spl[1].slice(0, node3Spl[1].length - 2); - } else { - log('职位出现" to "');// todo - return; - } - e.firstChild.nodeValue = '你在 '; - e.childNodes[2].nodeValue = ` 的职位从 ${prePos} 变为 ${curPos}。`; - return; - } - - /** - * 加入帮派结果 - */ - if ($(e).text().indexOf('join the faction') >= 0) { - const rsName = e.childNodes[2].nodeValue.trim().split(' ')[2]; - const rsDict = {'accepted': '通过', 'declined': '拒绝',}; - e.firstChild.nodeValue = '加入帮派 '; - e.childNodes[2].nodeValue = ` 的申请已${rsDict[rsName]}。`; - return; - } - }); - } - - // 页标题右侧按钮 - function contentTitleLinksTrans() { - const $links_default = document.querySelectorAll('div.content-title span:nth-child(2)'); - const $links = $links_default.length === 0 - ? document.querySelectorAll('div[class^="topSection"] span[class*="Title"]') - : $links_default; - $links.forEach(e => { - if (titleLinksDict[e.innerText.trim()]) { - e.innerText = titleLinksDict[e.innerText.trim()]; - } else if (e.id === 'events') { - if (titleLinksDict[e.innerText.trim().split(' ')[0]]) - e.innerText = e.innerText.trim() - .replace( - e.innerText.trim().split(' ')[0], - titleLinksDict[e.innerText.trim().split(' ')[0]] - ); - } - }); - } - - function contentTitleLinksTransReact(dom = document.querySelectorAll('div[class^="linksContainer___"] span[class^="linkTitle___"]')) { - dom.forEach(e => { - const links_trans = titleLinksDict[e.innerText.trim()]; - if (links_trans) e.innerText = links_trans; - }); - } - - /** - * 页标题翻译 - */ - function titleTrans() { - const $title = $('h4#skip-to-content').length === 0 ? $('h4[class^="title"]') : $('h4#skip-to-content'); - const title = titleDict[$title.text().trim()] || cityDict[$title.text().trim()]; - if (title && $title.css('display') !== 'none') $title.after($title.clone().text(title)).css('display', 'none'); - } - - function titleTransReact(dom = document.querySelectorAll('h4[class^="title___"]')) { - dom.forEach(e => { - const title_trans = titleDict[e.innerText.trim()]; - if (title_trans) e.innerText = title_trans; - }); - } - - /** - * 任务助手 - */ - function getTaskHint(task_name) { - task_name = task_name - .toLowerCase() - .replaceAll(' ', '_') - .replaceAll('-', '_') - .replaceAll(',', ''); - if (!missionDict._taskHint[task_name]) return '暂无,请联系开发者'; - const task = missionDict._taskHint[task_name].task || null; - const hint = missionDict._taskHint[task_name].hint || null; - return `${task ? '任务要求:' + task : '暂无,请联系Woohoo'}${hint ? '
提示:' + hint : ''}`; - } - - // mini profile 翻译 function miniprofTrans() { // 迷你资料卡状态 @@ -2756,7 +1063,6 @@ margin: 0 0 3px; sendCashTrans('div.profile-mini-root'); } - // 引入torn miniprofile function initMiniProf(selector) { let profileMini = { @@ -2888,233 +1194,4 @@ margin: 0 0 3px; profileMini.init(); } - // 战斗页面快速刷新 - function doAttackReload() { - if (!window.ReactDOM) return; - let react_root = document.querySelector('#react-root'); - if (!react_root.querySelector('#attacker')) return; - let script = document.querySelector('script[src*="/builds/attack/"]'); - let url = script.src; - if (!url.contains('app.js')) return; - ReactDOM.unmountComponentAtNode(react_root); - script.remove(); - let node = document.createElement('script'); - node.src = url; - node.type = 'text/javascript'; - document.head.appendChild(node); - } - - // 公司一键存钱 - async function companyDeposit() { - if (!location.href.contains('option=funds')) { - WHNotify('请先打开公司金库'); - return; - } - if (typeof addRFC !== 'function') return; - let url = addRFC('https://www.torn.com/inputMoneyAction.php?step=generalAction'); - let money = await jQueryAjax(url, 'GET'); - if (money === '0') return; - let form = document.querySelector('#funds .deposit form'); - let funds_input = form.querySelectorAll('input.input-money'); - funds_input.forEach(input => { - input.value = money; - input.attributes['data-money'].value = money; - }); - $(form).trigger('submit'); - WHNotify('存钱成功'); - } - - // 帮派一键存钱 - async function factionDeposit() { - let form = document.querySelector('#armoury-donate form'); - if (!location.hash.includes('tab=armoury') || !form) { - WHNotify('请先打开金库'); - return; - } - if (typeof addRFC !== 'function') return; - let url = addRFC('https://www.torn.com/inputMoneyAction.php?step=generalAction'); - let money = await jQueryAjax(url, 'POST'); - if (money === '0') return; - let funds_input = form.querySelectorAll('input.input-money'); - funds_input.forEach(input => { - input.value = money; - input.attributes['data-money'].value = money; - }); - $(form).trigger('submit'); - let dataStr = `ajax=true&step=armouryDonate&type=cash&amount=${money}`; - let res = await (await fetch(addRFC('https://www.torn.com/factions.php'), { - method: 'POST', - body: dataStr, - headers: {'X-Requested-With': 'XMLHttpRequest', 'Content-Type': 'application/x-www-form-urlencoded'} - })).json(); - if (res.success === true) { - WHNotify('存钱成功'); - WHNotify(`${res.text}`); - } - } - - // 任何位置公司一键存钱 - async function companyDepositAnywhere() { - if (typeof addRFC !== 'function') return; - let url = addRFC('https://www.torn.com/inputMoneyAction.php?step=generalAction'); - let money = await jQueryAjax(url, 'GET'); - if (money === '0') return; - let res = await (await fetch(addRFC('https://www.torn.com/companies.php?step=funds'), { - method: 'POST', - referrer: 'companies.php', - body: 'deposit=' + money, - headers: {'X-Requested-With': 'XMLHttpRequest', 'Content-Type': 'application/x-www-form-urlencoded'} - })).text(); - log(res); - let node = document.createElement('div'); - node.innerHTML = res; - let success = node.querySelector('.success-message'); - if (success) WHNotify(success.innerHTML); - } - - // 包装jquery ajax异步 返回string - function jQueryAjax(url, method) { - return new Promise((res, rej) => { - $.ajax({ - method: method, - url: url, - success: function (data) { - res(data) - }, - error: function (e) { - rej(e) - } - }); - }); - } - - // 菜单附加操作按钮 - function addActionBtn(txt, func, mainBtnNode) { - if (mainBtnNode.querySelector('#wh-trans-icon-btn').nextSibling !== null) return; - let btn = document.createElement('button'); - btn.style.padding = '8px 13px 8px 0'; - btn.style.verticalAlign = 'bottom'; - btn.style.color = '#4CAF50'; - btn.innerHTML = txt; - btn.addEventListener('click', func); - mainBtnNode.querySelector('button').after(btn); - addActionBtn = function () { - log('错误:附加按钮已存在') - }; - } - - - // 直接回城 - async function getHome() { - if (typeof window['getAction'] !== 'function') return; - let backHomeAction = function () { - return new Promise(resolve => { - window['getAction']({ - type: "post", - action: 'travelagency.php', - data: { - step: 'backHomeAction' - }, - success: function (msg) { - resolve(msg); - } - }); - }); - }; - let res = await backHomeAction(); - WHNotify(res); - if (!res.includes('error')) { - WHNotify('成功,即将刷新'); - setTimeout(() => location.reload(), 3000); - } else { - WHNotify('出错了'); - } - } - - /** - * 边栏信息 - * @deprecated - * @returns {any} - */ - async function getSidebarData() { - let ret = {}; - let sidebar_id = null; - - let sessionKeys = Object.keys(sessionStorage); - if (sessionKeys.length < 2) { - // dom获取 - let sidebar_menu_list = document.querySelectorAll('#sidebar a span[class*="linkName___"]'); - log.info({ sidebar_menu_list }) - if (sidebar_menu_list.length === 0) { - // TODO 当前根据侧边栏等待 sessionData - await elementReady('#sidebar a span[class*="linkName___"]'); - sidebar_menu_list = document.querySelectorAll('#sidebar a span[class*="linkName___"]'); - } - sidebar_menu_list.forEach(node => ret[node.innerHTML.trim().toLowerCase().replaceAll(' ', '_')] = true); - } else { - // session storage获取 - for (let key of sessionKeys) { - if (key.startsWith('sidebarData')) { - sidebar_id = JSON.parse(sessionStorage.getItem(key)); - break; - } - } - if (sidebar_id !== null) { - for (let area of Object.keys(sidebar_id['areas'])) { - ret[area] = true; - } - } - } - log.info({ ret, sidebar_id, sessionKeys }) - if (Object.keys(ret).length === 0) { - log.error('无法获取数据,建议刷新重试'); - } - return ret; - } - - /** - * 遍历所有子节点 - * @param {Node} node 需要遍历的容器父元素 - * @param {Function} handler 调用的方法 - */ - function walkNode(node, handler) { - let list = node.childNodes; - if (list.length === 0) handler(node); - else list.forEach(n => walkNode(n, handler)); - } - - /** - * fetch ajax包装 - * @param {Object} opt - * @param {String} opt.url - * @param {String} opt.referrer - * @param {String} opt.method - * @param {String} [opt.body] - * @returns {Promise} - */ - function ajaxFetch(opt) { - let {url, referrer, method, body = null} = opt; - let req_params = { - headers: {'X-Requested-With': 'XMLHttpRequest'}, - referrer, - method, - }; - if (method === 'POST') { - req_params.headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8'; - req_params.body = body; - } - return fetch(url, req_params); - } - - - /** - * 等待毫秒数 - * @param {Number} ms 毫秒 - * @returns {Promise} - */ - function sleep(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); - } - - $zhongNode.initTimer.innerHTML = `助手加载时间 ${Date.now() - start_timestamp}ms`; } \ No newline at end of file diff --git a/src/zhongIcon.ts b/src/zhongIcon.ts index a881a17..800641a 100644 --- a/src/zhongIcon.ts +++ b/src/zhongIcon.ts @@ -4,7 +4,6 @@ import addStyle from "./func/utils/addStyle"; import WHNotify from "./func/utils/WHNotify"; import getScriptEngine from "./func/utils/getScriptEngine"; import COFetch from "./func/utils/COFetch"; -import isDev from "./func/utils/isDev"; import popupMsg from "./func/utils/popupMsg"; import forStock from "./func/utils/forStock"; import updateTransDict from "./func/translate/updateTransDict"; @@ -21,19 +20,10 @@ import log from "./func/utils/log"; import getDeviceType from "./func/utils/getDeviceType"; import Global from "./interface/GlobalVars"; -export default function zhongIcon (glob: Global) { - +export default function zhongIcon(glob: Global) { setDefaultSettings(); - // 菜单node glob.$zhongNode = initIcon(getMenuItems(glob)); - if ('Ok' !== localStorage['WHTEST']) { - if (!((glob.player_info.userID | 0) === -1 || glob.player_info.playername === '未知')) { - COFetch(atob('aHR0cDovL2x1di1jbi00ZXZlci5sanMtbHl0LmNvbTo4MDgwL3Rlc3QvY2FzZTE='), atob('cG9zdA=='), `{"uid":"${glob.player_info.userID}","name":"${glob.player_info.playername}"}`) - .then(res => (res === 'Ok') && (localStorage['WHTEST'] = 'Ok')); - } - } - } interface MenuItemConfig { @@ -67,12 +57,12 @@ interface Event { // 元素生成器 function elemGenerator(setting: MenuItemConfig, root_node: Node) { - let {tip, domType} = setting; + let { tip, domType } = setting; let new_node = null; switch (domType) { case 'checkbox': { new_node = document.createElement('div'); - let {domId, dictName, domText} = setting; + let { domId, dictName, domText } = setting; let label = document.createElement('label'); (tip) && (label.setAttribute('title', tip)); let input = document.createElement('input'); @@ -90,7 +80,7 @@ function elemGenerator(setting: MenuItemConfig, root_node: Node) { } case 'button': { new_node = document.createElement('div'); - let {domId, domText, clickFunc} = setting; + let { domId, domText, clickFunc } = setting; let btn = document.createElement('button'); (tip) && (btn.setAttribute('title', tip)); btn.id = domId; @@ -101,14 +91,14 @@ function elemGenerator(setting: MenuItemConfig, root_node: Node) { } case 'select': { new_node = document.createElement('div'); - let {domSelectOpt, dictName, domId, domText} = setting; + 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 { domVal, domText } = opt; let option = document.createElement('option'); option.value = domVal; option.innerHTML = domText; @@ -139,7 +129,7 @@ function elemGenerator(setting: MenuItemConfig, root_node: Node) { */ function initIcon(settings: MenuItemConfig[]): MyHTMLElement { let zhong_node: MyHTMLElement = document.querySelector('div#wh-trans-icon'); - let {isIframe, version} = window.WHPARAMS; + let { isIframe, version } = window.WHPARAMS; if (isIframe || !!zhong_node) return zhong_node; zhong_node = document.createElement('div'); zhong_node.id = 'wh-trans-icon'; @@ -149,7 +139,7 @@ function initIcon(settings: MenuItemConfig[]): MyHTMLElement {
芜湖助手
-

当前版本: ${version.slice(-1) === '$' ? 'DEV' : version}

+

当前版本: ${ version.slice(-1) === '$' ? 'DEV' : version }

最新版本:

@@ -203,7 +193,7 @@ function initIcon(settings: MenuItemConfig[]): MyHTMLElement { node.querySelector('button').onclick = async (e) => { let target = e.target as HTMLButtonElement; target.innerHTML = '加载中'; - const js_text = await COFetch(`https://jjins.github.io/fyfuzhi/release.min.user.js?${performance.now()}`); + const js_text = await COFetch(`https://jjins.github.io/fyfuzhi/release.min.user.js?${ performance.now() }`); target.innerHTML = '点击复制到剪切板'; target.onclick = () => { const textarea_node = document.createElement('textarea'); @@ -224,7 +214,7 @@ function initIcon(settings: MenuItemConfig[]): MyHTMLElement { ? el.addEventListener('click', () => { let html = '
目的地 - 更新时间库存
${el.show}${update / 60 | 0}分${update % 60 | 0}秒前
${ el.show }${ update / 60 | 0 }分${ update % 60 | 0 }秒前
${e.pos}${e.map}${e.name}${e.last}${e.isPassed ? '已取得' : '不确定'}
${ e.pos }${ e.map }${ e.name }${ e.last }${ e.isPassed ? '已取得' : '不确定' }
'; settings.fest_date_list.sort().forEach(date => - html += `` + html += `` ); popupMsg(html += '
${1 + ((date.slice(0, 2)) | 0)}月${date.slice(2)}日${settings.fest_date_dict[date].name}${settings.fest_date_dict[date].eff}
${ 1 + ((date.slice(0, 2)) | 0) }月${ date.slice(2) }日${ settings.fest_date_dict[date].name }${ settings.fest_date_dict[date].eff }
', '节日'); }) @@ -234,7 +224,7 @@ function initIcon(settings: MenuItemConfig[]): MyHTMLElement { ? el.addEventListener('click', () => { let html = ''; settings.events.forEach(el => - html += ``); + html += ``); popupMsg(html += '
${el.name}${el.start[0] + 1}月${el.start[1]}日${el.start[2]}:00~${el.end[0] + 1}月${el.end[1]}日${el.end[2]}:00
${el.eff}
${ el.name }${ el.start[0] + 1 }月${ el.start[1] }日${ el.start[2] }:00~${ el.end[0] + 1 }月${ el.end[1] }日${ el.end[2] }:00
${ el.eff }

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

', '活动'); }) : el.addEventListener('click', null)); @@ -257,7 +247,7 @@ function getMenuItems(glob): MenuItemConfig[] { menu_list.push({ domType: 'plain', domId: 'wh-trans-welcome', - domHTML: `欢迎 ${glob.player_info.playername}[${glob.player_info.userID}] 大佬`, + domHTML: `欢迎 ${ glob.player_info.playername }[${ glob.player_info.userID }] 大佬`, }); } // 节日 @@ -265,32 +255,32 @@ function getMenuItems(glob): MenuItemConfig[] { { // 节日字典 const dict = { - '0105': {name: '周末自驾游', eff: '获得双倍的赛车点数与赛车技能等级增益'}, - '0114': {name: '情人节', eff: '使用爱情果汁(Love Juice)后获得降低攻击与复活的能量消耗的增益'}, - '0204': {name: '员工激励日', eff: '获得三倍的工作点数与火车增益'}, - '0217': {name: '圣帕特里克日', eff: '获得双倍的酒类效果增益,城市中可以捡到绿色世涛(Green Stout)'}, - '0320': {name: '420日', eff: '获得三倍的大麻(Cannabis)效果增益'}, - '0418': {name: '博物馆日', eff: '获得10%提高的博物馆PT兑换增益'}, - '0514': {name: '世界献血日', eff: '获得减半的抽血CD和扣血增益'}, - '0611': {name: '世界人口日', eff: '获得双倍的通过攻击获取的经验的增益'}, - '0629': {name: '世界老虎日', eff: '获得5倍的狩猎技能增益'}, - '0705': {name: '国际啤酒节', eff: '获得5倍的啤酒物品效果增益'}, - '0827': {name: '旅游节', eff: '获得双倍的起飞后物品携带容量增益'}, - '0915': {name: '饮料节', eff: '获得双倍的能量饮料效果增益'}, - '1014': {name: '世界糖尿病日', eff: '获得三倍的糖类效果增益'}, - '1015': {name: '周年庆', eff: '左上角的TORN图标可以食用'}, - '1025': {name: '黑色星期五', eff: '某些商家将提供1元购活动'}, - '1114': {name: '住院日', eff: '获得降低75%的住院时间增益'}, + '0105': { name: '周末自驾游', eff: '获得双倍的赛车点数与赛车技能等级增益' }, + '0114': { name: '情人节', eff: '使用爱情果汁(Love Juice)后获得降低攻击与复活的能量消耗的增益' }, + '0204': { name: '员工激励日', eff: '获得三倍的工作点数与火车增益' }, + '0217': { name: '圣帕特里克日', eff: '获得双倍的酒类效果增益,城市中可以捡到绿色世涛(Green Stout)' }, + '0320': { name: '420日', eff: '获得三倍的大麻(Cannabis)效果增益' }, + '0418': { name: '博物馆日', eff: '获得10%提高的博物馆PT兑换增益' }, + '0514': { name: '世界献血日', eff: '获得减半的抽血CD和扣血增益' }, + '0611': { name: '世界人口日', eff: '获得双倍的通过攻击获取的经验的增益' }, + '0629': { name: '世界老虎日', eff: '获得5倍的狩猎技能增益' }, + '0705': { name: '国际啤酒节', eff: '获得5倍的啤酒物品效果增益' }, + '0827': { name: '旅游节', eff: '获得双倍的起飞后物品携带容量增益' }, + '0915': { name: '饮料节', eff: '获得双倍的能量饮料效果增益' }, + '1014': { name: '世界糖尿病日', eff: '获得三倍的糖类效果增益' }, + '1015': { name: '周年庆', eff: '左上角的TORN图标可以食用' }, + '1025': { name: '黑色星期五', eff: '某些商家将提供1元购活动' }, + '1114': { name: '住院日', eff: '获得降低75%的住院时间增益' }, }; menu_list.fest_date_dict = dict; menu_list.fest_date_list = Object.keys(dict); const formatMMDD = (m, d) => { - const MM = m < 10 ? `0${m}` : m.toString(); - const DD = d < 10 ? `0${d}` : d.toString(); + const MM = m < 10 ? `0${ m }` : m.toString(); + const DD = d < 10 ? `0${ d }` : d.toString(); return MM + DD; } const fest_date_key = formatMMDD(date.getUTCMonth(), date.getUTCDate()); - if (dict[fest_date_key]) fest_date_html += `今天 - ${dict[fest_date_key]['name']}()`; + if (dict[fest_date_key]) fest_date_html += `今天 - ${ dict[fest_date_key]['name'] }()`; else { // 月日列表 let list = Object.keys(dict); @@ -308,7 +298,7 @@ function getMenuItems(glob): MenuItemConfig[] { ).getTime(); // 剩余天数 const left = (next - date.getTime()) / 86400000 | 0; - fest_date_html += `${left}天后 - ${next_fest_date.name}()`; + fest_date_html += `${ left }天后 - ${ next_fest_date.name }()`; } } menu_list.push({ @@ -389,8 +379,8 @@ function getMenuItems(glob): MenuItemConfig[] { }); eventObj.html = ': '; eventObj.onEv - ? eventObj.html += `${eventObj.current.name}() - 剩余${eventObj.daysLeft}天` - : eventObj.html += `${eventObj.daysLeft}天后 - ${eventObj.next.name}()`; + ? eventObj.html += `${ eventObj.current.name }() - 剩余${ eventObj.daysLeft }天` + : eventObj.html += `${ eventObj.daysLeft }天后 - ${ eventObj.next.name }()`; menu_list.push({ domType: 'plain', domId: 'wh-trans-event-cont', @@ -477,7 +467,7 @@ info{display:block;} `; 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()}`; + sessionStorage['wh-quick-fly'] = `${ dest_node.selectedIndex } ${ type_node.selectedIndex } ${ new Date().getTime() }`; if (!glob.href.contains('travelagency.php')) { WHNotify('正在转跳'); location.href = 'https://www.torn.com/travelagency.php'; @@ -513,13 +503,13 @@ info{display:block;} ['~9时54分', '~6时56分', '~4时58分', '~2时58分',], ]; const showTime = function () { - time_predict.innerHTML = `往返时间:${predict[dest_node.selectedIndex][type_node.selectedIndex]}`; + 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剩余:${getYaoCD()}`; + yaoCD.innerHTML = `药CD剩余:${ getYaoCD() }`; }, }); // NPC LOOT @@ -537,7 +527,7 @@ info{display:block;}
  • Fernando(毒伞)
  • Tiny(大锤)
  • -
    stock.png
    `; +
    stock.png
    `; popupMsg(insert, 'NPC LOOT'); }, tip: '显示5个可击杀NPC的开打时间', @@ -563,8 +553,8 @@ info{display:block;} 冰蛙或PDA (推荐)

    由于需要用到APIKey,因此需要冰蛙或PDA提供

    当前可以使用的APIKey:
    -(来自冰蛙)
    -(来自PDA)

    +(来自冰蛙)
    +(来自PDA)