// ==UserScript== // @name NGA Likes Support // @namespace https://greasyfork.org/users/263018 // @version 1.1.1 // @author snyssss // @description 显示被点赞和粉丝数量 // @match *://bbs.nga.cn/* // @match *://ngabbs.com/* // @match *://nga.178.com/* // @noframes // @downloadURL none // ==/UserScript== ((ui) => { if (!ui) return; // 钩子 const hookFunction = (object, functionName, callback) => { ((originalFunction) => { object[functionName] = function () { const returnValue = originalFunction.apply(this, arguments); callback.apply(this, [returnValue, originalFunction, arguments]); return returnValue; }; })(object[functionName]); }; class UserInfo { execute(task) { task().finally(() => { if (this.waitingQueue.length) { const next = this.waitingQueue.shift(); this.execute(next); } else { this.isRunning = false; } }); } enqueue(task) { if (this.isRunning) { this.waitingQueue.push(task); } else { this.isRunning = true; this.execute(task); } } rearrange() { if (this.data) { const list = Object.values(this.children); for (let i = 0; i < list.length; i++) { if (list[i].source === undefined) { list[i].create(this.data); } Object.entries(this.container).forEach((item) => { list[i].clone(this.data, item); }); } } } reload() { this.enqueue(async () => { this.data = await new Promise((resolve) => { fetch(`/nuke.php?lite=js&__lib=ucp&__act=get&uid=${this.uid}`) .then((res) => res.blob()) .then((blob) => { const reader = new FileReader(); reader.onload = () => { const text = reader.result; const result = JSON.parse( text.replace("window.script_muti_get_var_store=", "") ); resolve(result.data[0]); }; reader.readAsText(blob, "GBK"); }) .catch(() => { resolve(); }); }); Object.values(this.children).forEach((item) => item.destroy()); this.rearrange(); }); } constructor(id) { this.uid = id; this.waitingQueue = []; this.isRunning = false; this.container = {}; this.children = {}; this.reload(); } } class UserInfoWidget { destroy() { if (this.source) { this.source = undefined; } if (this.target) { Object.values(this.target).forEach((item) => { if (item.parentNode) { item.parentNode.removeChild(item); } }); } } clone(data, [argid, container]) { if (this.source) { if (this.target[argid] === undefined) { this.target[argid] = this.source.cloneNode(true); if (this.callback) { this.callback(data, this.target[argid]); } } container.appendChild(this.target[argid]); } } constructor(func, callback) { this.create = (data) => { this.destroy(); this.source = func(data); this.target = {}; }; this.callback = callback; } } ui.sn = ui.sn || {}; ui.sn.userInfo = ui.sn.userInfo || {}; ((info) => { const execute = (argid) => { const args = ui.postArg.data[argid]; if (args.comment) return; const uid = +args.pAid; if (uid > 0) { if (info[uid] === undefined) { info[uid] = new UserInfo(uid); } if (document.contains(info[uid].container[argid]) === false) { info[uid].container[argid] = args.uInfoC.querySelector( "[name=uid]" ).parentNode; } info[uid].enqueue(async () => { if (info[uid].children[8] === undefined) { info[uid].children[8] = new UserInfoWidget((data) => { const value = Object.values(data.more_info || {}).find((item) => item.type === 8) ?.data || 0; const element = document.createElement("SPAN"); element.className = "small_colored_text_btn stxt block_txt_c2 vertmod"; element.style.cursor = "default"; element.innerHTML = ` ${value}`; return element; }); } if (info[uid].children[16] === undefined) { info[uid].children[16] = new UserInfoWidget((data) => { const value = data.follow_by_num || 0; const element = document.createElement("SPAN"); element.className = "small_colored_text_btn stxt block_txt_c2 vertmod"; element.style.cursor = "default"; element.innerHTML = ` ${value}`; return element; }); } info[uid].rearrange(); }); } }; if (ui.postArg) { Object.keys(ui.postArg.data).forEach((i) => execute(i)); } let initialized = false; hookFunction(ui, "eval", () => { if (initialized) return; if (ui.postDisp) { hookFunction( ui, "postDisp", (returnValue, originalFunction, arguments) => execute(arguments[0]) ); initialized = true; } }); })(ui.sn.userInfo); })(commonui);