2022-12-12 23:31:15 +08:00
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 ( ) {
2022-12-25 23:32:19 +08:00
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 ;
2022-12-12 23:31:15 +08:00
}
2022-12-25 23:32:19 +08:00
} catch ( err ) {
$ . logger . error ( ` 获取用户信息出现异常: ${ err } ` ) ;
return defaultUserInfo ;
}
2022-12-12 23:31:15 +08:00
}
/ * *
* 优化软件配置
* @ return { * }
* /
function modifyAppConfig ( ) {
2022-12-25 23:32:19 +08:00
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 ;
}
2022-12-12 23:31:15 +08:00
}
2022-12-25 23:32:19 +08:00
) ;
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 ) } ;
2022-12-12 23:31:15 +08:00
}
2022-12-25 23:32:19 +08:00
} catch ( err ) {
$ . logger . error ( ` 优化软件配置出现异常: ${ err } ` ) ;
}
return response ;
2022-12-12 23:31:15 +08:00
}
/ * *
* 修改云端下发的配置
* @ return { * }
* /
function modifyMCloudConfig ( ) {
2022-12-25 23:32:19 +08:00
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 } ;
2022-12-12 23:31:15 +08:00
}
2022-12-25 23:32:19 +08:00
} catch ( err ) {
$ . logger . error ( ` 优化软件配置出现异常: ${ err } ` ) ;
}
return response ;
2022-12-12 23:31:15 +08:00
}
/ * *
* 屏蔽关键词解锁
* @ return { * }
* /
function unlockBlockedKeywords ( ) {
2022-12-25 23:32:19 +08:00
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 ( "、" ) } ` ) ;
}
2022-12-12 23:31:15 +08:00
2022-12-25 23:32:19 +08:00
// 添加屏蔽关键词
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 = [ ] ;
2022-12-12 23:31:15 +08:00
}
2022-12-25 23:32:19 +08:00
// 判断关键词是否存在
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" ,
2022-12-12 23:31:15 +08:00
} ;
2022-12-25 23:32:19 +08:00
} 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 } ,
} ;
}
2022-12-12 23:31:15 +08:00
}
2022-12-25 23:32:19 +08:00
}
2022-12-12 23:31:15 +08:00
}
2022-12-25 23:32:19 +08:00
// 删除屏蔽关键词
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 ;
2022-12-12 23:31:15 +08:00
}
/ * *
* 处理登录用户信息
*
* @ return { * }
* /
function processUserInfo ( ) {
2022-12-25 23:32:19 +08:00
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 (
` 没有获取到本次登录用户信息,如未对功能造成影响,请忽略此日志。 `
) ;
2022-12-12 23:31:15 +08:00
}
2022-12-25 23:32:19 +08:00
} catch ( err ) {
$ . logger . error ( ` 获取当前用户信息出现异常: ${ err } ` ) ;
}
return response ;
2022-12-12 23:31:15 +08:00
}
/ * *
* @ description : 黑名单管理
* @ return { * }
* /
function manageBlackUser ( ) {
2022-12-25 23:32:19 +08:00
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 ) } 。 ` ) ;
2022-12-12 23:31:15 +08:00
}
2022-12-25 23:32:19 +08:00
} else {
$ . logger . warning ( ` 获取黑名单失败,接口响应不合法: ${ $ . response . body } ` ) ;
}
} catch ( err ) {
$ . data . del ( blockedUsersKey ) ;
$ . logger . error ( ` 获取黑名单失败,异常信息: ${ err } ` ) ;
$ . notification . post ( "获取黑名单失败,执行异常,已清空黑名单。" ) ;
2022-12-12 23:31:15 +08:00
}
2022-12-25 23:32:19 +08:00
}
// 写入黑名单
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" ] } ”写入脚本黑名单失败! ` ) ;
2022-12-12 23:31:15 +08:00
}
2022-12-25 23:32:19 +08:00
} else {
$ . logger . warning ( ` 写入黑名单失败,接口响应不合法: ${ $ . response . body } ` ) ;
$ . notification . post ( "写入脚本黑名单失败,接口返回不合法。" ) ;
}
} catch ( err ) {
$ . logger . error ( ` 写入黑名单失败,异常信息: ${ err } ` ) ;
$ . notification . post ( "写入脚本黑名单失败,执行异常,请查阅日志。" ) ;
2022-12-12 23:31:15 +08:00
}
2022-12-25 23:32:19 +08:00
}
// 移出黑名单
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 ;
2022-12-12 23:31:15 +08:00
}
2022-12-25 23:32:19 +08:00
}
} else {
$ . logger . error ( "将用户移出脚本黑名单失败!\n建议从设置中刷新黑名单数据。" ) ;
$ . notification . post ( ` 将用户移出脚本黑名单失败, 没有获取到用户Id。 \n 建议从设置中刷新黑名单数据。 ` ) ;
2022-12-12 23:31:15 +08:00
}
2022-12-25 23:32:19 +08:00
} else {
$ . logger . warning ( ` 移出黑名单失败,接口响应不合法: ${ $ . response . body } ` ) ;
$ . notification . post ( "移出脚本黑名单失败,接口返回不合法。" ) ;
}
} catch ( err ) {
$ . logger . error ( ` 移出黑名单失败,异常信息: ${ err } ` ) ;
$ . notification . post ( "移出脚本黑名单失败,执行异常,请查阅日志。" ) ;
2022-12-12 23:31:15 +08:00
}
2022-12-25 23:32:19 +08:00
}
2022-12-12 23:31:15 +08:00
}
/ * *
* 黑名单增强 - 浏览黑名单用户信息时自动加入脚本黑名单
* @ return { * }
* /
function autoInsertBlackList ( ) {
2022-12-25 23:32:19 +08:00
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" ] } ”写入脚本黑名单。 ` ) ;
}
2022-12-12 23:31:15 +08:00
}
2022-12-25 23:32:19 +08:00
} catch ( err ) {
$ . logger . error ( ` 去除MCN信息出现异常: ${ err } ` ) ;
}
return response ;
2022-12-12 23:31:15 +08:00
}
/ * *
* 关注列表去广告
*
* @ return { * }
* /
function removeMoments ( ) {
2022-12-25 23:32:19 +08:00
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 ;
2022-12-12 23:31:15 +08:00
2022-12-25 23:32:19 +08:00
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 ) ;
2022-12-12 23:31:15 +08:00
2022-12-25 23:32:19 +08:00
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 ;
2022-12-12 23:31:15 +08:00
}
/ * *
* 推荐去广告与黑名单增强
*
* @ return { * }
* /
function removeRecommend ( ) {
2022-12-25 23:32:19 +08:00
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 ( ) ;
2022-12-12 23:31:15 +08:00
2022-12-25 23:32:19 +08:00
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 : { } ;
2022-12-12 23:31:15 +08:00
2022-12-25 23:32:19 +08:00
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
) ;
2022-12-12 23:31:15 +08:00
}
2022-12-25 23:32:19 +08:00
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
) ;
} ;
2022-12-12 23:31:15 +08:00
2022-12-25 23:32:19 +08:00
// 修复number类型精度丢失
let obj = JSON . parse (
$ . response . body . replace ( /(\w+"+\s?):\s?(\d{15,})/g , '$1:"$2"' )
) ;
2022-12-12 23:31:15 +08:00
2022-12-25 23:32:19 +08:00
if ( obj [ "data" ] . length > 0 && newData . length === 0 ) {
$ . notification . post ( "所有推荐内容都已被过滤,建议调整脚本过滤配置。" )
2022-12-12 23:31:15 +08:00
}
2022-12-25 23:32:19 +08:00
obj [ "data" ] = obj [ "data" ] . filter ( newData ) ;
response = { body : JSON . stringify ( obj ) } ;
} catch ( err ) {
$ . logger . error ( ` 推荐列表去广告出现异常: ${ err } ` ) ;
}
return response ;
2022-12-12 23:31:15 +08:00
}
/ * *
* 回答列表去广告与黑名单增强
*
* @ return { * }
* /
function removeQuestions ( ) {
2022-12-25 23:32:19 +08:00
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 } ` ) ;
2022-12-12 23:31:15 +08:00
}
2022-12-25 23:32:19 +08:00
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 ;
2022-12-12 23:31:15 +08:00
}
2022-12-25 23:32:19 +08:00
$ . data . write ( blackAnswersIdKey , blackUserAnswersId ) ;
const body = JSON . stringify ( obj ) ;
$ . logger . debug ( ` 修改后的回答列表数据: ${ body } ` ) ;
response = { body : body } ;
} catch ( err ) {
$ . logger . error ( ` 回答列表去广告出现异常: ${ err } ` ) ;
}
return response ;
2022-12-12 23:31:15 +08:00
}
/ * *
* 回答内容优化
*
* @ return { * }
* /
function modifyAnswer ( ) {
2022-12-25 23:32:19 +08:00
let response = null ;
try {
2022-12-12 23:31:15 +08:00
2022-12-25 23:32:19 +08:00
let html = $ . response . body ;
let insertText = "" ;
2022-12-12 23:31:15 +08:00
2022-12-25 23:32:19 +08:00
// 付费内容提醒
if ( ( html . indexOf ( "查看完整内容" ) >= 0 || html . indexOf ( "查看全部章节" ) >= 0 ) && html . indexOf ( "paid" ) >= 0 ) {
insertText = '<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>' ;
}
2022-12-12 23:31:15 +08:00
2022-12-25 23:32:19 +08:00
// 营销推广提醒
else if ( html . indexOf ( "ad-link-card" ) >= 0 || html . indexOf ( "xg.zhihu.com" ) >= 0 || html . indexOf ( "营销平台" ) >= 0 ) {
insertText = '<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>' ;
}
2022-12-12 23:31:15 +08:00
2022-12-25 23:32:19 +08:00
// 购物推广提醒
else if ( html . indexOf ( "mcn-link-card" ) >= 0 ) {
insertText = '<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>' ;
}
2022-12-12 23:31:15 +08:00
2022-12-25 23:32:19 +08:00
// 彩蛋
else if ( Math . floor ( Math . random ( ) * 200 ) === 7 ) {
insertText = '<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>' ;
}
2022-12-12 23:31:15 +08:00
2022-12-25 23:32:19 +08:00
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 ) } ;
2022-12-12 23:31:15 +08:00
}
2022-12-25 23:32:19 +08:00
} catch ( err ) {
$ . logger . error ( ` 付费内容提醒出现异常: ${ err } ` ) ;
}
return response ;
2022-12-12 23:31:15 +08:00
}
/ * *
* 评论去广告及黑名单增强
*
* @ return { * }
* /
function removeComment ( ) {
2022-12-25 23:32:19 +08:00
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" ;
}
}
2022-12-12 23:31:15 +08:00
2022-12-25 23:32:19 +08:00
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" ;
}
2022-12-12 23:31:15 +08:00
2022-12-25 23:32:19 +08:00
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 ) } ` ) ;
}
2022-12-12 23:31:15 +08:00
}
2022-12-25 23:32:19 +08:00
newChildComments . push ( childComment ) ;
} )
comment . child _comments = newChildComments ;
2022-12-12 23:31:15 +08:00
}
2022-12-25 23:32:19 +08:00
newComments . push ( comment ) ;
} ) ;
2022-12-12 23:31:15 +08:00
}
2022-12-25 23:32:19 +08:00
obj . data = newComments ;
}
const body = JSON . stringify ( obj ) ;
$ . logger . debug ( ` 过滤后的评论数据: \n ${ body } ` ) ;
response = { body : body } ;
2022-12-12 23:31:15 +08:00
}
2022-12-25 23:32:19 +08:00
} catch ( err ) {
$ . logger . error ( ` 去除评论广告出现异常: ${ err } ` ) ;
}
return response ;
2022-12-12 23:31:15 +08:00
}
/ * *
* 移除文章页面的广告
* @ return { * }
* /
function removeArticleAd ( ) {
2022-12-25 23:32:19 +08:00
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 } ;
2022-12-12 23:31:15 +08:00
}
2022-12-25 23:32:19 +08:00
} catch ( err ) {
$ . logger . error ( ` 去除文章广告出现异常: ${ err } ` ) ;
}
return response ;
2022-12-12 23:31:15 +08:00
}
/ * *
* 屏蔽官方营销消息
*
* @ return { * }
* /
function removeMarketingMsg ( ) {
2022-12-25 23:32:19 +08:00
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" ] = "全部消息已读" ;
2022-12-12 23:31:15 +08:00
}
2022-12-25 23:32:19 +08:00
item [ "is_read" ] = true ;
item [ "unread_count" ] = 0 ;
newItems . push ( item ) ;
} else if ( item [ "detail_title" ] !== "活动助手" ) {
newItems . push ( item ) ;
}
2022-12-12 23:31:15 +08:00
}
2022-12-25 23:32:19 +08:00
obj [ "data" ] = newItems ;
response = { body : JSON . stringify ( obj ) } ;
} catch ( err ) {
$ . logger . error ( ` 屏蔽官方营销消息出现异常: ${ err } ` ) ;
}
return response ;
2022-12-12 23:31:15 +08:00
}
/ * *
* 热榜去广告
*
* @ return { * }
* /
function removeHotListAds ( ) {
2022-12-25 23:32:19 +08:00
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 ) } ;
2022-12-12 23:31:15 +08:00
}
2022-12-25 23:32:19 +08:00
} catch ( err ) {
$ . logger . error ( ` 去除热榜广告出现异常: ${ err } ` ) ;
}
return response ;
2022-12-12 23:31:15 +08:00
}
/ * *
* 去除预置关键字广告
*
* @ return { * }
* /
function removeKeywordAds ( ) {
2022-12-25 23:32:19 +08:00
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 ) } ;
}
2022-12-12 23:31:15 +08:00
}
2022-12-25 23:32:19 +08:00
} catch ( err ) {
$ . logger . error ( ` 去除预置关键字广告出现异常: ${ err } ` ) ;
}
return response ;
2022-12-12 23:31:15 +08:00
}
/ * *
* 移除回答翻页时出现的黑名单用户的回答
* 小概率会移除失败
* @ return { * }
* /
2022-12-25 23:32:19 +08:00
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 ;
}
2022-12-12 23:31:15 +08:00
}
2022-12-25 23:32:19 +08:00
obj . data = newData ;
}
response = { body : JSON . stringify ( obj ) } ;
2022-12-12 23:31:15 +08:00
}
2022-12-25 23:32:19 +08:00
} 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 ;
2022-12-12 23:31:15 +08:00
}
/ * *
* 修改盐值
*
* @ return { * }
* /
2022-12-25 23:32:19 +08:00
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 ) } ;
2022-12-12 23:31:15 +08:00
}
2022-12-25 23:32:19 +08:00
} catch ( err ) {
$ . logger . error ( ` 修改用户盐值出现异常: ${ err } ` ) ;
}
return response ;
2022-12-12 23:31:15 +08:00
}
( ( ) => {
2022-12-25 23:32:19 +08:00
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 ;
2022-12-12 23:31:15 +08:00
}
2022-12-25 23:32:19 +08:00
} 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 ) ;
2022-12-12 23:31:15 +08:00
}
2022-12-25 23:32:19 +08:00
} else {
$ . data . del ( currentUserInfoKey ) ;
$ . data . del ( blockedUsersKey ) ;
$ . data . del ( keywordBlockKey ) ;
$ . notification . post ( "哲也同学数据清理完毕" ) ;
}
if ( response ) {
$ . done ( response ) ;
} else {
$ . done ( ) ;
}
2022-12-12 23:31:15 +08:00
} ) ( ) ;
// prettier-ignore
/ * *
*
* $$ \ $$ \ $$ \ $$$$$ \ $$$$$$ \ $$$$$$ \
* $$$ \ $$$ | \ _ _ | \ _ _$$ | $$ _ _$$ \ $$ _ _ _$$ \
* $$$$ \ $$$$ | $$$$$$ \ $$$$$$ \ $$ \ $$$$$$$ \ $$ | $$ / \ _ _ | \ _ / $$ |
* $$ \ $$ \ $$ $$ | \ _ _ _ _$$ \ $$ _ _$$ \ $$ | $$ _ _ _ _ _ | $$ | \ $$$$$$ \ $$$$$ /
* $$ \ $$$ $$ | $$$$$$$ | $$ / $$ | $$ | $$ / $$ \ $$ | \ _ _ _ _$$ \ \ _ _ _$$ \
* $$ | \ $ / $$ | $$ _ _$$ | $$ | $$ | $$ | $$ | $$ | $$ | $$ \ $$ | $$ \ $$ |
* $$ | \ _ / $$ | \ $$$$$$$ | \ $$$$$$$ | $$ | \ $$$$$$$ \ \ $$$$$$ | \ $$$$$$ | \ $$$$$$ |
* \ _ _ | \ _ _ | \ _ _ _ _ _ _ _ | \ _ _ _ _$$ | \ _ _ | \ _ _ _ _ _ _ _ | \ _ _ _ _ _ _ / \ _ _ _ _ _ _ / \ _ _ _ _ _ _ /
* $$ \ $$ |
* \ $$$$$$ |
* \ _ _ _ _ _ _ /
*
* /
2022-12-22 20:46:26 +08:00
// @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 ] < s [ t . toUpperCase ( ) ] ) ) console . log ( ` [ ${ t } ] [ ${ n } ] \n ${ r [ t . toUpperCase ( ) ] } ${ e } \n ` ) } ; const o = e => { 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 } \n subTitle: ${ t } \n body: ${ i } \n options: ${ 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