2021-04-09 19:34:05 +08:00
const scriptName = "知乎助手" ;
const blockedUsersKey = "zhihu_blocked_users" ;
const currentUserInfoKey = "zhihu_current_userinfo" ;
const keywordBlockKey = "zhihu_keyword_block" ;
// 默认屏蔽推荐列表的用户,通常不是真实用户,无法通过加入黑名单屏蔽
const defaultAnswerBlockedUsers = [ "会员推荐" ] ;
2021-09-14 19:47:35 +08:00
const keywordMaxCount = 1000 ; // 允许设置的关键词数量
2021-04-09 19:34:05 +08:00
let magicJS = MagicJS ( scriptName , "INFO" ) ;
( ( ) => {
let response = null ;
if ( magicJS . isResponse ) {
switch ( true ) {
// 回答内容优化
2021-12-15 23:20:29 +08:00
case magicJS . read ( "zhihu_settings_answer_tip" ) != false &&
/^https?:\/\/www\.zhihu\.com\/appview\/v2\/answer\/.*(entry=(?!(preload-topstory|preload-search|preload-subscription)))?/ . test ( magicJS . request . url ) :
response = modifyAnswer ( response ) ;
2021-04-09 19:34:05 +08:00
break ;
// 处理登录用户信息
case /^https:\/\/api\.zhihu\.com\/people\/self/ . test ( magicJS . request . url ) :
2021-12-15 23:20:29 +08:00
response = processUserInfo ( response ) ;
2021-04-09 19:34:05 +08:00
break ;
2021-10-04 01:34:07 +08:00
// 黑名单增强 - 浏览黑名单用户信息时自动加入脚本黑名单
case magicJS . read ( "zhihu_settings_blocked_users" ) != false && /^https?:\/\/api\.zhihu\.com\/people\/((?!self).)*$/ . test ( magicJS . request . url ) :
2021-12-15 23:20:29 +08:00
response = autoInsertBlackList ( response ) ;
2021-04-09 19:34:05 +08:00
break ;
// 推荐去广告与黑名单增强
case /^https:\/\/api\.zhihu\.com\/topstory\/recommend\?/ . test ( magicJS . request . url ) :
2021-12-15 23:20:29 +08:00
response = removeRecommendAds ( response ) ;
2021-04-09 19:34:05 +08:00
break ;
// 关注列表去广告
case /^https?:\/\/api\.zhihu\.com\/moments(\/|\?)?(recommend|action=|feed_type=)(?!\/people)/ . test ( magicJS . request . url ) :
2021-12-15 23:20:29 +08:00
response = removeMomentsAds ( response ) ;
2021-04-09 19:34:05 +08:00
break ;
// 回答列表去广告与黑名单增强
case /^https?:\/\/api\.zhihu\.com\/v4\/questions/ . test ( magicJS . request . url ) :
2021-12-15 23:20:29 +08:00
response = removeQuestionsAds ( response ) ;
2021-04-09 19:34:05 +08:00
break ;
2021-10-04 01:34:07 +08:00
// 知乎V5版本评论去广告及黑名单增强
case /^https?:\/\/api\.zhihu\.com\/comment_v5\/(answers|pins|comments?|articles)\/\d+\/(root|child)_comment/ . test ( magicJS . request . url ) :
2021-12-15 23:20:29 +08:00
response = removeCommentV5Ads ( response ) ;
2021-04-09 19:34:05 +08:00
break ;
2021-10-04 01:34:07 +08:00
// 知乎旧版回答中的评论黑名单增强
case /^https?:\/\/api\.zhihu\.com\/(answers|pins|comments?|articles)\/\d+\/(root|child)_comments/ . test ( magicJS . request . url ) :
2021-12-15 23:20:29 +08:00
response = removeCommentAds ( response ) ;
2021-10-04 01:34:07 +08:00
break ;
// 知乎热榜去广告
case magicJS . read ( "zhihu_settings_hot_list" ) != false && /^https?:\/\/api\.zhihu\.com\/topstory\/hot-lists?(\?|\/)/ . test ( magicJS . request . url ) :
2021-12-15 23:20:29 +08:00
response = removeHotListAds ( response ) ;
2021-04-09 19:34:05 +08:00
break ;
2021-10-04 01:34:07 +08:00
// 拦截官方账号推广消息
case magicJS . read ( "zhihu_settings_sys_msg" ) != false && /^https?:\/\/api\.zhihu\.com\/notifications\/v3\/timeline\/entry\/system_message/ . test ( magicJS . request . url ) :
2021-12-15 23:20:29 +08:00
response = removeSysMsgAds ( response ) ;
2021-10-04 01:34:07 +08:00
break ;
// 屏蔽官方营销消息
case magicJS . read ( "zhihu_settings_sys_msg" ) != false && /^https?:\/\/api\.zhihu\.com\/notifications\/v3\/message/ . test ( magicJS . request . url ) :
2021-12-15 23:20:29 +08:00
response = removeMarketingMsg ( response ) ;
2021-10-04 01:34:07 +08:00
break ;
2021-04-09 19:34:05 +08:00
// 去除预置关键字广告
2021-10-04 01:34:07 +08:00
case magicJS . read ( "zhihu_settings_preset_words" ) == true && /^https?:\/\/api\.zhihu\.com\/search\/preset_words\?/ . test ( magicJS . request . url ) :
2021-12-15 23:20:29 +08:00
response = removeKeywordAds ( response ) ;
2021-04-09 19:34:05 +08:00
break ;
// 优化知乎软件配置
2021-10-04 01:34:07 +08:00
case magicJS . read ( "zhihu_settings_app_conf" ) == true && /^https?:\/\/appcloud2\.zhihu\.com\/v\d+\/config/ . test ( magicJS . request . url ) :
2021-12-15 23:20:29 +08:00
response = modifyAppConfig ( response ) ;
2021-04-09 19:34:05 +08:00
break ;
// 知乎热搜去广告
2021-10-04 01:34:07 +08:00
case magicJS . read ( "zhihu_settings_hot_search" ) == true && /^https?:\/\/api\.zhihu\.com\/search\/top_search\/tabs\/hot\/items/ . test ( magicJS . request . url ) :
2021-12-15 23:20:29 +08:00
response = removeHotSearchAds ( response ) ;
break ;
// 黑名单管理
case magicJS . read ( "zhihu_settings_blocked_users" ) != false && /^https?:\/\/api\.zhihu\.com\/settings\/blocked_users/ . test ( magicJS . request . url ) :
manageBlackUser ( ) ;
2021-04-09 19:34:05 +08:00
break ;
default :
break ;
}
} else if ( magicJS . isRequest ) {
// 知乎屏蔽关键词解锁
2021-10-04 01:34:07 +08:00
if ( magicJS . read ( "zhihu_settings_blocked_keywords" ) != false && /^https?:\/\/api\.zhihu\.com\/feed-root\/block/ . test ( magicJS . request . url ) === true ) {
2021-12-15 23:20:29 +08:00
response = unlockBlockedKeywords ( response ) ;
}
} else {
magicJS . write ( currentUserInfoKey , "" ) ;
magicJS . write ( blockedUsersKey , "" ) ;
magicJS . write ( keywordBlockKey , "" ) ;
magicJS . notify ( "知乎助手数据清理完毕" ) ;
}
if ( response ) {
magicJS . done ( response ) ;
} else {
magicJS . done ( ) ;
}
} ) ( ) ;
/ * *
* 屏蔽官方营销消息
*
* @ param { * } response
* @ return { * }
* /
function removeMarketingMsg ( response ) {
try {
let obj = JSON . parse ( magicJS . 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 ) {
magicJS . logError ( ` 知乎屏蔽官方营销消息出现异常: ${ err } ` ) ;
}
return response ;
}
/ * *
* 知乎屏蔽关键词解锁
*
* @ param { * } response
* @ return { * }
* /
function unlockBlockedKeywords ( response ) {
try {
const userInfo = getUserInfo ( ) ;
// 获取屏蔽关键词列表
if ( magicJS . request . method === "GET" ) {
let keywords = magicJS . read ( keywordBlockKey , 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 ( magicJS . isQuanX ) {
response = { body : body , headers : headers , status : "HTTP/1.1 200 OK" } ;
} else {
response = { response : { body : body , headers : headers , status : 200 } } ;
}
magicJS . logDebug ( ` 获取本地脚本屏蔽关键词: \n ${ keywords . join ( "、" ) } ` ) ;
}
// 添加屏蔽关键词
else if ( magicJS . request . method === "POST" ) {
if ( ! ! magicJS . 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 ( magicJS . request . body ) . match ( /keyword=(.*)/ ) [ 1 ] ;
let keywords = magicJS . read ( keywordBlockKey , userInfo . id ) ;
if ( ! keywords ) {
keywords = [ ] ;
}
// 判断关键词是否存在
let keywordExists = false ;
for ( let i = 0 ; i < keywords . length ; i ++ ) {
if ( keyword === keywords [ i ] ) {
keywordExists = true ;
2021-04-09 19:34:05 +08:00
}
2021-12-15 23:20:29 +08:00
}
// 不存在添加,存在返回异常
if ( keywordExists === false ) {
keywords . push ( keyword ) ;
magicJS . write ( keywordBlockKey , keywords , userInfo . id ) ;
let body = JSON . stringify ( { success : true } ) ;
2021-04-09 19:34:05 +08:00
if ( magicJS . isQuanX ) {
response = { body : body , headers : headers , status : "HTTP/1.1 200 OK" } ;
} else {
response = { response : { body : body , headers : headers , status : 200 } } ;
}
2021-12-15 23:20:29 +08:00
magicJS . logDebug ( ` 添加本地脚本屏蔽关键词“ ${ keyword } ” ` ) ;
} else {
let body = JSON . stringify ( {
error : {
message : "关键词已存在" ,
code : 100002 ,
} ,
} ) ;
if ( magicJS . isQuanX ) {
response = {
body : body ,
headers : headers ,
status : "HTTP/1.1 400 Bad Request" ,
2021-04-09 19:34:05 +08:00
} ;
2021-12-15 23:20:29 +08:00
} else {
response = { response : { body : body , headers : headers , status : 400 } } ;
}
}
}
}
// 删除屏蔽关键词
else if ( magicJS . request . method === "DELETE" ) {
let keyword = decodeURIComponent ( magicJS . request . url ) . match ( /keyword=(.*)/ ) [ 1 ] ;
let keywords = magicJS . read ( keywordBlockKey , userInfo . id ) ;
if ( ! keywords ) {
keywords = [ ] ;
}
keywords = keywords . filter ( ( e ) => {
return e != keyword ;
} ) ;
magicJS . 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 ( magicJS . isQuanX ) {
response = { body : body , headers : headers , status : "HTTP/1.1 200 OK" } ;
} else {
response = { response : { body : body , headers : headers , status : 200 } } ;
}
magicJS . logDebug ( ` 删除本地脚本屏蔽关键词:“ ${ keyword } ” ` ) ;
}
} catch ( err ) {
magicJS . logError ( ` 知乎关键词屏蔽操作出现异常: ${ err } ` ) ;
}
return response ;
}
/ * *
* 知乎热搜去广告
*
* @ param { * } response
* @ return { * }
* /
function removeHotSearchAds ( response ) {
try {
if ( ! ! magicJS . response . body ) {
let obj = JSON . parse ( magicJS . response . body ) ;
obj [ "commercial_data" ] = [ ] ;
response = { body : JSON . stringify ( obj ) } ;
}
} catch ( err ) {
magicJS . logError ( ` 去除知乎热搜广告出现异常: ${ err } ` ) ;
}
return response ;
}
/ * *
* 优化知乎软件配置
*
* @ param { * } response
* @ return { * }
* /
function modifyAppConfig ( response ) {
try {
if ( ! ! magicJS . response . body ) {
let obj = JSON . parse ( magicJS . response . body ) ;
let tab _infos = obj [ "config" ] [ "homepage_feed_tab" ] [ "tab_infos" ] . filter ( ( e ) => {
if ( e . tab _type === "activity_tab" ) {
e . end _time = ( Date . parse ( new Date ( ) ) - 120000 ) . toString ( ) . substr ( 0 , 10 ) ;
return true ;
} else {
return false ;
}
} ) ;
obj [ "config" ] [ "homepage_feed_tab" ] [ "tab_infos" ] = tab _infos ;
obj [ "config" ] [ "zvideo_max_number" ] = 1 ;
response = { body : JSON . stringify ( obj ) } ;
}
} catch ( err ) {
magicJS . logError ( ` 优化知乎软件配置出现异常: ${ err } ` ) ;
}
return response ;
}
/ * *
* 去除预置关键字广告
*
* @ param { * } response
* @ return { * }
* /
function removeKeywordAds ( response ) {
try {
if ( ! ! magicJS . response . body ) {
magicJS . logDebug ( ` 预置关键字返回: ${ magicJS . response . body } ` ) ;
let obj = JSON . parse ( magicJS . response . body ) ;
if ( obj . hasOwnProperty ( "preset_words" ) && obj [ "preset_words" ] [ "words" ] ) {
let words = obj [ "preset_words" ] [ "words" ] . filter ( ( element ) => {
return element [ "type" ] !== "ad" ;
} ) ;
obj [ "preset_words" ] [ "words" ] = words ;
response = { body : JSON . stringify ( obj ) } ;
}
}
} catch ( err ) {
magicJS . logError ( ` 知乎去除预置关键字广告出现异常: ${ err } ` ) ;
}
return response ;
}
/ * *
* 拦截官方账号推广消息
*
* @ param { * } response
* @ return { * }
* /
function removeSysMsgAds ( response ) {
try {
const sysmsg _blacklist = [ "知乎小伙伴" , "知乎视频" , "知乎团队" , "知乎礼券" , "知乎读书会团队" ] ;
let obj = JSON . parse ( magicJS . response . body ) ;
let data = obj [ "data" ] . filter ( ( element ) => {
return sysmsg _blacklist . indexOf ( element [ "content" ] [ "title" ] ) < 0 ;
} ) ;
obj [ "data" ] = data ;
response = { body : JSON . stringify ( obj ) } ;
} catch ( err ) {
magicJS . logError ( ` 知乎拦截官方账号推广消息出现异常: ${ err } ` ) ;
}
return response ;
}
/ * *
* 知乎热榜去广告
*
* @ param { * } response
* @ return { * }
* /
function removeHotListAds ( response ) {
try {
if ( ! ! magicJS . response . body ) {
let obj = JSON . parse ( magicJS . response . body ) ;
let data = obj [ "data" ] . filter ( ( e ) => {
return e [ "type" ] === "hot_list_feed" || e [ "type" ] === "hot_list_feed_video" ;
} ) ;
obj [ "data" ] = data ;
response = { body : JSON . stringify ( obj ) } ;
}
} catch ( err ) {
magicJS . logError ( ` 去除知乎热搜广告出现异常: ${ err } ` ) ;
}
return response ;
}
/ * *
* 知乎旧版回答中的评论黑名单增强
*
* @ param { * } response
* @ return { * }
* /
function removeCommentAds ( response ) {
try {
if ( ! ! magicJS . response . body ) {
// 评论区去广告
let obj = JSON . parse ( magicJS . response . body ) ;
if ( magicJS . read ( "zhihu_settings_blocked_users" ) != false ) {
// 屏蔽黑名单用户
let user _info = getUserInfo ( ) ;
let customBlockedUsers = magicJS . read ( blockedUsersKey , user _info . id ) ;
let newData = [ ] ;
obj . data . forEach ( ( comment ) => {
// 评论人昵称
let commentUserName = comment . author . member . name ;
// 回复哪个人的评论(仅适用于独立子评论页面请求)
let replyUserName = "" ;
if ( comment . reply _to _author && comment . reply _to _author . member && comment . reply _to _author . member . name ) {
replyUserName = comment . reply _to _author . member . name ;
}
if ( customBlockedUsers [ commentUserName ] || customBlockedUsers [ replyUserName ] ) {
if ( customBlockedUsers [ commentUserName ] && ! replyUserName && magicJS . request . url . indexOf ( "root_comment" ) > 0 ) {
magicJS . notifyDebug ( ` 屏蔽黑名单用户“ ${ commentUserName } ”的主评论。 ` ) ;
} else if ( customBlockedUsers [ commentUserName ] && ! replyUserName && magicJS . request . url . indexOf ( "child_comment" ) > 0 ) {
magicJS . notifyDebug ( ` 屏蔽黑名单用户“ ${ commentUserName } ”的子评论。 ` ) ;
} else if ( customBlockedUsers [ commentUserName ] && replyUserName && magicJS . request . url . indexOf ( "child_comment" ) > 0 ) {
magicJS . notifyDebug ( ` 屏蔽黑名单用户“ ${ commentUserName } ”回复“ ${ replyUserName } ”的子评论。 ` ) ;
} else {
magicJS . notifyDebug ( ` 屏蔽“ ${ commentUserName } ”回复黑名单用户“ ${ replyUserName } ”的子评论。 ` ) ;
2021-04-09 19:34:05 +08:00
}
2021-12-15 23:20:29 +08:00
// 减少主评论页面中的评论总数(仅适用于独立的主评论页面请求)
if ( obj . common _counts ) {
obj . common _counts -= 1 ;
2021-04-09 19:34:05 +08:00
}
2021-12-15 23:20:29 +08:00
// 减少子评论页面中的评论总数(仅适用于独立子评论页面请求)
if ( obj . paging && obj . paging . totals ) {
obj . paging . totals -= 1 ;
}
} else {
// 屏蔽子评论中的黑名单用户(仅适用于独立的主评论页面请求)
if ( comment . child _comments ) {
let newChildComments = [ ] ;
comment . child _comments . forEach ( ( childComment ) => {
if ( customBlockedUsers [ childComment . author . member . name ] || customBlockedUsers [ childComment . reply _to _author . member . name ] ) {
if ( customBlockedUsers [ childComment . author . member . name ] ) {
magicJS . notifyDebug ( ` 屏蔽黑名单用户“ ${ childComment . author . member . name } ”的主评论。 ` ) ;
} else {
magicJS . notifyDebug ( ` 屏蔽“ ${ childComment . author . member . name } ”回复黑名单用户“ ${ childComment . reply _to _author . member . name } ”的子评论。 ` ) ;
}
comment . child _comment _count -= 1 ;
} else {
newChildComments . push ( childComment ) ;
}
} ) ;
comment . child _comments = newChildComments ;
}
newData . push ( comment ) ;
}
} ) ;
obj . data = newData ;
}
response = { body : JSON . stringify ( obj ) } ;
}
} catch ( err ) {
magicJS . logError ( ` 去除知乎评论广告出现异常: ${ err } ` ) ;
}
return response ;
}
/ * *
* 知乎V5版本评论去广告及黑名单增强
*
* @ param { * } response
* @ return { * }
* /
function removeCommentV5Ads ( response ) {
try {
if ( ! ! magicJS . response . body ) {
let obj = JSON . parse ( magicJS . response . body ) ;
obj [ "ad_info" ] = { } ;
// 屏蔽黑名单用户
if ( magicJS . read ( "zhihu_settings_blocked_users" ) != false ) {
let user _info = getUserInfo ( ) ;
let customBlockedUsers = magicJS . read ( blockedUsersKey , user _info . id ) ;
customBlockedUsers = ! ! customBlockedUsers ? customBlockedUsers : { } ;
let newComments = [ ] ;
let blockCommentIdObj = { } ;
obj . data . forEach ( ( comment ) => {
// 评论人昵称
let commentUserName = comment . author . name ;
// 回复哪个人的评论(仅适用于独立子评论页面请求)
let replyUserName = "" ;
if ( comment . reply _to _author && comment . reply _to _author && comment . reply _to _author . name ) {
replyUserName = comment . reply _to _author . name ;
}
if ( customBlockedUsers [ commentUserName ] || customBlockedUsers [ replyUserName ] ) {
if ( customBlockedUsers [ commentUserName ] && ! replyUserName && magicJS . request . url . indexOf ( "root_comment" ) > 0 ) {
magicJS . notifyDebug ( ` 屏蔽黑名单用户“ ${ commentUserName } ”的主评论。 ` ) ;
} else if ( customBlockedUsers [ commentUserName ] && ! replyUserName && magicJS . request . url . indexOf ( "child_comment" ) > 0 ) {
magicJS . notifyDebug ( ` 屏蔽黑名单用户“ ${ commentUserName } ”的子评论。 ` ) ;
} else if ( customBlockedUsers [ commentUserName ] && replyUserName && magicJS . request . url . indexOf ( "child_comment" ) > 0 ) {
magicJS . notifyDebug ( ` 屏蔽黑名单用户“ ${ commentUserName } ”回复“ ${ replyUserName } ”的子评论。 ` ) ;
2021-04-09 19:34:05 +08:00
} else {
2021-12-15 23:20:29 +08:00
magicJS . notifyDebug ( ` 屏蔽“ ${ commentUserName } ”回复黑名单用户“ ${ replyUserName } ”的子评论。 ` ) ;
}
blockCommentIdObj [ comment . id ] = commentUserName ;
// 主评论数量-1, 仅适用于root_comment主评论页面请求
if ( obj . counts && obj . counts . total _counts ) {
obj . counts . total _counts -= 1 ;
}
// 子评论数量-1, 仅适用于child_comment子评论页面请求
if ( obj . paging && obj . paging . totals ) {
obj . paging . totals -= 1 ;
}
if ( obj . root && obj . root . child _comment _count ) {
obj . root . child _comment _count -= 1 ;
}
} else {
if ( comment . child _comments ) {
let newChildComments = [ ] ;
comment . child _comments . forEach ( ( childComment ) => {
let childCommentUserName = childComment . author . name ;
if ( customBlockedUsers [ childCommentUserName ] || blockCommentIdObj [ childComment . reply _comment _id ] ) {
if ( customBlockedUsers [ childCommentUserName ] ) {
magicJS . notifyDebug ( ` 屏蔽黑名单用户“ ${ childCommentUserName } ”的子评论。 ` ) ;
blockCommentIdObj [ childComment . id ] = childCommentUserName ;
} else {
magicJS . notifyDebug ( ` 屏蔽“ ${ childCommentUserName } ”回复黑名单用户“ ${ blockCommentIdObj [ childComment . reply _comment _id ] } ”的子评论。 ` ) ;
}
comment . child _comment _count -= 1 ;
} else {
newChildComments . push ( childComment ) ;
}
2021-04-09 19:34:05 +08:00
} ) ;
2021-12-15 23:20:29 +08:00
comment . child _comments = newChildComments ;
2021-04-09 19:34:05 +08:00
}
2021-12-15 23:20:29 +08:00
newComments . push ( comment ) ;
2021-04-09 19:34:05 +08:00
}
2021-12-15 23:20:29 +08:00
} ) ;
obj . data = newComments ;
}
response = { body : JSON . stringify ( obj ) } ;
}
} catch ( err ) {
magicJS . logError ( ` 去除知乎评论广告出现异常: ${ err } ` ) ;
}
return response ;
}
/ * *
* 回答列表去广告与黑名单增强
*
* @ param { * } response
* @ return { * }
* /
function removeQuestionsAds ( response ) {
try {
const userInfo = getUserInfo ( ) ;
let customBlockedUsers = magicJS . read ( blockedUsersKey , userInfo . id ) ;
customBlockedUsers = ! ! customBlockedUsers ? customBlockedUsers : { } ;
let obj = JSON . parse ( magicJS . response . body ) ;
magicJS . logDebug ( ` 当前黑名单列表: ${ JSON . stringify ( customBlockedUsers ) } ` ) ;
delete obj [ "ad_info" ] ;
delete obj [ "roundtable_info" ] ;
let data = obj [ "data" ] . filter ( ( element ) => {
return ! customBlockedUsers [ element [ "author" ] [ "name" ] ] ;
} ) ;
obj [ "data" ] = data ;
response = { body : JSON . stringify ( obj ) } ;
} catch ( err ) {
magicJS . logError ( ` 知乎回答列表去广告出现异常: ${ err } ` ) ;
}
return response ;
}
/ * *
* 关注列表去广告
*
* @ param { * } response
* @ return { * }
* /
function removeMomentsAds ( response ) {
try {
let obj = JSON . parse ( magicJS . response . body . replace ( /(\w+"+\s?):\s?(\d{15,})/g , '$1:"$2"' ) ) ;
const user _info = getUserInfo ( ) ;
let customBlockedUsers = magicJS . read ( blockedUsersKey , user _info . id ) ;
customBlockedUsers = ! ! customBlockedUsers ? customBlockedUsers : { } ;
let data = [ ] ;
const settings _moments _stream = magicJS . read ( "zhihu_settings_moments_stream" ) == true ;
const settings _blocked _users = magicJS . read ( "zhihu_settings_blocked_users" ) != false ;
for ( let i = 0 ; i < obj [ "data" ] . length ; i ++ ) {
// let element = targetIdFix(obj["data"][i]);
let element = obj [ "data" ] [ i ] ;
if ( ! element [ "ad" ] && ! element [ "adjson" ] && ! element [ "ad_list" ] ) {
// 判断转发的想法是否含有黑名单用户
if ( settings _blocked _users && element . target && element . target . origin _pin && element . target . origin _pin . author && customBlockedUsers [ element . target . origin _pin . author . name ] ) {
magicJS . notifyDebug ( ` 屏蔽“ ${ element . target . author . name } ”转发黑名单用户“ ${ element . target . origin _pin . author . name } ”的想法。 ` ) ;
}
// 屏蔽关注页的“最新视频”
else if ( ! settings _moments _stream || element [ "type" ] != "videos" ) {
data . push ( element ) ;
2021-04-09 19:34:05 +08:00
}
2021-12-15 23:20:29 +08:00
}
}
obj [ "data" ] = data ;
response = { body : JSON . stringify ( obj ) } ;
} catch ( err ) {
magicJS . logError ( ` 知乎关注列表去广告出现异常: ${ err } ` ) ;
}
return response ;
}
/ * *
* 推荐去广告与黑名单增强
*
* @ param { * } response
* @ return { * }
* /
function removeRecommendAds ( response ) {
try {
const settings _remove _yanxuan = magicJS . read ( "zhihu_settings_remove_yanxuan" ) == true ;
const settings _recommend _stream = magicJS . read ( "zhihu_settings_recommend_stream" ) == true ;
// 默认开启
const settings _blocked _keywords = magicJS . read ( "zhihu_settings_blocked_keywords" ) != false ;
const settings _blocked _users = magicJS . read ( "zhihu_settings_blocked_users" ) != false ;
const user _info = getUserInfo ( ) ;
let keywords = magicJS . read ( keywordBlockKey , user _info . id ) ;
keywords = settings _blocked _keywords && ! ! keywords ? keywords : [ ] ;
let customBlockedUsers = magicJS . read ( blockedUsersKey , user _info . id ) ;
customBlockedUsers = settings _blocked _users && ! ! customBlockedUsers ? customBlockedUsers : { } ;
const dataFilter = ( element ) => {
let elementStr = JSON . stringify ( element ) ;
// 是否为广告
let isAd = element [ "card_type" ] === "slot_event_card" || element [ "card_type" ] === "slot_video_event_card" || element . hasOwnProperty ( "ad" ) ;
// 是否为流媒体 element["extra"]["type"] === "drama" || element["extra"]["type"] === "zvideo") || element["extra"]["type"] === "Video" || element["common_card"]["style"] === "BIG_IMAGE")
let isStream = isAd != true && settings _recommend _stream && elementStr . search ( /"(type|style)+"\s?:\s?"(drama|zvideo|Video|BIG_IMAGE)+"/i ) >= 0 ;
// 是否为盐选推荐
let isYanXuan = isStream != true && settings _remove _yanxuan && elementStr . indexOf ( "https://pic2.zhimg.com/80/v2-c46fc8ec4c4e9ffc8f846ae0d8158a80_1440w.png" ) >= 0 ;
// 是否匹配脚本关键词过滤
let matchKeyword = false ;
if ( isStream != true && settings _blocked _keywords ) {
for ( let i = 0 ; i < keywords . length ; i ++ ) {
if ( elementStr . search ( keywords [ i ] ) >= 0 ) {
if ( magicJS . 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 { }
magicJS . logDebug ( ` 匹配关键字: \n ${ keywords [ i ] } \n 标题: \n ${ elementTitle } \n 内容: \n ${ elementContent } ` ) ;
magicJS . notifyDebug ( scriptName , ` 关键字: ${ keywords [ i ] } ` , ` ${ elementTitle } \n ${ elementContent } ` , actionUrl ) ;
}
matchKeyword = true ;
break ;
2021-04-09 19:34:05 +08:00
}
2021-12-15 23:20:29 +08:00
}
}
// 是否为黑名单用户
let isBlockedUser = false ;
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 || isStream || isYanXuan || matchKeyword || isBlockedUser ) ;
} ;
// 修复number类型精度丢失
let obj = JSON . parse ( magicJS . response . body . replace ( /(\w+"+\s?):\s?(\d{15,})/g , '$1:"$2"' ) ) ;
obj [ "data" ] = obj [ "data" ] . filter ( dataFilter ) ;
response = { body : JSON . stringify ( obj ) } ;
} catch ( err ) {
magicJS . logError ( ` 知乎推荐列表去广告出现异常: ${ err } ` ) ;
}
return response ;
}
/ * *
* 黑名单增强 - 浏览黑名单用户信息时自动加入脚本黑名单
*
* @ param { * } response
* @ return { * }
* /
function autoInsertBlackList ( response ) {
try {
let obj = JSON . parse ( magicJS . 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 = magicJS . read ( blockedUsersKey , userInfo . id ) ;
customBlockedUsers = typeof customBlockedUsers === "object" && ! ! customBlockedUsers ? customBlockedUsers : { } ;
if ( ! customBlockedUsers [ obj . name ] ) {
magicJS . logDebug ( ` 当前需要加入黑名单的用户Id: ${ obj [ "id" ] } ,用户名: ${ obj [ "name" ] } ` ) ;
customBlockedUsers [ obj [ "name" ] ] = obj [ "id" ] ;
magicJS . write ( blockedUsersKey , customBlockedUsers , userInfo . id ) ;
magicJS . logDebug ( ` ${ obj [ "name" ] } 写入脚本黑名单成功,当前脚本黑名单数据: ${ JSON . stringify ( customBlockedUsers ) } ` ) ;
magicJS . notify ( ` 已自动将用户“ ${ obj [ "name" ] } ”写入脚本黑名单。 ` ) ;
}
}
} catch ( err ) {
magicJS . logError ( ` 知乎去除MCN信息出现异常: ${ err } ` ) ;
}
return response ;
}
/ * *
* 处理登录用户信息
*
* @ param { * } response
* @ return { * }
* /
function processUserInfo ( response ) {
try {
let obj = JSON . parse ( magicJS . response . body ) ;
magicJS . logDebug ( ` 用户登录用户信息,接口响应: ${ magicJS . 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 ,
} ;
magicJS . logDebug ( ` 当前用户id: ${ obj [ "id" ] } , 是否为VIP: ${ obj [ "vip_info" ] [ "is_vip" ] } ` ) ;
magicJS . write ( currentUserInfoKey , userInfo ) ;
// 在知乎APP显示VIP, 仅自己可见, 无实际用途
if ( magicJS . read ( "zhihu_settings_fake_vip" ) == true && obj [ "vip_info" ] [ "is_vip" ] === false ) {
obj [ "vip_info" ] [ "is_vip" ] = true ;
obj [ "vip_info" ] [ "vip_icon" ] = {
url : "https://pic1.zhimg.com/v2-4812630bc27d642f7cafcd6cdeca3d7a_r.png" ,
night _mode _url : "https://pic1.zhimg.com/v2-c9686ff064ea3579730756ac6c289978_r.png" ,
} ;
obj [ "vip_info" ] [ "entrance" ] = {
icon : {
url : "https://pic1.zhimg.com/v2-5b7012c8c22fd520f5677305e1e551bf.png" ,
night _mode _url : "https://pic1.zhimg.com/v2-e51e3252d7a2cb016a70879defd5da0b.png" ,
} ,
title : "我的盐选会员" ,
expires _day : "2033-12-24" ,
sub _title : null ,
button _text : "你好,知乎!" ,
jump _url : "zhihu://vip/purchase" ,
button _jump _url : "zhihu://vip/purchase" ,
sub _title _new : null ,
identity : "svip" ,
} ;
obj [ "vip_info" ] [ "entrance_new" ] = {
left _button : {
title : "精选会员内容" ,
description : "为您严选好内容" ,
jump _url : "zhihu://market/home" ,
} ,
right _button : {
title : "我的盐选会员" ,
description : "畅享 10w+ 优质内容" ,
jump _url : "zhihu://vip/my" ,
} ,
} ;
obj [ "vip_info" ] [ "entrance_v2" ] = {
title : "我的盐选会员" ,
sub _title : "畅享 10w+ 优质内容" ,
jump _url : "zhihu://vip/my" ,
button _text : "查看权益" ,
} ;
response = { body : JSON . stringify ( obj ) } ;
}
} else {
magicJS . logWarning ( ` 没有获取到本次登录用户信息,如未对功能造成影响,请忽略此日志。 ` ) ;
}
} catch ( err ) {
magicJS . logError ( ` 知乎获取当前用户信息出现异常: ${ err } ` ) ;
}
return response ;
}
/ * *
* 回答内容优化
*
* @ param { * } response
* @ return { * }
* /
function modifyAnswer ( response ) {
try {
let html = magicJS . response . body ;
// 付费内容提醒
if ( ( html . indexOf ( "查看完整内容" ) >= 0 || html . indexOf ( "查看全部章节" ) >= 0 ) && html . indexOf ( "paid" ) >= 0 ) {
let matchStr = html . match ( /(richText[^<]*>)(.)/ ) [ 1 ] ;
let start = html . lastIndexOf ( matchStr ) + matchStr . length ;
let 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" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1957"><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" p-id="1958"></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><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;color: #f36;line-height: normal;display: flex;-webkit-box-align: center;align-items: center;"><svg 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;color: #f36;line-height: normal;fill: currentcolor;width: 24px;height: 24px;margin: -2px;" fill="currentColor" viewBox="0 0 24 24" width="24" height="24"><path d="M9.218 16.78a.737.737 0 0 0 1.052 0l4.512-4.249a.758.758 0 0 0 0-1.063L10.27 7.22a.737.737 0 0 0-1.052 0 .759.759 0 0 0-.001 1.063L13 12l-3.782 3.716a.758.758 0 0 0 0 1.063z" fill-rule="evenodd"></path></svg></span></div></div></a>' ;
response = { body : html . slice ( 0 , start ) + insertText + html . slice ( start ) } ;
}
// 营销推广提醒
else if ( html . indexOf ( "ad-link-card" ) >= 0 || html . indexOf ( "xg.zhihu.com" ) >= 0 || html . indexOf ( "知乎营销平台" ) >= 0 ) {
let matchStr = html . match ( /(richText[^<]*>)(.)/ ) [ 1 ] ;
let start = html . lastIndexOf ( matchStr ) + matchStr . length ;
let 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" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1957"><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" p-id="5859"></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><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;color: #f36;line-height: normal;display: flex;-webkit-box-align: center;align-items: center;"><svg 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;color: #00BCD4;line-height: normal;fill: currentcolor;width: 24px;height: 24px;margin: -2px;" fill="currentColor" viewBox="0 0 24 24" width="24" height="24"><path d="M9.218 16.78a.737.737 0 0 0 1.052 0l4.512-4.249a.758.758 0 0 0 0-1.063L10.27 7.22a.737.737 0 0 0-1.052 0 .759.759 0 0 0-.001 1.063L13 12l-3.782 3.716a.758.758 0 0 0 0 1.063z" fill-rule="evenodd"></path></svg></span></div></div></a>' ;
response = { body : html . slice ( 0 , start ) + insertText + html . slice ( start ) } ;
}
// 购物推广提醒
else if ( html . indexOf ( "mcn-link-card" ) >= 0 ) {
let matchStr = html . match ( /(richText[^<]*>)(.)/ ) [ 1 ] ;
let start = html . lastIndexOf ( matchStr ) + matchStr . length ;
let 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" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1957"><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><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;color: #f36;line-height: normal;display: flex;-webkit-box-align: center;align-items: center;"><svg 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;color: #00BCD4;line-height: normal;fill: currentcolor;width: 24px;height: 24px;margin: -2px;" fill="currentColor" viewBox="0 0 24 24" width="24" height="24"><path d="M9.218 16.78a.737.737 0 0 0 1.052 0l4.512-4.249a.758.758 0 0 0 0-1.063L10.27 7.22a.737.737 0 0 0-1.052 0 .759.759 0 0 0-.001 1.063L13 12l-3.782 3.716a.758.758 0 0 0 0 1.063z" fill-rule="evenodd"></path></svg></span></div></div></a>' ;
response = { body : html . slice ( 0 , start ) + insertText + html . slice ( start ) } ;
}
// 彩蛋
else if ( Math . floor ( Math . random ( ) * 200 ) == 7 ) {
let matchStr = html . match ( /(richText[^<]*>)(.)/ ) [ 1 ] ;
let start = html . lastIndexOf ( matchStr ) + matchStr . length ;
let 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" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1465"><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" p-id="1466"></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><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;color: #619201;line-height: normal;display: flex;-webkit-box-align: center;align-items: center;"><svg 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;color: #619201;line-height: normal;fill: currentcolor;width: 24px;height: 24px;margin: -2px;" fill="currentColor" viewBox="0 0 24 24" width="24" height="24"><path d="M9.218 16.78a.737.737 0 0 0 1.052 0l4.512-4.249a.758.758 0 0 0 0-1.063L10.27 7.22a.737.737 0 0 0-1.052 0 .759.759 0 0 0-.001 1.063L13 12l-3.782 3.716a.758.758 0 0 0 0 1.063z" fill-rule="evenodd"></path></svg></span></div></div></a>' ;
response = { body : html . slice ( 0 , start ) + insertText + html . slice ( start ) } ;
}
} catch ( err ) {
magicJS . logError ( ` 知乎付费内容提醒出现异常: ${ err } ` ) ;
}
return response ;
}
/ * *
* 黑名单管理
*
* /
function manageBlackUser ( ) {
const userInfo = getUserInfo ( ) ;
let defaultBlockedUsers = { } ;
let customBlockedUsers = magicJS . read ( blockedUsersKey , userInfo . id ) ;
customBlockedUsers = typeof customBlockedUsers === "object" && ! ! customBlockedUsers ? customBlockedUsers : { } ;
defaultAnswerBlockedUsers . forEach ( ( element ) => {
customBlockedUsers [ element ] = "00000000000000000000000000000000" ;
defaultBlockedUsers [ element ] = "00000000000000000000000000000000" ;
} ) ;
magicJS . logDebug ( ` 当前用户id: ${ userInfo . id } ,脚本黑名单: ${ JSON . stringify ( customBlockedUsers ) } ` ) ;
// 获取黑名单
if ( magicJS . request . method == "GET" ) {
try {
// 加载黑名单首页时,清空历史黑名单,仅保留脚本默认黑名单
if ( magicJS . request . url . indexOf ( "offset" ) < 0 ) {
customBlockedUsers = defaultBlockedUsers ;
magicJS . logDebug ( "脚本黑名单已清空,请滑动至黑名单末尾保证重新获取完成。" ) ;
magicJS . notify ( "脚本黑名单已清空,请滑动至黑名单末尾保证重新获取完成。" ) ;
}
let obj = JSON . parse ( magicJS . response . body ) ;
if ( ! ! obj [ "data" ] ) {
magicJS . logDebug ( ` 本次滑动获取的黑名单信息: ${ JSON . stringify ( obj [ "data" ] ) } ` ) ;
obj [ "data" ] . forEach ( ( element ) => {
if ( element [ "name" ] != "[已重置]" ) {
customBlockedUsers [ element [ "name" ] ] = element [ "id" ] ;
2021-04-09 19:34:05 +08:00
}
2021-12-15 23:20:29 +08:00
} ) ;
magicJS . write ( blockedUsersKey , customBlockedUsers , userInfo . id ) ;
if ( obj [ "paging" ] [ "is_end" ] == true ) {
magicJS . notify ( ` 获取脚本黑名单结束,当前黑名单共 ${ Object . keys ( customBlockedUsers ) . length - defaultAnswerBlockedUsers . length } 人。 \n 脚本内置黑名单 ${ defaultAnswerBlockedUsers . length } 人。 ` ) ;
magicJS . logDebug ( ` 脚本黑名单内容: ${ JSON . stringify ( customBlockedUsers ) } 。 ` ) ;
2021-04-09 19:34:05 +08:00
}
2021-12-15 23:20:29 +08:00
} else {
magicJS . logWarning ( ` 获取黑名单失败,接口响应不合法: ${ magicJS . response . body } ` ) ;
2021-04-09 19:34:05 +08:00
}
2021-12-15 23:20:29 +08:00
} catch ( err ) {
magicJS . del ( blockedUsersKey ) ;
magicJS . logError ( ` 获取黑名单失败,异常信息: ${ err } ` ) ;
magicJS . notify ( "获取黑名单失败,执行异常,已清空黑名单。" ) ;
2021-04-09 19:34:05 +08:00
}
}
2021-12-15 23:20:29 +08:00
// 写入黑名单
else if ( magicJS . request . method == "POST" ) {
try {
let obj = JSON . parse ( magicJS . response . body ) ;
if ( obj . hasOwnProperty ( "name" ) && obj . hasOwnProperty ( "id" ) ) {
magicJS . logDebug ( ` 当前需要加入黑名单的用户Id: ${ obj [ "id" ] } ,用户名: ${ obj [ "name" ] } ` ) ;
if ( obj [ "id" ] ) {
customBlockedUsers [ obj [ "name" ] ] = obj [ "id" ] ;
magicJS . write ( blockedUsersKey , customBlockedUsers , userInfo . id ) ;
magicJS . logDebug ( ` ${ obj [ "name" ] } 写入脚本黑名单成功,当前脚本黑名单数据: ${ JSON . stringify ( customBlockedUsers ) } ` ) ;
magicJS . notify ( ` 已将用户“ ${ obj [ "name" ] } ”写入脚本黑名单。 ` ) ;
} else {
magicJS . logError ( ` ${ obj [ "name" ] } 写入脚本黑名单失败, 没有获取到用户Id。 ` ) ;
magicJS . notify ( ` 将用户“ ${ obj [ "name" ] } ”写入脚本黑名单失败! ` ) ;
}
} else {
magicJS . logWarning ( ` 写入黑名单失败,接口响应不合法: ${ magicJS . response . body } ` ) ;
magicJS . notify ( "写入脚本黑名单失败,接口返回不合法。" ) ;
}
} catch ( err ) {
magicJS . logError ( ` 写入黑名单失败,异常信息: ${ err } ` ) ;
magicJS . notify ( "写入脚本黑名单失败,执行异常,请查阅日志。" ) ;
}
2021-04-09 19:34:05 +08:00
}
2021-12-15 23:20:29 +08:00
// 移出黑名单
else if ( magicJS . request . method == "DELETE" ) {
try {
let obj = JSON . parse ( magicJS . response . body ) ;
if ( obj . success ) {
let user _id = magicJS . request . url . match ( /https?:\/\/api\.zhihu\.com\/settings\/blocked_users\/([0-9a-zA-Z]*)/ ) [ 1 ] ;
if ( user _id ) {
magicJS . logDebug ( ` 当前需要移出黑名单的用户Id: ${ user _id } ` ) ;
for ( let username in customBlockedUsers ) {
if ( customBlockedUsers [ username ] == user _id ) {
delete customBlockedUsers [ username ] ;
magicJS . write ( blockedUsersKey , customBlockedUsers , userInfo . id ) ;
magicJS . logDebug ( ` ${ username } 移出脚本黑名单成功,当前脚本黑名单数据: ${ JSON . stringify ( customBlockedUsers ) } ` ) ;
magicJS . notify ( ` 已将用户“ ${ username } ”移出脚本黑名单! ` ) ;
break ;
}
}
} else {
magicJS . logError ( "将用户移出脚本黑名单失败!\n建议从设置中刷新黑名单数据。" ) ;
magicJS . notify ( ` 将用户移出脚本黑名单失败, 没有获取到用户Id。 \n 建议从设置中刷新黑名单数据。 ` ) ;
}
} else {
magicJS . logWarning ( ` 移出黑名单失败,接口响应不合法: ${ magicJS . response . body } ` ) ;
magicJS . notify ( "移出脚本黑名单失败,接口返回不合法。" ) ;
}
} catch ( err ) {
magicJS . logError ( ` 移出黑名单失败,异常信息: ${ err } ` ) ;
magicJS . notify ( "移出脚本黑名单失败,执行异常,请查阅日志。" ) ;
}
}
}
2021-04-09 19:34:05 +08:00
2021-12-15 23:20:29 +08:00
/ * *
* 获取用户信息
*
* @ return { * }
* /
function getUserInfo ( ) {
2021-04-09 19:34:05 +08:00
let defaultUserInfo = { id : "default" , is _vip : false } ;
try {
2021-10-04 01:34:07 +08:00
const userInfo = magicJS . read ( currentUserInfoKey ) ;
2021-04-09 19:34:05 +08:00
if ( typeof userInfo === "string" ) userInfo = JSON . parse ( userInfo ) ;
if ( ! ! userInfo && userInfo . hasOwnProperty ( "id" ) ) {
return userInfo ;
} else {
return defaultUserInfo ;
}
} catch ( err ) {
magicJS . logError ( ` 获取用户信息出现异常: ${ err } ` ) ;
return defaultUserInfo ;
}
}
// prettier-ignore
2021-10-04 01:34:07 +08:00
function MagicJS ( scriptName = "MagicJS" , logLevel = "INFO" ) { return new class { constructor ( ) { if ( this . _startTime = Date . now ( ) , this . version = "2.2.3.6" , this . scriptName = scriptName , this . logLevels = { DEBUG : 5 , INFO : 4 , NOTIFY : 3 , WARNING : 2 , ERROR : 1 , CRITICAL : 0 , NONE : - 1 } , this . isLoon = "undefined" != typeof $loon , this . isQuanX = "undefined" != typeof $task , this . isJSBox = "undefined" != typeof $drive , this . isNode = "undefined" != typeof module && ! this . isJSBox , this . isSurge = "undefined" != typeof $httpClient && ! this . isLoon , this . node = { request : void 0 , fs : void 0 , data : { } } , this . iOSUserAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.5 Mobile/15E148 Safari/604.1" , this . pcUserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36 Edg/84.0.522.59" , this . _logLevel = "INFO" , this . logLevel = logLevel , this . _barkUrl = "" , this . _barkKey = "" , this . isNode ) { this . node . fs = require ( "fs" ) , this . node . request = require ( "request" ) ; try { this . node . fs . accessSync ( "./magic.json" , this . node . fs . constants . R _OK | this . node . fs . constants . W _OK ) } catch ( err ) { this . node . fs . writeFileSync ( "./magic.json" , "{}" , { encoding : "utf8" } ) } this . node . data = require ( "./magic.json" ) } else this . isJSBox && ( $file . exists ( "drive://MagicJS" ) || $file . mkdir ( "drive://MagicJS" ) , $file . exists ( "drive://MagicJS/magic.json" ) || $file . write ( { data : $data ( { string : "{}" } ) , path : "drive://MagicJS/magic.json" } ) ) } set barkUrl ( url ) { try { let _url = url . replace ( /\/+$/g , "" ) ; this . _barkUrl = ` ${ / ^ https ? : \ / \ / ( [ ^ /]*)/ . exec ( _url ) [ 0 ] } /push ` , this . _barkKey = /\/([^\/]+)\/?$/ . exec ( _url ) [ 1 ] } catch ( err ) { this . logDebug ( "Bark config error." ) } } set logLevel ( level ) { let magic _loglevel = this . read ( "magicjs_loglevel" ) ; this . _logLevel = magic _loglevel || level . toUpperCase ( ) } get logLevel ( ) { return this . _logLevel } get isRequest ( ) { return "undefined" != typeof $request && "undefined" == typeof $response } get isResponse ( ) { return "undefined" != typeof $response } get isDebug ( ) { return "DEBUG" === this . logLevel } get request ( ) { return "undefined" != typeof $request ? $request : void 0 } get response ( ) { return "undefined" != typeof $response ? ( $response . hasOwnProperty ( "status" ) && ( $response . statusCode = $response . status ) , $response . hasOwnProperty ( "statusCode" ) && ( $response . status = $response . statusCode ) , $response ) : void 0 } get platform ( ) { return this . isSurge ? "Surge" : this . isQuanX ? "Quantumult X" : this . isLoon ? "Loon" : this . isJSBox ? "JSBox" : this . isNode ? "Node.js" : "Unknown" } read ( key , session = "" ) { let val = "" ; this . isSurge || this . isLoon ? val = $persistentStore . read ( key ) : this . isQuanX ? val = $prefs . valueForKey ( key ) : this . isNode ? val = this . node . data : this . isJSBox && ( val = $file . read ( "drive://MagicJS/magic.json" ) . string ) ; try { this . isNode && ( val = val [ key ] ) , this . isJSBox && ( val = JSON . parse ( val ) [ key ] ) , session && ( "string" == typeof val && ( val = JSON . parse ( val ) ) , val = val && "object" == typeof val ? val [ session ] : null ) } catch ( err ) { this . logError ( err ) , val = session ? { } : null , this . del ( key ) } void 0 === val && ( val = null ) ; try { val && "string" == typeof val && ( val = JSON . parse ( val ) ) } catch ( err ) { } return this . logDebug ( ` READ DATA [ ${ key } ] ${ session ? ` [ ${ session } ] ` : "" } ( ${ typeof val } ) \n ${ JSON . stringify ( val ) } ` ) , val } write ( key , val , session = "" ) { let data = session ? { } : "" ; if ( session && ( this . isSurge || this . isLoon ) ? data = $persistentStore . read ( key ) : session && this . isQuanX ? data = $prefs . valueForKey ( key ) : this . isNode ? data = this . node . data : this . isJSBox && ( data = JSON . parse ( $file . read ( "drive://MagicJS/magic.json" ) . string ) ) , session ) { try { "string" == typeof data && ( data = JSON . parse ( data ) ) , data = "object" == typeof data && data ? data : { } } catch ( err ) { this . logError ( err ) , this . del ( key ) , data = { } } this . isJSBox || this . isNode ? ( data [ key ] && "object" == typeof data [ key ] || ( data [ key ] = { } ) , data [ key ] . hasOwnProperty ( session ) || ( data [ key ] [ session ] = null ) , void 0 === val ? delete data [ key ] [ session ] : data [ key ] [ session ] = val ) : void 0 === val ? delete data [ session ] : data [ session ] = val } else this . isNode || this . isJSBox ? void 0 === val ? delete data [ key ] : data [ key ] = val : data = void 0 === val ? null : val ; "object" == typeof data && ( data = JSON . stringify ( data ) ) , this . isSurge || this . isLoon ? $persistentStore . write ( data , key ) : this . isQuanX ? $prefs . setValueForKey ( data , key ) : this . isNode ? this . node . fs . writeFileSync ( "./magic.json" , data ) : this . isJSBox && $file . write ( {