// ==UserScript==
// @name NGA Likes Support
// @namespace https://greasyfork.org/users/263018
// @version 1.2.2
// @author snyssss
// @description 显示被点赞和粉丝数量,以及发帖数量、IP属地、曾用名
// @match *://bbs.nga.cn/*
// @match *://ngabbs.com/*
// @match *://nga.178.com/*
// @grant GM_registerMenuCommand
// @grant GM_setValue
// @grant GM_getValue
// @noframes
// @downloadURL none
// ==/UserScript==
((ui) => {
if (!ui) return;
// KEY
const SHOW_OLDNAME_ENABLE_KEY = "SHOW_OLDNAME_ENABLE";
const SHOW_POSTNUM_ENABLE_KEY = "SHOW_POSTNUM_ENABLE";
const SHOW_IPLOC_ENABLE_KEY = "SHOW_IPLOC_ENABLE";
// 显示曾用名
const showOldnameEnable = GM_getValue(SHOW_OLDNAME_ENABLE_KEY) || false;
// 显示发帖数
const showPostnumEnable = GM_getValue(SHOW_POSTNUM_ENABLE_KEY) || false;
// 显示IP属地
const showIpLocEnable = GM_getValue(SHOW_IPLOC_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]);
};
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();
});
});
if (this.data.usernameChanged && showOldnameEnable) {
this.data.oldname = await new Promise((resolve) => {
fetch(`/nuke.php?lite=js&__lib=ucp&__act=oldname&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.closest("tr").querySelector(".posterInfoLine") ||
args.uInfoC.querySelector("div");
}
info[uid].enqueue(async () => {
if (info[uid].children[8] === undefined) {
info[uid].children[8] = new UserInfoWidget((data) => {
const value =
Object.values(data.more_info || {}).find(
(item) => item.type === 8
)?.data || 0;
const element = document.createElement("SPAN");
element.className =
"small_colored_text_btn stxt block_txt_c2 vertmod";
element.style.cursor = "default";
element.innerHTML = `⯅ ${value}`;
return element;
});
}
if (info[uid].children[16] === undefined) {
info[uid].children[16] = new UserInfoWidget((data) => {
const value = data.follow_by_num || 0;
const element = document.createElement("SPAN");
element.className =
"small_colored_text_btn stxt block_txt_c2 vertmod";
element.style.cursor = "default";
element.innerHTML = `★ ${value}`;
return element;
});
}
info[uid].rearrange();
const container = info[uid].container[argid];
const isSmall = container.classList.contains("posterInfoLine");
if (showOldnameEnable) {
if (ui._w.__GP.admincheck) {
return;
}
if (isSmall) {
const anchor = [...container.querySelectorAll("span.gray")].pop()
.nextElementSibling;
const uInfo = info[uid].data;
if (anchor && uInfo && uInfo.oldname) {
const element = document.createElement("SPAN");
element.className = "gray nobr";
element.innerHTML = `
曾用名: ${Object.values(uInfo.oldname)
.map(
(item) =>
`${item.username}`
)
.join(", ")}`;
anchor.parentNode.insertBefore(element, anchor);
}
} else {
const anchor = container.parentNode.querySelector(
'.stat div[class="clear"]'
).parentNode;
const uInfo = info[uid].data;
if (anchor && uInfo && uInfo.oldname) {
const element = document.createElement("DIV");
element.innerHTML = `
曾用名: ${Object.values(uInfo.oldname)
.map(
(item) =>
`${item.username}`
)
.join(", ")}`;
anchor.parentNode.appendChild(element, anchor);
}
}
}
if (showPostnumEnable) {
if (ui._w.__GP.admincheck) {
return;
}
if (isSmall) {
const anchor = [...container.querySelectorAll("span.gray")].pop();
const uInfo = ui.userInfo.users[uid];
if (anchor && uInfo) {
const element = document.createElement("SPAN");
element.className = "gray nobr";
element.innerHTML = `
发帖: ${uInfo.postnum}`;
anchor.parentNode.insertBefore(element, anchor);
}
} else {
const anchor = container.parentNode.querySelector(
'.stat div[class="clear"]'
);
const uInfo = ui.userInfo.users[uid];
if (anchor && uInfo) {
const element = document.createElement("DIV");
element.style =
"float:left;margin-right:3px;min-width:49%;*width:49%";
element.innerHTML = `
发帖: ${uInfo.postnum}
`;
anchor.parentNode.insertBefore(element, anchor);
}
}
}
if (showIpLocEnable) {
if (ui._w.__GP.admincheck) {
return;
}
if (isSmall) {
const anchor = [...container.querySelectorAll("span.gray")].pop();
const uInfo = info[uid].data;
if (anchor && uInfo) {
const element = document.createElement("SPAN");
element.className = "gray nobr";
element.innerHTML = `
属地: ${uInfo.ipLoc}`;
anchor.parentNode.insertBefore(element, anchor);
}
} else {
const anchor = container.parentNode.querySelector(
'.stat div[class="clear"]'
);
const uInfo = info[uid].data;
if (anchor && uInfo) {
const element = document.createElement("DIV");
element.style =
"float:left;margin-right:3px;min-width:49%;*width:49%";
element.innerHTML = `
属地: ${uInfo.ipLoc}
`;
anchor.parentNode.insertBefore(element, anchor);
}
}
}
});
}
};
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);
// 菜单项
(() => {
// 显示曾用名
if (showOldnameEnable) {
GM_registerMenuCommand("显示曾用名:启用", () => {
GM_setValue(SHOW_OLDNAME_ENABLE_KEY, false);
location.reload();
});
} else {
GM_registerMenuCommand("显示曾用名:禁用", () => {
GM_setValue(SHOW_OLDNAME_ENABLE_KEY, true);
location.reload();
});
}
// 显示发帖数
if (showPostnumEnable) {
GM_registerMenuCommand("显示发帖数:启用", () => {
GM_setValue(SHOW_POSTNUM_ENABLE_KEY, false);
location.reload();
});
} else {
GM_registerMenuCommand("显示发帖数:禁用", () => {
GM_setValue(SHOW_POSTNUM_ENABLE_KEY, true);
location.reload();
});
}
// 显示IP属地
if (showIpLocEnable) {
GM_registerMenuCommand("显示属地:启用", () => {
GM_setValue(SHOW_IPLOC_ENABLE_KEY, false);
location.reload();
});
} else {
GM_registerMenuCommand("显示属地:禁用", () => {
GM_setValue(SHOW_IPLOC_ENABLE_KEY, true);
location.reload();
});
}
})();
})(commonui);