论坛 | NGA论坛常用油猴插件
置顶折叠 - NGA Topped Collapse
折叠版头,版块标题是切换按钮。
另有选项可选择是否折叠子版块和广告。
// ==UserScript==
// @name NGA Topped Collapse
// @namespace https://greasyfork.org/users/263018
// @version 1.0.1
// @author snyssss
// @description 置顶折叠
// @match *://bbs.nga.cn/*
// @match *://ngabbs.com/*
// @match *://nga.178.com/*
// @grant GM_registerMenuCommand
// @grant GM_setValue
// @grant GM_getValue
// @noframes
// ==/UserScript==
((ui) => {
if (!ui) return;
// KEY
const COLLAPSE_SUBFORUMS_ENABLE_KEY = "COLLAPSE_SUBFORUMS_ENABLE";
const COLLAPSE_ADS_ENABLE_KEY = "COLLAPSE_ADS_ENABLE";
// 折叠子版块
const collapseSubForumsEnable =
GM_getValue(COLLAPSE_SUBFORUMS_ENABLE_KEY) || false;
// 折叠广告
const collapseAdsEnable =
GM_getValue(COLLAPSE_ADS_ENABLE_KEY) || false;
// 钩子
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]);
};
// 是否折叠
let collapsed = true;
// 主函数
const execute = () => {
const topped = document.querySelector("#toptopics");
if (topped) {
const postrow = topped.querySelector(".postrow");
const subForums = collapseSubForumsEnable ? document.querySelectorAll(
"#sub_forums_c, #more_sub_forums_c"
) : [];
const ads = collapseAdsEnable ? document.querySelectorAll(
"[id*=bbs_ads]"
) : [];
const collapse = () => {
[postrow, ...subForums, ...ads].forEach(
(element) => {
element.style = `display: ${collapsed ? "none" : "block"}`;
}
);
};
const button = topped.querySelector("A");
button.onclick = () => {
collapsed = !collapsed;
collapse();
return false;
};
collapse();
}
};
// 绑定事件
(() => {
let initialized = false;
hookFunction(ui, "eval", () => {
if (initialized) return;
if (ui.parseToppedTopic) {
hookFunction(ui, "parseToppedTopic", execute);
initialized = true;
}
});
execute();
})();
// 菜单项
(() => {
// 折叠子版块
if (collapseSubForumsEnable) {
GM_registerMenuCommand("折叠子版块:启用", () => {
GM_setValue(COLLAPSE_SUBFORUMS_ENABLE_KEY, false);
location.reload();
});
} else {
GM_registerMenuCommand("折叠子版块:禁用", () => {
GM_setValue(COLLAPSE_SUBFORUMS_ENABLE_KEY, true);
location.reload();
});
}
// 折叠广告
if (collapseAdsEnable) {
GM_registerMenuCommand("折叠广告:启用", () => {
GM_setValue(COLLAPSE_ADS_ENABLE_KEY, false);
location.reload();
});
} else {
GM_registerMenuCommand("折叠广告:禁用", () => {
GM_setValue(COLLAPSE_ADS_ENABLE_KEY, true);
location.reload();
});
}
})();
})(commonui);
简单的自动翻页 - NGA Auto Pagerize
简单的自动翻页
附加功能:让帖子的附件标识更加明显。
// ==UserScript==
// @name NGA Auto Pagerize
// @namespace https://greasyfork.org/users/263018
// @version 1.1.4
// @author snyssss
// @description 简单的自动翻页
// @match *://bbs.nga.cn/*
// @match *://ngabbs.com/*
// @match *://nga.178.com/*
// @grant GM_registerMenuCommand
// @grant GM_setValue
// @grant GM_getValue
// @noframes
// ==/UserScript==
((ui) => {
if (!ui) return;
// KEY
const ATTACHMENT_STYLE_ENABLE_KEY = "ATTACHMENT_STYLE_ENABLE";
// 附件样式
const attachmentStyleEnable = GM_getValue(ATTACHMENT_STYLE_ENABLE_KEY) || false;
// 钩子
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]);
};
// 翻页
if (ui.pageBtn) {
const delay = (interval) =>
new Promise((resolve) => setTimeout(resolve, interval));
const retry = async (fn, retriesLeft = 10, interval = 160) => {
try {
return await fn();
} catch (error) {
await delay(interval);
if (retriesLeft > 0) {
return await retry(fn, retriesLeft - 1, interval);
}
}
};
const execute = (() => {
const observer = new IntersectionObserver((entries) => {
if (entries.find((item) => item.isIntersecting)) {
retry(() => {
if (ui.loadReadHidden.lock) {
throw new Error();
}
ui.loadReadHidden(0, 2);
});
}
});
return () => {
const anchor = document.querySelector('[title="加载下一页"]');
if (anchor) {
observer.observe(anchor);
} else {
observer.disconnect();
}
};
})();
hookFunction(ui, "pageBtn", execute);
execute();
}
// 移除重复内容
if (ui.topicArg)
{
const execute = () => {
ui.topicArg.data = ui.topicArg.data.reduce((accumulator, currentValue) => {
const index = accumulator.findIndex((item) => item[8] === currentValue[8]);
if (index < 0) {
return [...accumulator, currentValue];
}
currentValue[0].closest("TBODY").remove();
return accumulator;
}, []);
};
hookFunction(ui.topicArg, "loadAll", execute);
execute();
}
// 附件样式
if (ui.topicArg && attachmentStyleEnable)
{
const execute = () => {
const elements = document.querySelectorAll('[title="主题中有附件"]');
elements.forEach((element) => {
element.className = "block_txt white nobr vertmod";
element.style = "background-color: #BD7E6D";
element.innerHTML = "附件";
})
};
hookFunction(ui.topicArg, "loadAll", execute);
execute();
}
if (attachmentStyleEnable) {
GM_registerMenuCommand('附件样式:启用', () => {
GM_setValue(ATTACHMENT_STYLE_ENABLE_KEY, false);
location.reload();
});
} else {
GM_registerMenuCommand('附件样式:禁用', () => {
GM_setValue(ATTACHMENT_STYLE_ENABLE_KEY, true);
location.reload();
});
}
})(commonui);
狗叔,咱们有自己的论坛了 - NGA x Saraba1st Smiles
如果一个论坛发言像s1
表情像s1
还经常出现在s1微博中
那么它就是s1
// ==UserScript==
// @name NGA x Saraba1st Smiles
// @namespace https://greasyfork.org/users/263018
// @version 1.1.4
// @author snyssss
// @description 狗叔,咱们有自己的论坛了
// @match *://bbs.nga.cn/*
// @match *://ngabbs.com/*
// @match *://nga.178.com/*
// @noframes
// ==/UserScript==
((ui, poster) => {
if (!ui) return;
if (!poster) 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]);
};
const smiles = [
[
"麻将",
[
"./mon_202011/26/-9lddQ5-ga9hK0Sw-w.png",
"./mon_202011/26/-9lddQ5-18dlK0Sw-w.png",
"./mon_202011/26/-9lddQ5-7ymuK0Sw-w.gif",
"./mon_202011/26/-9lddQ5-dtlrK0Sw-w.png",
"./mon_202011/26/-9lddQ5-jmfjK2Sw-w.gif",
"./mon_202011/26/-9lddQ5-57p6K0Sw-w.png",
"./mon_202011/26/-9lddQ5-bvn7K0Sw-w.png",
"./mon_202011/26/-9lddQ5-jeaeK0Sw-w.png",
"./mon_202011/26/-9lddQ5-4y0mK0Sw-w.png",
"./mon_202011/26/-9lddQ5-bwgvK2S12-w.gif",
"./mon_202011/26/-9lddQ5-jbw3K0Sw-w.png",
"./mon_202011/26/-9lddQ5-6y0rK0Sw-w.png",
"./mon_202011/26/-9lddQ5-cmumK0Sw-w.png",
"./mon_202011/26/-9lddQ5-icanK0Sw-w.png",
"./mon_202011/26/-9lddQ5-3eklK0Sw-w.png",
"./mon_202011/26/-9lddQ5-bk1dK0Sw-w.png",
"./mon_202011/26/-9lddQ5-hj2hK0Sw-w.png",
"./mon_202011/26/-9lddQ5-21htK0Sw-w.png",
"./mon_202011/26/-9lddQ5-7oc9K0Sw-w.png",
"./mon_202011/26/-9lddQ5-dn7aK0Sw-w.png",
"./mon_202011/26/-9lddQ5-k91uK0Sw-w.png",
"./mon_202011/26/-9lddQ5-4y43K0Sw-w.png",
"./mon_202011/26/-9lddQ5-bszeK1Sw-w.png",
"./mon_202011/26/-9lddQ5-hrc1K0Sw-w.png",
"./mon_202011/26/-9lddQ5-2j95K0Sw-w.png",
"./mon_202011/26/-9lddQ5-8ge1K0Sw-w.png",
"./mon_202011/26/-9lddQ5-eqmxK0Sw-w.png",
"./mon_202011/26/-9lddQ5-kpz5K0Sw-w.png",
"./mon_202011/26/-9lddQ5-4n7iK0Sw-w.png",
"./mon_202011/26/-9lddQ5-akkzK0Sw-w.png",
],
[
"./mon_202011/26/-9lddQ5-9yu9K0Sw-w.png",
"./mon_202011/26/-9lddQ5-ga6xK0Sw-w.png",
"./mon_202011/26/-9lddQ5-tzyK0Sw-w.png",
"./mon_202011/26/-9lddQ5-78i4K0Sw-w.png",
"./mon_202011/26/-9lddQ5-dot4K0Sw-w.png",
"./mon_202011/26/-9lddQ5-jf0iK0Sw-w.png",
"./mon_202011/26/-9lddQ5-47cmK0Sw-w.png",
"./mon_202011/26/-9lddQ5-ati2K0Sw-w.png",
"./mon_202011/26/-9lddQ5-fz6rK0Sw-w.png",
"./mon_202011/26/-9lddQ5-laiaK0Sw-w.png",
"./mon_202011/26/-9lddQ5-5r2bK0Sw-w.png",
"./mon_202011/26/-9lddQ5-bhmbK0Sw-w.png",
"./mon_202011/26/-9lddQ5-ho52K0Sw-w.png",
"./mon_202011/26/-9lddQ5-1artK0Sw-w.png",
"./mon_202011/26/-9lddQ5-6pr7K0Sw-w.png",
"./mon_202011/26/-9lddQ5-bmh9K0Sw-w.png",
"./mon_202011/26/-9lddQ5-hrpuK0Sw-w.png",
"./mon_202011/26/-9lddQ5-2lw1K0Sw-w.png",
"./mon_202011/26/-9lddQ5-90wpK0Sw-w.png",
"./mon_202011/26/-9lddQ5-estbK0Sw-w.png",
"./mon_202011/26/-9lddQ5-jv2mK0Sw-w.png",
"./mon_202011/26/-9lddQ5-3sfoK0Sw-w.png",
"./mon_202011/26/-9lddQ5-9e5hK0Sw-w.png",
"./mon_202011/26/-9lddQ5-feezK0Sw-w.png",
"./mon_202011/26/-9lddQ5-lbsaK0Sw-w.png",
"./mon_202011/26/-9lddQ5-50bqK0Sw-w.png",
"./mon_202011/26/-9lddQ5-av8vK0Sw-w.png",
"./mon_202011/26/-9lddQ5-gi6iK0Sw-w.png",
"./mon_202011/26/-9lddQ5-iefK0Sw-w.png",
"./mon_202011/26/-9lddQ5-6rbjK0Sw-w.png",
],
[
"./mon_202011/26/-9lddQ5-3uK1Sw-w.png",
"./mon_202011/26/-9lddQ5-69lsK0Sw-w.png",
"./mon_202011/26/-9lddQ5-cfdrK0Sw-w.png",
"./mon_202011/26/-9lddQ5-hwm9K4T8Sw-w.gif",
"./mon_202011/26/-9lddQ5-2mavK0Sw-w.png",
"./mon_202011/26/-9lddQ5-87fpK0Sw-w.png",
"./mon_202011/26/-9lddQ5-eirbK0S10-x.png",
"./mon_202011/26/-9lddQ5-k0t5K0Sw-w.png",
"./mon_202011/26/-9lddQ5-4p0uK1S10-y.gif",
"./mon_202011/26/-9lddQ5-bf27K1S10-x.gif",
"./mon_202011/26/-9lddQ5-gtjxK0Sw-w.png",
"./mon_202011/26/-9lddQ5-2ncbK0Sw-w.png",
"./mon_202011/26/-9lddQ5-8evwK1Sw-w.png",
"./mon_202011/26/-9lddQ5-e1mvK0Sw-w.png",
"./mon_202011/26/-9lddQ5-kghcK0Sw-w.png",
"./mon_202011/26/-9lddQ5-6213K0Sw-w.png",
"./mon_202011/26/-9lddQ5-chfbK0Sw-w.png",
"./mon_202011/26/-9lddQ5-ix46K0Sw-w.png",
"./mon_202011/26/-9lddQ5-3o6kK1Sw-w.png",
"./mon_202011/26/-9lddQ5-anv6K0Sw-w.png",
"./mon_202011/26/-9lddQ5-h6hxK0Sw-w.png",
"./mon_202011/26/-9lddQ5-2xh1K0Sw-w.png",
"./mon_202011/26/-9lddQ5-9rhkK1Sw-w.png",
"./mon_202011/26/-9lddQ5-gm72K1Sw-w.png",
"./mon_202011/26/-9lddQ5-20f1K1Sw-w.png",
"./mon_202011/26/-9lddQ5-aaieK0Sw-11.png",
"./mon_202011/26/-9lddQ5-h6dwK0Sw-w.png",
"./mon_202011/26/-9lddQ5-1lngK0Sw-w.png",
"./mon_202011/26/-9lddQ5-7u18K0Sw-w.png",
"./mon_202011/26/-9lddQ5-e2ljK1Sw-w.png",
],
[
"./mon_202011/26/-9lddQ5-bkqdK0Sw-w.png",
"./mon_202011/26/-9lddQ5-hitfK0Sw-w.png",
"./mon_202011/26/-9lddQ5-23kkK0S14-10.png",
"./mon_202011/26/-9lddQ5-dl5bK1S1j-1c.png",
"./mon_202011/26/-9lddQ5-v1nK1Sw-y.png",
"./mon_202011/26/-9lddQ5-gnt0K0Sw-w.png",
"./mon_202011/26/-9lddQ5-eyt2K1Sw-w.png",
"./mon_202011/26/-9lddQ5-8qqsK0Sw-w.png",
"./mon_202011/26/-9lddQ5-frefK0Sw-w.png",
"./mon_202011/26/-9lddQ5-jh6vK2Sw-w.gif",
"./mon_202011/26/-9lddQ5-iv4jKbT8Sw-w.gif",
"./mon_202011/26/-9lddQ5-d5c7K5T8Sw-w.gif",
"./mon_202011/26/-9lddQ5-jsihK1Sw-w.png",
"./mon_202011/26/-9lddQ5-467aK0Sw-w.png",
"./mon_202011/26/-9lddQ5-gxnuK0Sw-w.png",
"./mon_202011/26/-9lddQ5-ai3tK0Sq-w.png",
"./mon_202011/26/-9lddQ5-dwt7K0Sw-w.png",
"./mon_202011/26/-9lddQ5-b578K1Sw-w.png",
"./mon_202011/26/-9lddQ5-1oncK0Sw-w.png",
"./mon_202011/26/-9lddQ5-bzhdK1Sw-w.png",
"./mon_202011/26/-9lddQ5-em4cK0Sw-14.png",
"./mon_202011/26/-9lddQ5-8e3dK1Sw-14.png",
"./mon_202011/26/-9lddQ5-9ujxK0Sw-w.png",
"./mon_202011/26/-9lddQ5-jticK0Sw-w.png",
"./mon_202011/26/-9lddQ5-1u7xK0Sw-w.png",
"./mon_202011/26/-9lddQ5-268hK0Sw-w.png",
"./mon_202011/26/-9lddQ5-cbq1K0Sw-w.png",
"./mon_202011/26/-9lddQ5-1o9lK0Sw-w.png",
"./mon_202011/26/-9lddQ5-hesqK0Sw-w.png",
"./mon_202011/26/-9lddQ5-e5awK0Sw-w.png",
],
[
"./mon_202011/26/-9lddQ5-istjK0Sy-14.png",
"./mon_202011/26/-9lddQ5-kzq9K0Sw-w.png",
"./mon_202011/26/-9lddQ5-5fvtK0Sw-w.png",
"./mon_202011/26/-9lddQ5-fgymK0Sw-w.png",
"./mon_202011/26/-9lddQ5-l0uzK0Sw-w.png",
"./mon_202011/26/-9lddQ5-d9fdK0Sw-w.png",
"./mon_202011/26/-9lddQ5-2bkfK1Sw-w.png",
"./mon_202011/26/-9lddQ5-4as6K7T8Sw-z.gif",
"./mon_202011/26/-9lddQ5-dkn2K0Sw-w.png",
"./mon_202011/26/-9lddQ5-341uK0Sw-w.png",
"./mon_202011/26/-9lddQ5-k3kvK0Sw-w.png",
"./mon_202011/26/-9lddQ5-gnigK2Sw-w.gif",
"./mon_202011/26/-9lddQ5-h39uK0Sw-w.png",
"./mon_202011/26/-9lddQ5-cl00K0Sw-w.png",
"./mon_202011/26/-9lddQ5-54i3K0Sw-w.png",
"./mon_202011/26/-9lddQ5-htnyK0Sw-w.png",
"./mon_202011/26/-9lddQ5-8uxmK0Sw-w.png",
"./mon_202011/26/-9lddQ5-1daK0Sw-w.gif",
"./mon_202011/26/-9lddQ5-b0qkK0Sw-w.png",
"./mon_202011/26/-9lddQ5-212jK0Sw-w.png",
"./mon_202011/26/-9lddQ5-gf6uK0Sw-w.png",
"./mon_202011/26/-9lddQ5-9kp7K0Sw-w.png",
"./mon_202011/26/-9lddQ5-5nc1K0Sw-w.png",
"./mon_202011/26/-9lddQ5-5ze4K0Sw-w.png",
"./mon_202011/26/-9lddQ5-8vz7K0Sw-w.png",
"./mon_202011/26/-9lddQ5-eckxK0Sw-w.png",
"./mon_202011/26/-9lddQ5-e3dhK0Sw-w.png",
"./mon_202011/26/-9lddQ5-asxzK0Sw-w.png",
"./mon_202011/26/-9lddQ5-8p4nK0Sw-w.png",
"./mon_202011/26/-9lddQ5-2v9nK0Sw-w.png",
],
[
"./mon_202011/26/-9lddQ5-2d4tK0Sw-w.png",
"./mon_202011/26/-9lddQ5-apb3K0Sw-w.png",
"./mon_202011/26/-9lddQ5-2n6fK0Sw-w.png",
"./mon_202011/26/-9lddQ5-2n4fK0Sw-w.png",
"./mon_202011/26/-9lddQ5-47g8K0Sw-w.png",
"./mon_202011/26/-9lddQ5-ablrK0Sw-w.png",
"./mon_202011/26/-9lddQ5-evp3K0Sw-w.png",
"./mon_202011/26/-9lddQ5-l0oqK1Sw-w.gif",
"./mon_202011/26/-9lddQ5-7ikzK0Sw-y.png",
"./mon_202011/26/-9lddQ5-bhe1K0S18-w.png",
"./mon_202011/26/-9lddQ5-6k33K0S12-w.png",
"./mon_202011/26/-9lddQ5-j4ihK0Sw-w.png",
"./mon_202011/26/-9lddQ5-bct3K0Sw-w.png",
"./mon_202011/26/-9lddQ5-2byqK0Sw-w.png",
"./mon_202011/26/-9lddQ5-dpp8K0Sw-w.png",
"./mon_202011/26/-9lddQ5-cgj7K0Sw-12.png",
"./mon_202011/26/-9lddQ5-5pv8K0Sz-w.png",
"./mon_202011/26/-9lddQ5-7bs3K0S12-w.png",
"./mon_202011/26/-9lddQ5-jwadK0S12-12.png",
"./mon_202011/26/-9lddQ5-9ccsK0S12-w.png",
"./mon_202011/26/-9lddQ5-kuuyK0S12-16.png",
"./mon_202011/26/-9lddQ5-af09K0S12-w.png",
"./mon_202011/26/-9lddQ5-27cfK0S12-w.png",
"./mon_202011/26/-9lddQ5-8buhK0S12-w.png",
"./mon_202011/26/-9lddQ5-2bihK0Sw-w.png",
"./mon_202011/26/-9lddQ5-huv9K0Sw-w.png",
"./mon_202011/26/-9lddQ5-fekuK0Sw-w.png",
"./mon_202011/26/-9lddQ5-daxrK0Sw-w.png",
"./mon_202011/26/-9lddQ5-64uoK0Sw-w.png",
"./mon_202011/26/-9lddQ5-jvk5K0Sw-w.png",
],
[
"./mon_202011/26/-9lddQ5-cyvrK0Sw-w.png",
"./mon_202011/26/-9lddQ5-6dk1K0Sw-x.png",
"./mon_202011/26/-9lddQ5-kprxK0Sw-w.png",
"./mon_202011/26/-9lddQ5-btueK0Sw-w.png",
"./mon_202011/26/-9lddQ5-5mukK0Sw-w.png",
"./mon_202011/26/-9lddQ5-j6wwK0Sw-w.png",
"./mon_202011/26/-9lddQ5-emybK0Sw-x.png",
"./mon_202011/26/-9lddQ5-70neK5T8S16-u.gif",
"./mon_202011/26/-9lddQ5-1ln9K0S12-16.png",
"./mon_202011/26/-9lddQ5-ds6cK0Sw-w.gif",
"./mon_202011/26/-9lddQ5-kjcqK1Sw-w.gif",
"./mon_202011/26/-9lddQ5-c421K0Sw-w.png",
"./mon_202011/26/-9lddQ5-ilvK1Sw-w.gif",
"./mon_202011/26/-9lddQ5-bwplK0Sw-w.png",
"./mon_202011/26/-9lddQ5-h20cK0Sy-10.png",
"./mon_202011/26/-9lddQ5-l3g6K1Sy-10.png",
"./mon_202011/26/-9lddQ5-86b4K0Sw-w.png",
"./mon_202011/26/-9lddQ5-g1rxK0Sw-w.png",
"./mon_202011/26/-9lddQ5-go7fK0Sw-w.png",
"./mon_202011/26/-9lddQ5-ikb0K1Sw-w.gif",
"./mon_202011/26/-9lddQ5-8iizK0Sw-w.png",
"./mon_202011/26/-9lddQ5-kxprK0Sw-w.png",
"./mon_202011/26/-9lddQ5-l5q1K0Sw-w.png",
"./mon_202011/26/-9lddQ5-8xjnK1S10-17.png",
"./mon_202011/26/-9lddQ5-izreK0Sw-w.png",
"./mon_202011/26/-9lddQ5-6yjbK0Sw-w.png",
"./mon_202011/26/-9lddQ5-curmK0Sw-w.png",
"./mon_202011/26/-9lddQ5-ih7kK1Sw-w.png",
"./mon_202011/26/-9lddQ5-53wwK0Sw-w.png",
"./mon_202011/26/-9lddQ5-fuflK0Sw-z.png",
],
[
"./mon_202011/26/-9lddQ5-428aK0Sw-w.png",
"./mon_202011/26/-9lddQ5-fudaK0Sw-w.png",
"./mon_202011/26/-9lddQ5-gukK1S1c-10.png",
"./mon_202011/26/-9lddQ5-7kfsK0Sw-w.png",
"./mon_202011/26/-9lddQ5-80gsK0Sw-w.png",
"./mon_202011/26/-9lddQ5-3m1eK0Sw-w.png",
"./mon_202011/26/-9lddQ5-ka7rK0Sw-w.png",
"./mon_202011/26/-9lddQ5-2m74K0Sw-w.png",
"./mon_202011/26/-9lddQ5-7sk4K0Sw-w.png",
"./mon_202011/26/-9lddQ5-d6trK0Sw-w.png",
"./mon_202011/26/-9lddQ5-h8b0K0Sw-w.png",
"./mon_202011/26/-9lddQ5-b670K0Sw-w.png",
"./mon_202011/26/-9lddQ5-ftzxK0Sw-w.png",
"./mon_202011/26/-9lddQ5-1pzdK1Sw-w.png",
"./mon_202011/26/-9lddQ5-6yprK0Sw-w.png",
"./mon_202011/26/-9lddQ5-caa2K0Sw-w.png",
"./mon_202011/26/-9lddQ5-hwnxK0Sw-w.png",
"./mon_202011/26/-9lddQ5-7v2rK0Sw-w.png",
"./mon_202011/26/-9lddQ5-2n1qK0Sw-w.png",
"./mon_202011/26/-9lddQ5-bpp0K0Sw-w.png",
"./mon_202011/26/-9lddQ5-gfvoK1Sw-w.png",
"./mon_202011/26/-9lddQ5-kaubK0Sw-w.png",
"./mon_202011/26/-9lddQ5-8a1oKhT8S18-18.gif",
"./mon_202011/26/-9lddQ5-cuzeK0Sw-w.png",
"./mon_202011/26/-9lddQ5-itlyK1S10-14.png",
"./mon_202011/26/-9lddQ5-olzK0Sw-w.png",
"./mon_202011/26/-9lddQ5-7r6yK7T8S16-t.gif",
"./mon_202011/26/-9lddQ5-bgn0K2S1f-1b.gif",
"./mon_202011/26/-9lddQ5-ekg3K2S1f-1b.gif",
"./mon_202011/26/-9lddQ5-kzbcK2S1j-12.gif",
],
[
"./mon_202011/26/-9lddQ5-6eujK2S1j-18.gif",
"./mon_202011/26/-9lddQ5-c93kK8T8S1j-18.gif",
"./mon_202011/26/-9lddQ5-i81zK7T8S1j-18.gif",
"./mon_202011/26/-9lddQ5-5s5vK4T8Sw-z.gif",
"./mon_202011/26/-9lddQ5-e1n1KcT8Sw-w.gif",
"./mon_202011/26/-9lddQ5-kq85K1S11-14.gif",
"./mon_202011/26/-9lddQ5-8b7zK1Sx-10.png",
"./mon_202011/26/-9lddQ5-hpxmK1Sx-10.png",
"./mon_202011/26/-9lddQ5-6e81K3Sw-11.gif",
"./mon_202011/26/-9lddQ5-cbjtK0Sw-w.png",
"./mon_202011/26/-9lddQ5-g9qyK0Sw-w.png",
"./mon_202011/26/-9lddQ5-167pK1Sw-w.png",
"./mon_202011/26/-9lddQ5-7453K0Sw-w.png",
"./mon_202011/26/-9lddQ5-erzpK3S14-12.gif",
"./mon_202011/26/-9lddQ5-g7lmK3Sw-14.gif",
"./mon_202011/26/-9lddQ5-88o7K1Sw-z.png",
"./mon_202011/26/-9lddQ5-73ynK0Sw-w.png",
],
[
"./mon_202105/27/-9lddQ2o-9f2hK0Sw-w.png",
"./mon_202105/27/-9lddQ2o-ku8sK0Sw-w.png",
]
],
[
"角色",
[
"./mon_202011/26/-9lddQ5-dp6K1Sw-w.png",
"./mon_202011/26/-9lddQ5-9u7qK0S10-y.png",
"./mon_202011/26/-9lddQ5-j408K1Sw-10.png",
"./mon_202011/26/-9lddQ5-yt8K1Sy-12.png",
"./mon_202011/26/-9lddQ5-k7szK1Sw-w.png",
"./mon_202011/26/-9lddQ5-gnwK1Sw-w.png",
"./mon_202011/26/-9lddQ5-bwmwK1Sw-11.png",
"./mon_202011/26/-9lddQ5-229yK1Sy-11.png",
"./mon_202011/26/-9lddQ5-8nr0K1Sy-10.png",
"./mon_202011/26/-9lddQ5-49ukK1Sw-x.png",
"./mon_202011/26/-9lddQ5-hk3rK0Sw-y.png",
"./mon_202011/26/-9lddQ5-1v65K0Sw-w.png",
"./mon_202011/26/-9lddQ5-9kloK0S12-11.png",
],
[
"./mon_202011/26/-9lddQ5-f5roK1Sw-10.png",
"./mon_202011/26/-9lddQ5-e187K1S10-y.png",
"./mon_202011/26/-9lddQ5-gub3K1Sw-12.png",
"./mon_202011/26/-9lddQ5-j9m9K2S14-w.gif",
"./mon_202011/26/-9lddQ5-fmgaK1Sy-1a.png",
"./mon_202011/26/-9lddQ5-jcg9K2S14-13.gif",
"./mon_202011/26/-9lddQ5-2j1cK1S14-17.png",
"./mon_202011/26/-9lddQ5-2wvqK1S14-17.png",
"./mon_202011/26/-9lddQ5-b1sxK0Sw-w.png",
"./mon_202011/26/-9lddQ5-48wvK0Sw-w.png",
"./mon_202011/26/-9lddQ5-dcpyK0Sw-w.png",
"./mon_202011/26/-9lddQ5-twnK0Sw-y.png",
"./mon_202011/26/-9lddQ5-9mveK1Sz-y.png",
"./mon_202011/26/-9lddQ5-hdtuK1Sy-y.png",
"./mon_202011/26/-9lddQ5-deoyK1Sy-y.png",
"./mon_202011/26/-9lddQ5-uwfK1Sw-y.png",
"./mon_202011/26/-9lddQ5-ahasK1S10-13.png",
"./mon_202011/26/-9lddQ5-aqirK1Sw-y.png",
"./mon_202011/26/-9lddQ5-khr4K1Sw-14.png",
"./mon_202011/26/-9lddQ5-8pszK0Sw-y.png",
"./mon_202011/26/-9lddQ5-hguqK0Sw-y.png",
"./mon_202011/26/-9lddQ5-i3kwK0Sw-y.png",
"./mon_202011/26/-9lddQ5-6hbiK0Sy-y.png",
"./mon_202011/26/-9lddQ5-gh22K0Sw-y.png",
"./mon_202011/26/-9lddQ5-6llvK0Sw-y.png",
"./mon_202011/26/-9lddQ5-5bndK0Sw-y.png",
"./mon_202011/26/-9lddQ5-bqinK1Sw-y.png",
"./mon_202011/26/-9lddQ5-j1zjK1Sy-12.png",
"./mon_202011/26/-9lddQ5-66f7K1Sy-12.png",
"./mon_202011/26/-9lddQ5-a80eK1Sy-12.png",
],
[
"./mon_202011/26/-9lddQ5-ad3rK1Sy-12.png",
"./mon_202011/26/-9lddQ5-g45vK1Sw-z.png",
"./mon_202011/26/-9lddQ5-j6lzK1Sw-z.png",
"./mon_202011/26/-9lddQ5-5lm8K1Sw-z.png",
"./mon_202011/26/-9lddQ5-acb2K1Sx-10.png",
"./mon_202011/26/-9lddQ5-edg5K1Sw-10.png",
"./mon_202011/26/-9lddQ5-hqxgK1Sw-w.png",
"./mon_202011/26/-9lddQ5-28viK1S10-10.gif",
"./mon_202011/26/-9lddQ5-4zpzK1Sw-y.png",
"./mon_202011/26/-9lddQ5-9ac6K1Sw-z.png",
"./mon_202011/26/-9lddQ5-cvkmK1Sw-1c.png",
"./mon_202011/26/-9lddQ5-fn51K1Sw-z.png",
"./mon_202011/26/-9lddQ5-hzbwK1Sw-z.png",
"./mon_202011/26/-9lddQ5-lrqK1Sw-10.png",
"./mon_202011/26/-9lddQ5-4g03K1Sw-y.png",
"./mon_202011/26/-9lddQ5-8ooaK0Sw-10.png",
"./mon_202011/26/-9lddQ5-bzs2K0Sy-w.png",
"./mon_202011/26/-9lddQ5-hk0nK1Sy-w.png",
"./mon_202011/26/-9lddQ5-20jK0Sw-w.png",
"./mon_202011/26/-9lddQ5-i9s0K1S10-y.png",
"./mon_202011/26/-9lddQ5-lc4kK0Sw-y.png",
"./mon_202011/26/-9lddQ5-8kksK0Sw-x.png",
"./mon_202011/26/-9lddQ5-b2asK0Sw-11.png",
"./mon_202011/26/-9lddQ5-e9wrK0Sw-11.png",
"./mon_202011/26/-9lddQ5-gvppK1Sy-11.png",
"./mon_202011/26/-9lddQ5-jebfK1S12-10.png",
"./mon_202011/26/-9lddQ5-1augK0Sw-10.png",
"./mon_202011/26/-9lddQ5-4uisK1Sy-14.png",
"./mon_202011/26/-9lddQ5-9bhzK1Sw-13.png",
"./mon_202011/26/-9lddQ5-553zK1Sw-10.png",
],
[
"./mon_202011/26/-9lddQ5-15huK1Sw-12.png",
"./mon_202011/26/-9lddQ5-4djsK1Sw-13.png",
"./mon_202011/26/-9lddQ5-97fgK1Sw-14.png",
"./mon_202011/26/-9lddQ5-cawgK1Sw-18.png",
"./mon_202011/26/-9lddQ5-gas1K1Sw-18.png",
"./mon_202011/26/-9lddQ5-hyczK1S12-18.png",
"./mon_202011/26/-9lddQ5-3mf2K1Sw-y.png",
"./mon_202011/26/-9lddQ5-6aruK1Sw-10.png",
"./mon_202011/26/-9lddQ5-9zw4K1Sw-z.png",
"./mon_202011/26/-9lddQ5-cujeK0Sw-w.png",
"./mon_202011/26/-9lddQ5-f0zlK1Sw-12.png",
"./mon_202011/26/-9lddQ5-icy1K1Sy-10.png",
"./mon_202011/26/-9lddQ5-6eipK1Sy-14.png",
"./mon_202011/26/-9lddQ5-affsK1Sw-12.png",
"./mon_202011/26/-9lddQ5-csaqK0Sw-y.png",
"./mon_202011/26/-9lddQ5-gru6K0Sw-y.png",
"./mon_202011/26/-9lddQ5-k4jtK1Sw-y.png",
"./mon_202011/26/-9lddQ5-2q1fK1Sy-14.png",
"./mon_202011/26/-9lddQ5-5jimK1S1c-14.gif",
"./mon_202011/26/-9lddQ5-9pybK2S1c-14.gif",
"./mon_202011/26/-9lddQ5-cgj8K2S10-10.gif",
"./mon_202011/26/-9lddQ5-h8bdK3S1e-18.gif",
"./mon_202011/26/-9lddQ5-k86xK3S10-1a.gif",
"./mon_202011/26/-9lddQ5-zw3K1S12-12.gif",
"./mon_202011/26/-9lddQ5-5jjnK3S14-1a.gif",
"./mon_202011/26/-9lddQ5-8pvjK5T8S19-1a.gif",
"./mon_202011/26/-9lddQ5-c7dvK1Sw-10.gif",
"./mon_202011/26/-9lddQ5-eyg6K1Sy-16.png",
"./mon_202011/26/-9lddQ5-hr06K1Sy-16.png",
"./mon_202011/26/-9lddQ5-gdvhK1Sw-12.png",
],
[
"./mon_202011/26/-9lddQ5-fir8K1Sw-12.png",
"./mon_202011/26/-9lddQ5-10ghK0Sw-w.png",
"./mon_202011/26/-9lddQ5-3khdK1Sw-y.png",
"./mon_202011/26/-9lddQ5-8lnaK1Sw-x.png",
"./mon_202011/26/-9lddQ5-au9sK0Sw-w.png",
"./mon_202011/26/-9lddQ5-f5mqK0Sw-w.png",
"./mon_202011/26/-9lddQ5-jtjwK1Sw-y.png",
"./mon_202011/26/-9lddQ5-xdnK1Sw-w.png",
"./mon_202011/26/-9lddQ5-597bK1Sw-w.png",
"./mon_202011/26/-9lddQ5-8uwfK1Sw-w.png",
"./mon_202011/26/-9lddQ5-geo8K1Sw-w.png",
"./mon_202011/26/-9lddQ5-juijK1Sw-w.png",
"./mon_202011/26/-9lddQ5-jimdK4T8Sy-10.gif",
"./mon_202011/26/-9lddQ5-1yegK1S16-10.png",
"./mon_202011/26/-9lddQ5-4twvK0Sy-y.png",
"./mon_202011/26/-9lddQ5-a60pK0Sy-y.png",
"./mon_202011/26/-9lddQ5-3sjwK1S1c-1e.png",
"./mon_202011/26/-9lddQ5-cgn5K0Sw-10.png",
"./mon_202011/26/-9lddQ5-9feoK1Sw-14.png",
"./mon_202011/26/-9lddQ5-hpgK0Sw-13.png",
"./mon_202011/26/-9lddQ5-8846K1Sy-13.png",
"./mon_202011/26/-9lddQ5-jjq1K0Sw-z.png",
"./mon_202011/26/-9lddQ5-2vjuK1Sw-x.png",
"./mon_202011/26/-9lddQ5-cnl2K0Sy-10.png",
"./mon_202011/26/-9lddQ5-hy49K0Sy-10.png",
"./mon_202011/26/-9lddQ5-15dfK0Sy-12.png",
"./mon_202011/26/-9lddQ5-bls0K0Sy-12.png",
"./mon_202011/26/-9lddQ5-kpa1K1Sw-11.png",
"./mon_202011/26/-9lddQ5-987vK1Sw-11.png",
"./mon_202011/26/-9lddQ5-gmlyK0Sw-11.png",
],
[
"./mon_202011/26/-9lddQ5-8rxdK1S14-18.png",
"./mon_202011/26/-9lddQ5-dq5rK0Sw-14.png",
"./mon_202011/26/-9lddQ5-h16xK1Sw-14.png",
"./mon_202011/26/-9lddQ5-vhkK0Sw-14.png",
"./mon_202011/26/-9lddQ5-csxfK1Sw-14.png",
"./mon_202011/26/-9lddQ5-a65vK1S12-11.png",
"./mon_202011/26/-9lddQ5-e9k1K1S12-11.png",
"./mon_202011/26/-9lddQ5-jc8yK1S12-11.png",
"./mon_202011/26/-9lddQ5-37q8K1S14-14.png",
"./mon_202011/26/-9lddQ5-7owaK1Sw-15.png",
"./mon_202011/26/-9lddQ5-e7s5K1Sw-15.png",
"./mon_202011/26/-9lddQ5-iq1rK1S12-15.png",
"./mon_202011/26/-9lddQ5-1jhlK1S12-15.png",
"./mon_202011/26/-9lddQ5-almaK0Sy-11.png",
"./mon_202011/26/-9lddQ5-dr9lK0Sy-11.png",
"./mon_202011/26/-9lddQ5-hg9xK1Sw-y.png",
"./mon_202011/26/-9lddQ5-sr5K1Sy-11.png",
"./mon_202011/26/-9lddQ5-dqszK1Sy-11.png",
"./mon_202011/26/-9lddQ5-kqoaK1Sy-11.png",
"./mon_202011/26/-9lddQ5-2qgeK0Sw-y.png",
"./mon_202011/26/-9lddQ5-6dacK1Sw-y.png",
"./mon_202011/26/-9lddQ5-blszK0Sw-y.png",
"./mon_202011/26/-9lddQ5-4hn0K1S12-16.png",
"./mon_202011/26/-9lddQ5-ai87K1S12-11.png",
"./mon_202011/26/-9lddQ5-dkh4K1S18-14.png",
"./mon_202011/26/-9lddQ5-gfkhK2S17-1d.gif",
"./mon_202011/26/-9lddQ5-e2orK2S17-1d.gif",
"./mon_202011/26/-9lddQ5-idmsK0St-13.png",
"./mon_202011/26/-9lddQ5-2iqeK0St-13.png",
"./mon_202011/26/-9lddQ5-66zjK0St-13.png",
],
[
"./mon_202011/26/-9lddQ5-b4stK0Sw-w.png",
"./mon_202011/26/-9lddQ5-e43qK0Sw-10.png",
"./mon_202011/26/-9lddQ5-ied4K0Sw-w.png",
"./mon_202011/26/-9lddQ5-1t6nK0Sw-w.png",
"./mon_202011/26/-9lddQ5-8ow6K1Sw-10.png",
"./mon_202011/26/-9lddQ5-howlK1Sw-y.gif",
"./mon_202011/26/-9lddQ5-3j2qK1Sw-y.png",
"./mon_202011/26/-9lddQ5-cgafK1Sw-y.png",
"./mon_202011/26/-9lddQ5-ksz1K1S10-12.png",
"./mon_202011/26/-9lddQ5-6424K1S10-12.png",
"./mon_202011/26/-9lddQ5-d7oaK1S10-12.png",
"./mon_202011/26/-9lddQ5-c2vwK1S10-12.png",
"./mon_202011/26/-9lddQ5-60ecK1S10-12.png",
"./mon_202011/26/-9lddQ5-ihwcK1S10-12.png",
"./mon_202011/26/-9lddQ5-cvuuK1S10-12.png",
"./mon_202011/26/-9lddQ5-6d0vK1S10-12.png",
"./mon_202011/26/-9lddQ5-65exK1S10-12.png",
"./mon_202011/26/-9lddQ5-bv3K1S10-12.png",
"./mon_202011/26/-9lddQ5-5hmgK1S10-12.png",
"./mon_202011/26/-9lddQ5-7hi3K1Sy-16.png",
"./mon_202011/26/-9lddQ5-gqevK1Sy-16.png",
"./mon_202011/26/-9lddQ5-bakrK0Sw-14.png",
"./mon_202011/26/-9lddQ5-jwzcK1Sw-1q.png",
"./mon_202011/26/-9lddQ5-93h0K1S12-12.png",
"./mon_202011/26/-9lddQ5-iv2xK1Sw-10.png",
"./mon_202011/26/-9lddQ5-d2zhK1Sw-10.png",
"./mon_202011/26/-9lddQ5-1xbwK0Sw-12.png",
"./mon_202011/26/-9lddQ5-ebhfK1Sw-14.png",
"./mon_202011/26/-9lddQ5-2dyyK0S12-16.png",
"./mon_202011/26/-9lddQ5-c878K1S16-1a.png",
],
[
"./mon_202011/26/-9lddQ5-2hkwK1Sw-y.png",
"./mon_202011/26/-9lddQ5-bx4yK0Sw-y.png",
"./mon_202011/26/-9lddQ5-kybjK1S10-12.png",
"./mon_202011/26/-9lddQ5-btrkK1Sy-13.png",
"./mon_202011/26/-9lddQ5-5kjeK1Sy-14.png",
"./mon_202011/26/-9lddQ5-emouK1Sy-14.png",
"./mon_202011/26/-9lddQ5-34x7K1Sy-1a.png",
"./mon_202011/26/-9lddQ5-cgkhK1S10-10.png",
"./mon_202011/26/-9lddQ5-1002K1Sy-10.png",
"./mon_202011/26/-9lddQ5-i8hsK0Sw-y.png",
"./mon_202011/26/-9lddQ5-673aK1Su-12.png",
"./mon_202011/26/-9lddQ5-ernjK1Sw-10.png",
"./mon_202011/26/-9lddQ5-g7faK1Sw-10.png",
"./mon_202011/26/-9lddQ5-4lohK1S12-17.png",
"./mon_202011/26/-9lddQ5-e15gK0Sw-w.gif",
"./mon_202011/26/-9lddQ5-7q5hK1Sy-14.png",
"./mon_202011/26/-9lddQ5-gvacK1S10-14.png",
"./mon_202011/26/-9lddQ5-53p6K1S10-14.png",
"./mon_202011/26/-9lddQ5-f35lK1Sw-10.png",
"./mon_202011/26/-9lddQ5-2h7kK0Sw-10.png",
"./mon_202011/26/-9lddQ5-8ogcK1S11-14.png",
"./mon_202011/26/-9lddQ5-hlbvK0Sw-w.png",
"./mon_202011/26/-9lddQ5-6op8K0Sw-w.png",
"./mon_202011/26/-9lddQ5-abemK0Sw-w.png",
"./mon_202011/26/-9lddQ5-jzrfK1Sw-w.png",
"./mon_202011/26/-9lddQ5-82g6K1S17-17.png",
"./mon_202011/26/-9lddQ5-80ogK1S12-10.gif",
"./mon_202011/26/-9lddQ5-aa5yK1S12-10.png",
"./mon_202011/26/-9lddQ5-jumjK1Sw-12.png",
"./mon_202011/26/-9lddQ5-7r97K1S12-y.png",
],
[
"./mon_202011/26/-9lddQ5-fz78K1Sw-w.png",
"./mon_202011/26/-9lddQ5-4n2pK1Sw-w.png",
"./mon_202011/26/-9lddQ5-ecanK1Sw-w.png",
"./mon_202011/26/-9lddQ5-dll6K1Sw-10.png",
"./mon_202011/26/-9lddQ5-ero6K1Sw-w.png",
"./mon_202011/26/-9lddQ5-xxmK1S10-14.png",
"./mon_202011/26/-9lddQ5-ajmyK1S10-15.png",
"./mon_202011/26/-9lddQ5-kg5qK1Sy-14.png",
"./mon_202011/26/-9lddQ5-9566K1Sy-14.png",
"./mon_202011/26/-9lddQ5-iyjjK1Sy-14.png",
"./mon_202011/26/-9lddQ5-58owK1S10-14.png",
"./mon_202011/26/-9lddQ5-7292K1S12-10.png",
"./mon_202011/26/-9lddQ5-hb3oK1S10-1e.png",
"./mon_202011/26/-9lddQ5-azqtK1S14-1a.png",
"./mon_202011/26/-9lddQ5-cmwbK1S14-16.png",
"./mon_202011/26/-9lddQ5-odtK1Sw-x.png",
"./mon_202011/26/-9lddQ5-9udtK1Sw-12.png",
"./mon_202011/26/-9lddQ5-cqzcK0Sw-w.png",
"./mon_202011/26/-9lddQ5-f2j0K1Sy-y.png",
"./mon_202011/26/-9lddQ5-4sznK1S10-14.png",
"./mon_202011/26/-9lddQ5-eyrhK1S14-14.png",
"./mon_202011/26/-9lddQ5-39veK1Sy-14.gif",
"./mon_202011/26/-9lddQ5-ctt3K1Sy-14.png",
"./mon_202011/26/-9lddQ5-107sK1S14-14.png",
"./mon_202011/26/-9lddQ5-b8jiK1S14-14.png",
"./mon_202011/26/-9lddQ5-cfy2K1S14-14.png",
"./mon_202011/26/-9lddQ5-1ul6K1S14-14.png",
"./mon_202011/26/-9lddQ5-375aK1S10-14.png",
"./mon_202011/26/-9lddQ5-db2zK1S10-14.png",
"./mon_202011/26/-9lddQ5-1lauK3S10-16.gif",
],
[
"./mon_202011/26/-9lddQ5-1au8K4T8S15-16.gif",
"./mon_202011/26/-9lddQ5-bgocK4T8S15-16.gif",
"./mon_202011/26/-9lddQ5-k697K1S12-1e.png",
"./mon_202011/26/-9lddQ5-97paK1S14-19.png",
"./mon_202011/26/-9lddQ5-j6w0K1S14-1e.png",
"./mon_202011/26/-9lddQ5-bsjzK1S13-18.png",
"./mon_202011/26/-9lddQ5-42rK1S13-18.png",
"./mon_202011/26/-9lddQ5-9xfjK1S13-18.png",
"./mon_202011/26/-9lddQ5-jdzhK1S18-1e.png",
"./mon_202011/26/-9lddQ5-8jcxK1Sy-1a.png",
"./mon_202011/26/-9lddQ5-ipezK1Sy-1a.png",
"./mon_202011/26/-9lddQ5-7327K1Sy-1c.png",
"./mon_202011/26/-9lddQ5-gn9aK2S10-16.png",
"./mon_202011/26/-9lddQ5-4t0pK1S10-16.png",
"./mon_202011/26/-9lddQ5-7823K1S16-18.png",
"./mon_202011/26/-9lddQ5-4jkaK1S16-18.png",
"./mon_202011/26/-9lddQ5-a28oK1S10-18.png",
"./mon_202011/26/-9lddQ5-l9m2K1S10-10.png",
"./mon_202011/26/-9lddQ5-aj62K1Sw-y.png",
"./mon_202011/26/-9lddQ5-keibK0Sw-y.png",
"./mon_202011/26/-9lddQ5-99atK1Sw-18.png",
"./mon_202011/26/-9lddQ5-ejo9K1Sw-18.png",
"./mon_202011/26/-9lddQ5-2yhcK1S10-1c.png",
"./mon_202011/26/-9lddQ5-380wK1Sw-12.png",
"./mon_202011/26/-9lddQ5-cuk0K1Sw-12.png",
"./mon_202011/26/-9lddQ5-1k2sK1Sw-12.png",
"./mon_202011/26/-9lddQ5-ji5vK1S14-12.png",
"./mon_202011/26/-9lddQ5-7z09K1S14-12.png",
"./mon_202011/26/-9lddQ5-i7huK2S14-12.gif",
"./mon_202011/26/-9lddQ5-620oK1Sw-1i.png",
],
[
"./mon_202011/26/-9lddQ5-6doxK1Sw-z.png",
"./mon_202011/26/-9lddQ5-gfffK1Su-10.png",
"./mon_202011/26/-9lddQ5-4ufcK0Su-11.png",
"./mon_202011/26/-9lddQ5-el4bK0Sw-y.png",
"./mon_202011/26/-9lddQ5-48k9K0Sw-y.png",
"./mon_202011/26/-9lddQ5-el5pK1Sx-y.png",
"./mon_202011/26/-9lddQ5-309hK4T8S34-32.png",
"./mon_202011/26/-9lddQ5-de8tK0Ss-w.png",
"./mon_202011/26/-9lddQ5-1zr0K7T8S14-14.gif",
"./mon_202011/26/-9lddQ5-ar83K1S19-10.gif",
"./mon_202011/26/-9lddQ5-kmi7K1S10-13.png",
"./mon_202011/26/-9lddQ5-lbywK1Sy-12.png",
"./mon_202011/26/-9lddQ5-9mpbK1Sy-10.png",
"./mon_202011/26/-9lddQ5-jcmqK1Sy-10.png",
"./mon_202011/26/-9lddQ5-7xysK3Sw-14.gif",
"./mon_202011/26/-9lddQ5-gqknK0Sw-10.png",
"./mon_202011/26/-9lddQ5-8rxaK3Sw-12.gif",
"./mon_202011/26/-9lddQ5-gw90K1S10-14.png",
"./mon_202011/26/-9lddQ5-426oK1Sy-12.png",
"./mon_202011/26/-9lddQ5-heyaK1S10-14.png",
"./mon_202011/26/-9lddQ5-25m2K0Sw-10.png",
"./mon_202011/26/-9lddQ5-c08kK1Sw-10.png",
"./mon_202011/26/-9lddQ5-bjsK0Sw-y.png",
"./mon_202011/26/-9lddQ5-2lsvK3Sw-w.gif",
"./mon_202011/26/-9lddQ5-7f2sK1Sy-12.png",
"./mon_202011/26/-9lddQ5-cp1bK0Sw-13.png",
"./mon_202011/26/-9lddQ5-upbK0Sw-1d.png",
"./mon_202011/26/-9lddQ5-a4toK3Sw-y.gif",
"./mon_202011/26/-9lddQ5-1acbK1Sz-y.png",
"./mon_202011/26/-9lddQ5-4j4fK1Sw-y.png",
],
[
"./mon_202011/26/-9lddQ5-a8qiK1Sw-12.png",
"./mon_202011/26/-9lddQ5-5pm8K1S12-1k.png",
"./mon_202011/26/-9lddQ5-eipgK1S10-16.png",
"./mon_202011/26/-9lddQ5-28plK0Sw-14.png",
"./mon_202011/26/-9lddQ5-bog6K0Sw-w.png",
"./mon_202011/26/-9lddQ5-lcc0K1Sy-12.png",
"./mon_202011/26/-9lddQ5-8gtcK0Sw-z.png",
"./mon_202011/26/-9lddQ5-ht9zK0Sw-z.png",
"./mon_202011/26/-9lddQ5-5ax2K0Sw-w.png",
"./mon_202011/26/-9lddQ5-5n1zK1Sx-14.png",
"./mon_202011/26/-9lddQ5-ddpaK0Sw-16.png",
"./mon_202011/26/-9lddQ5-ejfsK1Sy-16.png",
"./mon_202011/26/-9lddQ5-4if0K1S12-14.png",
"./mon_202011/26/-9lddQ5-e2mfK1S10-14.png",
"./mon_202011/26/-9lddQ5-kz6dK1Sy-11.png",
"./mon_202011/26/-9lddQ5-2wfaK0Sw-y.png",
"./mon_202011/26/-9lddQ5-cj27K0Sw-w.png",
"./mon_202011/26/-9lddQ5-ik4K0Sw-z.png",
"./mon_202011/26/-9lddQ5-9mmbK0S10-z.png",
"./mon_202011/26/-9lddQ5-igm6K1Sw-x.png",
"./mon_202011/26/-9lddQ5-61q3K1S16-1c.png",
"./mon_202011/26/-9lddQ5-ighoK1Sw-12.png",
"./mon_202011/26/-9lddQ5-bp98K1S12-18.png",
"./mon_202011/26/-9lddQ5-9s5K1Sw-17.png",
"./mon_202011/26/-9lddQ5-kn08K1S1e-10.png",
"./mon_202011/26/-9lddQ5-7m2rK1S12-1b.png",
"./mon_202011/26/-9lddQ5-gga7K0Sw-18.gif",
"./mon_202011/26/-9lddQ5-47p8K1Sy-12.png",
"./mon_202011/26/-9lddQ5-8eafK1S10-13.png",
"./mon_202011/26/-9lddQ5-gun7K1S10-11.png",
],
[
"./mon_202011/26/-9lddQ5-y7pK1Sy-11.png",
"./mon_202011/26/-9lddQ5-inwyKeT8S14-18.gif",
"./mon_202011/26/-9lddQ5-6lmaK0Sw-w.png",
"./mon_202011/26/-9lddQ5-g3kqK1Sw-14.png",
"./mon_202011/26/-9lddQ5-6fu7K1S1c-12.png",
],
[
"./mon_202105/27/-9lddQ2o-ekkqK1Sw-10.png",
"./mon_202105/27/-9lddQ2o-1g3sK1S10-18.png",
"./mon_202105/27/-9lddQ2o-dav0K1Sz-11.png",
"./mon_202105/27/-9lddQ2o-kfg8K1Sw-z.png",
]
],
[
"动物",
[
"./mon_202011/26/-9lddQ5-e97hK1Sw-12.png",
"./mon_202011/26/-9lddQ5-1g80K1Sw-12.png",
"./mon_202011/26/-9lddQ5-bewkK1Sw-10.png",
"./mon_202011/26/-9lddQ5-kw3pK0Sw-w.png",
"./mon_202011/26/-9lddQ5-kkb9K0Sw-w.png",
"./mon_202011/26/-9lddQ5-7t6qK0Sw-w.png",
"./mon_202011/26/-9lddQ5-gs6xK0Sw-13.png",
"./mon_202011/26/-9lddQ5-4goaK0Sw-w.png",
"./mon_202011/26/-9lddQ5-kejeK0Sw-y.png",
"./mon_202011/26/-9lddQ5-femlK1Sw-11.png",
"./mon_202011/26/-9lddQ5-47b5K1Sw-10.png",
"./mon_202011/26/-9lddQ5-crv3K0Sw-10.png",
"./mon_202011/26/-9lddQ5-4ke5K0Sw-11.png",
"./mon_202011/26/-9lddQ5-dda7K1Sw-w.png",
"./mon_202011/26/-9lddQ5-170yK0Sw-11.png",
"./mon_202011/26/-9lddQ5-amrqK1Sw-w.png",
"./mon_202011/26/-9lddQ5-bzykK1Sz-11.png",
"./mon_202011/26/-9lddQ5-l44gK0Sw-x.png",
"./mon_202011/26/-9lddQ5-9knoK1Sw-11.png",
"./mon_202011/26/-9lddQ5-iruoK1Sw-11.png",
"./mon_202011/26/-9lddQ5-6c2jK1Sx-10.png",
"./mon_202011/26/-9lddQ5-gcboK1Sw-10.png",
"./mon_202011/26/-9lddQ5-5307K0Sw-12.png",
"./mon_202011/26/-9lddQ5-9v1cK1Sw-10.png",
"./mon_202011/26/-9lddQ5-a58uK1Sw-y.png",
],
[
"./mon_202011/26/-9lddQ5-gxxqK1Sw-z.png",
"./mon_202011/26/-9lddQ5-4il9K1Sw-14.png",
"./mon_202011/26/-9lddQ5-c0tlK1Sw-w.png",
],
[
"./mon_202105/27/-9lddQ2o-57a5K1S16-1c.png",
"./mon_202105/27/-9lddQ2o-gz1mK0Sw-u.png",
]
],
[
"硬件",
[
"./mon_202011/26/-9lddQ5-ld2cK0Sw-w.png",
"./mon_202011/26/-9lddQ5-5dwqK0Sw-w.png",
"./mon_202011/26/-9lddQ5-k4lwK0Sw-w.png",
"./mon_202011/26/-9lddQ5-88byK0Sw-w.png",
"./mon_202011/26/-9lddQ5-hwc7K0Sw-w.png",
"./mon_202011/26/-9lddQ5-5xxyK0Sw-w.png",
"./mon_202011/26/-9lddQ5-9zlrK0Sw-w.png",
"./mon_202011/26/-9lddQ5-238xK0Sw-w.png",
"./mon_202011/26/-9lddQ5-a2j5K0Sw-w.png",
"./mon_202011/26/-9lddQ5-i7noK0Sw-w.png",
"./mon_202011/26/-9lddQ5-4o5tK0Sw-w.png",
"./mon_202011/26/-9lddQ5-d9oyK0Sw-w.png",
"./mon_202011/26/-9lddQ5-hexK0Sw-w.png",
"./mon_202011/26/-9lddQ5-9upkK0Sw-w.png",
"./mon_202011/26/-9lddQ5-ab9oK0Sw-w.png",
"./mon_202011/26/-9lddQ5-jhqvK0Sw-w.png",
"./mon_202011/26/-9lddQ5-7xasK1Sw-12.gif",
"./mon_202011/26/-9lddQ5-g91sK0S10-w.png",
"./mon_202011/26/-9lddQ5-4iezK0S10-w.png",
"./mon_202011/26/-9lddQ5-e9gnK0Sw-w.png",
"./mon_202011/26/-9lddQ5-faeK0Sw-w.png",
"./mon_202011/26/-9lddQ5-98muK0Sw-w.png",
"./mon_202011/26/-9lddQ5-itd9K0Sw-w.png",
"./mon_202011/26/-9lddQ5-serK0Sw-w.png",
"./mon_202011/26/-9lddQ5-9opdK0Sw-w.png",
"./mon_202011/26/-9lddQ5-j989K0Sw-w.png",
"./mon_202011/26/-9lddQ5-59s2K0Sw-w.png",
],
[
"./mon_202011/26/-9lddQ5-cjnbK0Sw-16.png",
"./mon_202011/26/-9lddQ5-ij83K0Sw-w.png",
"./mon_202011/26/-9lddQ5-cp84K0Sw-w.png",
"./mon_202011/26/-9lddQ5-9m1vK0Sw-x.png",
"./mon_202011/26/-9lddQ5-ivu7K0Sw-w.png",
"./mon_202011/26/-9lddQ5-6evrK0Sw-w.png",
"./mon_202011/26/-9lddQ5-fb7fK0Sw-11.png",
"./mon_202011/26/-9lddQ5-23ojK0Sw-11.png",
"./mon_202011/26/-9lddQ5-a4v0K0Sw-x.png",
"./mon_202011/26/-9lddQ5-islaK0Sw-x.png",
"./mon_202011/26/-9lddQ5-18hmK0Sw-x.png",
"./mon_202011/26/-9lddQ5-cwoxK0Sw-x.png",
"./mon_202011/26/-9lddQ5-au8jK0Sw-x.png",
"./mon_202011/26/-9lddQ5-4ydsK1Sw-10.png",
"./mon_202011/26/-9lddQ5-eygtK0Sw-x.png",
"./mon_202011/26/-9lddQ5-aeznK0Sw-x.png",
"./mon_202011/26/-9lddQ5-jdouK0Sw-x.png",
],
],
[
"白鹅",
[
"./mon_202011/26/-9lddQ5-8hnkK1Sw-w.png",
"./mon_202011/26/-9lddQ5-g18pK1Sw-w.png",
"./mon_202011/26/-9lddQ5-4rn9K1Sw-w.png",
"./mon_202011/26/-9lddQ5-60f5K1Sw-w.png",
"./mon_202011/26/-9lddQ5-reyK0Sy-w.png",
"./mon_202011/26/-9lddQ5-as2xK1Sw-w.png",
"./mon_202011/26/-9lddQ5-8r5kK1Sw-w.png",
"./mon_202011/26/-9lddQ5-3yjwK1Sw-w.png",
"./mon_202011/26/-9lddQ5-d8vxK1Sw-w.png",
"./mon_202011/26/-9lddQ5-1dteK0Sx-14.png",
"./mon_202011/26/-9lddQ5-goqcK0Sw-14.png",
"./mon_202011/26/-9lddQ5-5xelK1Sw-w.png",
"./mon_202011/26/-9lddQ5-fxmrK1Sw-w.png",
],
[
"./mon_202011/26/-9lddQ5-frzrK1Sw-w.png",
"./mon_202011/26/-9lddQ5-432jK1S12-11.png",
"./mon_202011/26/-9lddQ5-dtocK1Sw-w.png",
"./mon_202011/26/-9lddQ5-lc5dK1Sw-w.png",
"./mon_202011/26/-9lddQ5-dkwbK1Sw-w.png",
"./mon_202011/26/-9lddQ5-6ffaK1Sw-w.png",
"./mon_202011/26/-9lddQ5-hk7pK1Sw-w.png",
"./mon_202011/26/-9lddQ5-dj9tK1Sw-w.png",
"./mon_202011/26/-9lddQ5-kf9xK1Sw-w.png",
"./mon_202011/26/-9lddQ5-9zpqK1Sw-w.png",
"./mon_202011/26/-9lddQ5-6gkcK1Sz-z.png",
"./mon_202011/26/-9lddQ5-g7e6K1Sw-w.png",
"./mon_202011/26/-9lddQ5-436lK1Sw-w.png",
"./mon_202011/26/-9lddQ5-j2x1K1Sw-w.png",
"./mon_202011/26/-9lddQ5-ehy8K1Sw-w.png",
"./mon_202011/26/-9lddQ5-fmq8K1Sw-w.png",
"./mon_202011/26/-9lddQ5-a6ldK0Sw-z.png",
"./mon_202011/26/-9lddQ5-cbv0K1Sw-w.png",
"./mon_202011/26/-9lddQ5-3v9pK1Sw-w.png",
"./mon_202011/26/-9lddQ5-cuzhK0Sw-w.png",
"./mon_202011/26/-9lddQ5-dr3zK1Sw-w.png",
"./mon_202011/26/-9lddQ5-9f9iK1Sw-w.png",
"./mon_202011/26/-9lddQ5-54jzK1Sw-w.png",
"./mon_202011/26/-9lddQ5-1fthK1Sw-w.png",
"./mon_202011/26/-9lddQ5-ab22K1Sw-w.png",
"./mon_202011/26/-9lddQ5-5kdiK1Sw-w.png",
"./mon_202011/26/-9lddQ5-feo8K2T8S1q-1s.png",
"./mon_202011/26/-9lddQ5-6j1eK2S18-18.png",
"./mon_202011/26/-9lddQ5-doimK0S14-w.png",
"./mon_202011/26/-9lddQ5-ck3K1Sw-w.png",
],
[
"./mon_202011/26/-9lddQ5-co05K1Sw-w.png",
"./mon_202011/26/-9lddQ5-f5n9K1Sw-w.png",
"./mon_202011/26/-9lddQ5-gii1K1Sw-w.png",
"./mon_202011/26/-9lddQ5-hujoK0Sy-w.png",
"./mon_202011/26/-9lddQ5-5mu9K0Sy-w.png",
"./mon_202011/26/-9lddQ5-d2yvK1S12-11.png",
"./mon_202011/26/-9lddQ5-iof5K0Sy-y.png",
"./mon_202011/26/-9lddQ5-3evwK0Sz-z.png",
"./mon_202011/26/-9lddQ5-ax7vK1Sw-w.png",
"./mon_202011/26/-9lddQ5-fn5jK1Sw-w.png",
"./mon_202011/26/-9lddQ5-kxdxK1Sw-w.png",
"./mon_202011/26/-9lddQ5-7ovsK1Sw-w.png",
"./mon_202011/26/-9lddQ5-f4usK1Sw-w.png",
"./mon_202011/26/-9lddQ5-hsmdK1Sw-w.png",
"./mon_202011/26/-9lddQ5-318aK1Sw-w.png",
"./mon_202011/26/-9lddQ5-6u4sK0Sw-w.png",
"./mon_202011/26/-9lddQ5-ey5qK1S18-18.png",
"./mon_202011/26/-9lddQ5-isebK1Sw-w.png",
"./mon_202011/26/-9lddQ5-4tm0K1Sw-w.png",
"./mon_202011/26/-9lddQ5-d42oK0Sw-z.png",
"./mon_202011/26/-9lddQ5-j0cyK0Sz-w.png",
"./mon_202011/26/-9lddQ5-7nuyK1Sw-w.png",
"./mon_202011/26/-9lddQ5-dfnkK1Sw-w.png",
"./mon_202011/26/-9lddQ5-e0rK1S12-11.png",
"./mon_202011/26/-9lddQ5-5aejK0Sw-w.png",
"./mon_202011/26/-9lddQ5-e0maK1Sw-w.png",
"./mon_202011/26/-9lddQ5-j7isK1S18-18.png",
"./mon_202011/26/-9lddQ5-2zkoK0S10-x.png",
"./mon_202011/26/-9lddQ5-aem3K0Sy-18.png",
"./mon_202011/26/-9lddQ5-iptfK0Sy-10.png",
],
["./mon_202011/26/-9lddQ5-g7bsK0Sz-11.png"],
],
[
"高达",
[
"./mon_202011/26/-9lddQ5-cuvK0Sw-w.png",
"./mon_202011/26/-9lddQ5-626bK0S11-y.png",
"./mon_202011/26/-9lddQ5-c7leK1Sw-10.png",
"./mon_202011/26/-9lddQ5-gy97K0Sw-13.png",
"./mon_202011/26/-9lddQ5-46uuK0Sw-13.png",
"./mon_202011/26/-9lddQ5-cgrlK0Sw-w.png",
"./mon_202011/26/-9lddQ5-l2wcK0Sw-11.png",
"./mon_202011/26/-9lddQ5-5l6fK0Sw-11.png",
"./mon_202011/26/-9lddQ5-b967K0Sw-11.png",
"./mon_202011/26/-9lddQ5-jj5aK0Sw-11.png",
"./mon_202011/26/-9lddQ5-4pbeK0Sw-12.png",
"./mon_202011/26/-9lddQ5-apdqK0Sw-12.png",
"./mon_202011/26/-9lddQ5-hzlgK0Sw-12.png",
"./mon_202011/26/-9lddQ5-4s8nK0Sw-z.png",
"./mon_202011/26/-9lddQ5-cw5hK0Sw-z.png",
"./mon_202011/26/-9lddQ5-ldplK0Sw-z.png",
"./mon_202011/26/-9lddQ5-7mh6K0Sw-z.png",
"./mon_202011/26/-9lddQ5-dwvkK0Sw-z.png",
"./mon_202011/26/-9lddQ5-8j7yK0Sw-12.png",
"./mon_202011/26/-9lddQ5-h9yxK0Sw-11.png",
"./mon_202011/26/-9lddQ5-3obmK0Sw-10.png",
"./mon_202011/26/-9lddQ5-8vknK1Sw-11.png",
"./mon_202011/26/-9lddQ5-flfjK1Sw-w.png",
"./mon_202011/26/-9lddQ5-10oK1Sw-w.png",
"./mon_202011/26/-9lddQ5-55b4K0Sw-w.png",
"./mon_202011/26/-9lddQ5-cl30K0Sw-w.png",
"./mon_202011/26/-9lddQ5-huzmK0Sw-w.png",
"./mon_202011/26/-9lddQ5-2qxnK1Sw-w.png",
"./mon_202011/26/-9lddQ5-ah2hK1Sw-w.png",
],
[
"./mon_202011/26/-9lddQ5-311qK0Sw-10.png",
"./mon_202011/26/-9lddQ5-8e4iK0Sw-w.png",
"./mon_202011/26/-9lddQ5-dv7kK1Sw-w.png",
"./mon_202011/26/-9lddQ5-l6qbK1Sw-w.png",
"./mon_202011/26/-9lddQ5-8q3rK0Sw-w.png",
"./mon_202011/26/-9lddQ5-fybzK0Sw-w.png",
"./mon_202011/26/-9lddQ5-fippK0Sw-w.png",
],
],
];
const loadSmiles = (loaded) => {
if (loaded) return;
const { correctAttachUrl } = ui;
const tabs = poster.selectSmilesw._.__c.firstElementChild;
const contents = poster.selectSmilesw._.__c.lastElementChild;
smiles.forEach((item) => {
const name = item[0];
const list = item.flatMap((i) => (typeof i === "object" ? [...i] : []));
const pageSize = 60;
const pageCount = Math.ceil(list.length / pageSize);
for (let i = 0; i < pageCount; i++) {
const tab = document.createElement("BUTTON");
const content = document.createElement("DIV");
tab.className = "block_txt_big";
tab.innerText = `${name}${
pageCount > 1 ? `(${i + 1}/${pageCount})` : ""
}`;
tab.onclick = () => {
tabs.firstChild.innerHTML = `<a href="https://bbs.saraba1st.com/2b/" target="_blank" style="color: inherit;">《粪海狂蛆》</a>`;
contents.childNodes.forEach((c) => {
if (c !== content) {
c.style.display = "none";
} else {
c.style.display = "";
}
});
if (content.childNodes.length === 0) {
list.slice(pageSize * i, pageSize * (i + 1)).forEach((s) => {
const smile = document.createElement("IMG");
smile.src = correctAttachUrl(s);
smile.style = "max-width: 60px";
smile.onclick = () => {
poster.selectSmilesw._.hide();
poster.addText(`[img]${s}[/img]`);
};
content.appendChild(smile);
});
}
};
tabs.appendChild(tab);
contents.appendChild(content);
}
});
};
hookFunction(poster, "selectSmiles", (returnValue) =>
loadSmiles(returnValue)
);
if (location.pathname === "/post.php") {
const corsServices = [
"https://cors.bridged.cc/",
];
const { attach_url, fid, auth } = poster.currentPostStat;
const upload = async (url, corsIndex = 0) => {
const corsService = corsServices[corsIndex];
const fetch_retry = async (url, options, n) => {
let error;
for (let i = 0; i < n; i++) {
try {
return await fetch(url, options).then((res) => {
if (!res.ok) {
throw Error(res.statusText);
}
return res;
});
} catch (err) {
error = err;
}
}
throw error;
};
return fetch_retry(corsService + url, {
headers: {
"X-Requested-With": "XMLHttpRequest"
}}, 3)
.then((res) => res.blob())
.then((blob) => {
const filename = url.replace(/^.*[\\\/]/, "");
const file = new File([blob], filename, {
type: blob.type,
lastModified: Date.now(),
});
const formData = new FormData();
formData.append("v2", "1");
formData.append("func", "upload");
formData.append("attachment_file1", file);
formData.append(
"attachment_file1_url_utf8_name",
poster.rawUrlEncode(filename)
);
formData.append("attachment_file1_img", "1");
formData.append("attachment_file1_dscp", "");
formData.append("attachment_file1_auto_size", "0");
formData.append("fid", fid);
formData.append("auth", auth);
formData.append("__output", "11");
return fetch(attach_url, { method: "POST", body: formData });
})
.then((res) => res.json())
.then((res) => {
poster.add1Attach(
res.attachments,
res.attachments_check,
res.url,
res.isImg,
res.thumb
);
return res.url;
})
.catch(() => "");
};
const migration = (task, limit = 0, length = 60) => {
const SOURCEURL =
"https://bbs.saraba1st.com/2b/data/cache/common_smilies_var.js";
const STATICURL = "https://static.saraba1st.com/";
const interval = 100;
fetch(corsServices[0] + SOURCEURL)
.then((res) => res.text())
.then(async (res) => {
eval(res);
const pair = Object.entries(smilies_type).find(
([key, value]) => value[0] === task
);
if (pair) {
const typeid = pair[0].substr(1);
const typename = pair[1][0];
const typepath = pair[1][1];
poster.addText(
`正在搬运[${typename}]:${limit + 1} - ${limit + length}\n`
);
const array = smilies_array[typeid]
.flatMap((item) => [...item])
.slice(limit, limit + length);
const result = [];
for (let item in array) {
const filename = array[item][2];
const smilieimg =
STATICURL + "image/smiley/" + typepath + "/" + filename;
const url = await upload(smilieimg);
if (url) {
result.push(`./${url}`);
} else {
poster.addText(`搬运失败:${smilieimg}\n`);
}
await new Promise((resolve) => setTimeout(resolve, interval));
}
if (result.length) {
poster.addText(
`[collapse=${typename}][code]${JSON.stringify(
result
)}[/code]${result
.map((item) => `[img]${item}[/img]`)
.join("")}[/collapse]\n`
);
}
}
});
};
poster.migration = migration;
}
})(commonui, postfunc);
显示被点赞和粉丝数量 - NGA Likes Support
在回帖列表中显示每个楼层用户的总被点赞数量
v1.0.1 修复了贴条的BUG;不再显示匿名用户;现在总点赞数为0的也会被显示(方便给同情分
v1.0.2 不再显示匿名用户
v1.0.3 增加了关注数量的显示(不显示0关注),优化了加载方式
v1.0.4 修改了部分代码以兼容关注脚本
// ==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
// ==/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 = `<span class="white"><span style="font-family: comm_glyphs; -webkit-font-smoothing: antialiased; line-height: 1em;">⯅</span> ${value}</span>`;
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 = `<span class="white"><span style="font-family: comm_glyphs; -webkit-font-smoothing: antialiased; line-height: 1em;">★</span> ${value}</span>`;
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);
同步客户端关注功能 - NGA Watcher
事到如今我也不用装什么正人君子了.jpg
v1.1.0 采用官方接口实现网页版关注功能,与客户端同步。
故原有的关键词筛选功能和消息提示功能暂已取消,请谨慎选择更新。
v1.2.0 关键词筛选功能和消息提示功能回归,现在支持单独设置筛选条件。
v1.2.2 关注动态数量提示。
v1.3.0 解决官方接口会返回已取消关注用户动态的问题。重写了关注动态数量提示逻辑,现在会提示筛选后的准确数量了。
// ==UserScript==
// @name NGA Watcher
// @namespace https://greasyfork.org/users/263018
// @version 1.3.1
// @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]);
};
// 用户信息
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 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) =>
new Promise((resolve, reject) => {
fetch(`/nuke.php?lite=js&__lib=ucp&__act=get&uid=${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[0]);
} else {
reject(result.error[0]);
}
};
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.querySelector(
"[name=uid]"
).parentNode;
}
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);
troll must die - NGA Filter
NGA屏蔽脚本
v0.1 简单做了屏蔽逻辑,
根据trollArray里的用户ID删除相关帖子或者楼层。
v0.2 不再直接删除帖子或楼层,改为标题用删除线区分,楼层折叠。屏蔽方式为楼层ID边上的灰色UID按钮,红色为已屏蔽,再次点击取消屏蔽。
v0.3 简单的帖子标题关键词过滤,在代码里修改。
v0.4 加入了一个菜单用于切换过滤模式为删除或者标记。
v0.5 加入了一个菜单用于修改过滤关键词。
v0.6 现在点击屏蔽按钮时按住ctrl键可以增加标记。
v1.0 简单写了个UI,支持多个标记,支持标记但不屏蔽,增加了用户信息页的操作。入口集成在论坛右上角主菜单。
v1.1 更新过滤逻辑,解决NGA新框架下翻页等情况会导致过滤失效的问题。
v1.2 优化了过滤方式的设置,并可以针对某个用户或者标记采用单独的过滤规则。过滤优先级:用户>标记>全局。
v1.3 升级了关键词屏蔽机制,现在可以更好的设置关键词并采用单独的过滤规则,同时支持帖子内容过滤。附加功能
v0.6.1
屏蔽左上角广告相关的错误提示
v0.6.2 NGA去掉了广告提示,代码回滚
v0.7.0显示原始的赞踩数量
v0.7.1 赞踩相关接口失效,代码回滚
// ==UserScript==
// @name NGA Filter
// @namespace https://greasyfork.org/users/263018
// @version 1.3.2
// @author snyssss
// @description troll must die
// @match *://bbs.nga.cn/*
// @match *://ngabbs.com/*
// @match *://nga.178.com/*
// @grant GM_addStyle
// @grant GM_setValue
// @grant GM_getValue
// @noframes
// ==/UserScript==
((n, self) => {
if (n === undefined) return;
const key = "NGAFilter";
// 过滤提示
const FILTER_TIPS =
"过滤顺序:用户 > 标记 > 关键字<br/>过滤级别:隐藏 > 遮罩 > 标记 > 继承 > 显示<br/>多个标记或者关键字按最高级别过滤";
// 过滤方式
const FILTER_MODE = ["继承", "标记", "遮罩", "隐藏", "显示"];
// 切换过滤方式
const switchFilterMode = (value) => {
const next = FILTER_MODE.indexOf(value) + 1;
if (next >= FILTER_MODE.length) {
return FILTER_MODE[0];
}
return FILTER_MODE[next];
};
// 数据
const data = (() => {
const d = {
tags: {},
users: {},
keywords: {},
options: {
filterMode: "隐藏",
},
};
const v = GM_getValue(key);
if (typeof v !== "object") {
return d;
}
return Object.assign(d, v);
})();
// 保存数据
const saveData = () => {
GM_setValue(key, data);
};
// 增加标记
const addTag = (name) => {
const tag = Object.values(data.tags).find((item) => item.name === name);
if (tag) return tag.id;
const id =
Math.max(...Object.values(data.tags).map((item) => item.id), 0) + 1;
const hash = (() => {
let h = 5381;
for (var i = 0; i < name.length; i++) {
h = ((h << 5) + h + name.charCodeAt(i)) & 0xffffffff;
}
return h;
})();
const hex = Math.abs(hash).toString(16) + "000000";
const hsv = [
`0x${hex.substr(2, 2)}` / 255,
`0x${hex.substr(2, 2)}` / 255 / 2 + 0.25,
`0x${hex.substr(4, 2)}` / 255 / 2 + 0.25,
];
const rgb = n.hsvToRgb(hsv[0], hsv[1], hsv[2]);
const color = ["#", ...rgb].reduce((a, b) => {
return a + ("0" + b.toString(16)).slice(-2);
});
data.tags[id] = {
id,
name,
color,
filterMode: FILTER_MODE[0],
};
saveData();
return id;
};
// 增加用户
const addUser = (id, name = null, tags = [], filterMode = FILTER_MODE[0]) => {
if (data.users[id]) return data.users[id];
data.users[id] = {
id,
name,
tags,
filterMode,
};
saveData();
return data.users[id];
};
// 增加关键字
const addKeyword = (
keyword,
filterMode = FILTER_MODE[0],
filterLevel = 0
) => {
const id =
Math.max(...Object.values(data.keywords).map((item) => item.id), 0) + 1;
data.keywords[id] = {
id,
keyword,
filterMode,
filterLevel,
};
saveData();
return id;
};
// 旧版本数据迁移
{
const dataKey = "troll_data";
const modeKey = "troll_mode";
const keywordKey = "troll_keyword";
if (localStorage.getItem(dataKey)) {
let trollMap = (function () {
try {
return JSON.parse(localStorage.getItem(dataKey)) || {};
} catch (e) {}
return {};
})();
let filterMode = ~~localStorage.getItem(modeKey);
let filterKeyword = localStorage.getItem(keywordKey) || "";
// 整理标签
[...new Set(Object.values(trollMap).flat())].forEach((item) =>
addTag(item)
);
// 整理用户
Object.keys(trollMap).forEach((item) => {
addUser(
item,
null,
(typeof trollMap[item] === "object" ? trollMap[item] : []).map(
(tag) => addTag(tag)
)
);
});
data.options.filterMode = filterMode ? "隐藏" : "标记";
data.options.keyword = filterKeyword;
localStorage.removeItem(dataKey);
localStorage.removeItem(modeKey);
localStorage.removeItem(keywordKey);
saveData();
}
// v1.1.0 -> v1.1.1
{
Object.values(data.users).forEach(({ id, name, tags, enabled }) => {
if (enabled !== undefined) {
data.users[id] = {
id,
name,
tags,
filterMode: enabled ? "继承" : "显示",
};
}
});
Object.values(data.tags).forEach(({ id, name, color, enabled }) => {
if (enabled !== undefined) {
data.tags[id] = {
id,
name,
color,
filterMode: enabled ? "继承" : "显示",
};
}
});
if (data.options.filterMode === 0) {
data.options.filterMode = "隐藏";
} else if (data.options.filterMode === 1) {
data.options.filterMode = "标记";
}
saveData();
}
// v1.2.x -> v1.3.0
{
if (data.options.keyword) {
addKeyword(data.options.keyword);
delete data.options.keyword;
saveData();
}
}
}
// 编辑用户标记
const editUser = (() => {
let window;
return (uid, name, callback) => {
if (window === undefined) {
window = n.createCommmonWindow();
}
const user = data.users[uid];
const content = document.createElement("div");
const size = Math.floor((screen.width * 0.8) / 200);
const items = Object.values(data.tags).map(
(tag, index) => `
<td class="c1">
<label for="s-tag-${index}" style="display: block; cursor: pointer;">
<b class="block_txt nobr" style="background:${
tag.color
}; color:#fff; margin: 0.1em 0.2em;">${tag.name}</b>
</label>
</td>
<td class="c2" width="1">
<input id="s-tag-${index}" type="checkbox" value="${tag.id}" ${
user && user.tags.find((item) => item === tag.id) && "checked"
}/>
</td>
`
);
const rows = [...new Array(Math.ceil(items.length / size))].map(
(item, index) =>
`
<tr class="row${(index % 2) + 1}">
${items.slice(size * index, size * (index + 1)).join("")}
</tr>
`
);
content.className = "w100";
content.innerHTML = `
<div class="filter-table-wrapper" style="width: 80vw;">
<table class="filter-table forumbox">
<tbody>
${rows.join("")}
</tbody>
</table>
</div>
<div style="margin: 10px 0;">
<input placeholder="一次性添加多个标记用"|"隔开,不会添加重名标记" style="width: -webkit-fill-available;" />
</div>
<div style="margin: 10px 0;">
<span>过滤方式:</span>
<button>${(user && user.filterMode) || FILTER_MODE[0]}</button>
<div class="right_">
<button>删除</button>
<button>保存</button>
</div>
</div>
<div class="silver" style="margin-top: 5px;">${FILTER_TIPS}</div>
`;
const actions = content.getElementsByTagName("button");
actions[0].onclick = () => {
actions[0].innerText = switchFilterMode(
actions[0].innerText || FILTER_MODE[0]
);
};
actions[1].onclick = () => {
if (confirm("是否确认?")) {
delete data.users[uid];
saveData();
callback && callback();
window._.hide();
}
};
actions[2].onclick = () => {
if (confirm("是否确认?")) {
const values = [...content.getElementsByTagName("input")];
const newTags = values[values.length - 1].value
.split("|")
.filter((item) => item.length)
.map((item) => addTag(item));
const tags = [
...new Set(
values
.filter((item) => item.type === "checkbox" && item.checked)
.map((item) => ~~item.value)
.concat(newTags)
),
].sort();
if (user) {
user.tags = tags;
user.filterMode = actions[0].innerText;
} else {
addUser(uid, name, tags, actions[0].innerText);
}
saveData();
callback && callback();
window._.hide();
}
};
if (user === undefined) {
actions[1].style = "display: none;";
}
window._.addContent(null);
window._.addTitle(`编辑标记 - ${name ? name : "#" + uid}`);
window._.addContent(content);
window._.show();
};
})();
// 判断过滤方式
const getFilterMode = (uid, content, level) => {
let result = -1;
const user = data.users[uid];
const tags = user ? user.tags.map((tag) => data.tags[tag]) : [];
const keywords = Object.values(data.keywords);
if (user) {
const filterMode = FILTER_MODE.indexOf(user.filterMode);
if (filterMode > 0) {
return filterMode;
}
result = filterMode;
}
if (tags.length) {
const filterMode = (() => {
if (tags.some((tag) => tag.filterMode !== "显示")) {
return tags
.filter((tag) => tag.filterMode !== "显示")
.map((tag) => FILTER_MODE.indexOf(tag.filterMode) || 0)
.sort((a, b) => b - a)[0];
}
return FILTER_MODE.indexOf("显示");
})();
if (filterMode > 0) {
return filterMode;
}
result = filterMode;
}
if (keywords.length) {
const filterMode = (() => {
const r = keywords
.filter((item) => item.keyword && item.filterMode !== "显示")
.filter((item) => (item.filterLevel || 0) >= level)
.sort(
(a, b) =>
FILTER_MODE.indexOf(b.filterMode) -
FILTER_MODE.indexOf(a.filterMode)
)
.find((item) => content.search(item.keyword) >= 0);
if (r) {
return FILTER_MODE.indexOf(r.filterMode);
}
return result;
})();
if (filterMode > 0) {
return filterMode;
}
result = filterMode;
}
return result;
};
// 处理引用
const handleQuote = (content) => {
const quotes = content.querySelectorAll(".quote");
quotes.forEach((quote) => {
const uid = (() => {
const ele = quote.querySelector("a[href^='/nuke.php']");
if (ele) {
const res = ele.getAttribute("href").match(/uid=(\S+)/);
if (res) {
return res[1];
}
}
return 0;
})();
if (uid) {
const filterMode = (() => {
const mode = getFilterMode(uid, quote.innerText, 1);
if (mode === 0) {
return data.options.filterMode;
}
if (mode > 0) {
return FILTER_MODE[mode];
}
return "";
})();
if (filterMode === "标记") {
quote.innerHTML = `
<div class="lessernuke" style="background: #81C7D4; border-color: #66BAB7; ">
<span class="crimson">Troll must die.</span>
<a href="javascript:void(0)" onclick="[...document.getElementsByName('troll_${uid}')].forEach(item => item.style.display = '')">点击查看</a>
<div style="display: none;" name="troll_${uid}">
${quote.innerHTML}
</div>
</div>`;
} else if (filterMode === "遮罩") {
const source = document.createElement("DIV");
source.innerHTML = quote.innerHTML;
source.style.display = "none";
const caption = document.createElement("CAPTION");
caption.className = "filter-mask filter-mask-block";
caption.innerHTML = `<span class="crimson">Troll must die.</span>`;
caption.onclick = () => {
quote.removeChild(caption);
source.style.display = "";
};
quote.innerHTML = "";
quote.appendChild(source);
quote.appendChild(caption);
} else if (filterMode === "隐藏") {
quote.innerHTML = "";
}
}
});
};
// 过滤
const reFilter = () => {
const tPage = location.pathname === "/thread.php";
const pPage = location.pathname === "/read.php";
const uPage = location.pathname === "/nuke.php";
if (tPage) {
const tData = n.topicArg.data;
Object.values(tData).forEach((item) => {
if (item.containerC) return;
const uid =
item[2].search.match(/uid=(\S+)/) &&
item[2].search.match(/uid=(\S+)/)[1];
const filterMode = (() => {
const mode = getFilterMode(uid, item[1].innerText, 0);
if (mode === 0) {
return data.options.filterMode;
}
if (mode > 0) {
return FILTER_MODE[mode];
}
return "";
})();
item.contentC = item[1];
item.contentB = item.contentB || item.contentC.innerHTML;
item.containerC =
item.containerC || item.contentC.parentNode.parentNode;
item.containerC.style = "";
item.contentC.style = "";
item[1].className = item[1].className.replace(" filter-mask", "");
item[2].className = item[2].className.replace(" filter-mask", "");
if (filterMode === "标记") {
item.contentC.style = "text-decoration: line-through;";
} else if (filterMode === "遮罩") {
item[1].className += " filter-mask";
item[2].className += " filter-mask";
} else if (filterMode === "隐藏") {
item.containerC.style = "display: none;";
}
});
} else if (pPage) {
const pData = n.postArg.data;
Object.values(pData).forEach((item) => {
if (~~item.pAid === self) return;
if (item.containerC) return;
if (typeof item.i === "number") {
item.actionC =
item.actionC ||
(() => {
const ele = item.uInfoC.querySelector('[name="uid"]');
ele.onclick = null;
return ele;
})();
item.tagC =
item.tagC ||
(() => {
const tc = document.createElement("div");
tc.className = "filter-tags";
item.uInfoC.appendChild(tc);
return tc;
})();
}
item.pName =
item.pName ||
item.uInfoC.getElementsByClassName("author")[0].innerText;
item.reFilter =
item.reFilter ||
(() => {
const uid = item.pAid;
const filterMode = (() => {
const mode = getFilterMode(uid, item.contentC.innerText, 1);
if (mode === 0) {
return data.options.filterMode;
}
if (mode > 0) {
return FILTER_MODE[mode];
}
return "";
})();
item.avatarC =
item.avatarC ||
(() => {
const tc = document.createElement("div");
const avatar = document.getElementById(`posteravatar${item.i}`);
if (avatar) {
avatar.parentNode.insertBefore(tc, avatar.nextSibling);
tc.appendChild(avatar);
}
return tc;
})();
item.contentB = item.contentB || item.contentC.innerHTML;
item.containerC =
item.containerC ||
(() => {
let temp = item.contentC;
if (item.i >= 0) {
while (temp.nodeName !== "TBODY") {
temp = temp.parentNode;
}
} else {
while (temp.nodeName !== "DIV") {
temp = temp.parentNode;
}
}
return temp;
})();
item.avatarC.style.display = "";
item.containerC.style.display = "";
item.contentC.innerHTML = item.contentB;
if (item.actionC) {
item.actionC.style = "background: #aaa;";
}
if (filterMode === "标记") {
item.avatarC.style.display = "none";
item.contentC.innerHTML = `
<div class="lessernuke" style="background: #81C7D4; border-color: #66BAB7; ">
<span class="crimson">Troll must die.</span>
<a href="javascript:void(0)" onclick="[...document.getElementsByName('troll_${uid}')].forEach(item => item.style.display = '')">点击查看</a>
<div style="display: none;" name="troll_${uid}">
${item.contentB}
</div>
</div>`;
if (item.actionC && data.users[uid]) {
item.actionC.style = "background: #cb4042;";
}
} else if (filterMode === "遮罩") {
const caption = document.createElement("CAPTION");
if (item.i >= 0) {
caption.className = "filter-mask filter-mask-block";
} else {
caption.className = "filter-mask filter-mask-block left";
caption.style = "width: 47%;";
}
caption.innerHTML = `<span class="crimson">Troll must die.</span>`;
caption.onclick = () => {
item.containerC.parentNode.removeChild(caption);
item.containerC.style.display = "";
};
item.containerC.parentNode.insertBefore(caption, item.containerC);
item.containerC.style.display = "none";
if (item.actionC && data.users[uid]) {
item.actionC.style = "background: #cb4042;";
}
} else if (filterMode === "隐藏") {
item.containerC.style.display = "none";
} else {
handleQuote(item.contentC);
}
if (item.tagC) {
const tags = data.users[uid]
? data.users[uid].tags.map((tag) => data.tags[tag]) || []
: [];
item.tagC.style.display = tags.length ? "" : "none";
item.tagC.innerHTML = tags
.map(
(tag) =>
`<b class="block_txt nobr" style="background:${tag.color}; color:#fff; margin: 0.1em 0.2em;">${tag.name}</b>`
)
.join("");
}
});
if (item.actionC) {
item.actionC.onclick =
item.actionC.onclick ||
((e) => {
if (item.pAid < 0) return;
const user = data.users[item.pAid];
if (e.ctrlKey === false) {
editUser(item.pAid, item.pName, item.reFilter);
} else {
if (user) {
delete data.users[user.id];
} else {
addUser(item.pAid, item.pName);
}
saveData();
item.reFilter();
}
});
}
item.reFilter();
});
} else if (uPage) {
const container = document.getElementById("ucp_block");
if (container.firstChild) {
const uid = container.innerText.match(/用户ID\s*:\s*(\S+)/)[1];
const name = container.innerText.match(/用户名\s*:\s*(\S+)/)[1];
container.tagC =
container.tagC ||
(() => {
const c = document.createElement("span");
c.innerHTML = `
<h2 class="catetitle">:: ${name} 的标记 ::</h2>
<div class="cateblock" style="text-align: left; line-height: 1.8em;">
<div class="contentBlock" style="padding: 5px 10px;">
<span>
<ul class="actions" style="padding: 0px; margin: 0px;">
<li style="padding-right: 5px;">
<span>
<a href="javascript: void(0);">[编辑 ${name} 的标记]</a>
</span>
</li>
<div class="clear"></div>
</ul>
</span>
<div class="filter-tags"></div>
<div class="clear"></div>
</div>
</div>
`;
c.getElementsByTagName("a")[0].onclick = () => {
editUser(uid, name, container.refresh);
};
container.firstChild.insertBefore(
c,
container.firstChild.childNodes[1]
);
return c.getElementsByClassName("filter-tags")[0];
})();
container.refresh = () => {
container.tagC.innerHTML = data.users[uid].tags
.map(
(tag) =>
`<b class="block_txt nobr" style="background:${data.tags[tag].color}; color:#fff; margin: 0.1em 0.2em;">${data.tags[tag].name}</b>`
)
.join("");
};
container.refresh();
}
}
};
// STYLE
GM_addStyle(`
.filter-table-wrapper {
max-height: 80vh;
overflow-y: auto;
}
.filter-table {
margin: 0;
}
.filter-table th,
.filter-table td {
position: relative;
white-space: nowrap;
}
.filter-table th {
position: sticky;
top: 2px;
z-index: 1;
}
.filter-table input:not([type]), .filter-table input[type="text"] {
margin: 0;
box-sizing: border-box;
height: 100%;
width: 100%;
}
.filter-input-wrapper {
position: absolute;
top: 6px;
right: 6px;
bottom: 6px;
left: 6px;
}
.filter-text-ellipsis {
display: flex;
}
.filter-text-ellipsis > * {
flex: 1;
width: 1px;
overflow: hidden;
text-overflow: ellipsis;
}
.filter-button-group {
margin: -.1em -.2em;
}
.filter-tags {
margin: 2px -0.2em 0;
text-align: left;
}
.filter-mask {
margin: 1px;
color: #81C7D4;
background: #81C7D4;
}
.filter-mask-block {
display: block;
border: 1px solid #66BAB7;
text-align: center !important;
}
.filter-input-wrapper {
position: absolute;
top: 6px;
right: 6px;
bottom: 6px;
left: 6px;
}
`);
// UI
const u = (() => {
const modules = {};
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: 80vw;";
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.refresh();
} else {
item.tab.className = "nobr silver";
item.content.style = "display: none";
}
});
};
tc.append(tabBox);
cc.append(module.content);
tab.onclick = toggle;
modules[module.name] = {
...module,
tab,
toggle,
};
return modules[module.name];
};
})();
return {
content,
modules,
addModule,
};
})();
// 用户
const userModule = (() => {
const content = (() => {
const c = document.createElement("div");
c.style = "display: none";
c.innerHTML = `
<div class="filter-table-wrapper">
<table class="filter-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>
`;
return c;
})();
const refresh = (() => {
const container = content.getElementsByTagName("tbody")[0];
const func = () => {
container.innerHTML = "";
Object.values(data.users).forEach((item) => {
const tc = document.createElement("tr");
tc.className = `row${
(container.querySelectorAll("TR").length % 2) + 1
}`;
tc.refresh = () => {
if (data.users[item.id]) {
tc.innerHTML = `
<td class="c1">
<a href="/nuke.php?func=ucp&uid=${
item.id
}" class="b nobr">[${
item.name ? "@" + item.name : "#" + item.id
}]</a>
</td>
<td class="c2">
${item.tags
.map((tag) => {
if (data.tags[tag]) {
return `<b class="block_txt nobr" style="background:${data.tags[tag].color}; color:#fff; margin: 0.1em 0.2em;">${data.tags[tag].name}</b>`;
}
})
.join("")}
</td>
<td class="c3">
<div class="filter-table-button-group">
<button>${item.filterMode || FILTER_MODE[0]}</button>
</div>
</td>
<td class="c4">
<div class="filter-table-button-group">
<button>编辑</button>
<button>删除</button>
</div>
</td>
`;
const actions = tc.getElementsByTagName("button");
actions[0].onclick = () => {
data.users[item.id].filterMode = switchFilterMode(
data.users[item.id].filterMode || FILTER_MODE[0]
);
actions[0].innerHTML = data.users[item.id].filterMode;
saveData();
reFilter();
};
actions[1].onclick = () => {
editUser(item.id, item.name, tc.refresh);
};
actions[2].onclick = () => {
if (confirm("是否确认?")) {
delete data.users[item.id];
container.removeChild(tc);
saveData();
reFilter();
}
};
} else {
tc.remove();
}
};
tc.refresh();
container.appendChild(tc);
});
};
return func;
})();
return {
name: "用户",
content,
refresh,
};
})();
// 标记
const tagModule = (() => {
const content = (() => {
const c = document.createElement("div");
c.style = "display: none";
c.innerHTML = `
<div class="filter-table-wrapper">
<table class="filter-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>
`;
return c;
})();
const refresh = (() => {
const container = content.getElementsByTagName("tbody")[0];
const func = () => {
container.innerHTML = "";
Object.values(data.tags).forEach((item) => {
const tc = document.createElement("tr");
tc.className = `row${
(container.querySelectorAll("TR").length % 2) + 1
}`;
tc.innerHTML = `
<td class="c1">
<b class="block_txt nobr" style="background:${
item.color
}; color:#fff; margin: 0.1em 0.2em;">${item.name}</b>
</td>
<td class="c2">
<button>${
Object.values(data.users).filter((user) =>
user.tags.find((tag) => tag === item.id)
).length
}
</button>
<div style="white-space: normal; display: none;">
${Object.values(data.users)
.filter((user) =>
user.tags.find((tag) => tag === item.id)
)
.map(
(user) =>
`<a href="/nuke.php?func=ucp&uid=${
user.id
}" class="b nobr">[${
user.name ? "@" + user.name : "#" + user.id
}]</a>`
)
.join("")}
</div>
</td>
<td class="c3">
<div class="filter-table-button-group">
<button>${item.filterMode || FILTER_MODE[0]}</button>
</div>
</td>
<td class="c4">
<div class="filter-table-button-group">
<button>删除</button>
</div>
</td>
`;
const actions = tc.getElementsByTagName("button");
actions[0].onclick = (() => {
let hide = true;
return () => {
hide = !hide;
actions[0].nextElementSibling.style.display = hide
? "none"
: "block";
};
})();
actions[1].onclick = () => {
data.tags[item.id].filterMode = switchFilterMode(
data.tags[item.id].filterMode || FILTER_MODE[0]
);
actions[1].innerHTML = data.tags[item.id].filterMode;
saveData();
reFilter();
};
actions[2].onclick = () => {
if (confirm("是否确认?")) {
delete data.tags[item.id];
Object.values(data.users).forEach((user) => {
const index = user.tags.findIndex((tag) => tag === item.id);
if (index >= 0) {
user.tags.splice(index, 1);
}
});
container.removeChild(tc);
saveData();
reFilter();
}
};
container.appendChild(tc);
});
};
return func;
})();
return {
name: "标记",
content,
refresh,
};
})();
// 关键字
const keywordModule = (() => {
const content = (() => {
const c = document.createElement("div");
c.style = "display: none";
c.innerHTML = `
<div class="filter-table-wrapper">
<table class="filter-table forumbox">
<thead>
<tr class="block_txt_c0">
<th class="c1">列表</th>
<th class="c2" width="1">过滤方式</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: 10px;">支持正则表达式。比如同类型的可以写在一条规则内用"|"隔开,"ABC|DEF"即为屏蔽带有ABC或者DEF的内容。</div>
`;
return c;
})();
const refresh = (() => {
const container = content.getElementsByTagName("tbody")[0];
const func = () => {
container.innerHTML = "";
Object.values(data.keywords).forEach((item) => {
const tc = document.createElement("tr");
tc.className = `row${
(container.querySelectorAll("TR").length % 2) + 1
}`;
tc.innerHTML = `
<td class="c1">
<div class="filter-input-wrapper">
<input value="${item.keyword || ""}" />
</div>
</td>
<td class="c2">
<div class="filter-table-button-group">
<button>${item.filterMode || FILTER_MODE[0]}</button>
</div>
</td>
<td class="c3">
<div style="text-align: center;">
<input type="checkbox" ${
item.filterLevel ? `checked="checked"` : ""
} />
</div>
</td>
<td class="c4">
<div class="filter-table-button-group">
<button>保存</button>
<button>删除</button>
</div>
</td>
`;
const inputElement = tc.querySelector("INPUT");
const levelElement = tc.querySelector(`INPUT[type="checkbox"]`);
const actions = tc.getElementsByTagName("button");
actions[0].onclick = () => {
actions[0].innerHTML = switchFilterMode(actions[0].innerHTML);
};
actions[1].onclick = () => {
if (inputElement.value) {
data.keywords[item.id] = {
id: item.id,
keyword: inputElement.value,
filterMode: actions[0].innerHTML,
filterLevel: levelElement.checked ? 1 : 0,
};
saveData();
refresh();
}
};
actions[2].onclick = () => {
if (confirm("是否确认?")) {
delete data.keywords[item.id];
saveData();
refresh();
}
};
container.appendChild(tc);
});
{
const tc = document.createElement("tr");
tc.className = `row${
(container.querySelectorAll("TR").length % 2) + 1
}`;
tc.innerHTML = `
<td class="c1">
<div class="filter-input-wrapper">
<input value="" />
</div>
</td>
<td class="c2">
<div class="filter-table-button-group">
<button>${FILTER_MODE[0]}</button>
</div>
</td>
<td class="c3">
<div style="text-align: center;">
<input type="checkbox" />
</div>
</td>
<td class="c4">
<div class="filter-table-button-group">
<button>添加</button>
</div>
</td>
`;
const inputElement = tc.querySelector("INPUT");
const levelElement = tc.querySelector(`INPUT[type="checkbox"]`);
const actions = tc.getElementsByTagName("button");
actions[0].onclick = () => {
actions[0].innerHTML = switchFilterMode(actions[0].innerHTML);
};
actions[1].onclick = () => {
if (inputElement.value) {
addKeyword(
inputElement.value,
actions[0].innerHTML,
levelElement.checked ? 1 : 0
);
saveData();
refresh();
}
};
container.appendChild(tc);
}
};
return func;
})();
return {
name: "关键字",
content,
refresh,
};
})();
// 通用设置
const commonModule = (() => {
const content = (() => {
const c = document.createElement("div");
c.style = "display: none";
return c;
})();
const refresh = (() => {
const container = content;
const func = () => {
container.innerHTML = "";
// 默认过滤方式
{
const tc = document.createElement("div");
tc.innerHTML += `
<div>默认过滤方式</div>
<div></div>
<div class="silver" style="margin-top: 10px;">${FILTER_TIPS}</div>
`;
["标记", "遮罩", "隐藏"].forEach((item, index) => {
const ele = document.createElement("SPAN");
ele.innerHTML += `
<input id="s-fm-${index}" type="radio" name="filterType" ${
data.options.filterMode === item && "checked"
}>
<label for="s-fm-${index}" style="cursor: pointer;">${item}</label>
`;
const inp = ele.querySelector("input");
inp.onchange = () => {
if (inp.checked) {
data.options.filterMode = item;
saveData();
reFilter();
}
};
tc.querySelectorAll("div")[1].append(ele);
});
container.appendChild(tc);
}
// 删除没有标记的用户
{
const tc = document.createElement("div");
tc.innerHTML += `
<br/>
<div>
<button>删除没有标记的用户</button>
</div>
`;
const actions = tc.getElementsByTagName("button");
actions[0].onclick = () => {
if (confirm("是否确认?")) {
Object.values(data.users).forEach((item) => {
if (item.tags.length === 0) {
delete data.users[item.id];
}
});
saveData();
reFilter();
}
};
container.appendChild(tc);
}
// 删除没有用户的标记
{
const tc = document.createElement("div");
tc.innerHTML += `
<br/>
<div>
<button>删除没有用户的标记</button>
</div>
`;
const actions = tc.getElementsByTagName("button");
actions[0].onclick = () => {
if (confirm("是否确认?")) {
Object.values(data.tags).forEach((item) => {
if (
Object.values(data.users).filter((user) =>
user.tags.find((tag) => tag === item.id)
).length === 0
) {
delete data.tags[item.id];
}
});
saveData();
reFilter();
}
};
container.appendChild(tc);
}
};
return func;
})();
return {
name: "通用设置",
content,
refresh,
};
})();
u.addModule(userModule).toggle();
u.addModule(tagModule);
u.addModule(keywordModule);
u.addModule(commonModule);
// 增加菜单项
(() => {
const title = "过滤设置";
let window;
n.mainMenu.addItemOnTheFly(title, null, () => {
if (window === undefined) {
window = n.createCommmonWindow();
}
window._.addContent(null);
window._.addTitle(title);
window._.addContent(u.content);
window._.show();
});
})();
// 执行过滤
(() => {
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]);
};
const initialized = {
topicArg: false,
postArg: false,
};
hookFunction(n, "eval", () => {
if (Object.values(initialized).findIndex((item) => item === false) < 0) {
return;
}
if (n.topicArg && initialized.topicArg === false) {
hookFunction(n.topicArg, "add", reFilter);
initialized.topicArg = true;
}
if (n.postArg && initialized.postArg === false) {
hookFunction(n.postArg, "proc", reFilter);
initialized.postArg = true;
}
});
if (n.ucp) {
hookFunction(n.ucp, "_echo", reFilter);
}
reFilter();
})();
})(commonui, __CURRENT_UID);
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。
评论已关闭