您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
同步客户端关注功能
// ==UserScript== // @name NGA Follow Support // @namespace https://gf.qytechs.cn/users/263018 // @version 1.3.5 // @author snyssss // @description 同步客户端关注功能 // @match *://bbs.nga.cn/* // @match *://ngabbs.com/* // @match *://nga.178.com/* // @grant GM_addStyle // @grant GM_setValue // @grant GM_getValue // @grant GM_addValueChangeListener // @grant GM_registerMenuCommand // @noframes // ==/UserScript== ((ui, self) => { if (!ui || !self) 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]); }; ui.sn = ui.sn || {}; ui.sn.userInfo = ui.sn.userInfo || {}; ((info) => { // 用户信息 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 get_user_info(this.uid); 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]); } } const isSmall = container.classList.contains("posterInfoLine"); if (isSmall) { const anchor = container.querySelector(".author ~ br"); if (anchor) { anchor.parentNode.insertBefore(this.target[argid], anchor); } } else { container.appendChild(this.target[argid]); } } } constructor(func, callback) { this.create = (data) => { this.destroy(); this.source = func(data); this.target = {}; }; this.callback = callback; } } // 扩展规则 const extraData = (() => { const key = `EXTRA_DATA`; const data = GM_getValue(key) || { [0]: { time: 0, }, }; const save = () => { GM_setValue(key, data); }; const setValue = (uid, value) => { data[uid] = value; save(); }; const getValue = (uid) => data[uid]; const remove = (uid) => { delete data[uid]; save(); }; const specialList = () => { const result = Object.entries(data).filter( ([key, value]) => value.level ); if (Object.keys(result)) { return result; } return null; }; GM_addValueChangeListener(key, function (_, prev, next) { Object.assign(data, next); }); return { specialList, setValue, getValue, remove, }; })(); // 获取用户信息 const get_user_info = (uid) => { const searchPair = (content, keyword, start = "{", end = "}") => { // 获取成对括号的位置 const getLastIndex = (content, position, start = "{", end = "}") => { if (position >= 0) { let nextIndex = position + 1; while (nextIndex < content.length) { if (content[nextIndex] === end) { return nextIndex; } if (content[nextIndex] === start) { nextIndex = getLastIndex(content, nextIndex, start, end); if (nextIndex < 0) { break; } } nextIndex = nextIndex + 1; } } return -1; }; // 起始位置 const str = keyword + start; // 起始下标 const index = content.indexOf(str) + str.length; // 结尾下标 const lastIndex = getLastIndex(content, index, start, end); if (lastIndex >= 0) { return start + content.substring(index, lastIndex) + end; } return null; }; return new Promise((resolve, reject) => { fetch(`/nuke.php?func=ucp&uid=${uid}`) .then((res) => res.blob()) .then((blob) => { const reader = new FileReader(); reader.onload = () => { const text = searchPair(reader.result, `__UCPUSER =`); if (text) { try { resolve(JSON.parse(text)); return; } catch { reject(); return; } } reject(); }; reader.readAsText(blob, "GBK"); }) .catch(() => { reject(); }); }); }; // 获取用户发帖列表 const get_user_topic_list = (uid) => new Promise((resolve) => { fetch(`/thread.php?lite=js&authorid=${uid}`) .then((res) => res.blob()) .then((blob) => { const reader = new FileReader(); reader.onload = () => { const text = reader.result; const result = eval(` (${text.replace("window.script_muti_get_var_store=", "")}) `); if (result.data) { resolve(result.data.__T); } else { resolve({}); } }; reader.readAsText(blob, "GBK"); }) .catch(() => { resolve({}); }); }); // 获取用户回帖列表 const get_user_post_list = (uid) => new Promise((resolve, reject) => { fetch(`/thread.php?lite=js&authorid=${uid}&searchpost=1`) .then((res) => res.blob()) .then((blob) => { const reader = new FileReader(); reader.onload = () => { const text = reader.result; const result = eval(` (${text.replace("window.script_muti_get_var_store=", "")}) `); if (result.data) { resolve(result.data.__T); } else { resolve({}); } }; reader.readAsText(blob, "GBK"); }) .catch(() => { resolve({}); }); }); // 关注 const follow = (uid) => new Promise((resolve, reject) => { fetch( `/nuke.php?lite=js&__lib=follow_v2&__act=follow&id=${uid}&type=1`, { method: "post", } ) .then((res) => res.blob()) .then((blob) => { const reader = new FileReader(); reader.onload = () => { const text = reader.result; const result = eval(` (${text.replace("window.script_muti_get_var_store=", "")}) `); if (result.data) { resolve(result.data[0]); } else { reject(result.error[0]); } }; reader.readAsText(blob, "GBK"); }) .catch(() => { reject(); }); }); // 取消关注 const un_follow = (uid) => new Promise((resolve, reject) => { fetch( `/nuke.php?lite=js&__lib=follow_v2&__act=follow&id=${uid}&type=8`, { method: "post", } ) .then((res) => res.blob()) .then((blob) => { const reader = new FileReader(); reader.onload = () => { const text = reader.result; const result = eval(` (${text.replace("window.script_muti_get_var_store=", "")}) `); if (result.data) { resolve(result.data[0]); } else { reject(result.error[0]); } }; reader.readAsText(blob, "GBK"); }) .catch(() => { reject(); }); }); // 移除粉丝 const un_follow_fans = (uid) => new Promise((resolve, reject) => { fetch( `/nuke.php?lite=js&__lib=follow_v2&__act=follow&id=${uid}&type=256`, { method: "post", } ) .then((res) => res.blob()) .then((blob) => { const reader = new FileReader(); reader.onload = () => { const text = reader.result; const result = eval(` (${text.replace("window.script_muti_get_var_store=", "")}) `); if (result.data) { resolve(result.data[0]); } else { reject(result.error[0]); } }; reader.readAsText(blob, "GBK"); }) .catch(() => { reject(); }); }); // 获取关注列表 const follow_list = (page) => new Promise((resolve, reject) => { fetch( `/nuke.php?lite=js&__lib=follow_v2&__act=get_follow&page=${page}`, { method: "post", } ) .then((res) => res.blob()) .then((blob) => { const reader = new FileReader(); reader.onload = () => { const text = reader.result; const result = eval(` (${text.replace("window.script_muti_get_var_store=", "")}) `); if (result.data) { resolve(result.data[0]); } else { reject(result.error[0]); } }; reader.readAsText(blob, "GBK"); }) .catch(() => { reject(); }); }); // 获取粉丝列表 const follow_by_list = (page) => new Promise((resolve, reject) => { fetch( `/nuke.php?lite=js&__lib=follow_v2&__act=get_follow_by&page=${page}`, { method: "post", } ) .then((res) => res.blob()) .then((blob) => { const reader = new FileReader(); reader.onload = () => { const text = reader.result; const result = eval(` (${text.replace("window.script_muti_get_var_store=", "")}) `); if (result.data) { resolve(result.data[0]); } else { reject(result.error[0]); } }; reader.readAsText(blob, "GBK"); }) .catch(() => { reject(); }); }); // 获取关注动态 const follow_dymanic_list = (page) => new Promise((resolve, reject) => { fetch( `/nuke.php?lite=js&__lib=follow_v2&__act=get_push_list&page=${page}`, { method: "post", } ) .then((res) => res.blob()) .then((blob) => { const reader = new FileReader(); reader.onload = () => { const text = reader.result; const result = eval(` (${text.replace("window.script_muti_get_var_store=", "")}) `); if (result.data) { resolve(result.data); } else { reject(result.error[0]); } }; reader.readAsText(blob, "GBK"); }) .catch(() => { reject(); }); }); // 切换关注 const handleSwitchFollow = (uid, isFollow) => { if (isFollow) { if (confirm("取消关注?")) { un_follow(uid).then(() => { info[uid]?.reload(); u.refresh(); }); } } else { follow(uid).then(() => { info[uid]?.reload(); u.refresh(); }); } }; // 移除粉丝 const handleRemoveFans = (uid) => { if (confirm("移除粉丝?")) { un_follow_fans(uid).then(() => { u.refresh(); }); } }; // STYLE GM_addStyle(` .s-user-info-container:not(:hover) .ah { display: none !important; } .s-table-wrapper { height: calc((2em + 10px) * 11 + 3px); overflow-y: auto; } .s-table { margin: 0; } .s-table th, .s-table td { position: relative; white-space: nowrap; } .s-table th { position: sticky; top: 2px; z-index: 1; } .s-table input:not([type]), .s-table input[type="text"] { margin: 0; box-sizing: border-box; height: 100%; width: 100%; } .s-input-wrapper { position: absolute; top: 6px; right: 6px; bottom: 6px; left: 6px; } .s-text-ellipsis { display: flex; } .s-text-ellipsis > * { flex: 1; width: 1px; overflow: hidden; text-overflow: ellipsis; } .s-button-group { margin: -.1em -.2em; } `); // MENU const m = (() => { const container = document.createElement("DIV"); container.className = `td`; container.innerHTML = `<a class="mmdefault" href="javascript: void(0);" style="white-space: nowrap;">关注</a>`; const content = container.querySelector("A"); const create = (onclick) => { const anchor = document.querySelector("#mainmenu .td:last-child"); anchor.before(container); content.onclick = onclick; }; const update = (count) => { if (count) { content.innerHTML = `关注 <span class="small_colored_text_btn stxt block_txt_c0 vertmod">${count}</span>`; } else { content.innerHTML = `关注`; } }; return { create, update, }; })(); // UI const u = (() => { const modules = {}; const createView = () => { const tabContainer = (() => { const c = document.createElement("div"); c.className = "w100"; c.innerHTML = ` <div class="right_" style="margin-bottom: 5px;"> <table class="stdbtn" cellspacing="0"> <tbody> <tr></tr> </tbody> </table> </div> <div class="clear"></div> `; return c; })(); const tabPanelContainer = (() => { const c = document.createElement("div"); c.style = "width: 800px;"; return c; })(); const content = (() => { const c = document.createElement("div"); c.append(tabContainer); c.append(tabPanelContainer); return c; })(); const addModule = (() => { const tc = tabContainer.getElementsByTagName("tr")[0]; const cc = tabPanelContainer; return (module) => { const tabBox = document.createElement("td"); tabBox.innerHTML = `<a href="javascript:void(0)" class="nobr silver">${module.name}</a>`; const tab = tabBox.childNodes[0]; const toggle = () => { Object.values(modules).forEach((item) => { if (item.tab === tab) { item.tab.className = "nobr"; item.content.style = "display: block"; item.visible = true; } else { item.tab.className = "nobr silver"; item.content.style = "display: none"; item.visible = false; } }); module.refresh(); }; tc.append(tabBox); cc.append(module.content); tab.onclick = (() => { let timeout; return () => { if (timeout > 0) { return; } timeout = setTimeout(() => { timeout = 0; }, 320); toggle(); }; })(); modules[module.name] = { ...module, tab, toggle, visible: false, }; return modules[module.name]; }; })(); return { content, addModule, }; }; const refresh = () => { Object.values(modules) .find((item) => item.visible) ?.refresh(); }; return { modules, createView, refresh, }; })(); // 我的关注 { const name = "我的关注"; const content = (() => { const c = document.createElement("div"); c.style.display = "none"; c.innerHTML = ` <div class="s-table-wrapper"> <table class="s-table forumbox"> <thead> <tr class="block_txt_c0"> <th class="c1" width="1">用户</th> <th class="c2">过滤规则</th> <th class="c3" width="1">特别关注</th> <th class="c4" width="1">操作</th> </tr> </thead> <tbody></tbody> </table> </div> <div class="silver" style="margin-top: 5px;">特别关注功能需要占用额外的资源,请谨慎开启</div> `; return c; })(); let page = 0; let hasNext = false; let isFetching = false; const box = content.querySelector("DIV"); const list = content.querySelector("TBODY"); const wrapper = content.querySelector(".s-table-wrapper"); const fetchData = () => { isFetching = true; follow_list(page) .then((res) => { hasNext = Object.keys(res).length > 0; for (let i in res) { const { uid, username } = res[i]; const data = extraData.getValue(uid) || {}; if (list.querySelector(`[data-id="${uid}"]`)) { continue; } const item = document.createElement("TR"); item.className = `row${ (list.querySelectorAll("TR").length % 2) + 1 }`; item.setAttribute("data-id", uid); item.innerHTML = ` <td class="c1"> <a href="/nuke.php?func=ucp&uid=${uid}" class="b nobr">${username}</a> </td> <td class="c2"> <div class="s-input-wrapper"> <input value="${data.rule || ""}" /> </div> </td> <td class="c3"> <div style="text-align: center;"> <input type="checkbox" ${ data.level ? `checked="checked"` : "" } /> </div> </td> <td class="c4"> <div class="s-button-group"> <button>重置</button> <button>移除</button> </div> </td> `; const ruleElement = item.querySelector("INPUT"); const levelElement = item.querySelector(`INPUT[type="checkbox"]`); const actions = item.querySelectorAll("BUTTON"); const save = () => { extraData.setValue(uid, { rule: ruleElement.value, level: levelElement.checked ? 1 : 0, }); }; const clear = () => { ruleElement.value = ""; levelElement.checked = false; save(); }; ruleElement.onchange = save; levelElement.onchange = save; actions[0].onclick = () => clear(); actions[1].onclick = () => handleSwitchFollow(uid, 1); list.appendChild(item); } }) .finally(() => { isFetching = false; }); }; box.onscroll = () => { if (isFetching || !hasNext) { return; } if ( box.scrollHeight - box.scrollTop - box.clientHeight <= wrapper.clientHeight ) { page = page + 1; fetchData(); } }; const refresh = () => { list.innerHTML = ""; page = 1; hasNext = false; fetchData(); }; hookFunction(u, "createView", (view) => { view.addModule({ name, content, refresh, }); }); } // 我的粉丝 { const name = "我的粉丝"; const content = (() => { const c = document.createElement("div"); c.style.display = "none"; c.innerHTML = ` <div class="s-table-wrapper"> <table class="s-table forumbox"> <thead> <tr class="block_txt_c0"> <th class="c1">用户</th> <th class="c2" width="1">操作</th> </tr> </thead> <tbody></tbody> </table> </div> `; return c; })(); let page = 0; let hasNext = false; let isFetching = false; const box = content.querySelector("DIV"); const list = content.querySelector("TBODY"); const wrapper = content.querySelector(".s-table-wrapper"); const fetchData = () => { isFetching = true; follow_by_list(page) .then((res) => { hasNext = Object.keys(res).length > 0; for (let i in res) { const { uid, username } = res[i]; if (list.querySelector(`[data-id="${uid}"]`)) { continue; } const item = document.createElement("TR"); item.className = `row${ (list.querySelectorAll("TR").length % 2) + 1 }`; item.setAttribute("data-id", uid); item.innerHTML = ` <td class="c1"> <a href="/nuke.php?func=ucp&uid=${uid}" class="b nobr">${username}</a> </td> <td class="c2"> <div class="s-button-group"> <button>移除</button> </div> </td> `; const action = item.querySelector("BUTTON"); action.onclick = () => handleRemoveFans(uid); list.appendChild(item); } }) .finally(() => { isFetching = false; }); }; box.onscroll = () => { if (isFetching || !hasNext) { return; } if ( box.scrollHeight - box.scrollTop - box.clientHeight <= wrapper.clientHeight ) { page = page + 1; fetchData(); } }; const refresh = () => { list.innerHTML = ""; page = 1; hasNext = false; fetchData(); }; hookFunction(u, "createView", (view) => { view.addModule({ name, content, refresh, }); }); } // 关注动态 { const name = "关注动态"; const content = (() => { const c = document.createElement("div"); c.style.display = "none"; c.innerHTML = ` <div class="s-table-wrapper"> <table class="s-table forumbox"> <thead> <tr class="block_txt_c0"> <th class="c1" width="1">时间</th> <th class="c2">内容</th> </tr> </thead> <tbody></tbody> </table> </div> `; return c; })(); let page = 0; let hasNext = false; let isFetching = false; const box = content.querySelector("DIV"); const list = content.querySelector("TBODY"); const wrapper = content.querySelector(".s-table-wrapper"); const fetchData = () => { isFetching = true; follow_dymanic_list(page) .then((res) => Promise.all( Object.keys(res[1]).map((uid) => get_user_info(uid).then((item) => { if (item.follow) { const info = extraData.getValue(uid) || { rule: "", level: 0, }; extraData.setValue(uid, { ...info, }); } else { extraData.remove(uid); } }) ) ).then(() => { return res; }) ) .then((res) => { hasNext = res[2] > res[3]; extraData.setValue(0, { time: Math.floor(new Date() / 1000), unread: 0, }); return res; }) .then((res) => { const filtered = Object.values(res[0]) .map((item) => ({ id: item[0], uid: item[2], info: item[4] ? res[4][`${item[3]}_${item[4]}`] : res[4][item[3]], time: item[6], summary: item.summary .replace( /\[uid=(\d+)\](.+)\[\/uid\]/, `<a href="/nuke.php?func=ucp&uid=${item[2]}" class="b nobr">$2</a>` ) .replace( /\[pid=(\d+)\](.+)\[\/pid\](\s?)/, `<a href="/read.php?pid=${item[4]}" class="b nobr">回复</a>` ) .replace( /\[tid=(\d+)\](.+)\[\/tid\]/, item[4] === 0 ? `<a href="/read.php?tid=${item[3]}" title="$2" class="b nobr">$2</a>` : `<a href="/read.php?pid=${item[4]}&opt=128" title="$2" class="b nobr">$2</a>` ), })) .filter((item) => { const { uid, info } = item; const data = extraData.getValue(uid); if (data) { const { rule } = data; if (rule) { return ( info.subject.search(rule) >= 0 || info.content.search(rule) >= 0 ); } return true; } return false; }); return filtered; }) .then((res) => { for (let i in res) { const { id, time, summary } = res[i]; if (list.querySelector(`[data-id="${id}"]`)) { continue; } const item = document.createElement("TR"); item.className = `row${ (list.querySelectorAll("TR").length % 2) + 1 }`; item.setAttribute("data-id", id); item.setAttribute("data-time", time); item.innerHTML = ` <td class="c1"> <span class="nobr">${ui.time2dis(time)}</span> </td> <td class="c2"> <div class="s-text-ellipsis"> <span>${summary}</span> </div> </td> `; list.appendChild(item); } if (box.scrollHeight === box.clientHeight && hasNext) { page = page + 1; fetchData(); } }) .finally(() => { isFetching = false; }); }; box.onscroll = () => { if (isFetching || !hasNext) { return; } if ( box.scrollHeight - box.scrollTop - box.clientHeight <= wrapper.clientHeight ) { page = page + 1; fetchData(); } }; const refresh = () => { list.innerHTML = ""; page = 1; hasNext = false; fetchData(); }; hookFunction(u, "createView", (view) => { view.addModule({ name, content, refresh, }); }); } // 打开菜单 const handleCreateView = (() => { let view, window; return () => { if (view === undefined) { view = u.createView(); } u.modules["关注动态"].toggle(); m.update(0); if (window === undefined) { window = ui.createCommmonWindow(); } window._.addContent(null); window._.addTitle(`关注`); window._.addContent(view.content); window._.show(); }; })(); // 扩展用户信息 (() => { 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.closest("tr").querySelector(".posterInfoLine") || args.uInfoC.querySelector("div"); } info[uid].enqueue(async () => { args.uInfoC.className = args.uInfoC.className + " s-user-info-container"; if (info[uid].children[16]) { info[uid].children[16].destroy(); } info[uid].children[16] = new UserInfoWidget( (data) => { const value = data.follow_by_num || 0; const element = document.createElement("SPAN"); if (uid === self || data.follow) { element.className = "small_colored_text_btn stxt block_txt_c2 vertmod"; } else { element.className = "small_colored_text_btn stxt block_txt_c2 vertmod ah"; } element.style.cursor = "default"; element.innerHTML = `<span class="white"><span style="font-family: comm_glyphs; -webkit-font-smoothing: antialiased; line-height: 1em;">★</span> ${value}</span>`; element.style.cursor = "pointer"; return element; }, (data, element) => { element.onclick = () => { if (data.uid === self) { handleCreateView(); } else { handleSwitchFollow(data.uid, data.follow); } }; } ); info[uid].rearrange(); }); } }; let initialized = false; if (ui.postArg) { Object.keys(ui.postArg.data).forEach((i) => execute(i)); } hookFunction(ui, "eval", () => { if (initialized) return; if (ui.postDisp) { hookFunction( ui, "postDisp", (returnValue, originalFunction, arguments) => execute(arguments[0]) ); initialized = true; } }); })(); // 提醒关注 (async () => { // 增加菜单项 m.create(handleCreateView); // 获取动态 (() => { const cache = extraData.getValue(0) || { time: 0, unread: 0, }; const fetchData = async (page = 1, result = {}) => new Promise((resolve) => { follow_dymanic_list(page).then(async (res) => { const list = Object.values(res[0]); const prefiltered = list .map((item) => ({ id: item[0], uid: item[2], info: item[4] ? res[4][`${item[3]}_${item[4]}`] : res[4][item[3]], time: item[6], })) .filter((item) => item.time > (cache.time || 0)) .filter((item) => { if (result[item.id]) { return false; } result[item.id] = item; return true; }); if (prefiltered.length) { await Promise.all( Object.keys(res[1]).map((uid) => get_user_info(uid).then((item) => { if (item.follow) { const info = extraData.getValue(uid) || { rule: "", level: 0, }; extraData.setValue(uid, { ...info, }); } else { extraData.remove(uid); } }) ) ); const hasNext = prefiltered.length === list.length && res[2] > res[3]; if (hasNext) { const withNext = await fetchData(page + 1, result); resolve(withNext); } } resolve(result); }); }); fetchData().then((res) => { const filtered = Object.values(res).filter((item) => { const { uid, info } = item; const data = extraData.getValue(uid); if (data) { const { rule } = data; if (rule) { return ( info.subject.search(rule) >= 0 || info.content.search(rule) >= 0 ); } return true; } return false; }); const unread = (cache.unread || 0) + filtered.length; extraData.setValue(0, { time: Math.floor(new Date() / 1000), unread: unread, }); m.update(unread); }); })(); // 特别关注 { const fetchData = async (uid, value) => { // 请求用户信息 const { username, follow, posts } = await get_user_info(uid); // 用户缓存 const { rule, time, postNum } = value; // 已取消关注 if (follow === 0) { extraData.remove(uid); return []; } // 判断是否有新活动 if (posts <= (postNum || 0)) { return []; } // 是否匹配 const isMatch = (text) => { if (rule) { return text.search(rule) >= 0; } return true; }; // 请求发帖记录 const ts = await get_user_topic_list(uid).then((res) => Object.values(res) .filter( (item) => item.postdate > (time || 0) && isMatch(item.subject) ) .map((item) => ({ 0: 5, 1: item.authorid, 2: item.author, 5: item.subject, 6: item.tid, 9: item.postdate, 10: 1, })) ); // 请求回帖记录 const ps = await get_user_post_list(uid).then((res) => Object.values(res) .filter( (item) => item.__P.postdate > (time || 0) && isMatch(item.__P.content) ) .map((item) => ({ 0: 6, 1: uid, 2: username, 5: item.subject, 6: item.__P.tid, 7: item.__P.pid, 9: item.__P.postdate, 10: 1, })) ); // 更新缓存 extraData.setValue(uid, { ...value, time: Math.floor(new Date() / 1000), postNum: posts, }); // 返回结果 return [...ts, ...ps]; }; const data = ( await Promise.all( extraData .specialList() .map(async ([key, value]) => await fetchData(key, value)) ) ) .flat() .sort((a, b) => a[9] - b[9]); if (Object.keys(data).length) { const func = () => { // 修复 NGA 脚本错误 TPL[KEY["_BIT_SYS"]][KEY["_TYPE_KEYWORD_WATCH_REPLY"]] = function ( x ) { return x[KEY["_ABOUT_ID_4"]] ? "{_U} 在{_T1} {_R2} 中的 {_R5} 触发了关键词监视<br/>" : "{_U} 在主题 {_T} 中的 {_R5} 触发了关键词监视<br/>"; }; // 推送消息 for (let i in data) { ui.notification._add(1, data[i], 1); } // 打开窗口 ui.notification.openBox(); }; if (ui.notification) { func(); } else { ui.loadNotiScript(() => { func(); }); } } } })(); })(ui.sn.userInfo); })(commonui, __CURRENT_UID);
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址