Rules-For-Quantumult-X/Scripts/AdBlock/Zhihu/Zhihu.js

2121 lines
69 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const scriptName = "哲也同学";
const blockedUsersKey = "zhihu_blocked_users";
const currentUserInfoKey = "zhihu_current_userinfo";
const keywordBlockKey = "zhihu_keyword_block";
const blackAnswersIdKey = "zhihu_black_answers";
const userCreditScoreKey = "zhihu_credit_score";
const zheyeServerKey = "zheye_server_url";
const defaultAnswerBlockedUsers = ["会员推荐", "盐选推荐"];
const keywordMaxCount = 1e3;
const $ = MagicJS(scriptName, "INFO");
function getUserInfo() {
let t = { id: "default", is_vip: false };
try {
let e = $.data.read(currentUserInfoKey);
if (typeof e === "string") e = JSON.parse(e);
if (!!e && e.hasOwnProperty("id")) {
return e;
} else {
return t;
}
} catch (e) {
$.logger.error(`获取用户信息出现异常:${e}`);
return t;
}
}
function modifyAppConfig() {
let t = null;
try {
if (!!$.response.body) {
let e = JSON.parse($.response.body);
e["config"]["homepage_feed_tab"]["tab_infos"] = e["config"][
"homepage_feed_tab"
]["tab_infos"].filter((e) => {
if (e["tab_type"] === "activity_tab") {
e["end_time"] = (new Date() - 12e4).toString().slice(0, 10);
return true;
} else {
return false;
}
});
e["config"]["zvideo_max_number"] = 1;
e["config"]["is_show_followguide_alert"] = false;
delete e["config"]["hp_channel_tab"];
if (e["config"]["zombie_conf"]) {
e["config"]["zombie_conf"]["zombieEnable"] = false;
}
if (e["config"]["gray_mode"]) {
e["config"]["gray_mode"]["enable"] = false;
e["config"]["gray_mode"]["start_time"] = "4092566400";
e["config"]["gray_mode"]["end_time"] = "4092566400";
}
if (e["config"].hasOwnProperty("zhcnh_thread_sync")) {
$.logger.debug(JSON.stringify(e["config"]["zhcnh_thread_sync"]));
e["config"]["zhcnh_thread_sync"]["LocalDNSSetHostWhiteList"] = [];
e["config"]["zhcnh_thread_sync"]["isOpenLocalDNS"] = "0";
e["config"]["zhcnh_thread_sync"]["ZHBackUpIP_Switch_Open"] = "0";
e["config"]["zhcnh_thread_sync"]["dns_ip_detector_operation_lock"] =
"1";
e["config"]["zhcnh_thread_sync"][
"ZHHTTPSessionManager_setupZHHTTPHeaderField"
] = "1";
}
t = { body: JSON.stringify(e) };
}
} catch (e) {
$.logger.error(`优化软件配置出现异常:${e}`);
}
return t;
}
function modifyMCloudConfig() {
let t = null;
try {
if (!!$.response.body) {
let e = JSON.parse($.response.body);
if (e.data && e.data["configs"]) {
e.data["configs"].forEach((e) => {
if (e["configKey"] === "feed_gray_theme") {
e["configValue"].start_time = "1669824000";
e["configValue"].end_time = "1669824001";
e.status = false;
}
});
}
const r = JSON.stringify(e);
$.logger.debug(r);
t = { body: r };
}
} catch (e) {
$.logger.error(`优化软件配置出现异常:${e}`);
}
return t;
}
function unlockBlockedKeywords() {
let i = null;
try {
const s = getUserInfo();
if ($.request.method === "GET") {
let e = $.data.read(keywordBlockKey, null, s.id);
if (!e) {
e = [];
}
let t = {
"Cache-Control":
"no-cache, no-store, must-revalidate, private, max-age=0",
Connection: "keep-alive",
"Content-Type": "application/json;charset=utf-8",
Pragma: "no-cache",
"Referrer-Policy": "no-referrer-when-downgrade",
Server: "CLOUD ELB 1.0.0",
Vary: "Accept-Encoding",
"X-Cache-Lookup": "Cache Miss",
"x-cdn-provider": "tencent",
};
let r = JSON.stringify({
success: true,
is_vip: true,
kw_min_length: 2,
kw_max_length: 100,
kw_max_count: keywordMaxCount,
data: e,
});
if ($.env.isQuanX) {
i = { body: r, headers: t, status: "HTTP/1.1 200 OK" };
} else {
i = { response: { body: r, headers: t, status: 200 } };
}
$.logger.debug(`获取本地脚本屏蔽关键词:\n${e.join("、")}`);
} else if ($.request.method === "POST") {
if (!!$.request.body) {
let t = {
"Cache-Control":
"no-cache, no-store, must-revalidate, private, max-age=0",
Connection: "keep-alive",
"Content-Type": "application/json;charset=utf-8",
Pragma: "no-cache",
"Referrer-Policy": "no-referrer-when-downgrade",
Server: "CLOUD ELB 1.0.0",
Vary: "Accept-Encoding",
"X-Cache-Lookup": "Cache Miss",
"x-cdn-provider": "tencent",
};
let r = decodeURIComponent($.request.body).match(/keyword=(.*)/)[1];
let n = $.data.read(keywordBlockKey, null, s.id);
if (!n) {
n = [];
}
let o = false;
for (let e = 0; e < n.length; e++) {
if (r === n[e]) {
o = true;
break;
}
}
if (o === false) {
n.push(r);
$.data.write(keywordBlockKey, n, s.id);
let e = JSON.stringify({ success: true });
if ($.env.isQuanX) {
i = { body: e, headers: t, status: "HTTP/1.1 200 OK" };
} else {
i = { response: { body: e, headers: t, status: 200 } };
}
$.logger.debug(`添加本地脚本屏蔽关键词“${r}`);
} else {
let e = JSON.stringify({
error: { message: "关键词已存在", code: 100002 },
});
if ($.env.isQuanX) {
i = { body: e, headers: t, status: "HTTP/1.1 400 Bad Request" };
} else {
i = { response: { body: e, headers: t, status: 400 } };
}
}
}
} else if ($.request.method === "DELETE") {
let t = decodeURIComponent($.request.url).match(/keyword=(.*)/)[1];
let e = $.data.read(keywordBlockKey, null, s.id);
if (!e) {
e = [];
}
e = e.filter((e) => {
return e !== t;
});
$.data.write(keywordBlockKey, e, s.id);
let r = {
"Cache-Control":
"no-cache, no-store, must-revalidate, private, max-age=0",
Connection: "keep-alive",
"Content-Type": "application/json;charset=utf-8",
Pragma: "no-cache",
"Referrer-Policy": "no-referrer-when-downgrade",
Server: "CLOUD ELB 1.0.0",
Vary: "Accept-Encoding",
"X-Cache-Lookup": "Cache Miss",
"x-cdn-provider": "tencent",
};
let n = JSON.stringify({ success: true });
if ($.env.isQuanX) {
i = { body: n, headers: r, status: "HTTP/1.1 200 OK" };
} else {
i = { response: { body: n, headers: r, status: 200 } };
}
$.logger.debug(`删除本地脚本屏蔽关键词:“${t}`);
}
} catch (e) {
$.logger.debug(`关键词屏蔽操作出现异常:${e}`);
}
return i;
}
function processUserInfo() {
let t = null;
try {
let e = JSON.parse($.response.body);
$.data.write(blackAnswersIdKey, []);
$.logger.debug(`用户登录用户信息,接口响应:${$.response.body}`);
if (
e &&
e["id"] &&
e.hasOwnProperty("vip_info") &&
e["vip_info"].hasOwnProperty("is_vip")
) {
const r = {
id: e["id"],
is_vip: e["vip_info"]["is_vip"]
? e["vip_info"]["is_vip"] !== undefined
: false,
};
$.logger.debug(
`当前用户id${e["id"]}是否为VIP${e["vip_info"]["is_vip"]}`
);
$.data.write(currentUserInfoKey, r);
if (
$.data.read("zhihu_settings_fake_vip") !== false &&
e["vip_info"]["is_vip"] === false
) {
e["vip_info"]["is_vip"] = true;
e["vip_info"]["vip_type"] = 2;
e["vip_info"]["vip_icon"] = {
url: "https://picx.zhimg.com/v2-aa8a1823abfc46f14136f01d55224925.jpg?source=88ceefae",
night_mode_url:
"https://picx.zhimg.com/v2-aa8a1823abfc46f14136f01d55224925.jpg?source=88ceefae",
};
e["vip_info"]["vip_icon_v2"] = {
url: "https://picx.zhimg.com/v2-aa8a1823abfc46f14136f01d55224925.jpg?source=88ceefae",
night_mode_url:
"https://picx.zhimg.com/v2-aa8a1823abfc46f14136f01d55224925.jpg?source=88ceefae",
};
e["vip_info"]["entrance"] = {
icon: {
url: "https://pic3.zhimg.com/v2-5b7012c8c22fd520f5677305e1e551bf.png",
night_mode_url:
"https://pic4.zhimg.com/v2-e51e3252d7a2cb016a70879defd5da0b.png",
},
title: "盐选会员 为你严选好内容",
expires_day: "2099-12-31",
sub_title: null,
button_text: "首月 9 元",
jump_url: "zhihu://vip/purchase",
button_jump_url: "zhihu://vip/purchase",
sub_title_new: null,
identity: "super_svip",
};
e["vip_info"]["entrance_new"] = {
left_button: {
title: "精选会员内容",
description: "为您严选好内容",
jump_url: "zhihu://market/home",
},
right_button: {
title: "开通盐选会员",
description: "畅享 10w+ 场优质内容等特权",
jump_url: "zhihu://vip/purchase",
},
};
e["vip_info"]["entrance_v2"] = {
title: "我的超级盐选会员",
sub_title: "畅享 5000W+ 优质内容",
jump_url: "zhihu://market/home",
button_text: "查看会员",
sub_title_color: "#F8E2C4",
sub_title_list: ["畅享 5000W+ 优质内容"],
card_jump_url: "zhihu://market/home",
};
$.logger.debug("设置用户为本地盐选会员");
t = { body: JSON.stringify(e) };
}
} else {
$.logger.warning(
`没有获取到本次登录用户信息,如未对功能造成影响,请忽略此日志。`
);
}
} catch (e) {
$.logger.error(`获取当前用户信息出现异常:${e}`);
}
return t;
}
function manageBlackUser() {
const r = getUserInfo();
let t = {};
let n = $.data.read(blockedUsersKey, "", r.id);
n = typeof n === "object" && !!n ? n : {};
defaultAnswerBlockedUsers.forEach((e) => {
n[e] = "00000000000000000000000000000000";
t[e] = "00000000000000000000000000000000";
});
$.logger.debug(`当前用户id${r.id},脚本黑名单:${JSON.stringify(n)}`);
if ($.request.method === "GET") {
try {
if ($.request.url.indexOf("offset") < 0) {
n = t;
$.logger.debug(
"脚本黑名单已清空,请滑动至黑名单末尾保证重新获取完成。"
);
$.notification.post(
"开始同步黑名单数据,请滑动至黑名单末尾,直至弹出“同步成功”的通知。"
);
}
let e = JSON.parse($.response.body);
if (!!e["data"]) {
$.logger.debug(
`本次滑动获取的黑名单信息:${JSON.stringify(e["data"])}`
);
e["data"].forEach((e) => {
if (e["name"] !== "[已重置]") {
n[e["name"]] = e["id"];
}
});
$.data.write(blockedUsersKey, n, r.id);
if (e["paging"]["is_end"] === true) {
$.notification.post(
`同步黑名单数据成功!当前黑名单共${
Object.keys(n).length - defaultAnswerBlockedUsers.length
}人。\n脚本内置黑名单${defaultAnswerBlockedUsers.length}人。`
);
$.logger.debug(`脚本黑名单内容:${JSON.stringify(n)}`);
}
} else {
$.logger.warning(`获取黑名单失败,接口响应不合法:${$.response.body}`);
}
} catch (e) {
$.data.del(blockedUsersKey);
$.logger.error(`获取黑名单失败,异常信息:${e}`);
$.notification.post("获取黑名单失败,执行异常,已清空黑名单。");
}
} else if ($.request.method === "POST") {
try {
let e = JSON.parse($.response.body);
if (e.hasOwnProperty("name") && e.hasOwnProperty("id")) {
$.logger.debug(
`当前需要加入黑名单的用户Id${e["id"]},用户名:${e["name"]}`
);
if (e["id"]) {
n[e["name"]] = e["id"];
$.data.write(blockedUsersKey, n, r.id);
$.logger.debug(
`${
e["name"]
}写入脚本黑名单成功,当前脚本黑名单数据:${JSON.stringify(n)}`
);
$.notification.post(`已将用户“${e["name"]}”写入脚本黑名单。`);
} else {
$.logger.error(`${e["name"]}写入脚本黑名单失败没有获取到用户Id。`);
$.notification.post(`将用户“${e["name"]}”写入脚本黑名单失败!`);
}
} else {
$.logger.warning(`写入黑名单失败,接口响应不合法:${$.response.body}`);
$.notification.post("写入脚本黑名单失败,接口返回不合法。");
}
} catch (e) {
$.logger.error(`写入黑名单失败,异常信息:${e}`);
$.notification.post("写入脚本黑名单失败,执行异常,请查阅日志。");
}
} else if ($.request.method === "DELETE") {
try {
let e = JSON.parse($.response.body);
if (e.success) {
let t = $.request.url.match(
/^https?:\/\/api\.zhihu\.com\/settings\/blocked_users\/([0-9a-zA-Z]*)/
)[1];
if (t) {
$.logger.debug(`当前需要移出黑名单的用户Id${t}`);
for (let e in n) {
if (n[e] === t) {
delete n[e];
$.data.write(blockedUsersKey, n, r.id);
$.logger.debug(
`${e}移出脚本黑名单成功,当前脚本黑名单数据:${JSON.stringify(
n
)}`
);
$.notification.post(`已将用户“${e}”移出脚本黑名单!`);
break;
}
}
} else {
$.logger.error(
"将用户移出脚本黑名单失败!\n建议从设置中刷新黑名单数据。"
);
$.notification.post(
`将用户移出脚本黑名单失败没有获取到用户Id。\n建议从设置中刷新黑名单数据。`
);
}
} else {
$.logger.warning(`移出黑名单失败,接口响应不合法:${$.response.body}`);
$.notification.post("移出脚本黑名单失败,接口返回不合法。");
}
} catch (e) {
$.logger.error(`移出黑名单失败,异常信息:${e}`);
$.notification.post("移出脚本黑名单失败,执行异常,请查阅日志。");
}
}
}
function autoInsertBlackList() {
let e = null;
try {
let t = JSON.parse($.response.body);
delete t["mcn_user_info"];
e = { body: JSON.stringify(t) };
if (t.name && t.id && t["is_blocking"] === true) {
const r = getUserInfo();
let e = $.data.read(blockedUsersKey, "", r.id);
e = typeof e === "object" && !!e ? e : {};
if (!e[t.name]) {
$.logger.debug(
`当前需要加入黑名单的用户Id${t["id"]},用户名:${t["name"]}`
);
e[t["name"]] = t["id"];
$.data.write(blockedUsersKey, e, r.id);
$.logger.debug(
`${t["name"]}写入脚本黑名单成功,当前脚本黑名单数据:${JSON.stringify(
e
)}`
);
$.notification.post(`已自动将用户“${t["name"]}”写入脚本黑名单。`);
}
}
} catch (e) {
$.logger.error(`去除MCN信息出现异常${e}`);
}
return e;
}
function removeMoments() {
let r = null;
try {
let e = JSON.parse(
$.response.body.replace(/(\w+"+\s?):\s?(\d{15,})/g, '$1:"$2"')
);
const n = getUserInfo();
let i = $.data.read(blockedUsersKey, "", n.id);
i = !!i ? i : {};
let t;
const s = $.data.read("zhihu_settings_moments_stream", false);
const a = $.data.read("zhihu_settings_moments_recommend", false);
const l = $.data.read("zhihu_settings_moments_activity", false);
const c = $.data.read("zhihu_settings_blocked_users", false);
t = e.data.filter((e) => {
const t =
c &&
e.target &&
e.target["origin_pin"] &&
e.target["origin_pin"].author &&
typeof i[e.target["origin_pin"].author.name] != "undefined";
const r = s && e["target_type"] === "zvideo";
const n = a && e.type === "recommend_user_card_list";
const o = l && e.type === "message_activity_card";
return !(t || r || n || o);
});
e["data"] = t;
r = { body: JSON.stringify(e) };
} catch (e) {
$.logger.error(`关注列表去广告出现异常:${e}`);
}
return r;
}
function _setRecommendTag(e, t, r = "GBK02A") {
if (!e["common_card"]["footline"]) {
e["common_card"]["footline"] = { elements: [] };
}
e["common_card"]["footline"]["elements"].unshift({
tag: { text: t, color: r, type: "MASK_ROUNDED_RECTANGLE" },
});
}
async function _checkPaidContentByCloud(e, n) {
const t = $.data.read(zheyeServerKey);
if (!t) {
$.notification.post(
"未设置服务端地址,无法进行付费/推广内容探测。\n请配置服务端地址或使用本地探测。"
);
} else {
$.logger.debug(`向云端请求以下链接\n${e.join("\n")}`);
const r = `${t}/api/v1/answer/links`;
$.logger.debug(`服务端地址\n${r}`);
await $.http
.post({
url: r,
headers: { "Content-Type": "application/json" },
body: e,
})
.then((r) => {
$.logger.debug(
`云端探测结果<${typeof r.body}>\n${JSON.stringify(r.body)}`
);
for (let t = 0; t < r.body.length; t++) {
try {
let e = r.body[t];
if (e !== "") {
_setRecommendTag(n[t], e, "GBK02A");
}
} catch (e) {
$.logger.error(e);
}
}
})
.catch((e) => {
$.logger.error(`云端请求出现异常\n${JSON.stringify(e)}`);
});
}
}
async function _checkPaidContentByLocal(n, o) {
$.logger.debug(`将在本地请求以下链接\n${n.join("\n")}`);
let t = [];
function r(t) {
return new Promise((r) => {
const e = n[t];
if (
!e ||
e === "" ||
!e.startsWith("https://www.zhihu.com/appview/v2/answer")
) {
r("");
} else {
$.http
.get({ url: n[t], timeout: 1e3 })
.then((e) => {
const t = e.body;
if (
(t.indexOf("查看完整内容") >= 0 ||
t.indexOf("查看全部章节") >= 0) &&
t.indexOf("paid") >= 0
) {
r("付费内容");
} else if (
t.indexOf("ad-link-card") >= 0 ||
t.indexOf("xg.zhihu.com") >= 0 ||
t.indexOf("营销平台") >= 0
) {
r("营销推广");
} else if (t.indexOf("mcn-link-card") >= 0) {
r("购物推广");
} else {
r("");
}
})
.catch((e) => {
$.logger.error(`本地请求出现异常\n${JSON.stringify(e)}`);
r("");
});
}
});
}
for (let e = 0; e < n.length; e++) {
t.push(r(e));
}
await Promise.all(t).then((r) => {
$.logger.debug(`本地探测结果<${r.length}>\n${JSON.stringify(r)}`);
for (let t = 0; t < r.length; t++) {
try {
let e = r[t];
if (e !== "") {
_setRecommendTag(o[t], e, "GBK02A");
}
} catch (e) {
$.logger.error(e);
}
}
});
}
async function removeRecommend() {
let t = null;
try {
const g = $.data.read("zhihu_settings_recommend_pin", false);
const p = $.data.read("zhihu_settings_recommend_stream", false);
const h = $.data.read("zhihu_settings_remove_article", false);
const y = $.data.read("zhihu_settings_blocked_users", false);
const m = $.data.read("zhihu_settings_blocked_keywords", true);
const r = $.data.read("zhihu_settings_check_paid_content", false);
const o = $.data.read("zhihu_settings_request_content", "local");
const i = getUserInfo();
let u = $.data.read(keywordBlockKey, "", i.id);
u = m && !!u ? u : [];
let f = $.data.read(blockedUsersKey, "", i.id);
f = y && !!f ? f : {};
const s = (o) => {
const e = JSON.stringify(o);
const t =
o["card_type"] === "slot_event_card" ||
o["card_type"] === "slot_video_event_card" ||
o.hasOwnProperty("ad") ||
(o["brief"] && o["brief"].indexOf("slot_card") >= 0) ||
(o["extra"] && o["extra"]["type"] === "Training");
const r =
t !== true &&
e.search(/"(type|style)+"\s?:\s?"(drama|zvideo|Video|BIG_IMAGE)+"/i) >=
0;
const n = r && p;
const i = r !== true && e.search(/"(type|style)+"\s?:\s?"pin"/i) >= 0;
const s = i && g;
const a = e.search(/"(type|style)+"\s?:\s?"article"/i) >= 0;
const l = a && h;
let c = false;
if (r !== true && m) {
for (let n = 0; n < u.length; n++) {
if (e.search(u[n]) >= 0) {
if ($.isDebug) {
let e = o["common_card"]["feed_content"]["title"]["panel_text"];
let t = o["common_card"]["feed_content"]["content"]["panel_text"];
let r = "";
try {
r =
o["common_card"]["feed_content"]["title"]["action"][
"intent_url"
];
} catch {}
$.logger.debug(
`匹配关键字:\n${u[n]}\n标题:\n${e}\n内容:\n${t}`
);
$.notification.debug(
scriptName,
`关键字:${u[n]}`,
`${e}\n${t}`,
r
);
}
c = true;
break;
}
}
}
let d;
try {
d =
c !== true &&
y &&
f &&
o["common_card"]["feed_content"]["source_line"]["elements"][1][
"text"
]["panel_text"] in f;
} catch {
d = false;
}
return !(t || s || l || n || c || d);
};
let e = JSON.parse(
$.response.body.replace(/(\w+"+\s?):\s?(\d{15,})/g, '$1:"$2"')
);
let n = e["data"].filter(s);
if (r === true) {
let r = [];
for (let t = 0; t < n.length; t++) {
if (n[t]) {
try {
let e =
n[t]["common_card"]["feed_content"]["title"]["action"][
"intent_url"
];
e = e.replace(
/^https:\/\/zhihu\.com\/question\/\d+\/answer\//,
"https://www.zhihu.com/appview/v2/answer/"
);
r.push(e);
} catch {
r.push("");
}
}
}
if (r.length > 0 && o === "cloud") {
await _checkPaidContentByCloud(r, n);
} else if (r.length > 0 && o === "local") {
await _checkPaidContentByLocal(r, n);
}
}
e["data"] = n;
t = { body: JSON.stringify(e) };
} catch (e) {
$.logger.error(`推荐列表去广告出现异常:${e}`);
}
return t;
}
function removeQuestions() {
let t = null;
try {
const r = getUserInfo();
let n = $.data.read(blockedUsersKey, "", r.id);
n = !!n ? n : {};
let e = JSON.parse($.response.body);
const i = $.data.read("zhihu_settings_blocked_users", false);
$.logger.debug(`当前黑名单列表: ${JSON.stringify(n)}`);
let o = $.data.read(blackAnswersIdKey, []);
delete e["ad_info"];
if (e["data"]) {
let r = [];
for (let t of e.data) {
let e = "";
const a = t.target.id.toString();
try {
if ("target" in t) {
e = t["target"]["author"]["name"];
}
} catch (e) {
$.logger.error(`获取回答列表用户名出现异常:${e}`);
}
const l = typeof n[e] != "undefined";
const c = i && l;
if ("target" in t) {
t["target"]["visible_only_to_author"] = false;
t["target"]["is_visible"] = true;
t["target"]["is_copyable"] = true;
}
if (!c) {
r.push(t);
} else if (c === true && o.includes(a) === false) {
o.push(a);
$.notification.debug(`记录黑名单用户${e}的回答Id:${a}`);
}
}
e.data = r;
}
$.data.write(blackAnswersIdKey, o);
const s = JSON.stringify(e);
$.logger.debug(`修改后的回答列表数据:${s}`);
t = { body: s };
} catch (e) {
$.logger.error(`回答列表去广告出现异常:${e}`);
}
return t;
}
function modifyAnswer() {
let r = null;
try {
let e = $.response.body;
let t = "";
if (
(e.indexOf("查看完整内容") >= 0 || e.indexOf("查看全部章节") >= 0) &&
e.indexOf("paid") >= 0
) {
t =
'<a style="height: 42px;padding: 0 12px;border-radius: 6px;background-color: rgb(247 104 104 / 8%);display: block;text-decoration: none;" href="#"><div style="color: #f36;display: flex;-webkit-box-align: center;align-items: center;height: 100%;"><svg style="width: 1.2em; height: 1em;vertical-align: middle;fill: currentColor;overflow: hidden;" viewBox="0 0 1024 1024"><path d="M821.333333 138.666667c64.8 0 117.333333 52.533333 117.333334 117.333333v149.333333a32 32 0 0 1-32 32 74.666667 74.666667 0 0 0 0 149.333334 32 32 0 0 1 32 32v149.333333c0 64.8-52.533333 117.333333-117.333334 117.333333H202.666667c-64.8 0-117.333333-52.533333-117.333334-117.333333V618.666667a32 32 0 0 1 32-32 74.666667 74.666667 0 0 0 0-149.333334 32 32 0 0 1-32-32V256c0-64.8 52.533333-117.333333 117.333334-117.333333h618.666666zM428.576 329.994667a32 32 0 0 0-43.733333-2.581334l-1.514667 1.344a32 32 0 0 0-2.581333 43.733334L452.565333 458.666667H405.333333l-1.877333 0.053333A32 32 0 0 0 373.333333 490.666667l0.053334 1.877333A32 32 0 0 0 405.333333 522.666667h80v42.666666H405.333333l-1.877333 0.053334A32 32 0 0 0 373.333333 597.333333l0.053334 1.877334A32 32 0 0 0 405.333333 629.333333h80v42.666667l0.053334 1.877333A32 32 0 0 0 517.333333 704l1.877334-0.053333A32 32 0 0 0 549.333333 672v-42.666667H618.666667l1.877333-0.053333A32 32 0 0 0 650.666667 597.333333l-0.053334-1.877333A32 32 0 0 0 618.666667 565.333333h-69.333334v-42.666666H618.666667l1.877333-0.053334A32 32 0 0 0 650.666667 490.666667l-0.053334-1.877334A32 32 0 0 0 618.666667 458.666667h-47.253334l71.84-86.186667 1.248-1.589333a32 32 0 0 0-50.421333-39.381334L512 430.016l-82.08-98.506667z"></path></svg><div style="flex: 1 1;white-space: nowrap;text-overflow: ellipsis;padding-left:4px"><span style="font-family: -apple-system,BlinkMacSystemFont,Helvetica Neue,PingFang SC,Microsoft YaHei,Source Han Sans SC,Noto Sans CJK SC,WenQuanYi Micro Hei,sans-serif;-webkit-tap-highlight-color: rgba(26,26,26,0);font-size: 14px;line-height: 20px;color: #f36;white-space: nowrap;font-weight: 600;">本文为付费内容</span></div><div></div></div></a>';
} else if (
e.indexOf("ad-link-card") >= 0 ||
e.indexOf("xg.zhihu.com") >= 0 ||
e.indexOf("营销平台") >= 0
) {
t =
'<a style="height: 42px;padding: 0 12px;border-radius: 6px;background-color: rgb(8 188 212 / 8%);display: block;text-decoration: none;" href="#"><div style="color: #00bcd4;display: flex;-webkit-box-align: center;align-items: center;height: 100%;"><svg style="width: 1.2em; height: 1em;vertical-align: middle;fill: currentColor;overflow: hidden;" viewBox="0 0 1024 1024"><path d="M128 765.952q0 26.624 18.432 45.056t45.056 18.432l191.488 0 0 128-254.976 0q-26.624 0-49.664-10.24t-40.448-27.648-27.648-40.448-10.24-49.664l0-637.952q0-25.6 10.24-49.152t27.648-40.448 40.448-27.136 49.664-10.24l701.44 0q26.624 0 49.664 10.24t40.448 27.136 27.648 40.448 10.24 49.152l0 251.904-128 1.024 0-61.44q0-26.624-18.432-45.056t-45.056-18.432l-574.464 0q-26.624 0-45.056 18.432t-18.432 45.056l0 382.976zM990.208 705.536q21.504 18.432 22.016 34.304t-20.992 33.28q-21.504 18.432-51.2 41.472t-60.928 48.128-61.952 49.152-55.296 43.52q-26.624 20.48-43.52 15.36t-16.896-31.744q1.024-16.384 0-40.448t-1.024-41.472q0-19.456-10.752-24.064t-31.232-4.608q-21.504 0-39.936-0.512t-35.84-0.512-36.352-0.512-41.472-0.512q-9.216 0-19.968-2.048t-19.456-7.168-14.336-15.36-5.632-27.648l0-80.896q0-31.744 15.36-42.496t48.128-10.752q30.72 1.024 61.44 1.024t71.68 1.024q29.696 0 46.08-5.12t16.384-25.6q-1.024-14.336 0.512-35.328t1.536-37.376q0-26.624 14.336-33.28t36.864 10.752q22.528 18.432 52.736 43.008t61.952 50.688 62.976 51.2 54.784 44.544z"></path></svg><div style="flex: 1 1;white-space: nowrap;text-overflow: ellipsis;padding-left:4px"><span style="font-family: -apple-system,BlinkMacSystemFont,Helvetica Neue,PingFang SC,Microsoft YaHei,Source Han Sans SC,Noto Sans CJK SC,WenQuanYi Micro Hei,sans-serif;-webkit-tap-highlight-color: rgba(26,26,26,0);font-size: 14px;line-height: 20px;color: #00bcd4;white-space: nowrap;font-weight: 600;">本文含有营销推广</span></div><div></div></div></a>';
} else if (e.indexOf("mcn-link-card") >= 0) {
t =
'<a style="height: 42px;padding: 0 12px;border-radius: 6px;background-color: rgb(8 188 212 / 8%);display: block;text-decoration: none;" href="#"><div style="color: #00bcd4;display: flex;-webkit-box-align: center;align-items: center;height: 100%;"><svg style="width: 1.2em; height: 1em;vertical-align: middle;fill: currentColor;overflow: hidden;" viewBox="0 0 1024 1024"><path d="M346.112 806.912q19.456 0 36.864 7.168t30.208 19.968 20.48 30.208 7.68 36.864-7.68 36.864-20.48 30.208-30.208 20.48-36.864 7.68q-20.48 0-37.888-7.68t-30.208-20.48-20.48-30.208-7.68-36.864 7.68-36.864 20.48-30.208 30.208-19.968 37.888-7.168zM772.096 808.96q19.456 0 37.376 7.168t30.72 19.968 20.48 30.208 7.68 36.864-7.68 36.864-20.48 30.208-30.72 20.48-37.376 7.68-36.864-7.68-30.208-20.48-20.48-30.208-7.68-36.864 7.68-36.864 20.48-30.208 30.208-19.968 36.864-7.168zM944.128 227.328q28.672 0 44.544 7.68t22.528 18.944 6.144 24.064-3.584 22.016-13.312 37.888-22.016 62.976-23.552 68.096-18.944 53.248q-13.312 40.96-33.28 56.832t-49.664 15.872l-35.84 0-65.536 0-86.016 0-96.256 0-253.952 0 14.336 92.16 517.12 0q49.152 0 49.152 41.984 0 20.48-9.728 35.328t-38.4 14.848l-49.152 0-94.208 0-118.784 0-119.808 0-99.328 0-55.296 0q-20.48 0-34.304-9.216t-23.04-24.064-14.848-32.256-8.704-32.768q-1.024-6.144-5.632-29.696t-11.264-58.88-14.848-78.848-16.384-87.552q-19.456-103.424-44.032-230.4l-76.8 0q-15.36 0-25.6-7.68t-16.896-18.432-9.216-23.04-2.56-22.528q0-20.48 13.824-33.792t37.376-13.312l21.504 0 21.504 0 25.6 0 34.816 0q20.48 0 32.768 6.144t19.456 15.36 10.24 19.456 5.12 17.408q2.048 8.192 4.096 23.04t4.096 30.208q3.072 18.432 6.144 38.912l700.416 0zM867.328 194.56l-374.784 0 135.168-135.168q23.552-23.552 51.712-24.064t51.712 23.04z"></path></svg><div style="flex: 1 1;white-space: nowrap;text-overflow: ellipsis;padding-left:4px"><span style="font-family: -apple-system,BlinkMacSystemFont,Helvetica Neue,PingFang SC,Microsoft YaHei,Source Han Sans SC,Noto Sans CJK SC,WenQuanYi Micro Hei,sans-serif;-webkit-tap-highlight-color: rgba(26,26,26,0);font-size: 14px;line-height: 20px;color: #00bcd4;white-space: nowrap;font-weight: 600;">本文含有购物推广</span></div><div></div></div></a>';
} else if (Math.floor(Math.random() * 200) === 7) {
t =
'<a style="height: 42px;padding: 0 12px;border-radius: 6px;background-color: rgb(74 162 56 / 8%);display: block;text-decoration: none;" href="#"><div style="color: #619201;display: flex;-webkit-box-align: center;align-items: center;height: 100%;"><svg class="icon" style="width: 1.2em; height: 1em;vertical-align: middle;fill: currentColor;overflow: hidden;" viewBox="0 0 1024 1024"><path d="M512 85.333333c71.477333 0 159.68 57.546667 229.258667 147.018667C817.845333 330.826667 864 455.978667 864 586.666667c0 211.808-148.501333 352-352 352S160 798.474667 160 586.666667c0-130.688 46.144-255.84 122.741333-354.314667C352.32 142.88 440.522667 85.333333 512 85.333333z m0 64c-48.213333 0-120.096 46.912-178.741333 122.314667C265.109333 359.253333 224 470.762667 224 586.666667c0 175.616 119.050667 288 288 288s288-112.384 288-288c0-115.904-41.109333-227.402667-109.258667-315.018667C632.096 196.234667 560.213333 149.333333 512 149.333333z m-74.666667 522.666667a53.333333 53.333333 0 1 1 0 106.666667 53.333333 53.333333 0 0 1 0-106.666667z m-96-128a42.666667 42.666667 0 1 1 0 85.333333 42.666667 42.666667 0 0 1 0-85.333333z"></path></svg><div style="flex: 1 1;white-space: nowrap;text-overflow: ellipsis;padding-left:4px"><span style="font-family: -apple-system,BlinkMacSystemFont,Helvetica Neue,PingFang SC,Microsoft YaHei,Source Han Sans SC,Noto Sans CJK SC,WenQuanYi Micro Hei,sans-serif;-webkit-tap-highlight-color: rgba(26,26,26,0);font-size: 14px;line-height: 20px;color: #619201;white-space: nowrap;font-weight: 600;">本文为免费内容</span></div><div></div></div></a>';
}
if (t !== "") {
const n = e.match(/(richText[^<]*>)(.)/)[1];
const o = e.lastIndexOf(n) + n.length;
r = { body: e.slice(0, o) + t + e.slice(o) };
}
} catch (e) {
$.logger.error(`付费内容提醒出现异常:${e}`);
}
return r;
}
function removeComment() {
let e = null;
try {
if (!!$.response.body) {
let t = JSON.parse($.response.body);
t["ad_info"] = {};
if ($.data.read("zhihu_settings_blocked_users", false) === true) {
let e = getUserInfo();
let s = $.data.read(blockedUsersKey, "", e.id);
s = !!s ? s : {};
let a = [];
let l = {};
if (typeof t.root != "undefined") {
const n = t.root.author.name;
const o = typeof s[n] != "undefined";
if (o === true) {
t.root.is_delete = true;
t.root.can_reply = false;
t.root.can_like = false;
t.root.author.name = "黑名单用户";
t.root.author.avatar_url =
"https://picx.zhimg.com/v2-abed1a8c04700ba7d72b45195223e0ff_xll.jpg";
}
}
if (typeof t.data != "undefined") {
t.data.forEach((e) => {
const t = e.author.name;
let r = "";
if (e["reply_to_author"] && e["reply_to_author"].name) {
r = e["reply_to_author"].name;
}
const n = r !== "";
const o = typeof s[t] != "undefined";
const i = typeof s[r] != "undefined";
if (o === true || i === true) {
if (o && !n && $.request.url.indexOf("root_comment") > 0) {
$.notification.debug(`屏蔽黑名单用户“${t}”的主评论。`);
} else if (
!o &&
n &&
!i &&
$.request.url.indexOf("child_comment") > 0
) {
$.notification.debug(`屏蔽黑名单用户“${t}”的子评论。`);
} else if (
o &&
!i &&
$.request.url.indexOf("child_comment") > 0
) {
$.notification.debug(
`屏蔽黑名单用户“${t}”回复“${r}”的子评论。`
);
} else if (o && i && $.request.url.indexOf("child_comment") > 0) {
$.notification.debug(
`屏蔽黑名单用户“${t}”回复黑名单用户“${r}”的子评论。`
);
}
l[e.id] = t;
if (o) {
e.is_delete = true;
e.can_reply = false;
e.can_like = false;
e.author.exposed_medal = {};
e.author.name = "[黑名单用户]";
e.author.avatar_url =
"https://picx.zhimg.com/v2-abed1a8c04700ba7d72b45195223e0ff_xll.jpg";
}
if (i) {
e["reply_to_author"].name = "[黑名单用户]";
e["reply_to_author"].exposed_medal = {};
e["reply_to_author"].avatar_url =
"https://picx.zhimg.com/v2-abed1a8c04700ba7d72b45195223e0ff_xll.jpg";
}
}
if (e.child_comments) {
let i = [];
e.child_comments.forEach((e) => {
const t = e.author.name;
const r =
typeof e["reply_to_author"] != "undefined"
? e["reply_to_author"].name
: "";
const n = typeof s[t] != "undefined";
const o = typeof s[r] != "undefined";
if (n || o) {
if (n === true) {
$.notification.debug(`屏蔽黑名单用户“${t}”的子评论。`);
l[e.id] = t;
e.is_delete = true;
e.can_reply = false;
e.can_like = false;
e.author.name = "[黑名单用户]";
e.author.exposed_medal = {};
e.author.avatar_url =
"https://picx.zhimg.com/v2-abed1a8c04700ba7d72b45195223e0ff_xll.jpg";
}
if (o === true) {
$.logger.debug(`修改前的子评论数据:\n${JSON.stringify(e)}`);
e["reply_to_author"].name = "[黑名单用户]";
e["reply_to_author"].exposed_medal = {};
e["reply_to_author"].avatar_url =
"https://picx.zhimg.com/v2-abed1a8c04700ba7d72b45195223e0ff_xll.jpg";
$.notification.debug(
`隐藏“${t}”回复黑名单用户“${r}”的名称与头像。`
);
$.logger.debug(`修改后的子评论数据:\n${JSON.stringify(e)}`);
}
}
i.push(e);
});
e.child_comments = i;
}
a.push(e);
});
}
t.data = a;
}
const r = JSON.stringify(t);
$.logger.debug(`过滤后的评论数据:\n${r}`);
e = { body: r };
}
} catch (e) {
$.logger.error(`去除评论广告出现异常:${e}`);
}
return e;
}
function removeArticleAd() {
let t = null;
try {
if (!!$.response.body) {
let e = JSON.parse($.response.body);
e["ad_info"] = {};
const r = JSON.stringify(e);
$.logger.debug(`过滤后的文章数据:\n${r}`);
t = { body: r };
}
} catch (e) {
$.logger.error(`去除文章广告出现异常:${e}`);
}
return t;
}
function removeMarketingMsg() {
let t = null;
try {
let e = JSON.parse($.response.body);
let r = [];
for (let t of e["data"]) {
if (t["detail_title"] === "官方帐号消息") {
let e = t["unread_count"];
if (e > 0) {
t["content"]["text"] = "未读消息" + e + "条";
} else {
t["content"]["text"] = "全部消息已读";
}
t["is_read"] = true;
t["unread_count"] = 0;
r.push(t);
} else if (t["detail_title"] !== "活动助手") {
r.push(t);
}
}
e["data"] = r;
t = { body: JSON.stringify(e) };
} catch (e) {
$.logger.error(`屏蔽官方营销消息出现异常:${e}`);
}
return t;
}
function removeHotListAds() {
let t = null;
try {
if (!!$.response.body) {
let e = JSON.parse($.response.body);
if ("data" in e) {
e["data"] = e["data"].filter((e) => {
return (
e["type"] === "hot_list_feed" || e["type"] === "hot_list_feed_video"
);
});
}
t = { body: JSON.stringify(e) };
}
} catch (e) {
$.logger.error(`去除热榜广告出现异常:${e}`);
}
return t;
}
function removeKeywordAds() {
let t = null;
try {
if (!!$.response.body) {
$.logger.debug(`预置关键字返回:${$.response.body}`);
let e = JSON.parse($.response.body);
if (e.hasOwnProperty("preset_words") && e["preset_words"]["words"]) {
e["preset_words"]["words"] = e["preset_words"]["words"].filter((e) => {
return e["type"] !== "ad";
});
t = { body: JSON.stringify(e) };
}
}
} catch (e) {
$.logger.error(`去除预置关键字广告出现异常:${e}`);
}
return t;
}
function removeNextBlackUserAnswer() {
let t = null;
try {
if (!!$.response.body) {
let e = JSON.parse($.response.body);
const n = $.data.read(blackAnswersIdKey, []);
if (n.length > 0) {
let r = [];
e.data.forEach((e) => {
const t = n.includes(e.id.toString());
if (t === false) {
e.ad_info = { data: "" };
r.push(e);
} else {
$.notification.debug(
`屏蔽翻页过程中出现的黑名单用户回答Id:${e.id}`
);
}
});
for (let e = 0; e < r.length; e++) {
if (r[e]["extra"] && r[e]["extra"]["question_index"]) {
r[e]["extra"]["question_index"] = e + 1;
}
if (r[e]["strategy_info"]) {
r[e]["strategy_info"]["global_index"] = e + 1;
r[e]["strategy_info"]["strategy_index"] = e + 1;
}
}
e.data = r;
}
t = { body: JSON.stringify(e) };
}
} catch (e) {
$.logger.error(`屏蔽下翻黑名单用户的回答出现异常:${e}`);
}
return t;
}
function modifyAnswersNextData() {
let o = null;
try {
if (!!$.response.body) {
let e = JSON.parse($.response.body);
let t = getUserInfo();
let r = $.data.read(blockedUsersKey, {}, t.id);
$.logger.debug(`脚本黑名单用户:\n${JSON.stringify(r)}`);
let n = [];
e.data.data.forEach((e) => {
e["ad_info"] = { data: "" };
const t = typeof r[e.data.author.name] != "undefined";
$.logger.debug(`用户${e.data.author.name}是否在黑名单中:${t}`);
if (
$.data.read("zhihu_settings_blocked_users", false) === false ||
t === false
) {
n.push(e);
}
});
e.data.data = n;
o = { body: JSON.stringify(e) };
}
} catch (e) {
$.logger.error(`屏蔽回答信息流黑名单用户及广告:${e}`);
}
return o;
}
function changeUserCredit() {
$.notification.debug("开始修改用户盐值");
let t = null;
try {
if (!!$.response.body) {
const r = parseInt($.data.read(userCreditScoreKey, 780));
$.logger.debug(`准备修改用户盐值为${r}`);
let e = JSON.parse($.response.body);
if (e["credit_basis"].total_score < r) {
e["credit_basis"].total_score = r;
$.logger.debug(`已修改用户盐值为:${r}`);
}
t = { body: JSON.stringify(e) };
}
} catch (e) {
$.logger.error(`修改用户盐值出现异常:${e}`);
}
return t;
}
(async () => {
let e = null;
if ($.isResponse) {
switch (true) {
case /^https:\/\/api\.zhihu\.com\/people\/self$/.test($.request.url):
e = processUserInfo();
break;
case $.data.read("zhihu_settings_app_conf", false) === true &&
/^https?:\/\/appcloud2\.zhihu\.com\/v\d+\/config/.test($.request.url):
e = modifyAppConfig();
break;
case $.data.read("zhihu_settings_app_conf", false) === true &&
/^https?:\/\/m-cloud\.zhihu\.com\/api\/cloud\/config\/all\?/.test(
$.request.url
):
e = modifyMCloudConfig();
break;
case /^https?:\/\/api\.zhihu\.com\/user-credit\/basis/.test(
$.request.url
):
e = changeUserCredit();
break;
case /^https:\/\/api\.zhihu\.com\/topstory\/recommend/.test(
$.request.url
):
e = await removeRecommend();
break;
case /^https?:\/\/api\.zhihu\.com\/(v4\/)?questions\/\d+/.test(
$.request.url
):
e = removeQuestions();
break;
case /^https?:\/\/api\.zhihu\.com\/next-data\?/.test($.request.url):
e = modifyAnswersNextData();
break;
case $.data.read("zhihu_settings_sys_msg", true) !== false &&
/^https?:\/\/api\.zhihu\.com\/notifications\/v3\/message/.test(
$.request.url
):
e = removeMarketingMsg();
break;
case /^https?:\/\/api\.zhihu\.com\/comment_v5\/(answers|pins|comments?|articles)\/\d+\/(root|child)_comment/.test(
$.request.url
):
e = removeComment();
break;
case /^https?:\/\/www\.zhihu\.com\/api\/v\d\/articles\/\d+\/recommendation\?/.test(
$.request.url
):
e = removeArticleAd();
break;
case /^https?:\/\/www\.zhihu\.com\/api\/v4\/comment_v5\/answers\/\d+\/abstract_comment\?/.test(
$.request.url
):
e = removeComment();
break;
case $.data.read("zhihu_settings_answer_tip", true) === true &&
/^https?:\/\/www\.zhihu\.com\/appview\/v2\/answer\/.*(entry=(?!(preload-topstory|preload-search|preload-subscription)))?/.test(
$.request.url
):
e = modifyAnswer();
break;
case $.data.read("zhihu_settings_blocked_users", false) !== false &&
/^https?:\/\/api\.zhihu\.com\/next\?/.test($.request.url):
e = removeNextBlackUserAnswer();
break;
case $.data.read("zhihu_settings_blocked_users", true) === true &&
/^https?:\/\/api\.zhihu\.com\/people\/((?!self).)*$/.test(
$.request.url
):
e = autoInsertBlackList();
break;
case /^https?:\/\/api\.zhihu\.com\/moments_v3\?/.test($.request.url):
e = removeMoments();
break;
case $.data.read("zhihu_settings_hot_list", true) === true &&
/^https?:\/\/api\.zhihu\.com\/topstory\/hot-lists(\?|\/)/.test(
$.request.url
):
e = removeHotListAds();
break;
case $.data.read("zhihu_settings_preset_words", true) === true &&
/^https?:\/\/api\.zhihu\.com\/search\/preset_words\?/.test(
$.request.url
):
e = removeKeywordAds();
break;
case $.data.read("zhihu_settings_blocked_users", false) !== false &&
/^https?:\/\/api\.zhihu\.com\/settings\/blocked_users/.test(
$.request.url
):
manageBlackUser();
break;
default:
$.logger.debug("没有匹配到任何请求,请确认配置正确。");
break;
}
} else if ($.isRequest) {
if (
$.data.read("zhihu_settings_blocked_keywords", false) !== false &&
/^https?:\/\/api\.zhihu\.com\/feed-root\/block/.test($.request.url) ===
true
) {
e = unlockBlockedKeywords(e);
}
} else {
$.data.del(currentUserInfoKey);
$.data.del(blockedUsersKey);
$.data.del(keywordBlockKey);
$.notification.post("哲也同学数据清理完毕");
}
if (e) {
$.done(e);
} else {
$.done();
}
})();
function MagicJS(e = "MagicJS", t = "INFO") {
const n = () => {
const e = typeof $loon !== "undefined";
const t = typeof $task !== "undefined";
const r = typeof module !== "undefined";
const n = typeof $httpClient !== "undefined" && !e;
const o = typeof $storm !== "undefined";
const i =
typeof $environment !== "undefined" &&
typeof $environment["stash-build"] !== "undefined";
const s = n || e || o || i;
const a = typeof importModule !== "undefined";
return {
isLoon: e,
isQuanX: t,
isNode: r,
isSurge: n,
isStorm: o,
isStash: i,
isSurgeLike: s,
isScriptable: a,
get name() {
if (e) {
return "Loon";
} else if (t) {
return "QuantumultX";
} else if (r) {
return "NodeJS";
} else if (n) {
return "Surge";
} else if (a) {
return "Scriptable";
} else {
return "unknown";
}
},
get build() {
if (n) {
return $environment["surge-build"];
} else if (i) {
return $environment["stash-build"];
} else if (o) {
return $storm.buildVersion;
}
},
get language() {
if (n || i) {
return $environment["language"];
}
},
get version() {
if (n) {
return $environment["surge-version"];
} else if (i) {
return $environment["stash-version"];
} else if (o) {
return $storm.appVersion;
} else if (r) {
return process.version;
}
},
get system() {
if (n) {
return $environment["system"];
} else if (r) {
return process.platform;
}
},
get systemVersion() {
if (o) {
return $storm.systemVersion;
}
},
get deviceName() {
if (o) {
return $storm.deviceName;
}
},
};
};
const o = (r, e = "INFO") => {
let n = e;
const o = {
SNIFFER: 6,
DEBUG: 5,
INFO: 4,
NOTIFY: 3,
WARNING: 2,
ERROR: 1,
CRITICAL: 0,
NONE: -1,
};
const i = {
SNIFFER: "",
DEBUG: "",
INFO: "",
NOTIFY: "",
WARNING: "❗ ",
ERROR: "❌ ",
CRITICAL: "❌ ",
NONE: "",
};
const t = (e, t = "INFO") => {
if (!(o[n] < o[t.toUpperCase()]))
console.log(`[${t}] [${r}]\n${i[t.toUpperCase()]}${e}\n`);
};
const s = (e) => {
n = e;
};
return {
getLevel: () => {
return n;
},
setLevel: s,
sniffer: (e) => {
t(e, "SNIFFER");
},
debug: (e) => {
t(e, "DEBUG");
},
info: (e) => {
t(e, "INFO");
},
notify: (e) => {
t(e, "NOTIFY");
},
warning: (e) => {
t(e, "WARNING");
},
error: (e) => {
t(e, "ERROR");
},
retry: (e) => {
t(e, "RETRY");
},
};
};
return new (class {
constructor(e, t) {
this._startTime = Date.now();
this.version = "3.0.0";
this.scriptName = e;
this.env = n();
this.logger = o(e, t);
this.http =
typeof MagicHttp === "function"
? MagicHttp(this.env, this.logger)
: undefined;
this.data =
typeof MagicData === "function"
? MagicData(this.env, this.logger)
: undefined;
this.notification =
typeof MagicNotification === "function"
? MagicNotification(this.scriptName, this.env, this.logger, this.http)
: undefined;
this.utils =
typeof MagicUtils === "function"
? MagicUtils(this.env, this.logger)
: undefined;
this.qinglong =
typeof MagicQingLong === "function"
? MagicQingLong(this.env, this.data, this.logger)
: undefined;
if (typeof this.data !== "undefined") {
let e = this.data.read("magic_loglevel");
const r = this.data.read("magic_bark_url");
if (e) {
this.logger.setLevel(e.toUpperCase());
}
if (r) {
this.notification.setBark(r);
}
}
}
get isRequest() {
return (
typeof $request !== "undefined" && typeof $response === "undefined"
);
}
get isResponse() {
return typeof $response !== "undefined";
}
get isDebug() {
return this.logger.level === "DEBUG";
}
get request() {
return typeof $request !== "undefined" ? $request : undefined;
}
get response() {
if (typeof $response !== "undefined") {
if ($response.hasOwnProperty("status"))
$response["statusCode"] = $response["status"];
if ($response.hasOwnProperty("statusCode"))
$response["status"] = $response["statusCode"];
return $response;
} else {
return undefined;
}
}
done = (e = {}) => {
this._endTime = Date.now();
let t = (this._endTime - this._startTime) / 1e3;
this.logger.info(`SCRIPT COMPLETED: ${t} S.`);
if (typeof $done !== "undefined") {
$done(e);
}
};
})(e, t);
}
function MagicNotification(i, s, a, l) {
let c = null;
let d = null;
const e = (t) => {
try {
let e = t.replace(/\/+$/g, "");
c = `${/^https?:\/\/([^/]*)/.exec(e)[0]}/push`;
d = /\/([^\/]+)\/?$/.exec(e)[1];
} catch (e) {
a.error(`Bark url error: ${e}.`);
}
};
function t(e = i, t = "", r = "", n = "") {
const o = (r) => {
try {
let t = {};
if (typeof r === "string") {
if (s.isLoon) t = { openUrl: r };
else if (s.isQuanX) t = { "open-url": r };
else if (s.isSurge) t = { url: r };
} else if (typeof r === "object") {
if (s.isLoon) {
t["openUrl"] = !!r["open-url"] ? r["open-url"] : "";
t["mediaUrl"] = !!r["media-url"] ? r["media-url"] : "";
} else if (s.isQuanX) {
t = !!r["open-url"] || !!r["media-url"] ? r : {};
} else if (s.isSurge) {
let e = r["open-url"] || r["openUrl"];
t = e ? { url: e } : {};
}
}
return t;
} catch (e) {
a.error(`通知选项转换失败${e}`);
}
return r;
};
n = o(n);
if (arguments.length === 1) {
e = i;
(t = ""), (r = arguments[0]);
}
a.notify(
`title:${e}\nsubTitle:${t}\nbody:${r}\noptions:${
typeof n === "object" ? JSON.stringify(n) : n
}`
);
if (s.isSurge) {
$notification.post(e, t, r, n);
} else if (s.isLoon) {
if (!!n) $notification.post(e, t, r, n);
else $notification.post(e, t, r);
} else if (s.isQuanX) {
$notify(e, t, r, n);
}
if (c && d) {
u(e, t, r);
}
}
function r(e = i, t = "", r = "", n = "") {
if (a.getLevel() === "DEBUG") {
if (arguments.length === 1) {
e = i;
t = "";
r = arguments[0];
}
this.post(e, t, r, n);
}
}
function u(e = i, t = "", r = "", n = "") {
if (typeof l === "undefined" || typeof l.post === "undefined") {
throw "Bark notification needs to import MagicHttp module.";
}
let o = {
url: c,
headers: { "content-type": "application/json; charset=utf-8" },
body: { title: e, body: t ? `${t}\n${r}` : r, device_key: d },
};
l.post(o).catch((e) => {
a.error(`Bark notify error: ${e}`);
});
}
return { post: t, debug: r, bark: u, setBark: e };
}
function MagicData(s, a) {
let l = { fs: undefined, data: {} };
if (s.isNode) {
l.fs = require("fs");
try {
l.fs.accessSync(
"./magic.json",
l.fs.constants.R_OK | l.fs.constants.W_OK
);
} catch (e) {
l.fs.writeFileSync("./magic.json", "{}", { encoding: "utf8" });
}
l.data = require("./magic.json");
}
const c = (e, t) => {
if (typeof t === "object") {
return false;
} else {
return e === t;
}
};
const d = (e) => {
if (e === "true") {
return true;
} else if (e === "false") {
return false;
} else if (typeof e === "undefined") {
return null;
} else {
return e;
}
};
const u = (e, t, r, n) => {
if (r) {
try {
if (typeof e === "string") e = JSON.parse(e);
if (e["magic_session"] === true) {
e = e[r];
} else {
e = null;
}
} catch {
e = null;
}
}
if (typeof e === "string" && e !== "null") {
try {
e = JSON.parse(e);
} catch {}
}
if (n === false && !!e && e["magic_session"] === true) {
e = null;
}
if (
(e === null || typeof e === "undefined") &&
t !== null &&
typeof t !== "undefined"
) {
e = t;
}
e = d(e);
return e;
};
const i = (t) => {
if (typeof t === "string") {
let e = {};
try {
e = JSON.parse(t);
const r = typeof e;
if (
r !== "object" ||
e instanceof Array ||
r === "bool" ||
e === null
) {
e = {};
}
} catch {}
return e;
} else if (
t instanceof Array ||
t === null ||
typeof t === "undefined" ||
t !== t ||
typeof t === "boolean"
) {
return {};
} else {
return t;
}
};
const f = (e, t = null, r = "", n = false, o = null) => {
let i = o || l.data;
if (!!i && typeof i[e] !== "undefined" && i[e] !== null) {
val = i[e];
} else {
val = !!r ? {} : null;
}
val = u(val, t, r, n);
return val;
};
const g = (e, t = null, r = "", n = false, o = null) => {
let i = "";
if (o || s.isNode) {
i = f(e, t, r, n, o);
} else {
if (s.isSurgeLike) {
i = $persistentStore.read(e);
} else if (s.isQuanX) {
i = $prefs.valueForKey(e);
}
i = u(i, t, r, n);
}
a.debug(
`READ DATA [${e}]${!!r ? `[${r}]` : ""} <${typeof i}>\n${JSON.stringify(
i
)}`
);
return i;
};
const p = (t, r, n = "", e = null) => {
let o = e || l.data;
o = i(o);
if (!!n) {
let e = i(o[t]);
e["magic_session"] = true;
e[n] = r;
o[t] = e;
} else {
o[t] = r;
}
if (e !== null) {
e = o;
}
return o;
};
const h = (e, t, r = "", n = null) => {
if (typeof t === "undefined" || t !== t) {
return false;
}
if (!s.isNode && (typeof t === "boolean" || typeof t === "number")) {
t = String(t);
}
let o = "";
if (n || s.isNode) {
o = p(e, t, r, n);
} else {
if (!r) {
o = t;
} else {
if (s.isSurgeLike) {
o = !!$persistentStore.read(e) ? $persistentStore.read(e) : o;
} else if (s.isQuanX) {
o = !!$prefs.valueForKey(e) ? $prefs.valueForKey(e) : o;
}
o = i(o);
o["magic_session"] = true;
o[r] = t;
}
}
if (!!o && typeof o === "object") {
o = JSON.stringify(o, null, 4);
}
a.debug(
`WRITE DATA [${e}]${r ? `[${r}]` : ""} <${typeof t}>\n${JSON.stringify(
t
)}`
);
if (!n) {
if (s.isSurgeLike) {
return $persistentStore.write(o, e);
} else if (s.isQuanX) {
return $prefs.setValueForKey(o, e);
} else if (s.isNode) {
try {
l.fs.writeFileSync("./magic.json", o);
return true;
} catch (e) {
a.error(e);
return false;
}
}
}
return true;
};
const e = (t, r, n, o = c, i = null) => {
r = d(r);
const e = g(t, null, n, false, i);
if (o(e, r) === true) {
return false;
} else {
const s = h(t, r, n, i);
let e = g(t, null, n, false, i);
if (o === c && typeof e === "object") {
return s;
}
return o(r, e);
}
};
const y = (e, t, r) => {
let n = r || l.data;
n = i(n);
if (!!t) {
obj = i(n[e]);
delete obj[t];
n[e] = obj;
} else {
delete n[e];
}
if (!!r) {
r = n;
}
return n;
};
const t = (e, t = "", r = null) => {
let n = {};
if (r || s.isNode) {
n = y(e, t, r);
if (!r) {
l.fs.writeFileSync("./magic.json", JSON.stringify(n, null, 4));
} else {
r = n;
}
} else {
if (!t) {
if (s.isStorm) {
return $persistentStore.remove(e);
} else if (s.isSurgeLike) {
return $persistentStore.write(null, e);
} else if (s.isQuanX) {
return $prefs.removeValueForKey(e);
}
} else {
if (s.isSurgeLike) {
n = $persistentStore.read(e);
} else if (s.isQuanX) {
n = $prefs.valueForKey(e);
}
n = i(n);
delete n[t];
const o = JSON.stringify(n, null, 4);
h(e, o);
}
}
a.debug(`DELETE KEY [${e}]${!!t ? `[${t}]` : ""}`);
};
const r = (e, t = null) => {
let r = [];
let n = g(e, null, null, true, t);
n = i(n);
if (n["magic_session"] !== true) {
r = [];
} else {
r = Object.keys(n).filter((e) => e !== "magic_session");
}
a.debug(
`READ ALL SESSIONS [${e}] <${typeof r}>\n${JSON.stringify(r, null, 4)}`
);
return r;
};
const n = (e, t = null) => {
let r = {};
let n = g(e, null, null, true, t);
n = i(n);
if (n["magic_session"] === true) {
r = { ...n };
delete r["magic_session"];
}
a.debug(
`READ ALL SESSIONS [${e}] <${typeof r}>\n${JSON.stringify(r, null, 4)}`
);
return r;
};
return {
read: g,
write: h,
del: t,
update: e,
allSessions: n,
allSessionNames: r,
defaultValueComparator: c,
convertToObject: i,
};
}
function MagicHttp(c, d) {
let r;
if (c.isNode) {
const a = require("axios");
r = a.create();
}
class e {
constructor(e = true) {
this.handlers = [];
this.isRequest = e;
}
use(e, t, r) {
if (typeof e === "function") {
d.debug(`Register fulfilled ${e.name}`);
}
if (typeof t === "function") {
d.debug(`Register rejected ${t.name}`);
}
this.handlers.push({
fulfilled: e,
rejected: t,
synchronous:
r && typeof r.synchronous === "boolean" ? r.synchronous : false,
runWhen: r ? r.runWhen : null,
});
return this.handlers.length - 1;
}
eject(e) {
if (this.handlers[e]) {
this.handlers[e] = null;
}
}
forEach(t) {
this.handlers.forEach((e) => {
if (e !== null) {
t(e);
}
});
}
}
function o(e) {
let r = { ...e };
if (!!r.params) {
if (!c.isNode) {
let e = Object.keys(r.params)
.map((e) => {
const t = encodeURIComponent(e);
r.url = r.url.replace(new RegExp(`${e}=[^&]*`, "ig"), "");
r.url = r.url.replace(new RegExp(`${t}=[^&]*`, "ig"), "");
return `${t}=${encodeURIComponent(r.params[e])}`;
})
.join("&");
if (r.url.indexOf("?") < 0) r.url += "?";
if (!/(&|\?)$/g.test(r.url)) {
r.url += "&";
}
r.url += e;
delete r.params;
d.debug(`Params to QueryString: ${r.url}`);
}
}
return r;
}
const u = (e, t) => {
let r =
typeof t === "object" ? { headers: {}, ...t } : { url: t, headers: {} };
if (!r.method) {
r["method"] = e;
}
r = o(r);
if (r["rewrite"] === true) {
if (c.isSurge) {
r.headers["X-Surge-Skip-Scripting"] = false;
delete r["rewrite"];
} else if (c.isQuanX) {
r["hints"] = false;
delete r["rewrite"];
}
}
if (c.isSurgeLike) {
const n = r.headers["content-type"] || r.headers["Content-Type"];
if (
r["method"] !== "GET" &&
n &&
n.indexOf("application/json") >= 0 &&
r.body instanceof Array
) {
r.body = JSON.stringify(r.body);
d.debug(`Convert Array object to String: ${r.body}`);
}
} else if (c.isQuanX) {
if (r.hasOwnProperty("body") && typeof r["body"] !== "string")
r["body"] = JSON.stringify(r["body"]);
r["method"] = e;
} else if (c.isNode) {
if (e === "POST" || e === "PUT" || e === "PATCH" || e === "DELETE") {
r.data = r.data || r.body;
} else if (e === "GET") {
r.params = r.params || r.body;
}
delete r.body;
}
return r;
};
const f = (t, r = null) => {
if (t) {
let e = {
...t,
config: t.config || r,
status: t.statusCode || t.status,
body: t.body || t.data,
headers: t.headers || t.header,
};
if (typeof e.body === "string") {
try {
e.body = JSON.parse(e.body);
} catch {}
}
delete e.data;
return e;
} else {
return t;
}
};
const t = (r) => {
return Object.keys(r).reduce((e, t) => {
e[t.toLowerCase()] = r[t];
return e;
}, {});
};
const n = (n) => {
return Object.keys(n).reduce((e, t) => {
const r = t
.split("-")
.map((e) => e[0].toUpperCase() + e.slice(1))
.join("-");
e[r] = n[t];
return e;
}, {});
};
const g = (e, t = null) => {
if (!!e && e.status >= 400) {
d.debug(`Raise exception when status code is ${e.status}`);
return {
name: "RequestException",
message: `Request failed with status code ${e.status}`,
config: t || e.config,
response: e,
};
}
};
const i = { request: new e(), response: new e(false) };
let p = [];
let h = [];
let y = true;
function $(e) {
e = o(e);
d.debug(`HTTP ${e["method"].toUpperCase()}:\n${JSON.stringify(e)}`);
return e;
}
function m(e) {
try {
e = !!e ? f(e) : e;
d.sniffer(
`HTTP ${e.config["method"].toUpperCase()}:\n${JSON.stringify(
e.config
)}\nSTATUS CODE:\n${e.status}\nRESPONSE:\n${
typeof e.body === "object" ? JSON.stringify(e.body) : e.body
}`
);
const t = g(e);
if (!!t) {
return Promise.reject(t);
}
return e;
} catch (t) {
d.error(t);
return e;
}
}
const _ = (t) => {
try {
p = [];
h = [];
i.request.forEach((e) => {
if (typeof e.runWhen === "function" && e.runWhen(t) === false) {
return;
}
y = y && e.synchronous;
p.unshift(e.fulfilled, e.rejected);
});
i.response.forEach((e) => {
h.push(e.fulfilled, e.rejected);
});
} catch (e) {
d.error(`Failed to register interceptors: ${e}.`);
}
};
const s = (e, n) => {
let o;
const t = e.toUpperCase();
n = u(t, n);
if (c.isNode) {
o = r;
} else {
if (c.isSurgeLike) {
o = (i) => {
return new Promise((n, o) => {
$httpClient[e.toLowerCase()](i, (t, r, e) => {
if (t) {
let e = {
name: t.name || t,
message: t.message || t,
stack: t.stack || t,
config: i,
response: f(r),
};
o(e);
} else {
r.config = i;
r.body = e;
n(r);
}
});
});
};
} else {
o = (o) => {
return new Promise((r, n) => {
$task
.fetch(o)
.then((e) => {
e = f(e, o);
const t = g(e, o);
if (t) {
return Promise.reject(t);
}
r(e);
})
.catch((e) => {
let t = {
name: e.message || e.error,
message: e.message || e.error,
stack: e.error,
config: o,
response: !!e.response ? f(e.response) : null,
};
n(t);
});
});
};
}
}
let i;
_(n);
const s = [$, undefined];
const a = [m, undefined];
if (!y) {
d.debug("Interceptors are executed in asynchronous mode");
let r = [o, undefined];
Array.prototype.unshift.apply(r, s);
Array.prototype.unshift.apply(r, p);
r = r.concat(a);
r = r.concat(h);
i = Promise.resolve(n);
while (r.length) {
try {
let e = r.shift();
let t = r.shift();
if (!c.isNode && n["timeout"] && e === o) {
e = l;
}
if (typeof e === "function") {
d.debug(`Executing request fulfilled ${e.name}`);
}
if (typeof t === "function") {
d.debug(`Executing request rejected ${t.name}`);
}
i = i.then(e, t);
} catch (e) {
d.error(`request exception: ${e}`);
}
}
return i;
} else {
d.debug("Interceptors are executed in synchronous mode");
Array.prototype.unshift.apply(p, s);
p = p.concat([$, undefined]);
while (p.length) {
let e = p.shift();
let t = p.shift();
try {
if (typeof e === "function") {
d.debug(`Executing request fulfilled ${e.name}`);
}
n = e(n);
} catch (e) {
if (typeof t === "function") {
d.debug(`Executing request rejected ${t.name}`);
}
t(e);
break;
}
}
try {
if (!c.isNode && n["timeout"]) {
i = l(n);
} else {
i = o(n);
}
} catch (e) {
return Promise.reject(e);
}
Array.prototype.unshift.apply(h, a);
while (h.length) {
i = i.then(h.shift(), h.shift());
}
return i;
}
function l(r) {
try {
const e = new Promise((e, t) => {
setTimeout(() => {
let e = {
message: `timeout of ${r["timeout"]}ms exceeded.`,
config: r,
};
t(e);
}, r["timeout"]);
});
return Promise.race([o(r), e]);
} catch (e) {
d.error(`Request Timeout exception: ${e}.`);
}
}
};
return {
request: s,
interceptors: i,
convertHeadersToLowerCase: t,
convertHeadersToCamelCase: n,
modifyResponse: f,
get: (e) => {
return s("GET", e);
},
post: (e) => {
return s("POST", e);
},
put: (e) => {
return s("PUT", e);
},
patch: (e) => {
return s("PATCH", e);
},
delete: (e) => {
return s("DELETE", e);
},
head: (e) => {
return s("HEAD", e);
},
options: (e) => {
return s("OPTIONS", e);
},
};
}