const scriptName = "哲也同学"; const blockedUsersKey = "zhihu_blocked_users"; const currentUserInfoKey = "zhihu_current_userinfo"; const keywordBlockKey = "zhihu_keyword_block"; const blackAnswersIdKey = "zhihu_black_answers"; const userCreditScore = "zhihu_credit_score"; // 默认屏蔽推荐列表的用户,通常不是真实用户,无法通过加入黑名单屏蔽 const defaultAnswerBlockedUsers = ["会员推荐", "盐选推荐"]; const keywordMaxCount = 1000; // 允许设置的关键词数量 const $ = MagicJS(scriptName, "INFO"); /** * @description: 获取用户信息 * @return {*} */ function getUserInfo() { let defaultUserInfo = {id: "default", is_vip: false}; try { let userInfo = $.data.read(currentUserInfoKey); if (typeof userInfo === "string") userInfo = JSON.parse(userInfo); if (!!userInfo && userInfo.hasOwnProperty("id")) { return userInfo; } else { return defaultUserInfo; } } catch (err) { $.logger.error(`获取用户信息出现异常:${err}`); return defaultUserInfo; } } /** * 优化软件配置 * @return {*} */ function modifyAppConfig() { let response = null; try { if (!!$.response.body) { let obj = JSON.parse($.response.body); obj["config"]["homepage_feed_tab"]["tab_infos"] = obj["config"]["homepage_feed_tab"]["tab_infos"].filter( (e) => { // 将活动标签设置为已过期 if (e["tab_type"] === "activity_tab") { e["end_time"] = (new Date() - 120000) .toString() .slice(0, 10); return true; } else { return false; } } ); obj["config"]["zvideo_max_number"] = 1; // 似乎是控制内部弹窗 obj["config"]["is_show_followguide_alert"] = false; // 似乎是某个地方的标签,待定 delete obj["config"]["hp_channel_tab"]; // 灰色模式 if (obj["config"]["zombie_conf"]) { obj["config"]["zombie_conf"]["zombieEnable"] = false; } if (obj["config"]["gray_mode"]) { obj["config"]["gray_mode"]["enable"] = false; obj["config"]["gray_mode"]["start_time"] = '4092566400'; obj["config"]["gray_mode"]["end_time"] = '4092566400'; } // 屏蔽8.X版本以上本地DNS解析,以下修改不清楚哪些是有效的,暂时全部保留 if (obj["config"].hasOwnProperty("zhcnh_thread_sync")) { $.logger.debug(JSON.stringify(obj["config"]["zhcnh_thread_sync"])); obj["config"]["zhcnh_thread_sync"]["LocalDNSSetHostWhiteList"] = []; obj["config"]["zhcnh_thread_sync"]["isOpenLocalDNS"] = "0"; obj["config"]["zhcnh_thread_sync"]["ZHBackUpIP_Switch_Open"] = "0"; obj["config"]["zhcnh_thread_sync"]["dns_ip_detector_operation_lock"] = "1"; obj["config"]["zhcnh_thread_sync"][ "ZHHTTPSessionManager_setupZHHTTPHeaderField" ] = "1"; } response = {body: JSON.stringify(obj)}; } } catch (err) { $.logger.error(`优化软件配置出现异常:${err}`); } return response; } /** * 修改云端下发的配置 * @return {*} */ function modifyMCloudConfig() { let response = null; try { if (!!$.response.body) { let obj = JSON.parse($.response.body); if (obj.data && obj.data["configs"]) { // 去除灰色主题 obj.data["configs"].forEach(element => { if (element["configKey"] === "feed_gray_theme") { element["configValue"].start_time = "1669824000"; element["configValue"].end_time = "1669824001"; element.status = false; } }); } const body = JSON.stringify(obj); $.logger.debug(body); response = {body: body}; } } catch (err) { $.logger.error(`优化软件配置出现异常:${err}`); } return response; } /** * 屏蔽关键词解锁 * @return {*} */ function unlockBlockedKeywords() { let response = null; try { const userInfo = getUserInfo(); // 获取屏蔽关键词列表 if ($.request.method === "GET") { let keywords = $.data.read(keywordBlockKey, null, userInfo.id); if (!keywords) { keywords = []; } let headers = { "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 body = JSON.stringify({ success: true, is_vip: true, kw_min_length: 2, kw_max_length: 100, kw_max_count: keywordMaxCount, data: keywords, }); if ($.env.isQuanX) { response = {body: body, headers: headers, status: "HTTP/1.1 200 OK"}; } else { response = {response: {body: body, headers: headers, status: 200}}; } $.logger.debug(`获取本地脚本屏蔽关键词:\n${keywords.join("、")}`); } // 添加屏蔽关键词 else if ($.request.method === "POST") { if (!!$.request.body) { // 构造 response headers let headers = { "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 keyword = decodeURIComponent($.request.body).match( /keyword=(.*)/ )[1]; let keywords = $.data.read(keywordBlockKey, null, userInfo.id); if (!keywords) { keywords = []; } // 判断关键词是否存在 let keywordExists = false; for (let i = 0; i < keywords.length; i++) { if (keyword === keywords[i]) { keywordExists = true; break; } } // 不存在添加,存在返回异常 if (keywordExists === false) { keywords.push(keyword); $.data.write(keywordBlockKey, keywords, userInfo.id); let body = JSON.stringify({success: true}); if ($.env.isQuanX) { response = { body: body, headers: headers, status: "HTTP/1.1 200 OK", }; } else { response = { response: {body: body, headers: headers, status: 200}, }; } $.logger.debug(`添加本地脚本屏蔽关键词“${keyword}”`); } else { let body = JSON.stringify({ error: { message: "关键词已存在", code: 100002, }, }); if ($.env.isQuanX) { response = { body: body, headers: headers, status: "HTTP/1.1 400 Bad Request", }; } else { response = { response: {body: body, headers: headers, status: 400}, }; } } } } // 删除屏蔽关键词 else if ($.request.method === "DELETE") { let keyword = decodeURIComponent($.request.url).match(/keyword=(.*)/)[1]; let keywords = $.data.read(keywordBlockKey, null, userInfo.id); if (!keywords) { keywords = []; } keywords = keywords.filter((e) => { return e !== keyword; }); $.data.write(keywordBlockKey, keywords, userInfo.id); let headers = { "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 body = JSON.stringify({success: true}); if ($.env.isQuanX) { response = {body: body, headers: headers, status: "HTTP/1.1 200 OK"}; } else { response = {response: {body: body, headers: headers, status: 200}}; } $.logger.debug(`删除本地脚本屏蔽关键词:“${keyword}”`); } } catch (err) { $.logger.debug(`关键词屏蔽操作出现异常:${err}`); } return response; } /** * 处理登录用户信息 * * @return {*} */ function processUserInfo() { let response = null; try { let obj = JSON.parse($.response.body); $.data.write(blackAnswersIdKey, []); $.logger.debug(`用户登录用户信息,接口响应:${$.response.body}`); if ( obj && obj["id"] && obj.hasOwnProperty("vip_info") && obj["vip_info"].hasOwnProperty("is_vip") ) { const userInfo = { id: obj["id"], is_vip: obj["vip_info"]["is_vip"] ? obj["vip_info"]["is_vip"] !== undefined : false, }; $.logger.debug( `当前用户id:${obj["id"]},是否为VIP:${obj["vip_info"]["is_vip"]}` ); $.data.write(currentUserInfoKey, userInfo); // 在APP显示VIP,仅自己可见,打开后才能使用屏蔽关键词解锁 if ( $.data.read("zhihu_settings_fake_vip") !== false && obj["vip_info"]["is_vip"] === false ) { obj["vip_info"]["is_vip"] = true; obj["vip_info"]["vip_type"] = 2; obj["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" }; obj["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" }; obj["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" }; obj["vip_info"]["entrance_new"] = { "left_button": { "title": "精选会员内容", "description": "为您严选好内容", "jump_url": "zhihu://market/home" }, "right_button": { "title": "开通盐选会员", "description": "畅享 10w+ 场优质内容等特权", "jump_url": "zhihu://vip/purchase" } }; obj["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("设置用户为本地盐选会员"); response = {body: JSON.stringify(obj)}; } } else { $.logger.warning( `没有获取到本次登录用户信息,如未对功能造成影响,请忽略此日志。` ); } } catch (err) { $.logger.error(`获取当前用户信息出现异常:${err}`); } return response; } /** * @description: 黑名单管理 * @return {*} */ function manageBlackUser() { const userInfo = getUserInfo(); let defaultBlockedUsers = {}; let customBlockedUsers = $.data.read(blockedUsersKey, "", userInfo.id); customBlockedUsers = typeof customBlockedUsers === "object" && !!customBlockedUsers ? customBlockedUsers : {}; defaultAnswerBlockedUsers.forEach((element) => { customBlockedUsers[element] = "00000000000000000000000000000000"; defaultBlockedUsers[element] = "00000000000000000000000000000000"; }); $.logger.debug( `当前用户id:${userInfo.id},脚本黑名单:${JSON.stringify( customBlockedUsers )}` ); // 获取黑名单 if ($.request.method === "GET") { try { // 加载黑名单首页时,清空历史黑名单,仅保留脚本默认黑名单 if ($.request.url.indexOf("offset") < 0) { customBlockedUsers = defaultBlockedUsers; $.logger.debug("脚本黑名单已清空,请滑动至黑名单末尾保证重新获取完成。"); $.notification.post( "开始同步黑名单数据,请滑动至黑名单末尾,直至弹出“同步成功”的通知。" ); } let obj = JSON.parse($.response.body); if (!!obj["data"]) { $.logger.debug(`本次滑动获取的黑名单信息:${JSON.stringify(obj["data"])}`); obj["data"].forEach((element) => { if (element["name"] !== "[已重置]") { customBlockedUsers[element["name"]] = element["id"]; } }); $.data.write(blockedUsersKey, customBlockedUsers, userInfo.id); if (obj["paging"]["is_end"] === true) { $.notification.post( `同步黑名单数据成功!当前黑名单共${Object.keys(customBlockedUsers).length - defaultAnswerBlockedUsers.length }人。\n脚本内置黑名单${defaultAnswerBlockedUsers.length}人。` ); $.logger.debug(`脚本黑名单内容:${JSON.stringify(customBlockedUsers)}。`); } } else { $.logger.warning(`获取黑名单失败,接口响应不合法:${$.response.body}`); } } catch (err) { $.data.del(blockedUsersKey); $.logger.error(`获取黑名单失败,异常信息:${err}`); $.notification.post("获取黑名单失败,执行异常,已清空黑名单。"); } } // 写入黑名单 else if ($.request.method === "POST") { try { let obj = JSON.parse($.response.body); if (obj.hasOwnProperty("name") && obj.hasOwnProperty("id")) { $.logger.debug( `当前需要加入黑名单的用户Id:${obj["id"]},用户名:${obj["name"]}` ); if (obj["id"]) { customBlockedUsers[obj["name"]] = obj["id"]; $.data.write(blockedUsersKey, customBlockedUsers, userInfo.id); $.logger.debug( `${obj["name"] }写入脚本黑名单成功,当前脚本黑名单数据:${JSON.stringify( customBlockedUsers )}` ); $.notification.post(`已将用户“${obj["name"]}”写入脚本黑名单。`); } else { $.logger.error(`${obj["name"]}写入脚本黑名单失败,没有获取到用户Id。`); $.notification.post(`将用户“${obj["name"]}”写入脚本黑名单失败!`); } } else { $.logger.warning(`写入黑名单失败,接口响应不合法:${$.response.body}`); $.notification.post("写入脚本黑名单失败,接口返回不合法。"); } } catch (err) { $.logger.error(`写入黑名单失败,异常信息:${err}`); $.notification.post("写入脚本黑名单失败,执行异常,请查阅日志。"); } } // 移出黑名单 else if ($.request.method === "DELETE") { try { let obj = JSON.parse($.response.body); if (obj.success) { let user_id = $.request.url.match( /^https?:\/\/api\.zhihu\.com\/settings\/blocked_users\/([0-9a-zA-Z]*)/ )[1]; if (user_id) { $.logger.debug(`当前需要移出黑名单的用户Id:${user_id}`); for (let username in customBlockedUsers) { if (customBlockedUsers[username] === user_id) { delete customBlockedUsers[username]; $.data.write(blockedUsersKey, customBlockedUsers, userInfo.id); $.logger.debug( `${username}移出脚本黑名单成功,当前脚本黑名单数据:${JSON.stringify( customBlockedUsers )}` ); $.notification.post(`已将用户“${username}”移出脚本黑名单!`); break; } } } else { $.logger.error("将用户移出脚本黑名单失败!\n建议从设置中刷新黑名单数据。"); $.notification.post(`将用户移出脚本黑名单失败,没有获取到用户Id。\n建议从设置中刷新黑名单数据。`); } } else { $.logger.warning(`移出黑名单失败,接口响应不合法:${$.response.body}`); $.notification.post("移出脚本黑名单失败,接口返回不合法。"); } } catch (err) { $.logger.error(`移出黑名单失败,异常信息:${err}`); $.notification.post("移出脚本黑名单失败,执行异常,请查阅日志。"); } } } /** * 黑名单增强 - 浏览黑名单用户信息时自动加入脚本黑名单 * @return {*} */ function autoInsertBlackList() { let response = null; try { let obj = JSON.parse($.response.body); // 删除MCN信息 delete obj["mcn_user_info"]; response = {body: JSON.stringify(obj)}; // 如已是黑名单用户,但不在脚本黑名单中,则自动加入 if (obj.name && obj.id && obj["is_blocking"] === true) { const userInfo = getUserInfo(); let customBlockedUsers = $.data.read(blockedUsersKey, "", userInfo.id); customBlockedUsers = typeof customBlockedUsers === "object" && !!customBlockedUsers ? customBlockedUsers : {}; if (!customBlockedUsers[obj.name]) { $.logger.debug( `当前需要加入黑名单的用户Id:${obj["id"]},用户名:${obj["name"]}` ); customBlockedUsers[obj["name"]] = obj["id"]; $.data.write(blockedUsersKey, customBlockedUsers, userInfo.id); $.logger.debug( `${obj["name"] }写入脚本黑名单成功,当前脚本黑名单数据:${JSON.stringify( customBlockedUsers )}` ); $.notification.post(`已自动将用户“${obj["name"]}”写入脚本黑名单。`); } } } catch (err) { $.logger.error(`去除MCN信息出现异常:${err}`); } return response; } /** * 关注列表去广告 * * @return {*} */ function removeMoments() { let response = null; try { let obj = JSON.parse($.response.body.replace(/(\w+"+\s?):\s?(\d{15,})/g, '$1:"$2"')); const user_info = getUserInfo(); let customBlockedUsers = $.data.read(blockedUsersKey, "", user_info.id); customBlockedUsers = !!customBlockedUsers ? customBlockedUsers : {}; let data; const settings_remove_stream = $.data.read("zhihu_settings_moments_stream", false); const settings_remove_recommend = $.data.read("zhihu_settings_moments_recommend", false); const settings_remove_activity = $.data.read("zhihu_settings_moments_activity", false); const settings_blocked_users = $.data.read("zhihu_settings_blocked_users", false); data = obj.data.filter( (item) => { // 转发的想法是否含有黑名单用户 const isBlackUserPin = settings_blocked_users && item.target && item.target["origin_pin"] && item.target["origin_pin"].author && typeof customBlockedUsers[item.target["origin_pin"].author.name] != "undefined"; // 是否为流媒体 const isStream = settings_remove_stream && item["target_type"] === "zvideo"; // 是否为推荐关注用户 const isRecommend = settings_remove_recommend && item.type === "recommend_user_card_list"; // 是否为关注的问题有新动态 const isActivity = settings_remove_activity && item.type === "message_activity_card"; return !(isBlackUserPin || isStream || isRecommend || isActivity); } ) obj["data"] = data; response = {body: JSON.stringify(obj)}; } catch (err) { $.logger.error(`关注列表去广告出现异常:${err}`); } return response; } /** * 推荐去广告与黑名单增强 * * @return {*} */ function removeRecommend() { let response = null; try { // 移除推荐列表中的想法 const settings_remove_pin = $.data.read("zhihu_settings_recommend_pin", false); // 移除推荐列表的流媒体 const settings_recommend_stream = $.data.read("zhihu_settings_recommend_stream", false); // 移除推荐列表的文章 const settings_remove_article = $.data.read("zhihu_settings_remove_article", false); // 屏蔽黑名单用户 const settings_blocked_users = $.data.read("zhihu_settings_blocked_users", false); // 屏蔽关键词内容 const settings_blocked_keywords = $.data.read("zhihu_settings_blocked_keywords", true); // 获取用户信息 const user_info = getUserInfo(); let keywords = $.data.read(keywordBlockKey, "", user_info.id); keywords = settings_blocked_keywords && !!keywords ? keywords : []; let customBlockedUsers = $.data.read(blockedUsersKey, "", user_info.id); customBlockedUsers = settings_blocked_users && !!customBlockedUsers ? customBlockedUsers : {}; const newData = (element) => { const elementStr = JSON.stringify(element); // 是否为广告 const isAd = element["card_type"] === "slot_event_card" || element["card_type"] === "slot_video_event_card" || element.hasOwnProperty("ad") || // 训练营 (element["extra"] && element["extra"]["type"] === "Training"); // 是否为流媒体 const isStream = isAd !== true && elementStr.search( /"(type|style)+"\s?:\s?"(drama|zvideo|Video|BIG_IMAGE)+"/i ) >= 0; const removeStream = isStream && settings_recommend_stream; // 是否为想法 const isPin = isStream !== true && elementStr.search(/"(type|style)+"\s?:\s?"pin"/i) >= 0; const removePin = isPin && settings_remove_pin; // 是否为文章 const isArticle = elementStr.search(/"(type|style)+"\s?:\s?"article"/i) >= 0; const removeArticle = isArticle && settings_remove_article; // 是否匹配脚本关键词过滤 let matchKeyword = false; if (isStream !== true && settings_blocked_keywords) { for (let i = 0; i < keywords.length; i++) { if (elementStr.search(keywords[i]) >= 0) { if ($.isDebug) { let elementTitle = element["common_card"]["feed_content"]["title"]["panel_text"]; let elementContent = element["common_card"]["feed_content"]["content"]["panel_text"]; let actionUrl = ""; try { actionUrl = element["common_card"]["feed_content"]["title"]["action"]["intent_url"]; } catch { } $.logger.debug( `匹配关键字:\n${keywords[i]}\n标题:\n${elementTitle}\n内容:\n${elementContent}` ); $.notification.debug( scriptName, `关键字:${keywords[i]}`, `${elementTitle}\n${elementContent}`, actionUrl ); } matchKeyword = true; break; } } } // 是否为黑名单用户 let isBlockedUser; try { isBlockedUser = matchKeyword !== true && settings_blocked_users && customBlockedUsers && element["common_card"]["feed_content"]["source_line"]["elements"][1][ "text" ]["panel_text"] in customBlockedUsers; } catch { isBlockedUser = false; } return !( isAd || removePin || removeArticle || removeStream || matchKeyword || isBlockedUser ); }; // 修复number类型精度丢失 let obj = JSON.parse( $.response.body.replace(/(\w+"+\s?):\s?(\d{15,})/g, '$1:"$2"') ); if (obj["data"].length > 0 && newData.length === 0) { $.notification.post("所有推荐内容都已被过滤,建议调整脚本过滤配置。") } obj["data"] = obj["data"].filter(newData); response = {body: JSON.stringify(obj)}; } catch (err) { $.logger.error(`推荐列表去广告出现异常:${err}`); } return response; } /** * 回答列表去广告与黑名单增强 * * @return {*} */ function removeQuestions() { let response = null; try { const userInfo = getUserInfo(); let customBlockedUsers = $.data.read(blockedUsersKey, "", userInfo.id); customBlockedUsers = !!customBlockedUsers ? customBlockedUsers : {}; let obj = JSON.parse($.response.body); const settingsBlockedUsers = $.data.read("zhihu_settings_blocked_users", false); $.logger.debug(`当前黑名单列表: ${JSON.stringify(customBlockedUsers)}`); // 黑名单用户的回答Id let blackUserAnswersId = $.data.read(blackAnswersIdKey, []); // 去除广告 delete obj["ad_info"]; // 去除回答列表中的黑名单用户 if (obj["data"]) { let newData = []; for (let element of obj.data) { let blackUserName = ""; const answerId = element.target.id.toString(); try { if ("target" in element) { blackUserName = element["target"]["author"]["name"]; } } catch (ex) { $.logger.error(`获取回答列表用户名出现异常:${ex}`); } const isBlackUser = typeof customBlockedUsers[blackUserName] != "undefined"; const removeBlackUserAnswer = settingsBlockedUsers && isBlackUser; // 显示仅作者自己可见的回答,允许复制 if ("target" in element) { element["target"]["visible_only_to_author"] = false; element["target"]["is_visible"] = true; element["target"]["is_copyable"] = true; } if (!removeBlackUserAnswer) { newData.push(element); } else if (removeBlackUserAnswer === true && blackUserAnswersId.includes(answerId) === false) { blackUserAnswersId.push(answerId); $.notification.debug(`记录黑名单用户${blackUserName}的回答Id:${answerId}`); } } obj.data = newData; } $.data.write(blackAnswersIdKey, blackUserAnswersId); const body = JSON.stringify(obj); $.logger.debug(`修改后的回答列表数据:${body}`); response = {body: body}; } catch (err) { $.logger.error(`回答列表去广告出现异常:${err}`); } return response; } /** * 回答内容优化 * * @return {*} */ function modifyAnswer() { let response = null; try { let html = $.response.body; let insertText = ""; // 付费内容提醒 if ((html.indexOf("查看完整内容") >= 0 || html.indexOf("查看全部章节") >= 0) && html.indexOf("paid") >= 0) { insertText = '
本文为付费内容
'; } // 营销推广提醒 else if (html.indexOf("ad-link-card") >= 0 || html.indexOf("xg.zhihu.com") >= 0 || html.indexOf("营销平台") >= 0) { insertText = '
本文含有营销推广
'; } // 购物推广提醒 else if (html.indexOf("mcn-link-card") >= 0) { insertText = '
本文含有购物推广
'; } // 彩蛋 else if (Math.floor(Math.random() * 200) === 7) { insertText = '
本文为免费内容
'; } if (insertText !== "") { const matchStr = html.match(/(richText[^<]*>)(.)/)[1]; const start = html.lastIndexOf(matchStr) + matchStr.length; response = {body: html.slice(0, start) + insertText + html.slice(start)}; } } catch (err) { $.logger.error(`付费内容提醒出现异常:${err}`); } return response; } /** * 评论去广告及黑名单增强 * * @return {*} */ function removeComment() { let response = null; try { if (!!$.response.body) { let obj = JSON.parse($.response.body); obj["ad_info"] = {}; // 屏蔽黑名单用户 if ($.data.read("zhihu_settings_blocked_users", false) === true) { let user_info = getUserInfo(); let customBlockedUsers = $.data.read(blockedUsersKey, "", user_info.id); customBlockedUsers = !!customBlockedUsers ? customBlockedUsers : {}; let newComments = []; let blockCommentIdObj = {}; if (typeof obj.root != "undefined") { // 屏蔽黑名单用户的评论 const rootUserName = obj.root.author.name; const isBlackRootUser = typeof customBlockedUsers[rootUserName] != "undefined"; if (isBlackRootUser === true) { obj.root.is_delete = true; obj.root.can_reply = false; obj.root.can_like = false; obj.root.author.name = "黑名单用户"; obj.root.author.avatar_url = "https://picx.zhimg.com/v2-abed1a8c04700ba7d72b45195223e0ff_xll.jpg"; } } if (typeof obj.data != "undefined") { obj.data.forEach((comment) => { // 屏蔽黑名单用户的评论 // 评论人昵称 const commentUserName = comment.author.name; // 回复哪个人的评论(仅适用于独立子评论页面请求) let replyUserName = ""; if (comment["reply_to_author"] && comment["reply_to_author"].name) { replyUserName = comment["reply_to_author"].name; } const isSubComment = replyUserName !== ""; const isBlackCommentUser = typeof customBlockedUsers[commentUserName] != "undefined"; const isBlackReplyUser = typeof customBlockedUsers[replyUserName] != "undefined"; if (isBlackCommentUser === true || isBlackReplyUser === true) { if (isBlackCommentUser && !isSubComment && $.request.url.indexOf("root_comment") > 0) { $.notification.debug(`屏蔽黑名单用户“${commentUserName}”的主评论。`); } else if (!isBlackCommentUser && isSubComment && !isBlackReplyUser && $.request.url.indexOf("child_comment") > 0) { $.notification.debug(`屏蔽黑名单用户“${commentUserName}”的子评论。`); } else if (isBlackCommentUser && !isBlackReplyUser && $.request.url.indexOf("child_comment") > 0) { $.notification.debug(`屏蔽黑名单用户“${commentUserName}”回复“${replyUserName}”的子评论。`); } else if (isBlackCommentUser && isBlackReplyUser && $.request.url.indexOf("child_comment") > 0) { $.notification.debug(`屏蔽黑名单用户“${commentUserName}”回复黑名单用户“${replyUserName}”的子评论。`); } blockCommentIdObj[comment.id] = commentUserName; if (isBlackCommentUser) { comment.is_delete = true; comment.can_reply = false; comment.can_like = false; comment.author.exposed_medal = {}; comment.author.name = "[黑名单用户]"; comment.author.avatar_url = "https://picx.zhimg.com/v2-abed1a8c04700ba7d72b45195223e0ff_xll.jpg"; } if (isBlackReplyUser) { comment["reply_to_author"].name = "[黑名单用户]"; comment["reply_to_author"].exposed_medal = {}; comment["reply_to_author"].avatar_url = "https://picx.zhimg.com/v2-abed1a8c04700ba7d72b45195223e0ff_xll.jpg"; } } if (comment.child_comments) { let newChildComments = []; comment.child_comments.forEach((childComment) => { // 屏蔽黑名单用户的评论 const childCommentUserName = childComment.author.name; const childCommentReplyUserName = typeof childComment["reply_to_author"] != "undefined" ? childComment["reply_to_author"].name : ""; const isChildBlackCommentUser = typeof customBlockedUsers[childCommentUserName] != "undefined"; const isChildBlackReplyUser = typeof customBlockedUsers[childCommentReplyUserName] != "undefined"; if (isChildBlackCommentUser || isChildBlackReplyUser) { if (isChildBlackCommentUser === true) { $.notification.debug(`屏蔽黑名单用户“${childCommentUserName}”的子评论。`); blockCommentIdObj[childComment.id] = childCommentUserName; childComment.is_delete = true; childComment.can_reply = false; childComment.can_like = false; childComment.author.name = "[黑名单用户]"; childComment.author.exposed_medal = {}; childComment.author.avatar_url = "https://picx.zhimg.com/v2-abed1a8c04700ba7d72b45195223e0ff_xll.jpg"; } if (isChildBlackReplyUser === true) { $.logger.debug(`修改前的子评论数据:\n${JSON.stringify(childComment)}`); childComment["reply_to_author"].name = "[黑名单用户]"; childComment["reply_to_author"].exposed_medal = {}; childComment["reply_to_author"].avatar_url = "https://picx.zhimg.com/v2-abed1a8c04700ba7d72b45195223e0ff_xll.jpg"; $.notification.debug(`隐藏“${childCommentUserName}”回复黑名单用户“${childCommentReplyUserName}”的名称与头像。`); $.logger.debug(`修改后的子评论数据:\n${JSON.stringify(childComment)}`); } } newChildComments.push(childComment); }) comment.child_comments = newChildComments; } newComments.push(comment); }); } obj.data = newComments; } const body = JSON.stringify(obj); $.logger.debug(`过滤后的评论数据:\n${body}`); response = {body: body}; } } catch (err) { $.logger.error(`去除评论广告出现异常:${err}`); } return response; } /** * 移除文章页面的广告 * @return {*} */ function removeArticleAd() { let response = null; try { if (!!$.response.body) { let obj = JSON.parse($.response.body); obj["ad_info"] = {}; const body = JSON.stringify(obj); $.logger.debug(`过滤后的文章数据:\n${body}`); response = {body: body}; } } catch (err) { $.logger.error(`去除文章广告出现异常:${err}`); } return response; } /** * 屏蔽官方营销消息 * * @return {*} */ function removeMarketingMsg() { let response = null; try { let obj = JSON.parse($.response.body); let newItems = []; for (let item of obj["data"]) { if (item["detail_title"] === "官方帐号消息") { let unread_count = item["unread_count"]; if (unread_count > 0) { item["content"]["text"] = "未读消息" + unread_count + "条"; } else { item["content"]["text"] = "全部消息已读"; } item["is_read"] = true; item["unread_count"] = 0; newItems.push(item); } else if (item["detail_title"] !== "活动助手") { newItems.push(item); } } obj["data"] = newItems; response = {body: JSON.stringify(obj)}; } catch (err) { $.logger.error(`屏蔽官方营销消息出现异常:${err}`); } return response; } /** * 热榜去广告 * * @return {*} */ function removeHotListAds() { let response = null; try { if (!!$.response.body) { let obj = JSON.parse($.response.body); if ("data" in obj) { obj["data"] = obj["data"].filter((e) => { return ( e["type"] === "hot_list_feed" || e["type"] === "hot_list_feed_video" ); }); } response = {body: JSON.stringify(obj)}; } } catch (err) { $.logger.error(`去除热榜广告出现异常:${err}`); } return response; } /** * 去除预置关键字广告 * * @return {*} */ function removeKeywordAds() { let response = null; try { if (!!$.response.body) { $.logger.debug(`预置关键字返回:${$.response.body}`); let obj = JSON.parse($.response.body); if (obj.hasOwnProperty("preset_words") && obj["preset_words"]["words"]) { obj["preset_words"]["words"] = obj["preset_words"]["words"].filter((element) => { return element["type"] !== "ad"; }); response = {body: JSON.stringify(obj)}; } } } catch (err) { $.logger.error(`去除预置关键字广告出现异常:${err}`); } return response; } /** * 移除回答翻页时出现的黑名单用户的回答 * 小概率会移除失败 * @return {*} */ function removeNextBlackUserAnswer() { let response = null; try { if (!!$.response.body) { let obj = JSON.parse($.response.body); const blackUserAnswersId = $.data.read(blackAnswersIdKey, []); if (blackUserAnswersId.length > 0) { let newData = []; obj.data.forEach(element => { const tag = blackUserAnswersId.includes(element.id.toString()); if (tag === false) { // 去除可能的广告 element.ad_info = {"data": ""}; newData.push(element); } else { $.notification.debug(`屏蔽翻页过程中出现的黑名单用户回答Id:${element.id}`); } }); // 重新为答案排序 for (let i = 0; i < newData.length; i++) { if (newData[i]["extra"] && newData[i]["extra"]["question_index"]) { newData[i]["extra"]["question_index"] = i + 1; } if (newData[i]["strategy_info"]) { newData[i]["strategy_info"]["global_index"] = i + 1; newData[i]["strategy_info"]["strategy_index"] = i + 1; } } obj.data = newData; } response = {body: JSON.stringify(obj)}; } } catch (err) { $.logger.error(`屏蔽下翻黑名单用户的回答出现异常:${err}`); } return response; } function modifyAnswersNextData() { let response = null; try { if (!!$.response.body) { let obj = JSON.parse($.response.body); let user_info = getUserInfo(); let customBlockedUsers = $.data.read(blockedUsersKey, {}, user_info.id); $.logger.debug(`脚本黑名单用户:\n${JSON.stringify(customBlockedUsers)}`); let newData = []; obj.data.data.forEach(element => { element["ad_info"] = {"data": ""}; const isBlackUser = typeof customBlockedUsers[element.data.author.name] != "undefined"; $.logger.debug(`用户${element.data.author.name}是否在黑名单中:${isBlackUser}`); if ($.data.read("zhihu_settings_blocked_users", false) === false || isBlackUser === false) { newData.push(element); } }) obj.data.data = newData; response = {body: JSON.stringify(obj)}; } } catch (err) { $.logger.error(`屏蔽回答信息流黑名单用户及广告:${err}`); } return response; } /** * 修改盐值 * * @return {*} */ function changeUserCredit() { $.notification.debug("开始修改用户盐值"); let response = null; try { if (!!$.response.body) { // 自定义盐值 const score = parseInt($.data.read(userCreditScore, 780)); $.logger.debug(`准备修改用户盐值为${score}`); let obj = JSON.parse($.response.body); if (obj["credit_basis"].total_score < score) { obj["credit_basis"].total_score = score; $.logger.debug(`已修改用户盐值为:${score}`); } response = {body: JSON.stringify(obj)}; } } catch (err) { $.logger.error(`修改用户盐值出现异常:${err}`); } return response; } (() => { let response = null; if ($.isResponse) { switch (true) { // 获取用户信息 - 隔离用户数据,开启本地盐选会员等 case /^https:\/\/api\.zhihu\.com\/people\/self$/.test($.request.url): response = processUserInfo(); break; // 优化软件配置 - 优化下发的配置文件来实现某些效果 case $.data.read("zhihu_settings_app_conf", false) === true && /^https?:\/\/appcloud2\.zhihu\.com\/v\d+\/config/.test($.request.url): response = modifyAppConfig(); break; case $.data.read("zhihu_settings_app_conf", false) === true && /^https?:\/\/m-cloud\.zhihu\.com\/api\/cloud\/config\/all\?/.test($.request.url): response = modifyMCloudConfig(); break; // 修改用户盐值 - 仅当自定义盐值大于真实盐值时生效 case /^https?:\/\/api\.zhihu\.com\/user-credit\/basis/.test($.request.url): $.notification.debug("准备修改用户盐值"); response = changeUserCredit(); break; // 推荐页 - 移除黑名单用户发布的文章、去除广告,及自定义一些屏蔽项目 case /^https:\/\/api\.zhihu\.com\/topstory\/recommend\?/.test($.request.url): response = removeRecommend(); break; // 问题的回答列表 - 移除黑名单用户的回答、去除广告 case /^https?:\/\/api\.zhihu\.com\/(v4\/)?questions\/\d+/.test($.request.url): response = removeQuestions(); break; // 回答信息流 - 移除黑名单用户的回答、去除广告 case /^https?:\/\/api\.zhihu\.com\/next-data\?/.test($.request.url): response = modifyAnswersNextData(); break; // 消息页 - 折叠官方消息、屏蔽营销消息 case $.data.read("zhihu_settings_sys_msg", true) !== false && /^https?:\/\/api\.zhihu\.com\/notifications\/v3\/message/.test($.request.url): response = removeMarketingMsg(); break; // 评论页及子页面 - 去除黑名单用户发表的评论 case /^https?:\/\/api\.zhihu\.com\/comment_v5\/(answers|pins|comments?|articles)\/\d+\/(root|child)_comment/.test($.request.url): response = removeComment(); break; // 文章页 - 去除底部卡片广告 case /^https?:\/\/www\.zhihu\.com\/api\/v\d\/articles\/\d+\/recommendation\?/.test($.request.url): response = removeArticleAd(); break; // 回答页底部评论摘要 - 移除黑名单用户发表的评论 case /^https?:\/\/www\.zhihu\.com\/api\/v4\/comment_v5\/answers\/\d+\/abstract_comment\?/.test($.request.url): response = 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): response = modifyAnswer(); break; // 回答页 - 屏蔽下翻出现的黑名单用户 case $.data.read("zhihu_settings_blocked_users", false) !== false && /^https?:\/\/api\.zhihu\.com\/next\?/.test($.request.url): response = removeNextBlackUserAnswer(); break; // 黑名单增强 - 浏览黑名单用户信息时自动加入脚本黑名单 case $.data.read("zhihu_settings_blocked_users", true) === true && /^https?:\/\/api\.zhihu\.com\/people\/((?!self).)*$/.test($.request.url): response = autoInsertBlackList(); break; // 关注页 - 去广告 case /^https?:\/\/api\.zhihu\.com\/moments_v3\?/.test($.request.url): response = removeMoments(); break; // 热榜页 - 去广告 case $.data.read("zhihu_settings_hot_list", true) === true && /^https?:\/\/api\.zhihu\.com\/topstory\/hot-lists(\?|\/)/.test($.request.url): response = removeHotListAds(); break; // 搜索页 - 去除预置广告 case $.data.read("zhihu_settings_preset_words", true) === true && /^https?:\/\/api\.zhihu\.com\/search\/preset_words\?/.test($.request.url): response = 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 ) { response = unlockBlockedKeywords(response); } } else { $.data.del(currentUserInfoKey); $.data.del(blockedUsersKey); $.data.del(keywordBlockKey); $.notification.post("哲也同学数据清理完毕"); } if (response) { $.done(response); } else { $.done(); } })(); // prettier-ignore /** * * $$\ $$\ $$\ $$$$$\ $$$$$$\ $$$$$$\ * $$$\ $$$ | \__| \__$$ |$$ __$$\ $$ ___$$\ * $$$$\ $$$$ | $$$$$$\ $$$$$$\ $$\ $$$$$$$\ $$ |$$ / \__| \_/ $$ | * $$\$$\$$ $$ | \____$$\ $$ __$$\ $$ |$$ _____| $$ |\$$$$$$\ $$$$$ / * $$ \$$$ $$ | $$$$$$$ |$$ / $$ |$$ |$$ / $$\ $$ | \____$$\ \___$$\ * $$ |\$ /$$ |$$ __$$ |$$ | $$ |$$ |$$ | $$ | $$ |$$\ $$ | $$\ $$ | * $$ | \_/ $$ |\$$$$$$$ |\$$$$$$$ |$$ |\$$$$$$$\\$$$$$$ |\$$$$$$ | \$$$$$$ | * \__| \__| \_______| \____$$ |\__| \_______|\______/ \______/ \______/ * $$\ $$ | * \$$$$$$ | * \______/ * */ // @formatter:off function MagicJS(e="MagicJS",t="INFO"){const i=()=>{const e=typeof $loon!=="undefined";const t=typeof $task!=="undefined";const n=typeof module!=="undefined";const i=typeof $httpClient!=="undefined"&&!e;const s=typeof $storm!=="undefined";const r=typeof $environment!=="undefined"&&typeof $environment["stash-build"]!=="undefined";const o=i||e||s||r;const u=typeof importModule!=="undefined";return{isLoon:e,isQuanX:t,isNode:n,isSurge:i,isStorm:s,isStash:r,isSurgeLike:o,isScriptable:u,get name(){if(e){return"Loon"}else if(t){return"QuantumultX"}else if(n){return"NodeJS"}else if(i){return"Surge"}else if(u){return"Scriptable"}else{return"unknown"}},get build(){if(i){return $environment["surge-build"]}else if(r){return $environment["stash-build"]}else if(s){return $storm.buildVersion}},get language(){if(i||r){return $environment["language"]}},get version(){if(i){return $environment["surge-version"]}else if(r){return $environment["stash-version"]}else if(s){return $storm.appVersion}else if(n){return process.version}},get system(){if(i){return $environment["system"]}else if(n){return process.platform}},get systemVersion(){if(s){return $storm.systemVersion}},get deviceName(){if(s){return $storm.deviceName}}}};const s=(n,e="INFO")=>{let i=e;const s={SNIFFER:6,DEBUG:5,INFO:4,NOTIFY:3,WARNING:2,ERROR:1,CRITICAL:0,NONE:-1};const r={SNIFFER:"",DEBUG:"",INFO:"",NOTIFY:"",WARNING:"❗ ",ERROR:"❌ ",CRITICAL:"❌ ",NONE:""};const t=(e,t="INFO")=>{if(!(s[i]{i=e};return{setLevel:o,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=i();this.logger=s(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):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 n=this.data.read("magic_bark_url");if(e){this.logger.setLevel(e.toUpperCase())}if(n){this.notification.setBark(n)}}}get isRequest(){return typeof $request!=="undefined"&&typeof $response==="undefined"}get isResponse(){return typeof $response!=="undefined"}get isDebug(){return this.logger.level==="DEBUG"}get request(){if(typeof $request!=="undefined"){this.logger.sniffer(`RESPONSE:\n${JSON.stringify($request)}`);return $request}}get response(){if(typeof $response!=="undefined"){if($response.hasOwnProperty("status"))$response["statusCode"]=$response["status"];if($response.hasOwnProperty("statusCode"))$response["status"]=$response["statusCode"];this.logger.sniffer(`RESPONSE:\n${JSON.stringify($response)}`);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(r,f,l){let s=null;let u=null;const c=typeof MagicHttp==="function"?MagicHttp(f,l):undefined;const e=t=>{try{let e=t.replace(/\/+$/g,"");s=`${/^https?:\/\/([^/]*)/.exec(e)[0]}/push`;u=/\/([^\/]+)\/?$/.exec(e)[1]}catch(e){l.error(`Bark url error: ${e}.`)}};function t(e=r,t="",i="",o=""){const n=i=>{try{let t={};if(typeof i==="string"){if(f.isLoon)t={openUrl:i};else if(f.isQuanX)t={"open-url":i};else if(f.isSurge)t={url:i}}else if(typeof i==="object"){if(f.isLoon){t["openUrl"]=!!i["open-url"]?i["open-url"]:"";t["mediaUrl"]=!!i["media-url"]?i["media-url"]:""}else if(f.isQuanX){t=!!i["open-url"]||!!i["media-url"]?i:{}}else if(f.isSurge){let e=i["open-url"]||i["openUrl"];t=e?{url:e}:{}}}return t}catch(e){l.error(`Failed to convert notification option, ${e}`)}return i};o=n(o);if(arguments.length==1){e=r;t="",i=arguments[0]}l.notify(`title:${e}\nsubTitle:${t}\nbody:${i}\noptions:${typeof o==="object"?JSON.stringify(o):o}`);if(f.isSurge){$notification.post(e,t,i,o)}else if(f.isLoon){if(!!o)$notification.post(e,t,i,o);else $notification.post(e,t,i)}else if(f.isQuanX){$notify(e,t,i,o)}if(s&&u&&typeof c!=="undefined"){p(e,t,i)}}function i(e=r,t="",i="",o=""){if(l.level==="DEBUG"){if(arguments.length==1){e=r;t="",i=arguments[0]}this.notify(e,t,i,o)}}function p(e=r,t="",i="",o=""){if(typeof c==="undefined"||typeof c.post==="undefined"){throw"Bark notification needs to import MagicHttp module."}let n={url:s,headers:{"Content-Type":"application/json; charset=utf-8"},body:{title:e,body:t?`${t}\n${i}`:i,device_key:u}};c.post(n).catch(e=>{l.error(`Bark notify error: ${e}`)})}return{post:t,debug:i,bark:p,setBark:e}} function MagicData(i,u){let f={fs:undefined,data:{}};if(i.isNode){f.fs=require("fs");try{f.fs.accessSync("./magic.json",f.fs.constants.R_OK|f.fs.constants.W_OK)}catch(e){f.fs.writeFileSync("./magic.json","{}",{encoding:"utf8"})}f.data=require("./magic.json")}const o=(e,t)=>{if(typeof t==="object"){return false}else{return e===t}};const a=e=>{if(e==="true"){return true}else if(e==="false"){return false}else if(typeof e==="undefined"){return null}else{return e}};const c=(e,t,s,n)=>{if(s){try{if(typeof e==="string")e=JSON.parse(e);if(e["magic_session"]===true){e=e[s]}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=a(e);return e};const l=t=>{if(typeof t==="string"){let e={};try{e=JSON.parse(t);const s=typeof e;if(s!=="object"||e instanceof Array||s==="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 y=(e,t=null,s="",n=false,r=null)=>{let l=r||f.data;if(!!l&&typeof l[e]!=="undefined"&&l[e]!==null){val=l[e]}else{val=!!s?{}:null}val=c(val,t,s,n);return val};const d=(e,t=null,s="",n=false,r=null)=>{let l="";if(r||i.isNode){l=y(e,t,s,n,r)}else{if(i.isSurgeLike){l=$persistentStore.read(e)}else if(i.isQuanX){l=$prefs.valueForKey(e)}l=c(l,t,s,n)}u.debug(`READ DATA [${e}]${!!s?`[${s}]`:""} <${typeof l}>\n${JSON.stringify(l)}`);return l};const p=(t,s,n="",e=null)=>{let r=e||f.data;r=l(r);if(!!n){let e=l(r[t]);e["magic_session"]=true;e[n]=s;r[t]=e}else{r[t]=s}if(e!==null){e=r}return r};const S=(e,t,s="",n=null)=>{if(typeof t==="undefined"||t!==t){return false}if(!i.isNode&&(typeof t==="boolean"||typeof t==="number")){t=String(t)}let r="";if(n||i.isNode){r=p(e,t,s,n)}else{if(!s){r=t}else{if(i.isSurgeLike){r=!!$persistentStore.read(e)?$persistentStore.read(e):r}else if(i.isQuanX){r=!!$prefs.valueForKey(e)?$prefs.valueForKey(e):r}r=l(r);r["magic_session"]=true;r[s]=t}}if(!!r&&typeof r==="object"){r=JSON.stringify(r,null,4)}u.debug(`WRITE DATA [${e}]${s?`[${s}]`:""} <${typeof t}>\n${JSON.stringify(t)}`);if(!n){if(i.isSurgeLike){return $persistentStore.write(r,e)}else if(i.isQuanX){return $prefs.setValueForKey(r,e)}else if(i.isNode){try{f.fs.writeFileSync("./magic.json",r);return true}catch(e){u.error(e);return false}}}return true};const e=(t,s,n,r=o,l=null)=>{s=a(s);const e=d(t,null,n,false,l);if(r(e,s)===true){return false}else{const i=S(t,s,n,l);let e=d(t,null,n,false,l);if(r===o&&typeof e==="object"){return i}return r(s,e)}};const g=(e,t,s)=>{let n=s||f.data;n=l(n);if(!!t){obj=l(n[e]);delete obj[t];n[e]=obj}else{delete n[e]}if(!!s){s=n}return n};const t=(e,t="",s=null)=>{let n={};if(s||i.isNode){n=g(e,t,s);if(!s){f.fs.writeFileSync("./magic.json",JSON.stringify(n,null,4))}else{s=n}}else{if(!t){if(i.isStorm){return $persistentStore.remove(e)}else if(i.isSurgeLike){return $persistentStore.write(null,e)}else if(i.isQuanX){return $prefs.removeValueForKey(e)}}else{if(i.isSurgeLike){n=$persistentStore.read(e)}else if(i.isQuanX){n=$prefs.valueForKey(e)}n=l(n);delete n[t];const r=JSON.stringify(n,null,4);S(e,r)}}u.debug(`DELETE KEY [${e}]${!!t?`[${t}]`:""}`)};const s=(e,t=null)=>{let s=[];let n=d(e,null,null,true,t);n=l(n);if(n["magic_session"]!==true){s=[]}else{s=Object.keys(n).filter(e=>e!=="magic_session")}u.debug(`READ ALL SESSIONS [${e}] <${typeof s}>\n${JSON.stringify(s,null,4)}`);return s};const n=(e,t=null)=>{let s={};let n=d(e,null,null,true,t);n=l(n);if(n["magic_session"]===true){s={...n};delete s["magic_session"]}u.debug(`READ ALL SESSIONS [${e}] <${typeof s}>\n${JSON.stringify(s,null,4)}`);return s};return{read:d,write:S,del:t,update:e,allSessions:n,allSessionNames:s,defaultValueComparator:o,convertToObject:l}} // @formatter:on