TS重构
This commit is contained in:
parent
cd38bd1b36
commit
5534776e77
28
global.d.ts
vendored
28
global.d.ts
vendored
@ -9,14 +9,30 @@ declare interface Window {
|
||||
WHPARAMS?: any;
|
||||
ReactDOM?: any;
|
||||
hasWHQuickFlyOpt?: boolean;
|
||||
// 插件运行标识
|
||||
WHTRANS?: boolean;
|
||||
Vue?: Function;
|
||||
|
||||
eval(exc: string): void;
|
||||
|
||||
/* TORN自带 */
|
||||
addRFC(url: URL | string): string;
|
||||
|
||||
getAction(opt: TornGetActionParams): void;
|
||||
|
||||
initMiniProf(selector: string): void;
|
||||
|
||||
/* PDA自带 */
|
||||
PDA_httpGet(url: URL | string): Promise<PDA_Response>;
|
||||
|
||||
PDA_httpPost(url: URL | string, init: any, body: any): Promise<PDA_Response>;
|
||||
|
||||
/* 油猴脚本引擎自带 */
|
||||
GM_xmlhttpRequest(init: GM_RequestParams);
|
||||
|
||||
GM_getValue(k: string, def: any): any;
|
||||
|
||||
GM_setValue(k: string, v: any): void;
|
||||
}
|
||||
|
||||
declare interface GM_RequestParams {
|
||||
@ -52,3 +68,15 @@ declare interface Array<T> {
|
||||
declare interface Navigator {
|
||||
userAgentData?: any;
|
||||
}
|
||||
|
||||
declare interface TornGetActionParams {
|
||||
type: 'post' | 'get',
|
||||
data: {
|
||||
step: string,
|
||||
id: number,
|
||||
key: string,
|
||||
type: string
|
||||
},
|
||||
success: Function,
|
||||
before: Function
|
||||
}
|
||||
43
src/func/module/adHelper.ts
Normal file
43
src/func/module/adHelper.ts
Normal file
@ -0,0 +1,43 @@
|
||||
import popupMsg from "../utils/popupMsg";
|
||||
|
||||
// 传单助手
|
||||
export default function adHelper() {
|
||||
let popup = popupMsg('', '传单助手');
|
||||
document.querySelector('#chatRoot').classList.remove('wh-hide');
|
||||
let info = document.createElement('p');
|
||||
let ad_input = document.createElement('textarea');
|
||||
let place_button = document.createElement('button');
|
||||
let clear_button = document.createElement('button');
|
||||
let paste_button = document.createElement('button');
|
||||
let style = document.createElement('style');
|
||||
|
||||
info.innerHTML = '打开多个聊天框后,点击<b>填写传单</b>将自动粘贴文本框中的内容进入所有<b>已打开的聊天框</b>。页面外的聊天框同样有效。';
|
||||
ad_input.placeholder = '此处输入广告语';
|
||||
ad_input.style.width = '100%';
|
||||
ad_input.style.minHeight = '80px';
|
||||
place_button.innerText = '填写传单';
|
||||
clear_button.innerText = '清空所有聊天框';
|
||||
paste_button.innerText = '粘贴剪切板';
|
||||
style.innerHTML = '#chatRoot > div{z-index:199999 !important;}';
|
||||
|
||||
place_button.addEventListener('click', () => {
|
||||
let chats = Array.from(document.querySelectorAll('#chatRoot textarea[name="chatbox2"]') as NodeListOf<HTMLTextAreaElement>);
|
||||
chats.forEach(chat => chat.value = ad_input.value);
|
||||
});
|
||||
clear_button.addEventListener('click', () => {
|
||||
let chats = document.querySelectorAll('#chatRoot textarea[name="chatbox2"]') as NodeListOf<HTMLTextAreaElement>;
|
||||
chats.forEach(chat => chat.value = '');
|
||||
});
|
||||
paste_button.addEventListener('click', async () => {
|
||||
ad_input.focus();
|
||||
ad_input.value = await navigator.clipboard.readText();
|
||||
});
|
||||
|
||||
popup.appendChild(style);
|
||||
popup.appendChild(info);
|
||||
popup.appendChild(ad_input);
|
||||
popup.appendChild(document.createElement('br'));
|
||||
popup.appendChild(place_button);
|
||||
popup.appendChild(clear_button);
|
||||
popup.appendChild(paste_button);
|
||||
}
|
||||
43
src/func/module/doQuickFly.ts
Normal file
43
src/func/module/doQuickFly.ts
Normal file
@ -0,0 +1,43 @@
|
||||
import WHNotify from "../utils/WHNotify";
|
||||
|
||||
// 一键起飞
|
||||
export default function doQuickFly() {
|
||||
// [id: dest, _type: (1...4), ts: timestamp]
|
||||
const [_id, _type, ts] = sessionStorage['wh-quick-fly'].trim().split(' ');
|
||||
if (new Date().getTime() - ts > 20000) {
|
||||
WHNotify('超时,一键起飞计划已取消');
|
||||
return;
|
||||
}
|
||||
const keynode = document.querySelector('div[data-id][data-key]');
|
||||
if (!keynode) {
|
||||
WHNotify('出错了,无法起飞,已取消');
|
||||
return;
|
||||
}
|
||||
const _key = keynode.getAttribute('data-key');
|
||||
window.getAction({
|
||||
type: 'post',
|
||||
data: {
|
||||
step: 'travel',
|
||||
id: getDestId(_id),
|
||||
key: _key,
|
||||
type: ['standard', 'airstrip', 'private', 'business'][_type]
|
||||
},
|
||||
success: function (str) {
|
||||
WHNotify(str)
|
||||
if (str.includes('err')) {
|
||||
WHNotify('起飞出错了');
|
||||
return;
|
||||
}
|
||||
window.location.href = 'https://www.torn.com/index.php'
|
||||
},
|
||||
before: function () {
|
||||
}
|
||||
});
|
||||
delete sessionStorage['wh-quick-fly'];
|
||||
}
|
||||
|
||||
// 起飞目的地id
|
||||
function getDestId(dest) {
|
||||
// 墨、开、加、夏、英、阿、瑞s、立本、祖、迪、南
|
||||
return [2, 12, 9, 3, 10, 7, 8, 5, 6, 11, 4][dest];
|
||||
}
|
||||
35
src/func/module/landedRedirect.ts
Normal file
35
src/func/module/landedRedirect.ts
Normal file
@ -0,0 +1,35 @@
|
||||
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');
|
||||
let buttonSave = document.createElement('button');
|
||||
let buttonCmp = document.createElement('button');
|
||||
let buttonFct = document.createElement('button');
|
||||
let buttonTest = document.createElement('button');
|
||||
let br = document.createElement('br');
|
||||
|
||||
p.innerHTML = '飞机落地后转跳的页面,关闭功能请置空:';
|
||||
input.placeholder = 'URL';
|
||||
input.value = getWhSettingObj()['landedRedirect'] || '';
|
||||
input.style.display = 'block';
|
||||
input.style.textAlign = 'left';
|
||||
input.style.width = '100%';
|
||||
input.style.padding = '8px';
|
||||
input.style.margin = '8px -8px';
|
||||
buttonSave.innerHTML = '保存';
|
||||
buttonCmp.innerHTML = '填入公司金库';
|
||||
buttonFct.innerHTML = '填入帮派金库金库';
|
||||
buttonTest.innerHTML = '测试链接';
|
||||
|
||||
buttonSave.addEventListener('click', () => setWhSetting('landedRedirect', input.value));
|
||||
buttonCmp.addEventListener('click', () => input.value = 'https://www.torn.com/companies.php#/option=funds');
|
||||
buttonFct.addEventListener('click', () => input.value = 'https://www.torn.com/factions.php?step=your#/tab=armoury');
|
||||
buttonTest.addEventListener('click', () => window.open(input.value));
|
||||
|
||||
let node = popupMsg('', '落地转跳');
|
||||
node.append(p, input, buttonSave, br, buttonCmp, buttonFct, buttonTest);
|
||||
}
|
||||
119
src/func/module/loadGS.ts
Normal file
119
src/func/module/loadGS.ts
Normal file
@ -0,0 +1,119 @@
|
||||
import UserScriptEngine from "../../enum/UserScriptEngine";
|
||||
import WHNotify from "../utils/WHNotify";
|
||||
import addStyle from "../utils/addStyle";
|
||||
import COFetch from "../utils/COFetch";
|
||||
import log from "../utils/log";
|
||||
|
||||
// gs loader
|
||||
export default function loadGS(use) {
|
||||
if (use === UserScriptEngine.PDA) {
|
||||
let ifr: HTMLIFrameElement = document.querySelector('#wh-gs-loader-ifr');
|
||||
if (ifr) {
|
||||
WHNotify('飞贼小助手已经加载了');
|
||||
return;
|
||||
}
|
||||
const container = document.createElement('div');
|
||||
container.id = 'wh-gs-loader';
|
||||
ifr = document.createElement('iframe');
|
||||
ifr.id = 'wh-gs-loader-ifr';
|
||||
ifr.src = 'https://www.torn.com/crimes.php';
|
||||
container.append(ifr);
|
||||
document.body.append(container);
|
||||
addStyle(`
|
||||
#wh-gs-loader {
|
||||
position:fixed;
|
||||
top:0;
|
||||
left:0;
|
||||
z-index:100001;
|
||||
}
|
||||
`);
|
||||
let notify = WHNotify('加载中');
|
||||
ifr.onload = () => {
|
||||
notify.close();
|
||||
const _window = ifr.contentWindow;
|
||||
const _docu = _window.document;
|
||||
_docu.head.innerHTML = '';
|
||||
_docu.body.innerHTML = '';
|
||||
notify = WHNotify('加载依赖');
|
||||
COFetch('https://cdn.staticfile.org/vue/2.2.2/vue.min.js')
|
||||
.then(vuejs => {
|
||||
notify.close();
|
||||
_window.eval(vuejs);
|
||||
_window.GM_getValue = (k, v = undefined) => {
|
||||
const objV = JSON.parse(_window.localStorage.getItem('wh-gs-storage') || '{}')[k];
|
||||
return objV || v;
|
||||
};
|
||||
_window.GM_setValue = (k, v) => {
|
||||
const obj = JSON.parse(_window.localStorage.getItem('wh-gs-storage') || '{}');
|
||||
obj[k] = v;
|
||||
_window.localStorage.setItem('wh-gs-storage', JSON.stringify(obj));
|
||||
};
|
||||
_window.GM_xmlhttpRequest = function (opt) {
|
||||
// 暂不适配pda post
|
||||
if (opt.method.toLowerCase() === 'post') return;
|
||||
COFetch(opt.url).then(res => {
|
||||
const obj = {
|
||||
responseText: res
|
||||
};
|
||||
opt.onload(obj);
|
||||
});
|
||||
};
|
||||
notify = WHNotify('加载飞贼小助手');
|
||||
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});
|
||||
const gsp: HTMLElement = _docu.querySelector('#gsp');
|
||||
const init = () => {
|
||||
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});
|
||||
init();
|
||||
if (log.debug()) _window.GM_setValue("gsp_showContent", true)
|
||||
});
|
||||
});
|
||||
};
|
||||
return;
|
||||
}
|
||||
if (use === UserScriptEngine.GM) {
|
||||
if (typeof window.Vue !== 'function') {
|
||||
let notify = WHNotify('正在加载依赖');
|
||||
COFetch('https://cdn.staticfile.org/vue/2.2.2/vue.min.js')
|
||||
.then(VueJS => {
|
||||
window.eval(VueJS);
|
||||
notify.close();
|
||||
notify = WHNotify('已载入依赖');
|
||||
window.GM_getValue = (k, v = undefined) => {
|
||||
const objV = JSON.parse(window.localStorage.getItem('wh-gs-storage') || '{}')[k];
|
||||
return objV || v;
|
||||
};
|
||||
window.GM_setValue = (k, v) => {
|
||||
const obj = JSON.parse(window.localStorage.getItem('wh-gs-storage') || '{}');
|
||||
obj[k] = v;
|
||||
window.localStorage.setItem('wh-gs-storage', JSON.stringify(obj));
|
||||
};
|
||||
// TODO
|
||||
// window.GM_xmlhttpRequest = GM_xmlhttpRequest;
|
||||
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(JSON.stringify(err)));
|
||||
} else {
|
||||
WHNotify('飞贼助手已经加载了');
|
||||
}
|
||||
return;
|
||||
}
|
||||
WHNotify('暂不支持');
|
||||
}
|
||||
120
src/func/module/safeKeeper.ts
Normal file
120
src/func/module/safeKeeper.ts
Normal file
@ -0,0 +1,120 @@
|
||||
import getPlayerInfo from "../utils/getPlayerInfo";
|
||||
import popupMsg from "../utils/popupMsg";
|
||||
import WHNotify from "../utils/WHNotify";
|
||||
import log from "../utils/log";
|
||||
|
||||
// 守望者
|
||||
export default function safeKeeper() {
|
||||
let url = `https://www.torn.com/loader.php?sid=attackData&mode=json&step=poll&user2ID=`;
|
||||
let popup = popupMsg('<p>监测目标ID玩家的防御状态,找出隐身攻击者</p>', '守望者 (测试中)');
|
||||
let p = document.createElement('p');
|
||||
let uid: HTMLInputElement = document.createElement('input');
|
||||
let start = document.createElement('button');
|
||||
let stop = document.createElement('button');
|
||||
let self_target = document.createElement('button');
|
||||
let attackers: MyHTMLElement = document.createElement('div');
|
||||
attackers.obj = {};
|
||||
let records: MyHTMLElement = document.createElement('div');
|
||||
records.list = [];
|
||||
records.details = {};
|
||||
// interval loop_id
|
||||
let loop_id = null;
|
||||
let updateAttackersDOM = function () {
|
||||
let html = '进攻者:<br/>';
|
||||
Object.keys(attackers.obj).forEach(id => html += `[${id}]<br/>`);
|
||||
attackers.innerHTML = html;
|
||||
};
|
||||
let updateRecordsDOM = function () {
|
||||
let html = '战斗记录:<br/>';
|
||||
records.list.forEach(rid => {
|
||||
let {TimeCreated, attackID, attackerID, attackerItemID, result, text} = records.details[rid];
|
||||
html += `[${TimeCreated}] [${attackerID}] [${attackerItemID}] ${result} ${text}<br/>`;
|
||||
});
|
||||
records.innerHTML = html;
|
||||
};
|
||||
|
||||
uid.type = 'text';
|
||||
uid.placeholder = '目标ID';
|
||||
start.innerHTML = '开启';
|
||||
stop.innerHTML = '关闭';
|
||||
stop.disabled = true;
|
||||
self_target.innerHTML = '填入自己';
|
||||
// 弹出窗口关闭时结束
|
||||
let popup_close = popup.close;
|
||||
popup.close = () => {
|
||||
if (loop_id === null) popup_close();
|
||||
else WHNotify('守望者运行中,请先停止', {timeout: 2});
|
||||
}
|
||||
|
||||
popup.appendChild(p);
|
||||
popup.appendChild(uid);
|
||||
popup.appendChild(start);
|
||||
popup.appendChild(stop);
|
||||
popup.appendChild(self_target);
|
||||
popup.appendChild(attackers);
|
||||
popup.appendChild(records);
|
||||
|
||||
start.addEventListener('click', () => {
|
||||
if (loop_id !== null || !uid.value) return;
|
||||
start.disabled = true;
|
||||
stop.disabled = false;
|
||||
uid.readOnly = true;
|
||||
p.innerHTML = '状态:已开 ✅';
|
||||
let count = 0;
|
||||
loop_id = setInterval(async () => {
|
||||
// 记录当前循环的id
|
||||
let that_id = loop_id;
|
||||
let res = await (await fetch(url + uid.value, {
|
||||
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('<div')[0]);
|
||||
log.info(count++, data);
|
||||
let {DB, currentFightStatistics, histLog} = data;
|
||||
// 攻击人
|
||||
// 格式:currentFightStatistics = {uid: {...}, uid2: {...}}
|
||||
Object.keys(currentFightStatistics || {}).forEach(id => {
|
||||
if (id === uid.value) return;
|
||||
if (!attackers.obj[id]) {
|
||||
attackers.obj[id] = true;
|
||||
updateAttackersDOM();
|
||||
}
|
||||
});
|
||||
// 攻击历史
|
||||
(DB['currentFightHistory'] || []).forEach(record => {
|
||||
if (records.list.includes(record['ID'])) return;
|
||||
let {ID, TimeCreated, attackID, attackerID, attackerItemID, result, text} = record;
|
||||
records.list.push(ID);
|
||||
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;
|
||||
records.list.push(ID);
|
||||
records.details[ID] = {
|
||||
TimeCreated,
|
||||
attackID,
|
||||
attackerID: userID,
|
||||
attackerItemID: 0,
|
||||
result: attackResult,
|
||||
text: ''
|
||||
};
|
||||
updateRecordsDOM();
|
||||
});
|
||||
}, 900);
|
||||
});
|
||||
|
||||
stop.addEventListener('click', () => {
|
||||
if (loop_id === null) return;
|
||||
start.disabled = false;
|
||||
stop.disabled = true;
|
||||
uid.readOnly = false;
|
||||
clearInterval(loop_id);
|
||||
loop_id = null;
|
||||
p.innerHTML = '状态:已关 ❎';
|
||||
});
|
||||
self_target.addEventListener('click', () => uid.value = (getPlayerInfo()['userID']) + '');
|
||||
}
|
||||
6
src/func/translate/updateTransDict.ts
Normal file
6
src/func/translate/updateTransDict.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import WHNotify from "../utils/WHNotify";
|
||||
|
||||
// 更新词库
|
||||
export default function updateTransDict() {
|
||||
WHNotify('计划中');
|
||||
}
|
||||
55
src/func/utils/MarkdownParser.ts
Normal file
55
src/func/utils/MarkdownParser.ts
Normal file
@ -0,0 +1,55 @@
|
||||
/**
|
||||
* 解析 Markdown 内容
|
||||
* @param {String} from
|
||||
* @param {Number} max_line 最大行数,默认500
|
||||
* @returns {HTMLDivElement}
|
||||
*/
|
||||
export default function mdParse(from: string, max_line?: number): HTMLElement {
|
||||
max_line = max_line || 500;
|
||||
const base = document.createElement('div');
|
||||
let lines = from.split('\n');
|
||||
if (lines.length > max_line) {
|
||||
lines = lines.slice(0, max_line);
|
||||
lines.push("...");
|
||||
}
|
||||
|
||||
let prev = '';
|
||||
let child_cont;
|
||||
lines.forEach(line => {
|
||||
if (line.trim() === '') return;
|
||||
let node;
|
||||
let spl = line.split(' ');
|
||||
let md_flag = spl[0];
|
||||
|
||||
switch (md_flag) {
|
||||
// 标题
|
||||
case '#':
|
||||
case '##':
|
||||
case '###':
|
||||
if (prev === 'li') {
|
||||
child_cont = null;
|
||||
}
|
||||
prev = 'h' + (md_flag.length + 1);
|
||||
node = document.createElement(prev);
|
||||
node.innerText = line.slice(md_flag.length + 1);
|
||||
base.append(node);
|
||||
return;
|
||||
// 列表
|
||||
case '-':
|
||||
if (prev !== 'li') {
|
||||
child_cont = document.createElement('ul');
|
||||
if (!base.contains(child_cont)) base.append(child_cont);
|
||||
}
|
||||
prev = 'li';
|
||||
node = document.createElement(prev);
|
||||
node.innerText = line.slice(2);
|
||||
child_cont.append(node);
|
||||
return;
|
||||
}
|
||||
prev = 'p';
|
||||
node = document.createElement(prev);
|
||||
node.innerText = line.trim();
|
||||
base.append(node);
|
||||
})
|
||||
return base;
|
||||
}
|
||||
@ -12,9 +12,8 @@ import addStyle from "./addStyle";
|
||||
* @param {function} [options.sysNotifyClick] - 系统通知点击事件
|
||||
* @return {HTMLElement}
|
||||
*/
|
||||
export default function WHNotify(msg, options: WHNotifyOpt = {}): MyHTMLElement {
|
||||
let glob = window.WHPARAMS;
|
||||
let {isIframe, isWindowActive, notifies} = glob;
|
||||
export default function WHNotify(msg: string, options: WHNotifyOpt = {}): MyHTMLElement {
|
||||
let {isIframe, isWindowActive, notifies} = window.WHPARAMS;
|
||||
|
||||
let {
|
||||
timeout = 3,
|
||||
@ -24,6 +23,7 @@ export default function WHNotify(msg, options: WHNotifyOpt = {}): MyHTMLElement
|
||||
sysNotifyTag = '芜湖助手',
|
||||
sysNotifyClick = () => window.focus()
|
||||
} = options;
|
||||
|
||||
if (!isWindowActive() || isIframe) return null;
|
||||
const date = new Date();
|
||||
// 通知的唯一id
|
||||
|
||||
24
src/func/utils/elementReady.ts
Normal file
24
src/func/utils/elementReady.ts
Normal file
@ -0,0 +1,24 @@
|
||||
/**
|
||||
* 通过 mutation.observe 方法异步返回元素
|
||||
* @param {String} selector - CSS规则的HTML元素选择器
|
||||
* @param {Document} content - 上下文
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export default function elementReady(selector, content = document): Promise<HTMLElement> {
|
||||
return new Promise(resolve => {
|
||||
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.
|
||||
observer.disconnect();
|
||||
});
|
||||
})
|
||||
.observe(content.documentElement, {childList: true, subtree: true});
|
||||
});
|
||||
}
|
||||
82
src/func/utils/forStock.ts
Normal file
82
src/func/utils/forStock.ts
Normal file
@ -0,0 +1,82 @@
|
||||
import UserScriptEngine from "../../enum/UserScriptEngine";
|
||||
import getScriptEngine from "./getScriptEngine";
|
||||
import popupMsg from "./popupMsg";
|
||||
import loading_gif_html from "./loading_gif_html";
|
||||
|
||||
// 海外库存
|
||||
export default async function forStock() {
|
||||
let glob = window.WHPARAMS;
|
||||
if (getScriptEngine() === UserScriptEngine.RAW) {
|
||||
const insert = `<img alt="stock.png" src="https://jjins.github.io/t2i/stock.png?${performance.now()}" style="max-width:100%;display:block;margin:0 auto;" />`;
|
||||
popupMsg(insert, '飞花库存');
|
||||
} else {
|
||||
const popup = popupMsg(`请稍后${loading_gif_html()}`, '飞花库存');
|
||||
let table = `<table><tr><th colspan="2">目的地 - 更新时间</th><th colspan="3">库存</th></tr>`;
|
||||
const dest = [
|
||||
{
|
||||
name: 'mex', show: '墨西哥',
|
||||
stocks: {'Dahlia': '花', 'Jaguar Plushie': '偶'}
|
||||
},
|
||||
{
|
||||
name: 'cay', show: '开曼',
|
||||
stocks: {'Banana Orchid': '花', 'Stingray Plushie': '偶'}
|
||||
},
|
||||
{
|
||||
name: 'can', show: '加拿大',
|
||||
stocks: {'Crocus': '花', 'Wolverine Plushie': '偶'}
|
||||
},
|
||||
{
|
||||
name: 'haw', show: '夏威夷',
|
||||
stocks: {'Orchid': '花', 'Large Suitcase': '大箱'}
|
||||
},
|
||||
{
|
||||
name: 'uni', show: '嘤国',
|
||||
stocks: {'Heather': '花', 'Red Fox Plushie': '赤狐', 'Nessie Plushie': '水怪'}
|
||||
},
|
||||
{
|
||||
name: 'arg', show: '阿根廷',
|
||||
stocks: {'Ceibo Flower': '花', 'Monkey Plushie': '偶', 'Tear Gas': '催泪弹'},
|
||||
},
|
||||
{
|
||||
name: 'swi', show: '瑞士',
|
||||
stocks: {'Edelweiss': '花', 'Chamois Plushie': '偶'},
|
||||
},
|
||||
{
|
||||
name: 'jap', show: '日本',
|
||||
stocks: {'Cherry Blossom': '花'},
|
||||
},
|
||||
{
|
||||
name: 'chi', show: '祖国',
|
||||
stocks: {'Peony': '花', 'Panda Plushie': '偶'},
|
||||
},
|
||||
{
|
||||
name: 'uae', show: '迪拜',
|
||||
stocks: {'Tribulus Omanense': '花', 'Camel Plushie': '偶'},
|
||||
},
|
||||
{
|
||||
name: 'sou', show: '南非',
|
||||
stocks: {'African Violet': '花', 'Lion Plushie': '偶', 'Xanax': 'XAN'},
|
||||
}];
|
||||
const now = new Date();
|
||||
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 += `<tr><td>${el.show}</td><td>${update / 60 | 0}分${update % 60 | 0}秒前</td>`;
|
||||
let count = 0;
|
||||
res.stocks[el.name]['stocks'].forEach(stock => {
|
||||
if (el.stocks[stock.name]) {
|
||||
table += `<td${stock['quantity'] === 0 ? ' style="background-color:#f44336;color:white;border-color:#000;"' : ''}>${el.stocks[stock.name]} (${stock['quantity']})</td>`;
|
||||
count++;
|
||||
}
|
||||
});
|
||||
while (count < 3) {
|
||||
count++;
|
||||
table += '<td></td>';
|
||||
}
|
||||
table += '</tr>';
|
||||
});
|
||||
table += '</table>';
|
||||
popup.innerHTML = table;
|
||||
}
|
||||
}
|
||||
7
src/func/utils/getDeviceType.ts
Normal file
7
src/func/utils/getDeviceType.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import Device from "../../enum/Device";
|
||||
|
||||
// 用户设备类型 对应PC MOBILE TABLET
|
||||
export default function getDeviceType() {
|
||||
return window.innerWidth >= 1000
|
||||
? Device.PC : window.innerWidth <= 600 ? Device.MOBILE : Device.TABLET;
|
||||
}
|
||||
16
src/func/utils/getYaoCD.ts
Normal file
16
src/func/utils/getYaoCD.ts
Normal file
@ -0,0 +1,16 @@
|
||||
// 药cd
|
||||
export default function getYaoCD(): string {
|
||||
if (document.querySelector("#icon49-sidebar")) { // 0-10min
|
||||
return '<10分'
|
||||
} else if (document.querySelector("#icon50-sidebar")) { // 10min-1h
|
||||
return '<1时'
|
||||
} else if (document.querySelector("#icon51-sidebar")) { // 1h-2h
|
||||
return '1~2时'
|
||||
} else if (document.querySelector("#icon52-sidebar")) { // 2h-5h
|
||||
return '2~5时'
|
||||
} else if (document.querySelector("#icon53-sidebar")) { // 5h+
|
||||
return '>5时'
|
||||
} else {
|
||||
return '无效'
|
||||
}
|
||||
}
|
||||
5
src/func/utils/loading_gif_html.ts
Normal file
5
src/func/utils/loading_gif_html.ts
Normal file
@ -0,0 +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 `<img src="${gif_base64}" alt="lgif" style="width:14px;height:14px;" />`;
|
||||
}
|
||||
@ -1,14 +1,19 @@
|
||||
// console.log改写
|
||||
import isDev from "./isDev";
|
||||
import getWhSettingObj from "./getWhSettingObj";
|
||||
|
||||
function debug() {
|
||||
try {
|
||||
return getWhSettingObj()['isDev'] || false;
|
||||
} catch (e) {
|
||||
console.error(`[wh] dev状态错误 ${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const log = (...o) => (log.debug()) && (console.log('[WH]', ...o))
|
||||
const log = (...o) => (debug()) && (console.log('[WH]', ...o))
|
||||
|
||||
log.error = (...o) => (log.debug()) && (console.error('[WH]', ...o))
|
||||
log.info = (...o) => (log.debug()) && (console.log('[WH]', ...o))
|
||||
log.error = (...o) => (debug()) && (console.error('[WH]', ...o))
|
||||
log.info = (...o) => (debug()) && (console.log('[WH]', ...o))
|
||||
log.debug = debug;
|
||||
|
||||
export default log
|
||||
30
src/func/utils/popupMsg.ts
Normal file
30
src/func/utils/popupMsg.ts
Normal file
@ -0,0 +1,30 @@
|
||||
/**
|
||||
* 弹出窗口
|
||||
* @param {String} innerHTML 内容html string
|
||||
* @param {String} title 弹窗标题
|
||||
* @returns {null|Element}
|
||||
*/
|
||||
export default function popupMsg(innerHTML, title = '芜湖助手') {
|
||||
let glob = window.WHPARAMS;
|
||||
if (glob.popup_node) glob.popup_node.close();
|
||||
const chatRoot = document.querySelector('#chatRoot');
|
||||
chatRoot.classList.add('wh-hide');
|
||||
const popup = document.createElement('div');
|
||||
popup.id = 'wh-popup';
|
||||
popup.innerHTML = `<div id="wh-popup-container">
|
||||
<div id="wh-popup-title"><p>${title}</p></div>
|
||||
<div id="wh-popup-cont">${innerHTML}</div>
|
||||
</div>`;
|
||||
document.body.append(popup);
|
||||
const rt: MyHTMLElement = popup.querySelector('#wh-popup-cont');
|
||||
rt.close = function () {
|
||||
popup.remove();
|
||||
chatRoot.classList.remove('wh-hide');
|
||||
}
|
||||
popup.addEventListener('click', e => {
|
||||
e.stopImmediatePropagation();
|
||||
if (e.target === popup) rt.close();
|
||||
});
|
||||
glob.popup_node = rt;
|
||||
return rt;
|
||||
}
|
||||
@ -2,4 +2,7 @@ interface MyHTMLElement extends HTMLElement {
|
||||
sys_notify?: Notification;
|
||||
msgInnerText?: string;
|
||||
close?: () => void;
|
||||
|
||||
// 对象的其他参数
|
||||
[key: string]: any;
|
||||
}
|
||||
@ -52,22 +52,6 @@ export default function userscript(glob: Global): void {
|
||||
init(glob);
|
||||
let {version, isIframe, PDA_APIKey, isPDA, player_info, fstock, notifies} = glob;
|
||||
|
||||
|
||||
// 返回一个加载中gif图形HTML
|
||||
const loading_gif_html = () => {
|
||||
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 `<img src="${gif_base64}" alt="lgif" style="width:14px;height:14px;" />`;
|
||||
}
|
||||
|
||||
// 菜单node
|
||||
const $zhongNode = initIcon(menu_list);
|
||||
if ('Ok' !== localStorage['WHTEST']) {
|
||||
if (!(player_info.userID | 0 === -1 || player_info.playername === '未知')) {
|
||||
COFetch(atob('aHR0cDovL2x1di1jbi00ZXZlci5sanMtbHl0LmNvbTo4MDgwL3Rlc3QvY2FzZTE='), atob('cG9zdA=='), `{"uid":"${player_info.userID}","name":"${player_info.playername}"}`)
|
||||
.then(res => (res === 'Ok') && (localStorage['WHTEST'] = 'Ok'));
|
||||
}
|
||||
}
|
||||
|
||||
const href = window.location.href;
|
||||
// 开启翻译
|
||||
transToZhCN(href, getWhSettingObj()['transEnable']);
|
||||
@ -2842,119 +2826,6 @@ margin: 0 0 3px;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
添加左侧图标
|
||||
*/
|
||||
function initIcon(settings) {
|
||||
if (isIframe || !!document.querySelector('div#wh-trans-icon')) return;
|
||||
const zhong_node = document.createElement('div');
|
||||
zhong_node.id = 'wh-trans-icon';
|
||||
zhong_node.classList.add('cont-gray');
|
||||
zhong_node.innerHTML = `<div><button id="wh-trans-icon-btn"></button></div>
|
||||
<div class="wh-container">
|
||||
<div class="wh-main">
|
||||
<div><b>芜湖助手</b></div>
|
||||
<div id="wh-gSettings"></div>
|
||||
<div><p>当前版本: ${version.slice(-1) === '$' ? 'DEV' : version} <button id="wh-update-btn">更新</button></p></div>
|
||||
<div><p>最新版本: <span id="wh-latest-version"></span></p></div>
|
||||
<div><p id="wh-inittimer"></p></div>
|
||||
</div>
|
||||
</div>`;
|
||||
// 助手菜单
|
||||
const menu_cont = zhong_node.querySelector('#wh-gSettings');
|
||||
// 设置选项
|
||||
zhong_node.setting_root = document.createElement('div');
|
||||
zhong_node.setting_root.classList.add('gSetting');
|
||||
// 遍历菜单node设置
|
||||
settings.forEach(setting => {
|
||||
// if (!setting['isHide']) {
|
||||
elemGenerator(setting, menu_cont);
|
||||
// 最后移动节点
|
||||
// zhong_node.setting_root.appendChild(new_node);
|
||||
// setting['isHide'] ? zhong_node.setting_root.appendChild(new_node) : menu_cont.appendChild(new_node);
|
||||
// }
|
||||
});
|
||||
// 计时node
|
||||
zhong_node.initTimer = zhong_node.querySelector('#wh-inittimer');
|
||||
// 芜湖助手图标点击事件
|
||||
zhong_node.querySelector('#wh-trans-icon-btn').onclick = () => {
|
||||
zhong_node.classList.toggle('wh-icon-expanded');
|
||||
const click_func = e => {
|
||||
// e.stopImmediatePropagation();
|
||||
log(e.target);
|
||||
if (e.target === zhong_node.querySelector('#wh-trans-icon-btn')) return;
|
||||
if (!zhong_node.contains(e.target)) {
|
||||
log('移除事件监听器');
|
||||
document.body.removeEventListener('click', click_func);
|
||||
zhong_node.classList.remove('wh-icon-expanded');
|
||||
}
|
||||
};
|
||||
if (zhong_node.classList.contains('wh-icon-expanded')) {
|
||||
log('添加事件监听器');
|
||||
document.body.addEventListener('click', click_func);
|
||||
} else {
|
||||
log('移除事件监听器');
|
||||
document.body.removeEventListener('click', click_func);
|
||||
}
|
||||
};
|
||||
// 更新按钮点击事件
|
||||
zhong_node.querySelector('#wh-update-btn').onclick = e => {
|
||||
e.target.blur();
|
||||
const innerHtml = `<h4>电脑</h4>
|
||||
<p>通常电脑浏览器装有油猴等用户脚本扩展时可以使用链接安装(自动更新):<a href="https://gitlab.com/JJins/wuhu-torn-helper/-/raw/dev/release.min.user.js" target="_blank">点此安装</a>。</p>
|
||||
<p>这些扩展长这样:<img src="//jjins.github.io/tm.png" alt="tm.png" /><img src="//jjins.github.io/vm.png" alt="vm.png" /></p>
|
||||
<p></p>
|
||||
<h4>手机</h4>
|
||||
<p>安卓 KIWI 等可以用油猴脚本的浏览器也可以点上面的链接安装👆</p>
|
||||
<p>Torn PDA app 或 Alook 用户可打开<a href="//jjins.github.io/fyfuzhi/" target="_blank">这个网页</a>快捷复制粘贴。</p>
|
||||
<h4>直接复制</h4>
|
||||
<p>加载脚本然后直接复制粘贴到用户脚本处。</p>
|
||||
<p><button>加载</button></p>
|
||||
`;
|
||||
const node = popupMsg(innerHtml, '如何更新');
|
||||
// 直接复制的按钮
|
||||
node.querySelector('button').onclick = async (e) => {
|
||||
e.target.innerHTML = '加载中';
|
||||
const js_text = await COFetch(`https://jjins.github.io/fyfuzhi/release.min.user.js?${performance.now()}`);
|
||||
e.target.innerHTML = '点击复制到剪切板';
|
||||
e.target.onclick = () => {
|
||||
const textarea_node = document.createElement('textarea');
|
||||
textarea_node.innerHTML = js_text;
|
||||
e.target.parentElement.append(textarea_node);
|
||||
textarea_node.focus();
|
||||
textarea_node.select();
|
||||
document.execCommand('Copy');
|
||||
textarea_node.remove();
|
||||
e.target.innerHTML = '已复制';
|
||||
e.target.onclick = null;
|
||||
WHNotify('脚本已复制,请前往粘贴');
|
||||
};
|
||||
};
|
||||
};
|
||||
// 节日
|
||||
zhong_node.querySelectorAll('#wh-trans-fest-date button').forEach((el, i) => i === 0
|
||||
? el.addEventListener('click', () => {
|
||||
let html = '<table>';
|
||||
menu_list.fest_date_list.sort().forEach(date => html += `<tr><td>${1 + (date.slice(0, 2) | 0)}月${date.slice(2)}日</td><td>${menu_list.fest_date_dict[date].name}</td><td>${menu_list.fest_date_dict[date].eff}</td></tr>`);
|
||||
popupMsg(html += '</table>', '节日');
|
||||
})
|
||||
: el.addEventListener('click', null));
|
||||
// 活动
|
||||
zhong_node.querySelectorAll('#wh-trans-event-cont button').forEach((el, i) => i === 0
|
||||
? el.addEventListener('click', () => {
|
||||
let html = '<table>';
|
||||
menu_list.events.forEach(el =>
|
||||
html += `<tr><td><b>${el.name}</b></td><td>${el.start[0] + 1}月${el.start[1]}日${el.start[2]}:00~${el.end[0] + 1}月${el.end[1]}日${el.end[2]}:00</td></tr><tr><td colspan="2">${el.eff}</td></tr>`);
|
||||
popupMsg(html += '</table><p>更多信息请关注群聊和公众号</p>', '活动');
|
||||
})
|
||||
: el.addEventListener('click', null));
|
||||
document.body.append(zhong_node);
|
||||
// 引入torn自带浮动提示
|
||||
(window['initializeTooltip']) && (window['initializeTooltip']('.wh-container', 'white-tooltip'));
|
||||
// 加载torn mini profile
|
||||
initMiniProf('#wh-trans-icon');
|
||||
return zhong_node;
|
||||
}
|
||||
|
||||
// bool 返回当前是否dev状态
|
||||
function isDev() {
|
||||
@ -2996,158 +2867,6 @@ margin: 0 0 3px;
|
||||
return rt;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过 mutation.observe 方法异步返回元素
|
||||
* @param {String} selector - CSS规则的HTML元素选择器
|
||||
* @param {Document} content - 上下文
|
||||
* @returns {Promise}
|
||||
*/
|
||||
function elementReady(selector, content = document) {
|
||||
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.
|
||||
observer.disconnect();
|
||||
});
|
||||
})
|
||||
.observe(content.documentElement, {childList: true, subtree: true});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 用户设备类型 对应PC MOBILE TABLET
|
||||
function getDeviceType() {
|
||||
return window.innerWidth >= 1000
|
||||
? Device.PC : window.innerWidth <= 600 ? Device.MOBILE : Device.TABLET;
|
||||
}
|
||||
|
||||
// 简单 object 转字符串
|
||||
function Obj2Str(obj) {
|
||||
return JSON.stringify(obj);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// gs loader
|
||||
function loadGS(use) {
|
||||
if (use === UserScriptEngine.PDA) {
|
||||
let ifr = document.querySelector('#wh-gs-loader-ifr');
|
||||
if (ifr) {
|
||||
WHNotify('飞贼小助手已经加载了');
|
||||
return;
|
||||
}
|
||||
const container = document.createElement('div');
|
||||
container.id = 'wh-gs-loader';
|
||||
ifr = document.createElement('iframe');
|
||||
ifr.id = 'wh-gs-loader-ifr';
|
||||
ifr.src = 'https://www.torn.com/crimes.php';
|
||||
container.append(ifr);
|
||||
document.body.append(container);
|
||||
addStyle(`
|
||||
#wh-gs-loader {
|
||||
position:fixed;
|
||||
top:0;
|
||||
left:0;
|
||||
z-index:100001;
|
||||
}
|
||||
`);
|
||||
let notify = WHNotify('加载中');
|
||||
ifr.onload = () => {
|
||||
notify.del();
|
||||
const _window = ifr.contentWindow;
|
||||
const _docu = _window.document;
|
||||
_docu.head.innerHTML = '';
|
||||
_docu.body.innerHTML = '';
|
||||
notify = WHNotify('加载依赖');
|
||||
COFetch('https://cdn.staticfile.org/vue/2.2.2/vue.min.js')
|
||||
.then(vuejs => {
|
||||
notify.del();
|
||||
_window.eval(vuejs)
|
||||
_window.GM_getValue = (k, v = undefined) => {
|
||||
const objV = JSON.parse(_window.localStorage.getItem('wh-gs-storage') || '{}')[k];
|
||||
return objV || v;
|
||||
};
|
||||
_window.GM_setValue = (k, v) => {
|
||||
const obj = JSON.parse(_window.localStorage.getItem('wh-gs-storage') || '{}');
|
||||
obj[k] = v;
|
||||
_window.localStorage.setItem('wh-gs-storage', JSON.stringify(obj));
|
||||
};
|
||||
_window.GM_xmlhttpRequest = function (opt) {
|
||||
// 暂不适配pda post
|
||||
if (opt.method.toLowerCase() === 'post') return;
|
||||
COFetch(opt.url).then(res => {
|
||||
const obj = {};
|
||||
obj.responseText = res;
|
||||
opt.onload(obj);
|
||||
});
|
||||
};
|
||||
notify = WHNotify('加载飞贼小助手');
|
||||
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.del();
|
||||
notify = WHNotify('飞贼小助手已加载', {timeout: 1});
|
||||
const gsp = _docu.querySelector('#gsp');
|
||||
const init = () => {
|
||||
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});
|
||||
init();
|
||||
if (isDev()) _window.GM_setValue("gsp_showContent", true)
|
||||
});
|
||||
});
|
||||
};
|
||||
return;
|
||||
}
|
||||
if (use === UserScriptEngine.GM) {
|
||||
if (typeof window.Vue !== 'function') {
|
||||
let notify = WHNotify('正在加载依赖');
|
||||
COFetch('https://cdn.staticfile.org/vue/2.2.2/vue.min.js')
|
||||
.catch(err => WHNotify(Obj2Str(err)))
|
||||
.then(VueJS => {
|
||||
window.eval(VueJS);
|
||||
notify.del();
|
||||
notify = WHNotify('已载入依赖');
|
||||
window.GM_getValue = (k, v = undefined) => {
|
||||
const objV = JSON.parse(window.localStorage.getItem('wh-gs-storage') || '{}')[k];
|
||||
return objV || v;
|
||||
};
|
||||
window.GM_setValue = (k, v) => {
|
||||
const obj = JSON.parse(window.localStorage.getItem('wh-gs-storage') || '{}');
|
||||
obj[k] = v;
|
||||
window.localStorage.setItem('wh-gs-storage', JSON.stringify(obj));
|
||||
};
|
||||
window.GM_xmlhttpRequest = GM_xmlhttpRequest;
|
||||
COFetch(`https://gitee.com/ameto_kasao/tornjs/raw/master/GoldenSnitch.js?${performance.now()}`)
|
||||
.then(GSJS => {
|
||||
window.eval(GSJS);
|
||||
if (isDev()) window.GM_setValue("gsp_showContent", true);
|
||||
notify.del();
|
||||
notify = WHNotify('已载入飞贼助手');
|
||||
})
|
||||
.catch(err => WHNotify(`PDA API错误。${Obj2Str(err)}`));
|
||||
});
|
||||
} else {
|
||||
WHNotify('飞贼助手已经加载了');
|
||||
}
|
||||
return;
|
||||
}
|
||||
WHNotify('暂不支持');
|
||||
}
|
||||
|
||||
// 翻译
|
||||
function transToZhCN(href, onoff) {
|
||||
if (!onoff) return;
|
||||
@ -5215,11 +4934,6 @@ z-index:100001;
|
||||
sendCashTrans('div.profile-mini-root');
|
||||
}
|
||||
|
||||
// 起飞目的地id
|
||||
function getDestId(dest) {
|
||||
// 墨、开、加、夏、英、阿、瑞s、立本、祖、迪、南
|
||||
return [2, 12, 9, 3, 10, 7, 8, 5, 6, 11, 4][dest];
|
||||
}
|
||||
|
||||
// 引入torn miniprofile
|
||||
function initMiniProf(selector) {
|
||||
@ -5429,91 +5143,8 @@ z-index:100001;
|
||||
}
|
||||
}
|
||||
|
||||
// 药cd
|
||||
function getYaoCD() {
|
||||
if (document.querySelector("#icon49-sidebar")) { // 0-10min
|
||||
return '<10分'
|
||||
} else if (document.querySelector("#icon50-sidebar")) { // 10min-1h
|
||||
return '<1时'
|
||||
} else if (document.querySelector("#icon51-sidebar")) { // 1h-2h
|
||||
return '1~2时'
|
||||
} else if (document.querySelector("#icon52-sidebar")) { // 2h-5h
|
||||
return '2~5时'
|
||||
} else if (document.querySelector("#icon53-sidebar")) { // 5h+
|
||||
return '>5时'
|
||||
} else {
|
||||
return '无效'
|
||||
}
|
||||
}
|
||||
|
||||
// 元素生成器
|
||||
function elemGenerator(setting, root_node) {
|
||||
let {tip, domType} = setting;
|
||||
let new_node = null;
|
||||
switch (domType) {
|
||||
case 'checkbox': {
|
||||
new_node = document.createElement('div');
|
||||
let {domId, dictName, domText} = setting;
|
||||
let label = document.createElement('label');
|
||||
(tip) && (label.setAttribute('title', tip));
|
||||
let input = document.createElement('input');
|
||||
input.type = 'checkbox';
|
||||
input.id = domId;
|
||||
input.checked = getWhSettingObj()[dictName];
|
||||
input.onchange = e => {
|
||||
setWhSetting(dictName, e.target.checked);
|
||||
if (setting.changeEv) setting.changeEv(e);
|
||||
};
|
||||
label.innerHTML = domText;
|
||||
label.prepend(input);
|
||||
new_node.appendChild(label);
|
||||
break;
|
||||
}
|
||||
case 'button': {
|
||||
new_node = document.createElement('div');
|
||||
let {domId, domText, clickFunc} = setting;
|
||||
let btn = document.createElement('button');
|
||||
(tip) && (btn.setAttribute('title', tip));
|
||||
btn.id = domId;
|
||||
btn.innerHTML = domText;
|
||||
btn.onclick = clickFunc;
|
||||
new_node.appendChild(btn);
|
||||
break;
|
||||
}
|
||||
case 'select': {
|
||||
new_node = document.createElement('div');
|
||||
let {domSelectOpt, dictName, domId, domText} = setting;
|
||||
let label = document.createElement('label');
|
||||
(tip) && (label.setAttribute('title', tip));
|
||||
let text = document.createTextNode(domText);
|
||||
let select = document.createElement('select');
|
||||
select.id = domId;
|
||||
domSelectOpt.forEach((opt, i) => {
|
||||
let {domVal, domText} = opt;
|
||||
let option = document.createElement('option');
|
||||
option.value = domVal;
|
||||
option.innerHTML = domText;
|
||||
option.selected = i === getWhSettingObj()[dictName];
|
||||
option.innerHTML = domText;
|
||||
select.appendChild(option);
|
||||
});
|
||||
select.onchange = e => setWhSetting(dictName, e.target.selectedIndex);
|
||||
label.appendChild(text);
|
||||
label.appendChild(select);
|
||||
new_node.appendChild(label);
|
||||
break;
|
||||
}
|
||||
case 'plain': {
|
||||
let tag = setting.tagName || 'div';
|
||||
new_node = document.createElement(tag);
|
||||
if (setting.domId) new_node.id = setting.domId;
|
||||
new_node.innerHTML += setting['domHTML'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 移动节点
|
||||
return root_node.appendChild(new_node);
|
||||
}
|
||||
|
||||
|
||||
// 啤酒
|
||||
function buyBeer() {
|
||||
@ -5613,83 +5244,7 @@ z-index:100001;
|
||||
|
||||
|
||||
|
||||
// 一键起飞
|
||||
function doQuickFly() {
|
||||
// [id: dest, _type: (1...4), ts: timestamp]
|
||||
const [_id, _type, ts] = sessionStorage['wh-quick-fly'].trim().split(' ');
|
||||
if (new Date().getTime() - ts > 20000) {
|
||||
WHNotify('超时,一键起飞计划已取消');
|
||||
return;
|
||||
}
|
||||
const keynode = document.querySelector('div[data-id][data-key]');
|
||||
if (!keynode) {
|
||||
WHNotify('出错了,无法起飞,已取消');
|
||||
return;
|
||||
}
|
||||
const _key = keynode.getAttribute('data-key');
|
||||
getAction({
|
||||
type: 'post',
|
||||
data: {
|
||||
step: 'travel',
|
||||
id: getDestId(_id),
|
||||
key: _key,
|
||||
type: ['standard', 'airstrip', 'private', 'business'][_type]
|
||||
},
|
||||
success: function (str) {
|
||||
WHNotify(str)
|
||||
if (str.includes('err')) {
|
||||
WHNotify('起飞出错了');
|
||||
return;
|
||||
}
|
||||
window.location.href = 'https://www.torn.com/index.php'
|
||||
},
|
||||
before: function () {
|
||||
}
|
||||
});
|
||||
delete sessionStorage['wh-quick-fly'];
|
||||
}
|
||||
|
||||
// 传单助手
|
||||
function adHelper() {
|
||||
let popup = popupMsg('', '传单助手');
|
||||
document.querySelector('#chatRoot').classList.remove('wh-hide');
|
||||
let info = document.createElement('p');
|
||||
let ad_input = document.createElement('textarea');
|
||||
let place_button = document.createElement('button');
|
||||
let clear_button = document.createElement('button');
|
||||
let paste_button = document.createElement('button');
|
||||
let style = document.createElement('style');
|
||||
|
||||
info.innerHTML = '打开多个聊天框后,点击<b>填写传单</b>将自动粘贴文本框中的内容进入所有<b>已打开的聊天框</b>。页面外的聊天框同样有效。';
|
||||
ad_input.placeholder = '此处输入广告语';
|
||||
ad_input.style.width = '100%';
|
||||
ad_input.style.minHeight = '80px';
|
||||
place_button.innerText = '填写传单';
|
||||
clear_button.innerText = '清空所有聊天框';
|
||||
paste_button.innerText = '粘贴剪切板';
|
||||
style.innerHTML = '#chatRoot > div{z-index:199999 !important;}';
|
||||
|
||||
place_button.addEventListener('click', () => {
|
||||
let chats = document.querySelectorAll('#chatRoot textarea[name="chatbox2"]');
|
||||
chats.forEach(chat => chat.value = ad_input.value);
|
||||
});
|
||||
clear_button.addEventListener('click', () => {
|
||||
let chats = document.querySelectorAll('#chatRoot textarea[name="chatbox2"]');
|
||||
chats.forEach(chat => chat.value = '');
|
||||
});
|
||||
paste_button.addEventListener('click', async () => {
|
||||
ad_input.focus();
|
||||
ad_input.value = await navigator.clipboard.readText();
|
||||
});
|
||||
|
||||
popup.appendChild(style);
|
||||
popup.appendChild(info);
|
||||
popup.appendChild(ad_input);
|
||||
popup.appendChild(document.createElement('br'));
|
||||
popup.appendChild(place_button);
|
||||
popup.appendChild(clear_button);
|
||||
popup.appendChild(paste_button);
|
||||
}
|
||||
|
||||
// 公司一键存钱
|
||||
async function companyDeposit() {
|
||||
@ -5790,126 +5345,6 @@ z-index:100001;
|
||||
};
|
||||
}
|
||||
|
||||
// 守望者
|
||||
function safeKeeper() {
|
||||
let url = `https://www.torn.com/loader.php?sid=attackData&mode=json&step=poll&user2ID=`;
|
||||
let popup = popupMsg('<p>监测目标ID玩家的防御状态,找出隐身攻击者</p>', '守望者 (测试中)');
|
||||
let p = document.createElement('p');
|
||||
let uid = document.createElement('input');
|
||||
let start = document.createElement('button');
|
||||
let stop = document.createElement('button');
|
||||
let self_target = document.createElement('button');
|
||||
let attackers = document.createElement('div');
|
||||
attackers.obj = {};
|
||||
let records = document.createElement('div');
|
||||
records.list = [];
|
||||
records.details = {};
|
||||
// interval loop_id
|
||||
let loop_id = null;
|
||||
let updateAttackersDOM = function () {
|
||||
let html = '进攻者:<br/>';
|
||||
Object.keys(attackers.obj).forEach(id => html += `[${id}]<br/>`);
|
||||
attackers.innerHTML = html;
|
||||
};
|
||||
let updateRecordsDOM = function () {
|
||||
let html = '战斗记录:<br/>';
|
||||
records.list.forEach(rid => {
|
||||
let {TimeCreated, attackID, attackerID, attackerItemID, result, text} = records.details[rid];
|
||||
html += `[${TimeCreated}] [${attackerID}] [${attackerItemID}] ${result} ${text}<br/>`;
|
||||
});
|
||||
records.innerHTML = html;
|
||||
};
|
||||
|
||||
uid.type = 'text';
|
||||
uid.placeholder = '目标ID';
|
||||
start.innerHTML = '开启';
|
||||
stop.innerHTML = '关闭';
|
||||
stop.disabled = true;
|
||||
self_target.innerHTML = '填入自己';
|
||||
// 弹出窗口关闭时结束
|
||||
let popup_close = popup.close;
|
||||
popup.close = () => {
|
||||
if (loop_id === null) popup_close();
|
||||
else WHNotify('守望者运行中,请先停止', {timeout: 2});
|
||||
}
|
||||
|
||||
popup.appendChild(p);
|
||||
popup.appendChild(uid);
|
||||
popup.appendChild(start);
|
||||
popup.appendChild(stop);
|
||||
popup.appendChild(self_target);
|
||||
popup.appendChild(attackers);
|
||||
popup.appendChild(records);
|
||||
|
||||
start.addEventListener('click', () => {
|
||||
if (loop_id !== null || !uid.value) return;
|
||||
start.disabled = true;
|
||||
stop.disabled = false;
|
||||
uid.readOnly = true;
|
||||
p.innerHTML = '状态:已开 ✅';
|
||||
let count = 0;
|
||||
loop_id = setInterval(async () => {
|
||||
// 记录当前循环的id
|
||||
let that_id = loop_id;
|
||||
let res = await (await fetch(url + uid.value, {
|
||||
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('<div')[0]);
|
||||
log(count++, data);
|
||||
let {DB, currentFightStatistics, histLog} = data;
|
||||
// 攻击人
|
||||
// 格式:currentFightStatistics = {uid: {...}, uid2: {...}}
|
||||
Object.keys(currentFightStatistics || {}).forEach(id => {
|
||||
if (id === uid.value) return;
|
||||
if (!attackers.obj[id]) {
|
||||
attackers.obj[id] = true;
|
||||
updateAttackersDOM();
|
||||
}
|
||||
});
|
||||
// 攻击历史
|
||||
(DB['currentFightHistory'] || []).forEach(record => {
|
||||
if (records.list.includes(record['ID'])) return;
|
||||
let {ID, TimeCreated, attackID, attackerID, attackerItemID, result, text} = record;
|
||||
records.list.push(ID);
|
||||
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;
|
||||
records.list.push(ID);
|
||||
records.details[ID] = {
|
||||
TimeCreated,
|
||||
attackID,
|
||||
attackerID: userID,
|
||||
attackerItemID: 0,
|
||||
result: attackResult,
|
||||
text: ''
|
||||
};
|
||||
updateRecordsDOM();
|
||||
});
|
||||
}, 900);
|
||||
});
|
||||
|
||||
stop.addEventListener('click', () => {
|
||||
if (loop_id === null) return;
|
||||
start.disabled = false;
|
||||
stop.disabled = true;
|
||||
uid.readOnly = false;
|
||||
clearInterval(loop_id);
|
||||
loop_id = null;
|
||||
p.innerHTML = '状态:已关 ❎';
|
||||
});
|
||||
self_target.addEventListener('click', () => uid.value = getPlayerInfo()['userID']);
|
||||
}
|
||||
|
||||
// 更新词库
|
||||
function updateTransDict() {
|
||||
WHNotify('计划中');
|
||||
}
|
||||
|
||||
// 直接回城
|
||||
async function getHome() {
|
||||
@ -5990,38 +5425,6 @@ z-index:100001;
|
||||
else list.forEach(n => walkNode(n, handler));
|
||||
}
|
||||
|
||||
// 落地转跳
|
||||
function landedRedirect() {
|
||||
let p = document.createElement('p');
|
||||
let input = document.createElement('input');
|
||||
let buttonSave = document.createElement('button');
|
||||
let buttonCmp = document.createElement('button');
|
||||
let buttonFct = document.createElement('button');
|
||||
let buttonTest = document.createElement('button');
|
||||
let br = document.createElement('br');
|
||||
|
||||
p.innerHTML = '飞机落地后转跳的页面,关闭功能请置空:';
|
||||
input.placeholder = 'URL';
|
||||
input.value = getWhSettingObj()['landedRedirect'] || '';
|
||||
input.style.display = 'block';
|
||||
input.style.textAlign = 'left';
|
||||
input.style.width = '100%';
|
||||
input.style.padding = '8px';
|
||||
input.style.margin = '8px -8px';
|
||||
buttonSave.innerHTML = '保存';
|
||||
buttonCmp.innerHTML = '填入公司金库';
|
||||
buttonFct.innerHTML = '填入帮派金库金库';
|
||||
buttonTest.innerHTML = '测试链接';
|
||||
|
||||
buttonSave.addEventListener('click', () => setWhSetting('landedRedirect', input.value));
|
||||
buttonCmp.addEventListener('click', () => input.value = 'https://www.torn.com/companies.php#/option=funds');
|
||||
buttonFct.addEventListener('click', () => input.value = 'https://www.torn.com/factions.php?step=your#/tab=armoury');
|
||||
buttonTest.addEventListener('click', () => window.open(input.value));
|
||||
|
||||
let node = popupMsg('', '落地转跳');
|
||||
node.append(p, input, buttonSave, br, buttonCmp, buttonFct, buttonTest);
|
||||
}
|
||||
|
||||
/**
|
||||
* fetch ajax包装
|
||||
* @param {Object} opt
|
||||
@ -6045,61 +5448,6 @@ z-index:100001;
|
||||
return fetch(url, req_params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析 Markdown 内容
|
||||
* @param {String} from
|
||||
* @param {Number} max_line 最大行数,默认500
|
||||
* @returns {HTMLDivElement}
|
||||
*/
|
||||
function mdParse(from, max_line) {
|
||||
max_line = max_line || 500;
|
||||
const base = document.createElement('div');
|
||||
let lines = from.split('\n');
|
||||
if (lines.length > max_line) {
|
||||
lines = lines.slice(0, max_line);
|
||||
lines.push("...");
|
||||
}
|
||||
|
||||
let prev = '';
|
||||
let child_cont;
|
||||
lines.forEach(line => {
|
||||
if (line.trim() === '') return;
|
||||
let node;
|
||||
let spl = line.split(' ');
|
||||
let md_flag = spl[0];
|
||||
|
||||
switch (md_flag) {
|
||||
// 标题
|
||||
case '#':
|
||||
case '##':
|
||||
case '###':
|
||||
if (prev === 'li') {
|
||||
child_cont = null;
|
||||
}
|
||||
prev = 'h' + (md_flag.length + 1);
|
||||
node = document.createElement(prev);
|
||||
node.innerText = line.slice(md_flag.length + 1);
|
||||
base.append(node);
|
||||
return;
|
||||
// 列表
|
||||
case '-':
|
||||
if (prev !== 'li') {
|
||||
child_cont = document.createElement('ul');
|
||||
if (!base.contains(child_cont)) base.append(child_cont);
|
||||
}
|
||||
prev = 'li';
|
||||
node = document.createElement(prev);
|
||||
node.innerText = line.slice(2);
|
||||
child_cont.append(node);
|
||||
return;
|
||||
}
|
||||
prev = 'p';
|
||||
node = document.createElement(prev);
|
||||
node.innerText = line.trim();
|
||||
base.append(node);
|
||||
})
|
||||
return base;
|
||||
}
|
||||
|
||||
/**
|
||||
* 等待毫秒数
|
||||
|
||||
254
src/zhongIcon.ts
254
src/zhongIcon.ts
@ -5,6 +5,20 @@ 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";
|
||||
import landedRedirect from "./func/module/landedRedirect";
|
||||
import doQuickFly from "./func/module/doQuickFly";
|
||||
import getYaoCD from "./func/utils/getYaoCD";
|
||||
import loading_gif_html from "./func/utils/loading_gif_html";
|
||||
import elementReady from "./func/utils/elementReady";
|
||||
import loadGS from "./func/module/loadGS";
|
||||
import adHelper from "./func/module/adHelper";
|
||||
import safeKeeper from "./func/module/safeKeeper";
|
||||
import mdParse from "./func/utils/MarkdownParser";
|
||||
import log from "./func/utils/log";
|
||||
import getDeviceType from "./func/utils/getDeviceType";
|
||||
|
||||
// 对新值应用「默认」设置
|
||||
export default function () {
|
||||
@ -297,7 +311,7 @@ export default function () {
|
||||
tip: '每小时的整15分钟的倍数时通知提醒抢啤酒或者血包',
|
||||
isHide: true,
|
||||
changeEv: function (ev) {
|
||||
ev.target.checked ? beer.start() : beer.stop();
|
||||
ev.target.checked ? glob.beer.start() : glob.beer.stop();
|
||||
},
|
||||
});
|
||||
// 啤酒提醒状态
|
||||
@ -306,7 +320,7 @@ export default function () {
|
||||
domId: '',
|
||||
domText: '啤酒提醒状态',
|
||||
clickFunc: function () {
|
||||
WHNotify(`啤酒提醒${beer.status()}`);
|
||||
WHNotify(`啤酒提醒${glob.beer.status()}`);
|
||||
}
|
||||
});
|
||||
// 啤酒提醒时间
|
||||
@ -316,22 +330,22 @@ export default function () {
|
||||
domText: '啤酒提醒时间设定',
|
||||
// tip: '通知提前时间',
|
||||
clickFunc: function () {
|
||||
popup_node.close();
|
||||
glob.popup_node.close();
|
||||
let popup = popupMsg(`<label>提前提醒时间(秒):<input type="number" value="${getWhSettingObj()['_15AlarmTime']}" /></label><p>区间为 1 ~ 60,默认 50</p>`, '啤酒提醒时间设定');
|
||||
let confirm = document.createElement('button');
|
||||
confirm.innerHTML = '确定';
|
||||
confirm.style.float = 'right';
|
||||
confirm.addEventListener('click', () => {
|
||||
let input = popup.querySelector('input');
|
||||
let num = input.value | 0;
|
||||
let input: HTMLInputElement = popup.querySelector('input');
|
||||
let num = (input.value as any) | 0;
|
||||
if (num === getWhSettingObj()['_15AlarmTime']) return;
|
||||
if (num < 1 || num > 60) num = 50;
|
||||
input.value = num.toString();
|
||||
setWhSetting('_15AlarmTime', num);
|
||||
// 之前的运行状态
|
||||
let before_state = beer.is_running();
|
||||
beer.set_time(num);
|
||||
if (before_state) beer.start();
|
||||
let before_state = glob.beer.is_running();
|
||||
glob.beer.set_time(num);
|
||||
if (before_state) glob.beer.start();
|
||||
popup.close();
|
||||
});
|
||||
popup.appendChild(confirm);
|
||||
@ -805,7 +819,8 @@ info{display:block;}
|
||||
const select = popup.querySelector('input');
|
||||
const node = popup.querySelector('p');
|
||||
popup.querySelector('button').addEventListener('click', ev => {
|
||||
ev.target.style.display = 'none';
|
||||
let target = ev.target as HTMLInputElement;
|
||||
target.style.display = 'none';
|
||||
node.innerHTML = '加载中';
|
||||
// API 计算
|
||||
if (select.checked) {
|
||||
@ -815,7 +830,7 @@ info{display:block;}
|
||||
.then(data => {
|
||||
if (data['error']) {
|
||||
node.innerHTML = `出错了 ${JSON.stringify(data['error'])}`;
|
||||
ev.target.style.display = null;
|
||||
target.style.display = null;
|
||||
return;
|
||||
}
|
||||
let nb = data['nerve']['maximum'];
|
||||
@ -827,7 +842,7 @@ info{display:block;}
|
||||
})
|
||||
});
|
||||
node.innerHTML = `NNB: ${nb - perks}`;
|
||||
ev.target.style.display = null;
|
||||
target.style.display = null;
|
||||
});
|
||||
}
|
||||
// 主页计算
|
||||
@ -840,11 +855,11 @@ info{display:block;}
|
||||
str.includes('maximum nerve') && (perks += (/[0-9]./.exec(str) as any)[0] | 0)
|
||||
});
|
||||
node.innerHTML = `NNB: ${nb - perks}`;
|
||||
ev.target.style.display = null;
|
||||
target.style.display = null;
|
||||
return;
|
||||
}
|
||||
node.innerHTML = '不在主页面,<a href="/index.php">点击前往</a>';
|
||||
ev.target.style.display = null;
|
||||
target.style.display = null;
|
||||
}
|
||||
});
|
||||
},
|
||||
@ -947,7 +962,8 @@ background-size: 100% auto !important;
|
||||
let popup = popupMsg(insert, '常用链接');
|
||||
popup.classList.add('wh-link-collection-cont');
|
||||
popup.addEventListener('click', ev => {
|
||||
if (ev.target.tagName.toLowerCase() === 'a' || ev.target.tagName.toLowerCase() === 'span') {
|
||||
let target = ev.target as HTMLElement;
|
||||
if (target.tagName.toLowerCase() === 'a' || target.tagName.toLowerCase() === 'span') {
|
||||
popup.close();
|
||||
}
|
||||
});
|
||||
@ -987,9 +1003,9 @@ background-size: 100% auto !important;
|
||||
`;
|
||||
const popup = popupMsg(html, '价格监视设置');
|
||||
popup.querySelector('button').onclick = () => {
|
||||
const [pt_node, xan_node] = popup.querySelectorAll('input[type="number"]');
|
||||
watcher_conf.pt = pt_node.value | 0;
|
||||
watcher_conf.xan = xan_node.value | 0;
|
||||
const [pt_node, xan_node] = Array.from(popup.querySelectorAll('input[type="number"]'));
|
||||
watcher_conf.pt = (pt_node.value as any) | 0;
|
||||
watcher_conf.xan = (xan_node.value as any) | 0;
|
||||
if (JSON.stringify(watcher_conf) !== pre_str) setWhSetting('priceWatcher', watcher_conf);
|
||||
popup.close();
|
||||
};
|
||||
@ -1197,7 +1213,7 @@ background-size: 100% auto !important;
|
||||
<tr><td>设备类型</td><td>${getDeviceType().toUpperCase()}</td></tr>
|
||||
<tr><td>脚本运行方式</td><td>${{'gm': '油猴', 'raw': '直接运行', 'pda': 'TornPDA'}[getScriptEngine()]}</td></tr>
|
||||
<tr><td>时间</td><td>${date.getFullYear()}/${date.getMonth() + 1}/${date.getDate()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}</td></tr>
|
||||
<tr><td>插件版本</td><td>${version}</td></tr>
|
||||
<tr><td>插件版本</td><td>${glob.version}</td></tr>
|
||||
<tr><td>操作系统</td><td>${os}</td></tr>
|
||||
<tr><td>UA</td><td>${window.navigator.userAgent}</td></tr>
|
||||
<tr><td>用户ID</td><td>${glob.player_info.userID}</td></tr>
|
||||
@ -1209,7 +1225,7 @@ padding: 2px 4px;
|
||||
color:black;
|
||||
}
|
||||
</style>`;
|
||||
pop['close']();
|
||||
pop.close();
|
||||
popupMsg(insert, '开发者详情');
|
||||
};
|
||||
(window['initializeTooltip']) && (window['initializeTooltip']('#wh-popup-cont', 'white-tooltip'));
|
||||
@ -1222,20 +1238,33 @@ color:black;
|
||||
domText: '📐️ 测试',
|
||||
clickFunc: async function () {
|
||||
let res = await COFetch('https://gitlab.com/JJins/wuhu-torn-helper/-/raw/dev/CHANGELOG.md')
|
||||
log(mdParse(res))
|
||||
log.info(mdParse(res))
|
||||
},
|
||||
});
|
||||
// endregion
|
||||
|
||||
// 菜单node
|
||||
const $zhongNode = initIcon(menu_list);
|
||||
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 {
|
||||
domType: 'button' | 'plain';
|
||||
tagName?: string;
|
||||
domType: 'button' | 'plain' | 'checkbox' | 'select';
|
||||
domId?: string;
|
||||
domText?: string;
|
||||
clickFunc?: Function;
|
||||
clickFunc?: (ev?) => void;
|
||||
domHTML?: string;
|
||||
tip?: string;
|
||||
dictName?: string;
|
||||
changeEv?: (ev) => void;
|
||||
domSelectOpt?: { domVal: string, domText: string }[];
|
||||
}
|
||||
|
||||
interface EventWrapper {
|
||||
@ -1253,3 +1282,184 @@ interface Event {
|
||||
name: string;
|
||||
eff: string;
|
||||
}
|
||||
|
||||
// 元素生成器
|
||||
function elemGenerator(setting: MenuItemConfig, root_node: Node) {
|
||||
let {tip, domType} = setting;
|
||||
let new_node = null;
|
||||
switch (domType) {
|
||||
case 'checkbox': {
|
||||
new_node = document.createElement('div');
|
||||
let {domId, dictName, domText} = setting;
|
||||
let label = document.createElement('label');
|
||||
(tip) && (label.setAttribute('title', tip));
|
||||
let input = document.createElement('input');
|
||||
input.type = 'checkbox';
|
||||
input.id = domId;
|
||||
input.checked = getWhSettingObj()[dictName];
|
||||
input.onchange = e => {
|
||||
setWhSetting(dictName, (e.target as HTMLInputElement).checked);
|
||||
if (setting.changeEv) setting.changeEv(e);
|
||||
};
|
||||
label.innerHTML = domText;
|
||||
label.prepend(input);
|
||||
new_node.appendChild(label);
|
||||
break;
|
||||
}
|
||||
case 'button': {
|
||||
new_node = document.createElement('div');
|
||||
let {domId, domText, clickFunc} = setting;
|
||||
let btn = document.createElement('button');
|
||||
(tip) && (btn.setAttribute('title', tip));
|
||||
btn.id = domId;
|
||||
btn.innerHTML = domText;
|
||||
btn.addEventListener('click', clickFunc);
|
||||
new_node.appendChild(btn);
|
||||
break;
|
||||
}
|
||||
case 'select': {
|
||||
new_node = document.createElement('div');
|
||||
let {domSelectOpt, dictName, domId, domText} = setting;
|
||||
let label = document.createElement('label');
|
||||
(tip) && (label.setAttribute('title', tip));
|
||||
let text = document.createTextNode(domText);
|
||||
let select = document.createElement('select');
|
||||
select.id = domId;
|
||||
domSelectOpt.forEach((opt, i) => {
|
||||
let {domVal, domText} = opt;
|
||||
let option = document.createElement('option');
|
||||
option.value = domVal;
|
||||
option.innerHTML = domText;
|
||||
option.selected = i === getWhSettingObj()[dictName];
|
||||
option.innerHTML = domText;
|
||||
select.appendChild(option);
|
||||
});
|
||||
select.onchange = e => setWhSetting(dictName, (<HTMLSelectElement>e.target).selectedIndex);
|
||||
label.appendChild(text);
|
||||
label.appendChild(select);
|
||||
new_node.appendChild(label);
|
||||
break;
|
||||
}
|
||||
case 'plain': {
|
||||
let tag = setting.tagName || 'div';
|
||||
new_node = document.createElement(tag);
|
||||
if (setting.domId) new_node.id = setting.domId;
|
||||
new_node.innerHTML += setting['domHTML'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 移动节点
|
||||
return root_node.appendChild(new_node);
|
||||
}
|
||||
|
||||
/*
|
||||
添加左侧图标
|
||||
*/
|
||||
function initIcon(settings: MenuItemConfig[]): MyHTMLElement {
|
||||
let zhong_node: MyHTMLElement = document.querySelector('div#wh-trans-icon');
|
||||
let {isIframe, version} = window.WHPARAMS;
|
||||
if (isIframe || !!zhong_node) return zhong_node;
|
||||
zhong_node = document.createElement('div');
|
||||
zhong_node.id = 'wh-trans-icon';
|
||||
zhong_node.classList.add('cont-gray');
|
||||
zhong_node.innerHTML = `<div><button id="wh-trans-icon-btn"></button></div>
|
||||
<div class="wh-container">
|
||||
<div class="wh-main">
|
||||
<div><b>芜湖助手</b></div>
|
||||
<div id="wh-gSettings"></div>
|
||||
<div><p>当前版本: ${version.slice(-1) === '$' ? 'DEV' : version} <button id="wh-update-btn">更新</button></p></div>
|
||||
<div><p>最新版本: <span id="wh-latest-version"></span></p></div>
|
||||
<div><p id="wh-inittimer"></p></div>
|
||||
</div>
|
||||
</div>`;
|
||||
// 助手菜单
|
||||
const menu_cont = zhong_node.querySelector('#wh-gSettings');
|
||||
// 设置选项
|
||||
zhong_node.setting_root = document.createElement('div');
|
||||
zhong_node.setting_root.classList.add('gSetting');
|
||||
// 遍历菜单node设置
|
||||
settings.forEach(setting => elemGenerator(setting, menu_cont));
|
||||
// 计时node
|
||||
zhong_node.initTimer = zhong_node.querySelector('#wh-inittimer');
|
||||
// 芜湖助手图标点击事件
|
||||
(<MyHTMLElement>zhong_node.querySelector('#wh-trans-icon-btn')).onclick = () => {
|
||||
zhong_node.classList.toggle('wh-icon-expanded');
|
||||
const click_func = e => {
|
||||
// e.stopImmediatePropagation();
|
||||
log(e.target);
|
||||
if (e.target === zhong_node.querySelector('#wh-trans-icon-btn')) return;
|
||||
if (!zhong_node.contains(e.target)) {
|
||||
log('移除事件监听器');
|
||||
document.body.removeEventListener('click', click_func);
|
||||
zhong_node.classList.remove('wh-icon-expanded');
|
||||
}
|
||||
};
|
||||
if (zhong_node.classList.contains('wh-icon-expanded')) {
|
||||
log('添加事件监听器');
|
||||
document.body.addEventListener('click', click_func);
|
||||
} else {
|
||||
log('移除事件监听器');
|
||||
document.body.removeEventListener('click', click_func);
|
||||
}
|
||||
};
|
||||
// 更新按钮点击事件
|
||||
(<MyHTMLElement>zhong_node.querySelector('#wh-update-btn')).onclick = e => {
|
||||
(<HTMLButtonElement>e.target).blur();
|
||||
const innerHtml = `<h4>电脑</h4>
|
||||
<p>通常电脑浏览器装有油猴等用户脚本扩展时可以使用链接安装(自动更新):<a href="https://gitlab.com/JJins/wuhu-torn-helper/-/raw/dev/release.min.user.js" target="_blank">点此安装</a>。</p>
|
||||
<p>这些扩展长这样:<img src="//jjins.github.io/tm.png" alt="tm.png" /><img src="//jjins.github.io/vm.png" alt="vm.png" /></p>
|
||||
<p></p>
|
||||
<h4>手机</h4>
|
||||
<p>安卓 KIWI 等可以用油猴脚本的浏览器也可以点上面的链接安装👆</p>
|
||||
<p>Torn PDA app 或 Alook 用户可打开<a href="//jjins.github.io/fyfuzhi/" target="_blank">这个网页</a>快捷复制粘贴。</p>
|
||||
<h4>直接复制</h4>
|
||||
<p>加载脚本然后直接复制粘贴到用户脚本处。</p>
|
||||
<p><button>加载</button></p>
|
||||
`;
|
||||
const node = popupMsg(innerHtml, '如何更新');
|
||||
// 直接复制的按钮
|
||||
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()}`);
|
||||
target.innerHTML = '点击复制到剪切板';
|
||||
target.onclick = () => {
|
||||
const textarea_node = document.createElement('textarea');
|
||||
textarea_node.innerHTML = js_text;
|
||||
target.parentElement.append(textarea_node);
|
||||
textarea_node.focus();
|
||||
textarea_node.select();
|
||||
document.execCommand('Copy');
|
||||
textarea_node.remove();
|
||||
target.innerHTML = '已复制';
|
||||
target.onclick = null;
|
||||
WHNotify('脚本已复制,请前往粘贴');
|
||||
};
|
||||
};
|
||||
};
|
||||
// 节日
|
||||
zhong_node.querySelectorAll('#wh-trans-fest-date button').forEach((el, i) => i === 0
|
||||
? el.addEventListener('click', () => {
|
||||
let html = '<table>';
|
||||
settings.fest_date_list.sort().forEach(date =>
|
||||
html += `<tr><td>${1 + ((<any>date.slice(0, 2)) | 0)}月${date.slice(2)}日</td><td>${settings.fest_date_dict[date].name}</td><td>${settings.fest_date_dict[date].eff}</td></tr>`
|
||||
);
|
||||
popupMsg(html += '</table>', '节日');
|
||||
})
|
||||
: el.addEventListener('click', null));
|
||||
// 活动
|
||||
zhong_node.querySelectorAll('#wh-trans-event-cont button').forEach((el, i) => i === 0
|
||||
? el.addEventListener('click', () => {
|
||||
let html = '<table>';
|
||||
settings.events.forEach(el =>
|
||||
html += `<tr><td><b>${el.name}</b></td><td>${el.start[0] + 1}月${el.start[1]}日${el.start[2]}:00~${el.end[0] + 1}月${el.end[1]}日${el.end[2]}:00</td></tr><tr><td colspan="2">${el.eff}</td></tr>`);
|
||||
popupMsg(html += '</table><p>更多信息请关注群聊和公众号</p>', '活动');
|
||||
})
|
||||
: el.addEventListener('click', null));
|
||||
document.body.append(zhong_node);
|
||||
// 引入torn自带浮动提示
|
||||
(window['initializeTooltip']) && (window['initializeTooltip']('.wh-container', 'white-tooltip'));
|
||||
// 加载torn mini profile
|
||||
window.initMiniProf('#wh-trans-icon');
|
||||
return zhong_node;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user