├── README.md ├── js ├── Loon_to_Surge.js ├── QX_to_Surge.js ├── TFTinfo.js └── xianxing.js └── modules ├── QX_to_Surge.sgmodule ├── TFTinfo.sgmodule ├── WeiboLite.plugin ├── bilibili.sgmodule ├── pr.sgmodule ├── test2.sgmodule └── ytmusic.module /README.md: -------------------------------------------------------------------------------- 1 | #Surge 2 | 3 | 本仓库全部搬运自互联网,方便个人使用 4 | 大部分都在里面添加了原作者的仓库地址 5 | -------------------------------------------------------------------------------- /js/Loon_to_Surge.js: -------------------------------------------------------------------------------- 1 | /**************************** 2 | 原脚本作者@小白脸 脚本修改@chengkongyiban 3 | 感谢@xream 的指导 4 | 说明 5 | t&zd; = { , } 花括号中的逗号 6 | 7 | ***************************/ 8 | 9 | const modStore = "https://loon-plugin.vercel.app/"; 10 | 11 | let req = $request.url; 12 | 13 | !(async () => { 14 | let body = await http(req); 15 | //判断是否断网 16 | if(body == null){$notification.post("模块商店:未获取到body","请检查网络及节点是否畅通\n" + "源链接为" + $request.url,"认为是bug?点击通知反馈","https://t.me/zhangpeifu") 17 | $done({ response: { status: 404 ,body:{} } }); 18 | }else{//以下开始重写及脚本转换 19 | 20 | if (body.match(/\/\*+\n[\s\S]*\n\*+\/\n/)){ 21 | body = body.replace(/[\s\S]*(\/\*+\n[\s\S]*\n\*+\/\n)[\s\S]*/,"$1").match(/[^\r\n]+/g); 22 | }else{ 23 | body = body.match(/[^\r\n]+/g);}; 24 | 25 | let Rule = []; 26 | let urlRewrite = []; 27 | let plugin = []; 28 | let MapLocal = []; 29 | let uHalf = []; 30 | let lHalf = []; 31 | let mods = []; 32 | 33 | body.forEach((x, y, z) => { 34 | x = x.replace(/^ *(#|;|\/\/)/,"#").replace(" _ reject"," - reject").replace(/(\{.*?)\,(.*?\})/gi,'$1t&zd;$2').replace(/\[URL\x20Rewrite\]/i,"[Rewrite]"); 35 | 36 | if (x.match(/^[^#].+(\x20-)?\x20+reject-?/)){ 37 | 38 | let rejectType = x.match(/(\x20-)?\x20+(reject($|-.+))/)[2]; 39 | 40 | if (rejectType.match(/-/)){ 41 | 42 | z[y - 1]?.match(/^#/) && MapLocal.push(z[y - 1]); 43 | 44 | let dict2Mock = rejectType.match('dict') ? '"https://raw.githubusercontent.com/mieqq/mieqq/master/reject-dict.json"' : ''; 45 | 46 | let array2Mock = rejectType.match('array') ? '"https://raw.githubusercontent.com/mieqq/mieqq/master/reject-array.json"' : ''; 47 | 48 | let two002Mock = rejectType.match('200') ? '"https://raw.githubusercontent.com/mieqq/mieqq/master/reject-200.txt"' : ''; 49 | 50 | let img2Mock = rejectType.match('img') ? '"https://raw.githubusercontent.com/mieqq/mieqq/master/reject-img.gif"' : ''; 51 | 52 | MapLocal.push(x.replace(/(^#)?(.+?)(\x20+-)?\x20+reject-.+/, `$1$2 data=${dict2Mock}${array2Mock}${two002Mock}${img2Mock}`)); 53 | }else{ 54 | 55 | z[y - 1]?.match(/^#/) && urlRewrite.push(z[y - 1]); 56 | urlRewrite.push(x.replace(/(^#)?(.+?)(\x20+-)?\x20+reject$/,`$1$2 - reject`));}; 57 | 58 | }else if (x.match(/^(DOM|U|IP|GEO)[^,]+,[^,]+,.+/)){ 59 | z[y - 1]?.match(/^#/) && Rule.push(z[y - 1]); 60 | 61 | Rule.push(x.replace(/-(IMG|DICT|ARRAY)$/,"")); 62 | }else if (x.match(/^(DOM|USER|URL|IP|GEO)[^,]+,[^,]+$/)){ 63 | x.replace(/^(DOM|USER|URL|IP|GEO)[^,]+,[^,]+$/,""); 64 | }else if (x.match(/\x20+(302|307)\x20+/)){ 65 | 66 | z[y - 1]?.match(/^#/) && urlRewrite.push(z[y - 1]); 67 | 68 | urlRewrite.push(x.replace(/(.+)\x20+(302|307)\x20+(.+)/,"$1 $3 $2")); 69 | }else{ 70 | plugin.push(x) 71 | }; 72 | 73 | }); //循环结束 74 | 75 | plugin = (plugin[0] || '') && `${plugin.join("\n\n")}`; 76 | 77 | Rule = (Rule[0] || '') && `${Rule.join("\n")}`; 78 | 79 | urlRewrite = (urlRewrite[0] || '') && `${urlRewrite.join("\n\n")}`; 80 | 81 | MapLocal = (MapLocal[0] || '') && `\n\n[Map Local]\n\n${MapLocal.join("\n\n")}`; 82 | 83 | if (urlRewrite !== "" && plugin.match("[Rewrite]")){ 84 | uHalf = plugin.split(/\[Rewrite\]/i)[0]; 85 | lHalf = plugin.split(/\[Rewrite\]/i)[1]; 86 | mods = `${uHalf}\n\n[Rewrite]\n\n${urlRewrite}\n\n${lHalf}`; 87 | }else{if (urlRewrite != ""){ 88 | mods = `${plugin}${urlRewrite}` 89 | }else{ 90 | mods = `${plugin}`; 91 | } 92 | }; 93 | 94 | if (Rule !== "" && mods.match("[Rule]")){ 95 | uHalf = mods.split(/\[Rule\]/i)[0]; 96 | lHalf = mods.split(/\[Rule\]/i)[1]; 97 | mods = `${uHalf}\n\n[Rule]\n\n${Rule}\n\n${lHalf}`; 98 | }else{if (Rule != ""){ 99 | mods = `${mods}${Rule}` 100 | }else{ 101 | mods = `${mods}`; 102 | } 103 | }; 104 | 105 | body = `${mods} 106 | 107 | ${MapLocal}` 108 | .replace(/t&zd;/g,',') 109 | .replace(/\[Rewrite\]/gi,'\n[URL Rewrite]\n') 110 | .replace(/\[MITM\]/gi,'\n[MITM]\n') 111 | .replace(/\[Script\]/gi,'\n[Script]\n') 112 | .replace(/\[Rule\]/gi,'\n[Rule]\n') 113 | .replace(/\[General\]/gi,'\n[General]\n') 114 | .replace(/hostname\x20*=\x20*(.*)/gi,"hostname = %APPEND% $1") 115 | .replace(/skip-proxy\x20*=\x20*(.*)/gi,"skip-proxy = %APPEND% $1") 116 | .replace(/bypass-tun\x20*=\x20*(.*)/gi,"tun-excluded-routes = %APPEND% $1") 117 | .replace(/real-ip\x20*=\x20*(.*)/gi,"always-real-ip = %APPEND% $1") 118 | .replace(/(#.+\n)\n+/g,'$1') 119 | .replace(/\n{2,}/g,'\n\n') 120 | .replace(/hostname\x20=\x20%APPEND%\x20\n\n安装失败\n\n1、请检查模块商店是否安装\n\n2、请检查是否开启HTTPS解密\n\n小火箭开启HTTPS解密教程https:\/\/t\.me\/h5683577\/3\n\nSurge开启HTTPS解密\(MITM\)教程https:\/\/t\.me\/h5683577\/135/,"hostname = %APPEND% \n\n模块商店已成功安装!!!") 121 | 122 | 123 | if (body.match("验证结果↓↓↓") != null && body.match("请检查模块商店是否安装") == null) { 124 | $notification.post("已成功安装模块商店","点击通知跳转模块商店","https://loon-gallery.vercel.app/",{url:modStore}) 125 | }else{}; 126 | 127 | $done({ response: { status: 200 ,body:body ,headers: {'Content-Type': 'text/plain; charset=utf-8'} } }); 128 | }//判断是否断网的反括号 129 | 130 | })() 131 | .catch((e) => { 132 | $notification.post(`${e}`,'',''); 133 | $done() 134 | }) 135 | 136 | 137 | function http(req) { 138 | return new Promise((resolve, reject) => 139 | $httpClient.get(req, (err, resp,data) => { 140 | resolve(data) 141 | }) 142 | ) 143 | } -------------------------------------------------------------------------------- /js/QX_to_Surge.js: -------------------------------------------------------------------------------- 1 | /*************** 2 | 原脚本作者@小白脸 脚本修改@chengkongyiban 3 | 感谢@xream 的指导 4 | 使用方法 在qx重写链接末尾加上qx 5 | 6 | [Script] 7 | QX转换 = type=http-request,pattern=qx$|qx\?.*,requires-body=1,max-size=0,script-path=https://raw.githubusercontent.com/chengkongyiban/shadowrocket/main/scripts/QX_to_Surge.js 8 | 9 | [MITM] 10 | hostname = %APPEND% github.com:443, raw.githubusercontent.com:443 11 | **************/ 12 | const ua = $request.headers['User-Agent'] || $request.headers['user-agent'] 13 | const isStashiOS = 'undefined' !== typeof $environment && $environment['stash-version'] && ua.indexOf('Macintosh') === -1 14 | const isSurgeiOS = 'undefined' !== typeof $environment && $environment['surge-version']; 15 | const isShadowrocket = 'undefined' !== typeof $rocket; 16 | const isLooniOS = 'undefined' != typeof $loon && /iPhone/.test($loon); 17 | 18 | var name = ""; 19 | var desc = ""; 20 | let req = $request.url.replace(/qx$|qx\?.*/,''); 21 | let urlArg = $request.url.replace(/.+qx(\?.*)/,'$1'); 22 | var original = [];//用于获取原文行号 23 | //获取参数 24 | var nName = urlArg.indexOf("n=") != -1 ? (urlArg.split("n=")[1].split("&")[0].split("+")) : null; 25 | var Pin0 = urlArg.indexOf("y=") != -1 ? (urlArg.split("y=")[1].split("&")[0].split("+")).map(decodeURIComponent) : null; 26 | var Pout0 = urlArg.indexOf("x=") != -1 ? (urlArg.split("x=")[1].split("&")[0].split("+")).map(decodeURIComponent) : null; 27 | var delNoteSc = urlArg.indexOf("del=") != -1 ? true : false; 28 | 29 | //修改名字和简介 30 | if (nName === null){ 31 | name = req.match(/.+\/(.+)\.(conf|js|snippet|txt)/)?.[1] || '无名'; 32 | desc = name; 33 | }else{ 34 | name = nName[0] != "" ? nName[0] : req.match(/.+\/(.+)\.(conf|js|snippet|txt)/)?.[1]; 35 | desc = nName[1] != undefined ? nName[1] : nName[0]; 36 | }; 37 | name = "#!name=" + decodeURIComponent(name); 38 | desc = "#!desc=" + decodeURIComponent(desc); 39 | 40 | !(async () => { 41 | let body = await http(req); 42 | //判断是否断网 43 | if(body == null){if(isSurgeiOS || isStashiOS){ 44 | $notification.post("重写转换:未获取到body","请检查网络及节点是否畅通","认为是bug?点击通知反馈",{url:"https://t.me/zhangpeifu"}) 45 | $done({ response: { status: 404 ,body:{} } });}else{$notification.post("重写转换:未获取到body","请检查网络及节点是否畅通","认为是bug?点击通知反馈","https://t.me/zhangpeifu") 46 | $done({ response: { status: 404 ,body:{} } }); 47 | }//识别客户端通知 48 | }else{//以下开始重写及脚本转换 49 | 50 | original = body.replace(/^ *(#|;|\/\/)/g,'#').replace(/\x20+url\x20+/g," url ").replace(/(^[^#].+)\x20+\/\/.+/g,"$1").split("\n"); 51 | body = body.match(/[^\r\n]+/g); 52 | 53 | let script = []; 54 | let URLRewrite = []; 55 | let MapLocal = []; 56 | let MITM = ""; 57 | let others = []; 58 | 59 | body.forEach((x, y, z) => { 60 | x = x.replace(/^ *(#|;|\/\/)/,'#').replace(/\x20+url\x20+/," url ").replace(/hostname\x20*=/,"hostname=").replace(/(^[^#].+)\x20+\/\/.+/,"$1"); 61 | //去掉注释 62 | if(Pin0 != null) { 63 | for (let i=0; i < Pin0.length; i++) { 64 | const elem = Pin0[i]; 65 | if (x.indexOf(elem) != -1){ 66 | x = x.replace(/^#/,"") 67 | }else{}; 68 | };//循环结束 69 | }else{};//去掉注释结束 70 | 71 | //增加注释 72 | if(Pout0 != null){ 73 | for (let i=0; i < Pout0.length; i++) { 74 | const elem = Pout0[i]; 75 | if (x.indexOf(elem) != -1 && x.indexOf("hostname=") == -1){ 76 | x = x.replace(/(.+)/,"#$1") 77 | }else{}; 78 | };//循环结束 79 | }else{};//增加注释结束 80 | 81 | if (delNoteSc === true && x.match(/^#/)){ 82 | if (x.match(/\.js$/) || x.match(/\x20echo-response\x20/)){ 83 | x = x.replace(/(.+)/,'') 84 | } 85 | }; 86 | 87 | let type = x.match( 88 | /\x20url\x20script-|enabled=|\x20url\x20reject$|url\x20reject-|\x20echo-response\x20|\-header\x20|^hostname|url\x20(302|307)|\x20(request|response)-body/ 89 | )?.[0]; 90 | 91 | //判断注释 92 | if (x.match(/^[^#]/)){ 93 | var noteK = ""; 94 | }else{ 95 | var noteK = "#"; 96 | }; 97 | 98 | if (type) { 99 | switch (type) { 100 | case " url script-": 101 | z[y - 1]?.match(/^#/) && script.push(z[y - 1]); 102 | let sctype = x.match(' script-response') ? 'response' : 'request'; 103 | 104 | let rebody = x.match(/\x20script[^\s]*(-body|-analyze)/) ? ',requires-body=1' : ''; 105 | 106 | let size = x.match(/\x20script[^\s]*(-body|-analyze)/) ? ',max-size=3145728' : ''; 107 | 108 | let urlInNum = x.replace(/\x20{2,}/g," ").split(" ").indexOf("url"); 109 | 110 | let ptn = x.replace(/\x20{2,}/g," ").split(" ")[urlInNum - 1].replace(/^#/,"").replace(/(.*,.*)/,'"$1"'); 111 | 112 | let js = x.replace(/\x20{2,}/g," ").split(" ")[urlInNum + 2]; 113 | 114 | let proto = js.match('proto.js') ? ',binary-body-mode=1' : ''; 115 | 116 | let scname = js.substring(js.lastIndexOf('/') + 1, js.lastIndexOf('.') ); 117 | script.push( 118 | `${noteK}${scname}_${y} = type=http-${sctype},pattern=${ptn}${rebody}${size}${proto},script-path=${js},script-update-interval=0` 119 | ); 120 | break; 121 | 122 | case "enabled=": 123 | z[y - 1]?.match(/^#/) && script.push(z[y - 1]); 124 | 125 | let cronExp = x.replace(/\x20{2,}/g," ").split(" http")[0].replace(/^#/,''); 126 | if (cronExp.match(",")){ 127 | cronExp = '"' + cronExp + '"'; 128 | }; 129 | 130 | let cronJs = x.split("://")[1].split(",")[0].replace(/(.+)/,'https://$1'); 131 | 132 | let croName = x.replace(/\x20/g,"").split("tag=")[1].split(",")[0]; 133 | 134 | script.push( 135 | `${noteK}${croName} = type=cron,script-path=${cronJs},timeout=60,cronexp=${cronExp},wake-system=1`); 136 | break; 137 | 138 | case "url reject-": 139 | 140 | z[y - 1]?.match(/^#/) && MapLocal.push(z[y - 1]); 141 | 142 | let dict2Mock = x.match(/dict$/) ? '"https://raw.githubusercontent.com/mieqq/mieqq/master/reject-dict.json"' : ''; 143 | 144 | let array2Mock = x.match(/array$/) ? '"https://raw.githubusercontent.com/mieqq/mieqq/master/reject-array.json"' : ''; 145 | 146 | let two002Mock = x.match(/200$/) ? '"https://raw.githubusercontent.com/mieqq/mieqq/master/reject-200.txt"' : ''; 147 | 148 | let img2Mock = x.match(/img$/) ? '"https://raw.githubusercontent.com/mieqq/mieqq/master/reject-img.gif"' : ''; 149 | 150 | MapLocal.push(x.replace(/\x20{2,}/g," ").replace(/(^#)?(.+?)\x20url\x20reject-.+/, `${noteK}$2 data=${dict2Mock}${array2Mock}${two002Mock}${img2Mock}`)); 151 | break; 152 | 153 | case " url reject": 154 | 155 | z[y - 1]?.match(/^#/) && URLRewrite.push(z[y - 1]); 156 | 157 | URLRewrite.push(x.replace(/\x20{2,}/g," ").replace(/(^#)?(.+?)\x20url\x20reject$/, `${noteK}$2 - reject`)); 158 | break; 159 | 160 | case "-header ": 161 | z[y - 1]?.match(/^#/) && script.push(z[y - 1]); 162 | 163 | let reHdType = x.match(' response-header ') ? 'response' : 'request'; 164 | 165 | let reHdPtn = x.replace(/\x20{2,}/g," ").split(" url re")[0].replace(/^#/,"").replace(/(.*,.*)/,'"$1"'); 166 | 167 | let reHdArg1 = x.split(" " + reHdType + "-header ")[1]; 168 | 169 | let reHdArg2 = x.split(" " + reHdType + "-header ")[2]; 170 | 171 | script.push(`${noteK}replaceHeader_${y} = type=http-${reHdType},pattern=${reHdPtn},script-path=https://raw.githubusercontent.com/xream/scripts/main/surge/modules/replace-header/index.js,argument="${reHdArg1}->${reHdArg2}"`) 172 | 173 | break; 174 | 175 | case " echo-response ": 176 | z[y - 1]?.match(/^#/) && MapLocal.push(z[y - 1]); 177 | 178 | let mockPtn = x.replace(/\x20{2,}/g," ").split(" url echo-response")[0].replace(/^#/,""); 179 | 180 | let dataCon = x.replace(/\x20{2,}/g," ").split(" echo-response ")[2]; 181 | 182 | MapLocal.push(`${noteK}${mockPtn} data="${dataCon}"`); 183 | 184 | break; 185 | 186 | case "hostname": 187 | MITM = x.replace(/%.*%/g,"").replace(/\x20/g,"").replace(/hostname=(.*)/, `[MITM]\n\nhostname = %APPEND% $1`); 188 | break; 189 | 190 | default: 191 | if (type.match("url ")) { 192 | z[y - 1]?.match(/^#/) && URLRewrite.push(z[y - 1]); 193 | URLRewrite.push(x.replace(/\x20{2,}/g," ").replace(/(^#)?(.*?)\x20url\x20(302|307)\x20(.+)/, `${noteK}$2 $4 $3`)); 194 | } else { 195 | 196 | z[y - 1]?.match(/^#/) && script.push(z[y - 1]); 197 | 198 | let reBdType = x.match(' response-body ') ? 'response' : 'request'; 199 | 200 | let reBdPtn = x.replace(/\x20{2,}/g," ").split(" url re")[0].replace(/^#/,"").replace(/(.*,.*)/,'"$1"'); 201 | 202 | let reBdArg1 = x.split(" " + reBdType + "-body ")[1]; 203 | 204 | let reBdArg2 = x.split(" " + reBdType + "-body ")[2]; 205 | 206 | script.push( 207 | 208 | `${noteK}replaceBody_${y} = type=http-${reBdType},pattern=${reBdPtn},requires-body=1,max-size=3145728,script-path=https://raw.githubusercontent.com/mieqq/mieqq/master/replace-body.js,argument="${reBdArg1}->${reBdArg2}"`, 209 | 210 | ); 211 | } 212 | } //switch结束 213 | } 214 | }); //循环结束 215 | 216 | script = (script[0] || '') && `[Script]\n\n${script.join("\n\n")}`; 217 | 218 | URLRewrite = (URLRewrite[0] || '') && `[URL Rewrite]\n\n${URLRewrite.join("\n")}`; 219 | 220 | MapLocal = (MapLocal[0] || '') && `[Map Local]\n\n${MapLocal.join("\n\n")}`; 221 | 222 | others = (others[0] || '') && `${others.join("\n\n")}`; 223 | 224 | body = `${name} 225 | ${desc} 226 | 227 | 228 | ${URLRewrite} 229 | 230 | 231 | ${script} 232 | 233 | 234 | ${MapLocal} 235 | 236 | 237 | ${MITM}` 238 | .replace(/t&zd;/g,',') 239 | .replace(/(#.+\n)\n+/g,'$1') 240 | .replace(/\n{2,}/g,'\n\n') 241 | 242 | if (isSurgeiOS || isStashiOS) { 243 | others !="" && $notification.post("不支持的类型已跳过","第" + others,"点击查看原文,长按可展开查看跳过行",{url:req}); 244 | } else {if (isLooniOS || isShadowrocket) { 245 | others !="" && $notification.post("不支持的类型已跳过","第" + others,"点击查看原文,长按可展开查看跳过行",req)}} 246 | 247 | $done({ response: { status: 200 ,body:body ,headers: {'Content-Type': 'text/plain; charset=utf-8'} } }); 248 | }//判断是否断网的反括号 249 | 250 | })() 251 | .catch((e) => { 252 | $notification.post(`${e}`,'',''); 253 | $done() 254 | }) 255 | 256 | function http(req) { 257 | return new Promise((resolve, reject) => 258 | $httpClient.get(req, (err, resp,data) => { 259 | resolve(data) 260 | }) 261 | ) 262 | } -------------------------------------------------------------------------------- /js/TFTinfo.js: -------------------------------------------------------------------------------- 1 | const $ = new Env("TFT-info"); 2 | 3 | titleCN = {"IRON":"坚韧黑铁","BRONZE":"英勇青铜","SILVER":"不屈白银","GOLD":"荣耀黄金","PLATINUM":"华贵铂金","EMERALD":"流光翡翠","DIAMOND":"璀璨钻石","MASTER":"超凡大师","GRANDMASTER":"傲世宗师","CHALLENGER":"最强王者"}; 4 | 5 | serveCN = {"br":"巴西","eune":"北欧东欧","euw":"欧洲西部","jp":"日本","kr":"韩国","lan":"拉丁美洲北部","las":"拉丁美洲南部","na":"北美","oce":"大洋洲","tr":"土耳其","ru":"俄罗斯","ph":"菲律宾","sg":"新加坡","th":"泰国","tw":"台湾","vn":"越南"} 6 | 7 | if (typeof $argument != undefined && $argument != ""){ 8 | region = $argument.split("region=")[1].split("&")[0]; 9 | name = $argument.split("name=")[1].split("&")[0]; 10 | season = $argument.split("set=")[1].split("&")[0]; 11 | }; 12 | 13 | let reStatus = /("retry_after":1000|"done":true)/; 14 | 15 | let refreshUrl = `https://lolchess.gg/api/v1/profile/sync/by-name/${region}/${name}` 16 | 17 | let url = `https://lolchess.gg/profile/${region}/${name}/set${season}` 18 | 19 | !(async () => { 20 | 21 | let refreshBody = (await $.http.get(refreshUrl))['body']; 22 | 23 | if (reStatus.test(refreshBody)){ 24 | 25 | h = $.toObj((await $.http.get(url))['body'].split('type="application/json">')[1].split('')[0]); 26 | 27 | data = $.lodash_get(h, 'props.pageProps.dehydratedState.queries.0.state.data.summonerLeagues') 28 | 29 | lp = $.lodash_get(data, '0.leaguePoints');//胜点 30 | tier = $.lodash_get(data, '0.tier');//分段 31 | rank = $.lodash_get(data, '0.rank');//段位 32 | plays = $.lodash_get(data, '0.plays');//总场次 33 | wins = $.lodash_get(data, '0.wins');//吃鸡数 34 | tops = $.lodash_get(data, '0.tops');//前四数 35 | tierRating = $.lodash_get(data, '0.rating.tier.rank');//服务器总排名 36 | avgPlacement = $.lodash_get(data, '0.avgPlacement');//最近十局平均排名 37 | winRate = (wins/plays*100).toFixed(1) + "%";;//吃鸡率 38 | top4Rate = (tops/plays*100).toFixed(1) + "%";//前四率 39 | 40 | if (tier == "GRANDMASTER" || tier == "CHALLENGER"){rank = ""}; 41 | 42 | 43 | }else{ 44 | $.msg("TFT信息查询","弈士ID/大区填写错误","") 45 | }; 46 | 47 | tier = titleCN[tier]; 48 | region = serveCN[region]; 49 | $done({ 50 | title: `${name} S${season} 排名:${tierRating}`, 51 | content: `段位:${tier} ${rank} ${lp}胜点 52 | 大区:${region} 总场次:${plays} 53 | 吃鸡率:${winRate} 吃鸡数:${wins} 54 | 前四率:${top4Rate} 前四数:${tops}`, 55 | icon: "gamecontroller" 56 | 57 | }); 58 | 59 | })() 60 | .catch((e) => { 61 | $.msg(`TFT信息查询`,`${e}`,'',''); 62 | 63 | } 64 | ) 65 | 66 | function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,a)=>{s.call(this,t,(t,s,r)=>{t?a(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.encoding="utf-8",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`🔔${this.name}, 开始!`)}getEnv(){return"undefined"!=typeof $environment&&$environment["surge-version"]?"Surge":"undefined"!=typeof $environment&&$environment["stash-version"]?"Stash":"undefined"!=typeof module&&module.exports?"Node.js":"undefined"!=typeof $task?"Quantumult X":"undefined"!=typeof $loon?"Loon":"undefined"!=typeof $rocket?"Shadowrocket":void 0}isNode(){return"Node.js"===this.getEnv()}isQuanX(){return"Quantumult X"===this.getEnv()}isSurge(){return"Surge"===this.getEnv()}isLoon(){return"Loon"===this.getEnv()}isShadowrocket(){return"Shadowrocket"===this.getEnv()}isStash(){return"Stash"===this.getEnv()}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const a=this.getdata(t);if(a)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,a)=>e(a))})}runScript(t,e){return new Promise(s=>{let a=this.getdata("@chavy_boxjs_userCfgs.httpapi");a=a?a.replace(/\n/g,"").trim():a;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[i,o]=a.split("@"),n={url:`http://${o}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":i,Accept:"*/*"},timeout:r};this.post(n,(t,e,a)=>s(a))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),a=!s&&this.fs.existsSync(e);if(!s&&!a)return{};{const a=s?t:e;try{return JSON.parse(this.fs.readFileSync(a))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),a=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):a?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const a=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of a)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,a)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[a+1])>>0==+e[a+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,a]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,a,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,a,r]=/^@(.*?)\.(.*?)$/.exec(e),i=this.getval(a),o=a?"null"===i?null:i||"{}":"{}";try{const e=JSON.parse(o);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),a)}catch(e){const i={};this.lodash_set(i,r,t),s=this.setval(JSON.stringify(i),a)}}else s=this.setval(t,e);return s}getval(t){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":return $persistentStore.read(t);case"Quantumult X":return $prefs.valueForKey(t);case"Node.js":return this.data=this.loaddata(),this.data[t];default:return this.data&&this.data[t]||null}}setval(t,e){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":return $persistentStore.write(t,e);case"Quantumult X":return $prefs.setValueForKey(t,e);case"Node.js":return this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0;default:return this.data&&this.data[e]||null}}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){switch(t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"],delete t.headers["content-type"],delete t.headers["content-length"]),t.params&&(t.url+="?"+this.queryStr(t.params)),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,a)=>{!t&&s&&(s.body=a,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,a)});break;case"Quantumult X":this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:a,headers:r,body:i,bodyBytes:o}=t;e(null,{status:s,statusCode:a,headers:r,body:i,bodyBytes:o},i,o)},t=>e(t&&t.error||"UndefinedError"));break;case"Node.js":let s=require("iconv-lite");this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:a,statusCode:r,headers:i,rawBody:o}=t,n=s.decode(o,this.encoding);e(null,{status:a,statusCode:r,headers:i,rawBody:o,body:n},n)},t=>{const{message:a,response:r}=t;e(a,r,r&&s.decode(r.rawBody,this.encoding))})}}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";switch(t.body&&t.headers&&!t.headers["Content-Type"]&&!t.headers["content-type"]&&(t.headers["content-type"]="application/x-www-form-urlencoded"),t.headers&&(delete t.headers["Content-Length"],delete t.headers["content-length"]),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,(t,s,a)=>{!t&&s&&(s.body=a,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,a)});break;case"Quantumult X":t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:a,headers:r,body:i,bodyBytes:o}=t;e(null,{status:s,statusCode:a,headers:r,body:i,bodyBytes:o},i,o)},t=>e(t&&t.error||"UndefinedError"));break;case"Node.js":let a=require("iconv-lite");this.initGotEnv(t);const{url:r,...i}=t;this.got[s](r,i).then(t=>{const{statusCode:s,statusCode:r,headers:i,rawBody:o}=t,n=a.decode(o,this.encoding);e(null,{status:s,statusCode:r,headers:i,rawBody:o,body:n},n)},t=>{const{message:s,response:r}=t;e(s,r,r&&a.decode(r.rawBody,this.encoding))})}}time(t,e=null){const s=e?new Date(e):new Date;let a={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in a)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?a[e]:("00"+a[e]).substr((""+a[e]).length)));return t}queryStr(t){let e="";for(const s in t){let a=t[s];null!=a&&""!==a&&("object"==typeof a&&(a=JSON.stringify(a)),e+=`${s}=${a}&`)}return e=e.substring(0,e.length-1),e}msg(e=t,s="",a="",r){const i=t=>{switch(typeof t){case void 0:return t;case"string":switch(this.getEnv()){case"Surge":case"Stash":default:return{url:t};case"Loon":case"Shadowrocket":return t;case"Quantumult X":return{"open-url":t};case"Node.js":return}case"object":switch(this.getEnv()){case"Surge":case"Stash":case"Shadowrocket":default:{let e=t.url||t.openUrl||t["open-url"];return{url:e}}case"Loon":{let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}case"Quantumult X":{let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl,a=t["update-pasteboard"]||t.updatePasteboard;return{"open-url":e,"media-url":s,"update-pasteboard":a}}case"Node.js":return}default:return}};if(!this.isMute)switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:$notification.post(e,s,a,i(r));break;case"Quantumult X":$notify(e,s,a,i(r));break;case"Node.js":}if(!this.isMuteLog){let t=["","==============📣系统通知📣=============="];t.push(e),s&&t.push(s),a&&t.push(a),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Quantumult X":default:this.log("",`❗️${this.name}, 错误!`,t);break;case"Node.js":this.log("",`❗️${this.name}, 错误!`,t.stack)}}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;switch(this.log("",`🔔${this.name}, 结束! 🕛 ${s} 秒`),this.log(),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Quantumult X":default:$done(t);break;case"Node.js":process.exit(1)}}}(t,e)} -------------------------------------------------------------------------------- /js/xianxing.js: -------------------------------------------------------------------------------- 1 | /************************* 2 | #!name=限行查询 3 | #!desc=车辆限行信息 4 | 5 | #city缩写可前往 http://m.xy.bendibao.com/news/xianxingchaxun/city.php 查看 6 | 7 | 8 | [Panel] 9 | 10 | 车辆限行Panel = script-name=xianxing, update-interval=3600 11 | 12 | [Script] 13 | 14 | # Panel 15 | xianxing = type=generic, script-path=https://raw.githubusercontent.com/chengkongyiban/Surge/main/js/xianxing.js, timeout=60, argument=city=bj&cartype=燃油车&loo=本地车&displayxxregion=false 16 | 17 | 限行 = type=cron,script-path=https://raw.githubusercontent.com/chengkongyiban/Surge/main/js/xianxing.js,cronexp="0 7 * * *",timeout=10,script-update-interval=0,argument=city=bj&cartype=燃油车&loo=本地车&displayxxregion=false 18 | 19 | **************************/ 20 | 21 | const $ = new Env("限行查询"); 22 | 23 | var city = 'bj'; 24 | var cartype = encodeURIComponent('燃油车'); 25 | var loo = '本地车'; 26 | var displayxxregion = false; 27 | 28 | if (typeof $argument !== 'undefined' && $argument !== '') { 29 | city = $argument.split('city=')[1].split('&')[0]; 30 | cartype = encodeURIComponent($argument.split('cartype=')[1].split('&')[0]); 31 | loo = /外地车/.test($argument) ? '外地车' : loo; 32 | displayxxregion = /displayxxregion=/.test($argument) ? istrue($argument.split('displayxxregion=')[1].split('&')[0]) : false; 33 | }; 34 | 35 | let url = `http://m.${city}.bendibao.com/news/xianxingchaxun/index.php?category=${cartype}`; 36 | 37 | url = city == 'sz' ? 'http://m.bendibao.com/news/xianxingchaxun/' : url; 38 | 39 | !(async () => { 40 | 41 | let xxd = (await $.http.get(url))['body']; 42 | 43 | const cityCN = xxd.match(/.+?<\/title>/)[0].split(/<title>/)[1].split('限行规定')[0]; 44 | 45 | const localxxd = /<div class="content" style="display: none;">/.test(xxd) ? xxd.split('<div class="content" style="display: none;">')[0] : xxd; 46 | 47 | const otherxxd = /<div class="content" style="display: none;">/.test(xxd) ?xxd.split('<div class="content" style="display: none;">')[1] : xxd; 48 | 49 | xxd = loo == '本地车' ? localxxd : otherxxd; 50 | 51 | const reg_xxtoday = /<div class="days twenty-six font">今日限行<\/div>[\s\S]*?<div class="date twenty-two">(.+?)<\/div>[\s\S]*?<div class="rule thirty-four font-nine">(.+?)<\/div>/; 52 | 53 | const reg_xxtomorrow = /<div class="days twenty-six font">明日限行<\/div>[\s\S]*?<div class="date twenty-two">(.+?)<\/div>[\s\S]*?<div class="rule thirty-four font-nine">(.+?)<\/div>/; 54 | 55 | const reg_xxdate = /<div class="three twenty-eight">限行时间<\/div>[\s\S]*?<div class="limit-local xianxing-content">/; 56 | 57 | const reg_xxregion = /<div class="three twenty-eight">限行区域<\/div>[\s\S]+<div class="limit-rule xianxing-content">/; 58 | 59 | let xxtodaydate = reg_xxtoday.test(xxd) ? xxd.match(reg_xxtoday)[1] : ''; 60 | 61 | let xxtomorrowdate = reg_xxtoday.test(xxd) ? xxd.match(reg_xxtomorrow)[1] : ''; 62 | 63 | let xxtodaynum = reg_xxtoday.test(xxd) ? xxd.match(reg_xxtoday)[2] : '不限行或不是按尾号限行'; 64 | 65 | let xxtomorrownum = reg_xxtoday.test(xxd) ? xxd.match(reg_xxtomorrow)[2] : '不限行或不是按尾号限行'; 66 | 67 | let xxdate = reg_xxdate.test(xxd) ? a(xxd.match(reg_xxdate)[0].split(/<\/div>\s*<\/div>[\s\S]+?<div class="cicle-text">/)).join('\n') : '未获取到限行时间'; 68 | 69 | let xxregion = displayxxregion == true && reg_xxregion.test(xxd) ? a(xxd.match(reg_xxregion)[0].split(/<\/div>\s*<\/div>[\s\S]+?<div class="cicle-text">/)).join('\n') : ''; 70 | 71 | function a (arr) { 72 | for (let i=0; i < arr.length; i++) { 73 | arr[i] = arr[i].replace(/<div class="three twenty-eight">(.+)/,'$1: ↓↓↓').replace(/<\/div>\s+<\/div>[\s\S]+?<div class=".+xianxing-content">/,'').trim(); 74 | } 75 | return arr 76 | };//for 77 | 78 | cartype = decodeURIComponent(cartype); 79 | 80 | ($.isSurge() || $.isShadowrocket() || $.isStash()) && $script.type == 'cron' && $.msg(`${cityCN}限行信息 ${cartype} ${loo}`,`今日限行: ${xxtodaydate} ${xxtodaynum} 81 | 明日限行: ${xxtomorrowdate} ${xxtomorrownum}`,`${xxdate} 82 | ${xxregion} 83 | 详细限行规则请前往本地宝/点击通知查看`,{url:url}); 84 | 85 | ($.isLoon() || $.isQuanX()) && $.msg(`${cityCN}限行信息 ${cartype} ${loo}`,`今日限行: ${xxtodaydate} ${xxtodaynum} 86 | 明日限行: ${xxtomorrowdate} ${xxtomorrownum}`,`${xxdate} 87 | ${xxregion} 88 | 详细限行规则请前往本地宝/点击通知查看`,{url:url}); 89 | 90 | $.done({ 91 | title: `${cityCN}限行信息 ${cartype} ${loo}`, 92 | content: `今日限行: ${xxtodaydate} ${xxtodaynum} 93 | 明日限行: ${xxtomorrowdate} ${xxtomorrownum} 94 | ${xxdate} 95 | ${xxregion} 96 | 详细限行规则请前往本地宝/点击通知查看`, 97 | icon: "car" 98 | 99 | }); 100 | 101 | })() 102 | .catch((e) => { 103 | /xxd\.match/.test(e) && $.msg(`限行查询`,`请正确填写城市首字母缩写`,`${e}`,''); 104 | $.msg(`限行查询`,`${e}`,``,''); 105 | 106 | } 107 | ) 108 | 109 | function istrue(str) { 110 | if (str == true || str == 1 || str == "true"|| str == "1"){ 111 | return true; 112 | }else{return false;} 113 | }; 114 | 115 | function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,a)=>{s.call(this,t,(t,s,r)=>{t?a(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.encoding="utf-8",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`🔔${this.name}, 开始!`)}getEnv(){return"undefined"!=typeof $environment&&$environment["surge-version"]?"Surge":"undefined"!=typeof $environment&&$environment["stash-version"]?"Stash":"undefined"!=typeof module&&module.exports?"Node.js":"undefined"!=typeof $task?"Quantumult X":"undefined"!=typeof $loon?"Loon":"undefined"!=typeof $rocket?"Shadowrocket":void 0}isNode(){return"Node.js"===this.getEnv()}isQuanX(){return"Quantumult X"===this.getEnv()}isSurge(){return"Surge"===this.getEnv()}isLoon(){return"Loon"===this.getEnv()}isShadowrocket(){return"Shadowrocket"===this.getEnv()}isStash(){return"Stash"===this.getEnv()}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const a=this.getdata(t);if(a)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,a)=>e(a))})}runScript(t,e){return new Promise(s=>{let a=this.getdata("@chavy_boxjs_userCfgs.httpapi");a=a?a.replace(/\n/g,"").trim():a;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[i,o]=a.split("@"),n={url:`http://${o}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":i,Accept:"*/*"},timeout:r};this.post(n,(t,e,a)=>s(a))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),a=!s&&this.fs.existsSync(e);if(!s&&!a)return{};{const a=s?t:e;try{return JSON.parse(this.fs.readFileSync(a))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),a=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):a?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const a=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of a)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,a)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[a+1])>>0==+e[a+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,a]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,a,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,a,r]=/^@(.*?)\.(.*?)$/.exec(e),i=this.getval(a),o=a?"null"===i?null:i||"{}":"{}";try{const e=JSON.parse(o);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),a)}catch(e){const i={};this.lodash_set(i,r,t),s=this.setval(JSON.stringify(i),a)}}else s=this.setval(t,e);return s}getval(t){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":return $persistentStore.read(t);case"Quantumult X":return $prefs.valueForKey(t);case"Node.js":return this.data=this.loaddata(),this.data[t];default:return this.data&&this.data[t]||null}}setval(t,e){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":return $persistentStore.write(t,e);case"Quantumult X":return $prefs.setValueForKey(t,e);case"Node.js":return this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0;default:return this.data&&this.data[e]||null}}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){switch(t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"],delete t.headers["content-type"],delete t.headers["content-length"]),t.params&&(t.url+="?"+this.queryStr(t.params)),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,a)=>{!t&&s&&(s.body=a,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,a)});break;case"Quantumult X":this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:a,headers:r,body:i,bodyBytes:o}=t;e(null,{status:s,statusCode:a,headers:r,body:i,bodyBytes:o},i,o)},t=>e(t&&t.error||"UndefinedError"));break;case"Node.js":let s=require("iconv-lite");this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:a,statusCode:r,headers:i,rawBody:o}=t,n=s.decode(o,this.encoding);e(null,{status:a,statusCode:r,headers:i,rawBody:o,body:n},n)},t=>{const{message:a,response:r}=t;e(a,r,r&&s.decode(r.rawBody,this.encoding))})}}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";switch(t.body&&t.headers&&!t.headers["Content-Type"]&&!t.headers["content-type"]&&(t.headers["content-type"]="application/x-www-form-urlencoded"),t.headers&&(delete t.headers["Content-Length"],delete t.headers["content-length"]),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,(t,s,a)=>{!t&&s&&(s.body=a,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,a)});break;case"Quantumult X":t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:a,headers:r,body:i,bodyBytes:o}=t;e(null,{status:s,statusCode:a,headers:r,body:i,bodyBytes:o},i,o)},t=>e(t&&t.error||"UndefinedError"));break;case"Node.js":let a=require("iconv-lite");this.initGotEnv(t);const{url:r,...i}=t;this.got[s](r,i).then(t=>{const{statusCode:s,statusCode:r,headers:i,rawBody:o}=t,n=a.decode(o,this.encoding);e(null,{status:s,statusCode:r,headers:i,rawBody:o,body:n},n)},t=>{const{message:s,response:r}=t;e(s,r,r&&a.decode(r.rawBody,this.encoding))})}}time(t,e=null){const s=e?new Date(e):new Date;let a={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in a)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?a[e]:("00"+a[e]).substr((""+a[e]).length)));return t}queryStr(t){let e="";for(const s in t){let a=t[s];null!=a&&""!==a&&("object"==typeof a&&(a=JSON.stringify(a)),e+=`${s}=${a}&`)}return e=e.substring(0,e.length-1),e}msg(e=t,s="",a="",r){const i=t=>{switch(typeof t){case void 0:return t;case"string":switch(this.getEnv()){case"Surge":case"Stash":default:return{url:t};case"Loon":case"Shadowrocket":return t;case"Quantumult X":return{"open-url":t};case"Node.js":return}case"object":switch(this.getEnv()){case"Surge":case"Stash":case"Shadowrocket":default:{let e=t.url||t.openUrl||t["open-url"];return{url:e}}case"Loon":{let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}case"Quantumult X":{let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl,a=t["update-pasteboard"]||t.updatePasteboard;return{"open-url":e,"media-url":s,"update-pasteboard":a}}case"Node.js":return}default:return}};if(!this.isMute)switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:$notification.post(e,s,a,i(r));break;case"Quantumult X":$notify(e,s,a,i(r));break;case"Node.js":}if(!this.isMuteLog){let t=["","==============📣系统通知📣=============="];t.push(e),s&&t.push(s),a&&t.push(a),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Quantumult X":default:this.log("",`❗️${this.name}, 错误!`,t);break;case"Node.js":this.log("",`❗️${this.name}, 错误!`,t.stack)}}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;switch(this.log("",`🔔${this.name}, 结束! 🕛 ${s} 秒`),this.log(),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Quantumult X":default:$done(t);break;case"Node.js":process.exit(1)}}}(t,e)} -------------------------------------------------------------------------------- /modules/QX_to_Surge.sgmodule: -------------------------------------------------------------------------------- 1 | #!name=QX重写&规则集转化 2 | #!desc=现在默认缓存时间为1小时,可使用参数cachexp=修改缓存时间,单位:小时。使用方法在QX重写链接末尾面加上qx,在loon插件链接末尾加上loon,在Surge模块链接末尾加sg, 在规则集链接末尾加上r_parser.list 3 | #!author=@小白脸 4 | #!使用手册https://github.com/chengkongyiban/stash/tree/main/Rewrite_Parser_Wiki 5 | #!问题反馈https://t.me/zhangpeifu 6 | 7 | [Script] 8 | 9 | QX转换 = type=http-request,pattern=^https?:\/\/.+\/[^/]+\.[^/]+(qx$|qx\?.+=),requires-body=1,max-size=0,script-path=https://github.com/chengkongyiban/stash/raw/main/js/QX_Rewrite_Parser.js ,timeout=60 10 | 11 | Loon插件转换 = type=http-request, pattern=^https?:\/\/.+\/[^/]+\.[^/]+(loon$|loon\?.+=), requires-body=1, max-size=0, script-path=https://github.com/chengkongyiban/stash/raw/main/js/Loon_Rewrite_Parser.js ,timeout=60 12 | 13 | #对Surge/小火箭模块使用 可自动修正笔误的reject类型,并支持使用参数。 14 | 模块控制器 = type=http-request,pattern=^https?:\/\/.+\/[^/]+\.[^/]+[^Ttm](sg$|sg\?.+=),requires-body=1,max-size=0,script-path=https://raw.githubusercontent.com/chengkongyiban/stash/main/js/Surge_Rewrite_Parser.js, timeout=60 15 | 16 | 规则集转换 = type=http-request,pattern=r_parser.list$|r_parser.list\?.*,requires-body=1,max-size=0,script-path=https://raw.githubusercontent.com/chengkongyiban/stash/main/js/rule_parser.js ,timeout=60 17 | 18 | 脚本转换 = type=http-request,pattern=_script-converter-(stash|surge|loon|shadowrocket)\.js$,requires-body=1,max-size=0,script-path=https://raw.githubusercontent.com/xream/scripts/main/surge/modules/script-converter/script-converter.js, time=60 19 | 20 | 脚本转换2 = type=http-request,pattern=_script-converter-(STASH|SURGE|LOON|SHADOWROCKET)\.js$,requires-body=1,max-size=0,script-path=https://raw.githubusercontent.com/xream/scripts/main/surge/modules/script-converter/script-converter.js, timeout=60, argument="wrap_response=true" 21 | 22 | [MITM] 23 | hostname = %APPEND% github.com, raw.githubusercontent.com,gist.githubusercontent.com,gitlab.com,yfamily.ml 24 | -------------------------------------------------------------------------------- /modules/TFTinfo.sgmodule: -------------------------------------------------------------------------------- 1 | #!name=TFT信息查询 2 | #!desc=TFT外区信息概览 3 | #在argument填写弈士id,大区,赛季即可 4 | 5 | [Script] 6 | # Panel 7 | TFT-info = type=generic,timeout=60,script-path=https://raw.githubusercontent.com/chengkongyiban/Surge/main/js/TFTinfo.js,argument="name=xxx®ion=xxx&set=9.5" 8 | 9 | [Panel] 10 | TFT-info = script-name=TFT-info,update-interval=3600 11 | -------------------------------------------------------------------------------- /modules/WeiboLite.plugin: -------------------------------------------------------------------------------- 1 | #!name=微博Lite 2 | #!desc=微博轻享版去广告 3 | #需重装微博轻享版 4 | #搬运自@ddgksf2013 5 | [Rule] 6 | 7 | #广告联盟,去开屏广告 8 | RULE-SET,https://raw.githubusercontent.com/chengkongyiban/myself-rule-set/main/WeiboLiteAds.list,REJECT-TINYGIF 9 | 10 | [Script] 11 | 12 | # > 微博国际版_屏蔽开屏广告@ddgksf2013 13 | weibo_json = type=http-response,pattern=^https?:\/\/weibointl\.api\.weibo\.c(n|om)\/portal\.php.*get_coopen_ads,requires-body=1,max-size=0,script-path=https://github.com/ddgksf2013/Scripts/raw/master/weibo_json.js 14 | # > 微博&国际版_sdkad@ddgksf2013 15 | weibo_json = type=http-response,pattern=^https?://(sdk|wb)app\.uve\.weibo\.com(/interface/sdk/sdkad.php|/wbapplua/wbpullad.lua),requires-body=1,max-size=0,script-path=https://github.com/ddgksf2013/Scripts/raw/master/weibo_json.js 16 | # > 微博国际版_趋势顶部CARD去广告@ddgksf2013 17 | weibo_json = type=http-response,pattern=^https?:\/\/weibointl\.api\.weibo\.c(n|om)\/portal\.php.*feed&a=trends,requires-body=1,max-size=0,script-path=https://github.com/ddgksf2013/Scripts/raw/master/weibo_json.js 18 | # ~ WeiboLite_微博国际版_用户中心@ddgksf2013 19 | weibo_json = type=http-response,pattern=^https?:\/\/weibointl\.api\.weibo\.cn\/portal\.php\?a=user_center,requires-body=1,max-size=0,script-path=https://raw.githubusercontent.com/chengkongyiban/shadowrocket/main/scripts/weibo_json.js 20 | 21 | [Map Local] 22 | 23 | # > 微博国际版_hot_search@ddgksf2013 24 | ^https?:\/\/weibointl\.api\.weibo\.c(n|om)\/portal\.php\?a=hot_search_users data="https://raw.githubusercontent.com/Keywos/Rule/main/mocks/reject-dict.json" 25 | # > 微博国际版_热推荐@ddgksf2013 26 | ^https?:\/\/m?api\.weibo\.c(n|om)\/\d\/ad\/weibointl\? data="https://raw.githubusercontent.com/Keywos/Rule/main/mocks/reject-dict.json" 27 | # > 微博国际版_屏蔽search_suggest@ddgksf2013 28 | # ^https?:\/\/m?api\.weibo\.c(n|om)\/\d\/page\/get_search_suggest data="https://raw.githubusercontent.com/Keywos/Rule/main/mocks/reject-dict.json" 29 | # > 微博国际版_屏蔽searching_info@ddgksf2013 30 | ^https?:\/\/weibointl\.api\.weibo\.c(n|om)\/portal\.php.*user&a=get_searching_info data="https://github.com/ddgksf2013/Scripts/raw/master/weibo_search_info.json" 31 | # > 微博国际版_屏蔽search_topic@ddgksf2013 32 | ^https?:\/\/weibointl\.api\.weibo\.c(n|om)\/portal\.php.*feed&a=search_topic data="https://github.com/ddgksf2013/Scripts/raw/master/weibo_search_topic.json" 33 | 34 | [MITM] 35 | 36 | hostname = %APPEND% *api.weibo*, *uve.weibo.com, new.vip.weibo.cn 37 | -------------------------------------------------------------------------------- /modules/bilibili.sgmodule: -------------------------------------------------------------------------------- 1 | #!name=哔哩哔哩 2 | #!desc=哔哩哔哩功能整合 3 | # ==UserScript== 4 | # @ScriptName BiliBili_AdBlock_DIY 5 | # @Author @ddgksf2013, @blackmatrix7, @app2smile, @yjqiang 6 | //B站解锁普通视频高码率仅适用国区粉色APP,外区为自我安慰 7 | 8 | [MITM] 9 | hostname = %APPEND% *.hdslb.com,app.bilibili.com,api.live.bilibili.com,api.vc.bilibili.com,api.bilibili.com,manga.bilibili.com,grpc.biliapi.net,api.biliapi.net,-broadcast.chat.bilibili.com,-*cdn*.biliapi.net,-*tracker*.biliapi.net,upos-hz-mirrorakam.akamaized.net 10 | 11 | [URL Rewrite] 12 | 13 | #UPOS服务器替换为腾讯Cos对象存储 14 | ^https?:\/\/upos-hz-mirrorakam\.akamaized\.net\/(.*) https://upos-sz-mirrorcos.bilivideo.com/$1 302 15 | # ~ BiliBili_哔哩哔哩_屏蔽IP请求@ddgksf2013 16 | ^https?:\/\/app\.bilibili\.com\/x\/resource\/ip - reject 17 | # ~ BiliBili_哔哩哔哩_屏蔽DefaultWord@ddgksf2013 18 | ^https?:\/\/(app\.bilibili\.com|grpc\.biliapi\.net)\/bilibili\.app\.interface\.v1\.Search\/Default - reject 19 | 20 | [Map Local] 21 | 22 | # ~ BiliBili_哔哩哔哩_屏蔽广告浮窗@ddgksf2013 23 | ^https?:\/\/api\.bilibili\.com\/pgc\/activity\/deliver\/material\/receive data="https://raw.githubusercontent.com/mieqq/mieqq/master/reject-dict.json" 24 | 25 | # ~ BiliBili_哔哩哔哩_应用开屏去广告@bm7 26 | ^https://app.bilibili.com/x/v2/splash/show data="https://raw.githubusercontent.com/mieqq/mieqq/master/reject-dict.json" 27 | 28 | # ~ BiliBili_哔哩哔哩_Defaultword@ddgksf2013 29 | ^https://app.bilibili.com/x/v2/search/defaultwords data="https://raw.githubusercontent.com/mieqq/mieqq/master/reject-dict.json" 30 | 31 | # ~ BiliBili_哔哩哔哩_Material_Ad@ddgksf2013 32 | ^https?:\/\/api\.bilibili\.com\/x\/vip\/ads\/material\/report data="https://raw.githubusercontent.com/mieqq/mieqq/master/reject-dict.json" 33 | 34 | # ~ BiliBili_哔哩哔哩_小卡片广告@ddgksf2013 35 | ^https://api.bilibili.com/pgc/season/player/cards data="https://raw.githubusercontent.com/mieqq/mieqq/master/reject-dict.json" 36 | 37 | # ~ BiliBili_哔哩哔哩_漫画去广告@ddgksf2013 38 | ^https?:\/\/manga\.bilibili\.com\/twirp\/comic\.v\d\.Comic\/(Flash|ListFlash|GetActivityTab) data="https://raw.githubusercontent.com/mieqq/mieqq/master/reject-dict.json" 39 | 40 | [Script] 41 | 42 | # ~ BiliBili_哔哩哔哩_屏蔽首页右上活动@ddgksf2013 43 | bilibili_json = type=http-response,pattern=^https?:\/\/app\.bilibili\.com\/x\/resource\/top\/activity,requires-body=1,max-size=3145728,script-path=https://github.com/ddgksf2013/Scripts/raw/master/bilibili_json.js,script-update-interval=0 44 | 45 | # ~ BiliBili_哔哩哔哩_观影页面去广告@ddgksf2013 46 | bilibili_json = type=http-response,pattern=^https?:\/\/api\.(bilibili|biliapi)\.(com|net)\/pgc\/page\/cinema\/tab\?,requires-body=1,max-size=3145728,script-path=https://github.com/ddgksf2013/Scripts/raw/master/bilibili_json.js,script-update-interval=0 47 | 48 | # ~ BiliBili_哔哩哔哩_应用开屏广告预加载@yjqiang 49 | bilibili_json = type=http-response,pattern=^https:\/\/app\.bilibili\.com\/x\/v2\/splash\/list,requires-body=1,max-size=3145728,script-path=https://github.com/ddgksf2013/Scripts/raw/master/bilibili_json.js,script-update-interval=0 50 | 51 | #魔改皮肤脚本自带解锁4k,和我的页面处理功能,自行选择 52 | 53 | # ~ BiliBili_哔哩哔哩_我的页面处理@ddgksf2013 54 | #bilibili_json = type=http-response,pattern=^https?:\/\/app\.bilibili\.com\/x\/v2\/account\/mine,requires-body=1,max-size=3145728,script-path=https://github.com/ddgksf2013/Scripts/raw/master/bilibili_json.js,script-update-interval=0 55 | 56 | # ~ BiliBili_哔哩哔哩_1080P高码率+4K画质(番剧和影视除外)@ddgksf2013 57 | #bilibili_json = type=http-response,pattern=^https?:\/\/app\.bilibili\.com\/x\/v2\/account\/myinfo\?,requires-body=1,max-size=3145728,script-path=https://github.com/ddgksf2013/Scripts/raw/master/bilibili_json.js,script-update-interval=0 58 | 59 | #魔改皮肤 作者@ClydeTime 60 | 魔改皮肤 = type=http-response,requires-body=1,max-size=3145728,timeout=60,pattern=^https?:\/\/ap(i|p)\.bilibili\.com\/x\/(vip|v2|resource)\/(space|account|web|price|top_panel_info|show)(\/|\?)(mine|myinfo|access|vip_center|panel|_bridge|skin\?).*,script-path=https://raw.githubusercontent.com/ClydeTime/Quantumult/main/Script/BiliBili/bili_info.js 61 | 62 | # ~ BiliBili_哔哩哔哩_热搜发现@ddgksf2013 63 | bilibili_json = type=http-response,pattern=^https://app.bilibili.com/x/v2/search/square,requires-body=1,max-size=3145728,script-path=https://github.com/ddgksf2013/Scripts/raw/master/bilibili_json.js,script-update-interval=0 64 | 65 | # ~ BiliBili_哔哩哔哩_推荐去广告@ddgksf2013 66 | bilibili_json = type=http-response,pattern=^https?:\/\/app\.bilibili\.com\/x\/v2\/feed\/index,requires-body=1,max-size=3145728,script-path=https://github.com/ddgksf2013/Scripts/raw/master/bilibili_json.js,script-update-interval=0 67 | 68 | # ~ BiliBili_哔哩哔哩_追番去广告@ddgksf2013 69 | bilibili_json = type=http-response,pattern=^https?:\/\/api\.(bilibili|biliapi)\.(com|net)\/pgc\/page\/bangumi,requires-body=1,max-size=3145728,script-path=https://github.com/ddgksf2013/Scripts/raw/master/bilibili_json.js,script-update-interval=0 70 | 71 | # ~ BiliBili_哔哩哔哩_直播去广告@bm7 72 | bilibili_json = type=http-response,pattern=^https?:\/\/api\.live\.bilibili\.com\/xlive\/app-room\/v1\/index\/getInfoByRoom,requires-body=1,max-size=3145728,script-path=https://github.com/ddgksf2013/Scripts/raw/master/bilibili_json.js,script-update-interval=0 73 | 74 | # ~ BiliBili_哔哩哔哩_标签页处理@ddgksf2013 75 | bilibili_json = type=http-response,pattern=^https?:\/\/app\.bilibili\.com\/x\/resource\/show\/tab,requires-body=1,max-size=3145728,script-path=https://github.com/ddgksf2013/Scripts/raw/master/bilibili_json.js,script-update-interval=0 76 | 77 | # ~ BiliBili_哔哩哔哩_Proto去广告@app2smile 78 | bilibili_proto = type=http-response,pattern=^https:\/\/app\.bilibili\.com\/bilibili\.app\.(view\.v1\.View\/View|dynamic\.v2\.Dynamic\/DynAll|playurl\.v1\.PlayURL\/PlayView)$,requires-body=1,max-size=3145728,binary-body-mode=1,script-path=https://github.com/ddgksf2013/Scripts/raw/master/bilibili_proto.js,script-update-interval=0 79 | 80 | # ~ BiliBili_哔哩哔哩_繁体CC字幕转中文简体@ddgksf2013 81 | bilibili_cc = type=http-response,pattern=^https?:\/\/i.\.hdslb\.com\/bfs\/subtitle\/.+\.json$,requires-body=1,max-size=3145728,script-path=https://github.com/ddgksf2013/Scripts/raw/master/bilibili_cc.js,script-update-interval=0 82 | 83 | #以下切区脚本仅国际版B站有效,需设置分流和策略组,教程链接https://t.me/weltyfjd/4 请看完教程再考虑是否启用 84 | 85 | #B站切区 作者@Nobyda 86 | #Bili Region = type=http-response,pattern=^https:\/\/ap(p|i)\.bili(bili|api)\.(com|net)\/(pgc\/view\/v\d\/app\/season|x\/offline\/version)\?,requires-body=1,max-size=3145728,timeout=60,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Bili_Auto_Regions.js 87 | #可选, 适用于搜索指定地区的番剧 作者@Nobyda 88 | #Bili Search = type=http-request,timeout=60,pattern=^https:\/\/ap(p|i)\.bili(bili|api)\.(com|net)\/x\/v\d\/search(\/type)?\?.+?%20(%E6%B8%AF|%E5%8F%B0|%E4%B8%AD)&,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Bili_Auto_Regions.js 89 | -------------------------------------------------------------------------------- /modules/pr.sgmodule: -------------------------------------------------------------------------------- 1 | #!name=允许访问私有库 2 | #!desc=需自行替换用户名,和token,token获取方法请谷歌 3 | #!author=@xream 4 | 5 | [Header Rewrite] 6 | 7 | http-request ^https?:\/\/(raw|gist)\.githubusercontent\.com/你的用户名/ header-add Authorization "token 你的token" 8 | 9 | [MITM] 10 | 11 | hostname = %APPEND% raw.githubusercontent.com,gist.githubusercontent.com 12 | -------------------------------------------------------------------------------- /modules/test2.sgmodule: -------------------------------------------------------------------------------- 1 | #!name=防止tiktok主机名被mitm 2 | #!desc=如题 3 | 4 | [MITM] 5 | hostname = %INSERT% -*.tiktokv.com, -*.byteoversea.com, -*.tik-tokapi.com -------------------------------------------------------------------------------- /modules/ytmusic.module: -------------------------------------------------------------------------------- 1 | #!name=Youtube (Music) Enhance 2 | #!desc=适用于 Youtube & Youtube Music 3 | #!arguments=屏蔽上传按钮:true,屏蔽选段按钮:true,字幕翻译语言:zh-Hans,歌词翻译语言:zh-Hans,脚本执行引擎:jsc,启用调试模式:false 4 | #!arguments-desc=- 屏蔽参数:[true, false] \n- 翻译参数:[语言代码, off] \n- 脚本引擎:[auto, jsc, webview]\n\n1. 语言代码遵循 Google Translate Languages Codes, 当填入 off 时关闭翻译\n2. 推荐使用 jsc 引擎,但你仍可以切换成 webview 体验 Surge 新特性\n3. 开启调试模式用于输出更多日志 5 | 6 | [Rule] 7 | AND,((DOMAIN-SUFFIX,googlevideo.com), (PROTOCOL,UDP)),REJECT 8 | AND,((DOMAIN,youtubei.googleapis.com), (PROTOCOL,UDP)),REJECT 9 | 10 | [Map Local] 11 | ^https?:\/\/[\w-]+\.googlevideo\.com\/initplayback.+&oad data="https://raw.githubusercontent.com/Maasea/sgmodule/master/Script/Youtube/dist/blank.txt" 12 | 13 | 14 | [Script] 15 | youtube.request = type=http-request, pattern=^https:\/\/youtubei\.googleapis\.com\/youtubei\/v1\/(browse|next|player|reel\/reel_watch_sequence), script-path=https://raw.githubusercontent.com/Maasea/sgmodule/master/Script/Youtube/dist/youtube.request.preview.js, requires-body=true, binary-body-mode=true, max-size=-1 16 | 17 | youtube.response = type=http-response, pattern=^https:\/\/youtubei\.googleapis\.com\/youtubei\/v1\/(browse|next|player|search|reel\/reel_watch_sequence|guide|account\/get_setting), script-path=https://raw.githubusercontent.com/Maasea/sgmodule/master/Script/Youtube/dist/youtube.response.preview.js, requires-body=true, binary-body-mode=true, max-size=-1, argument="{"lyricLang":"zh-Hans","captionLang":"zh-Hans","blockUpload":true,"blockImmersive":true,"debug":false}" 18 | 19 | [MITM] 20 | hostname = %APPEND% *.googlevideo.com, youtubei.googleapis.com 21 | --------------------------------------------------------------------------------