├── 10000 └── index.js ├── 10010 └── index.js ├── 12123 ├── index.js └── index.sgmodule ├── .gitignore ├── README.md ├── Widget └── ftms │ ├── rewrite.js │ └── rewrite.sgmodule ├── dompling.boxjs.json ├── gist ├── backup.js ├── commit.js ├── refreshApps.js └── restore.js ├── icon ├── github-black.jpg ├── github-white.jpg └── setTime.png ├── image ├── 1.jpeg ├── 2.jpeg ├── 3.jpeg └── ql.png ├── jd ├── JD_extra_cookie.js ├── JD_extra_sign.js ├── README.md ├── boxjs_env_to_ql.js ├── jd_ck_del.js ├── jd_cookie_rewrite.sgmodule ├── jd_cookie_search.js ├── jd_login_help.js ├── jd_login_help.loon.conf ├── jd_login_help.sgmodule ├── ql_api.js ├── ql_cookie_sync.js ├── ql_env_back.js ├── ql_env_upload.js └── ql_sync_box.js ├── shortcut └── sgmodule.json ├── spotify ├── spotify-lyric.ios.js ├── spotify-lyric.mac.js ├── spotify-lyric.request.js ├── spotify-lyric.search.js ├── 歌词搜索.ios.online.sgmodule ├── 歌词搜索.mac.online.sgmodule ├── 歌词翻译.ios.online.sgmodule └── 歌词翻译.mac.online.sgmodule ├── sub.store └── rename.js ├── tools ├── open-api.js └── task.js ├── wsgw ├── index.js └── wsgw.sgmodule ├── yarn.lock └── 解析脚本.offline.sgmodule /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | # production 3 | /build 4 | /.vscode 5 | /.idea 6 | /.history 7 | /.output 8 | /*.json 9 | !dompling.boxjs.json 10 | test.js 11 | .DS_Store -------------------------------------------------------------------------------- /10000/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 获取方式:打开 https://e.dlife.cn/index.do 登录 4 | =================== 5 | [MITM] 6 | hostname = e.dlife.cn 7 | 8 | 【Surge脚本配置】: 9 | =================== 10 | [Script] 11 | 电信登录地址 = type=http-request,pattern=^https:\/\/e\.dlife\.cn\/user\/loginMiddle,requires-body=1,max-size=0,script-path=https://raw.githubusercontent.com/dompling/Script/master/10000/index.js,script-update-interval=0 12 | 13 | =================== 14 | 【Loon脚本配置】: 15 | =================== 16 | [Script] 17 | http-request ^https:\/\/e\.dlife\.cn\/user\/loginMiddle tag=电信登录地址, script-path=https://raw.githubusercontent.com/dompling/Script/master/10000/index.js 18 | 19 | =================== 20 | 【 QX 脚本配置 】 : 21 | =================== 22 | 23 | [rewrite_local] 24 | ^https:\/\/e\.dlife\.cn\/user\/loginMiddle url script-request-header https://raw.githubusercontent.com/dompling/Script/master/10000/index.js 25 | 26 | */ 27 | 28 | const APIKey = "yy_10000"; 29 | const $ = new API(APIKey, true); 30 | if ($request) GetCookie(); 31 | 32 | function GetCookie() { 33 | if ($request.url.indexOf("https://e.dlife.cn/user/loginMiddle") !== -1) { 34 | $.login_url = $request.url.match(/(http.+)&sign/)[1]; 35 | $.write($.login_url, `china_telecom_loginUrl`); 36 | $.notify(`中国电信`, `登录地址获取成功`, $.login_url); 37 | $.info(`登录地址:${$.login_url}`); 38 | } 39 | } 40 | 41 | $.done(); 42 | 43 | /* prettier-ignore */ 44 | function ENV(){const isJSBox=typeof require=="function"&&typeof $jsbox!="undefined";return{isQX:typeof $task!=="undefined",isLoon:typeof $loon!=="undefined",isSurge:typeof $httpClient!=="undefined"&&typeof $utils!=="undefined",isBrowser:typeof document!=="undefined",isNode:typeof require=="function"&&!isJSBox,isJSBox,isRequest:typeof $request!=="undefined",isScriptable:typeof importModule!=="undefined",isShadowrocket:"undefined"!==typeof $rocket,isStash:"undefined"!==typeof $environment&&$environment["stash-version"]}} 45 | /* prettier-ignore */ 46 | function HTTP(defaultOptions={baseURL:""}){const{isQX,isLoon,isSurge,isScriptable,isNode,isBrowser,isShadowrocket,isStash,}=ENV();const methods=["GET","POST","PUT","DELETE","HEAD","OPTIONS","PATCH"];const URL_REGEX=/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;function send(method,options){options=typeof options==="string"?{url:options}:options;const baseURL=defaultOptions.baseURL;if(baseURL&&!URL_REGEX.test(options.url||"")){options.url=baseURL?baseURL+options.url:options.url}if(options.body&&options.headers&&!options.headers["Content-Type"]){options.headers["Content-Type"]="application/x-www-form-urlencoded"}options={...defaultOptions,...options};const timeout=options.timeout;const events={...{onRequest:()=>{},onResponse:(resp)=>resp,onTimeout:()=>{},},...options.events,};events.onRequest(method,options);let worker;if(isQX){worker=$task.fetch({method,...options})}else if(isLoon||isSurge||isNode||isShadowrocket||isStash){worker=new Promise((resolve,reject)=>{const request=isNode?require("request"):$httpClient;request[method.toLowerCase()](options,(err,response,body)=>{if(err)reject(err);else resolve({statusCode:response.status||response.statusCode,headers:response.headers,body,})})})}else if(isScriptable){const request=new Request(options.url);request.method=method;request.headers=options.headers;request.body=options.body;worker=new Promise((resolve,reject)=>{request.loadString().then((body)=>{resolve({statusCode:request.response.statusCode,headers:request.response.headers,body,})}).catch((err)=>reject(err))})}else if(isBrowser){worker=new Promise((resolve,reject)=>{fetch(options.url,{method,headers:options.headers,body:options.body,}).then((response)=>response.json()).then((response)=>resolve({statusCode:response.status,headers:response.headers,body:response.data,})).catch(reject)})}let timeoutid;const timer=timeout?new Promise((_,reject)=>{timeoutid=setTimeout(()=>{events.onTimeout();return reject(`${method}URL:${options.url}exceeds the timeout ${timeout}ms`)},timeout)}):null;return(timer?Promise.race([timer,worker]).then((res)=>{clearTimeout(timeoutid);return res}):worker).then((resp)=>events.onResponse(resp))}const http={};methods.forEach((method)=>(http[method.toLowerCase()]=(options)=>send(method,options)));return http} 47 | /* prettier-ignore */ 48 | function API(name="untitled",debug=false){const{isQX,isLoon,isSurge,isScriptable,isNode,isShadowrocket,isStash,}=ENV();return new(class{constructor(name,debug){this.name=name;this.debug=debug;this.http=HTTP();this.env=ENV();this.node=(()=>{if(isNode){const fs=require("fs");return{fs}}else{return null}})();this.initCache();const delay=(t,v)=>new Promise(function(resolve){setTimeout(resolve.bind(null,v),t)});Promise.prototype.delay=function(t){return this.then(function(v){return delay(t,v)})}}initCache(){if(isQX)this.cache=JSON.parse($prefs.valueForKey(this.name)||"{}");if(isLoon||isSurge||isStash||isShadowrocket)this.cache=JSON.parse($persistentStore.read(this.name)||"{}");if(isNode){let fpath="root.json";if(!this.node.fs.existsSync(fpath)){this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},(err)=>console.log(err))}this.root={};fpath=`${this.name}.json`;if(!this.node.fs.existsSync(fpath)){this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},(err)=>console.log(err));this.cache={}}else{this.cache=JSON.parse(this.node.fs.readFileSync(`${this.name}.json`))}}}persistCache(){const data=JSON.stringify(this.cache,null,2);if(isQX)$prefs.setValueForKey(data,this.name);if(isLoon||isSurge||isStash||isShadowrocket)$persistentStore.write(data,this.name);if(isNode){this.node.fs.writeFileSync(`${this.name}.json`,data,{flag:"w"},(err)=>console.log(err));this.node.fs.writeFileSync("root.json",JSON.stringify(this.root,null,2),{flag:"w"},(err)=>console.log(err))}}write(data,key){this.log(`SET ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.write(data,key)}if(isQX){return $prefs.setValueForKey(data,key)}if(isNode){this.root[key]=data}}else{this.cache[key]=data}this.persistCache()}read(key){this.log(`READ ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.read(key)}if(isQX){return $prefs.valueForKey(key)}if(isNode){return this.root[key]}}else{return this.cache[key]}}delete(key){this.log(`DELETE ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.write(null,key)}if(isQX){return $prefs.removeValueForKey(key)}if(isNode){delete this.root[key]}}else{delete this.cache[key]}this.persistCache()}notify(title,subtitle="",content="",options={}){const openURL=options["open-url"];const mediaURL=options["media-url"];if(isQX)$notify(title,subtitle,content,options);if(isSurge){$notification.post(title,subtitle,content+`${mediaURL?"\n多媒体:"+mediaURL:""}`,{url:openURL})}if(isLoon||isStash||isShadowrocket){let opts={};if(openURL)opts["openUrl"]=openURL;if(mediaURL)opts["mediaUrl"]=mediaURL;if(JSON.stringify(opts)==="{}"){$notification.post(title,subtitle,content)}else{$notification.post(title,subtitle,content,opts)}}if(isNode||isScriptable){const content_=content+(openURL?`\n点击跳转:${openURL}`:"")+(mediaURL?`\n多媒体:${mediaURL}`:"");if(isJSBox){const push=require("push");push.schedule({title:title,body:(subtitle?subtitle+"\n":"")+content_,})}else{console.log(`${title}\n${subtitle}\n${content_}\n\n`)}}}log(msg){if(this.debug)console.log(`[${this.name}]LOG:${this.stringify(msg)}`)}info(msg){console.log(`[${this.name}]INFO:${this.stringify(msg)}`)}error(msg){console.log(`[${this.name}]ERROR:${this.stringify(msg)}`)}wait(millisec){return new Promise((resolve)=>setTimeout(resolve,millisec))}done(value={}){if(isQX||isLoon||isSurge||isStash||isShadowrocket){$done(value)}else if(isNode&&!isJSBox){if(typeof $context!=="undefined"){$context.headers=value.headers;$context.statusCode=value.statusCode;$context.body=value.body}}}stringify(obj_or_str){if(typeof obj_or_str==="string"||obj_or_str instanceof String)return obj_or_str;else try{return JSON.stringify(obj_or_str,null,2)}catch(err){return"[object Object]"}}})(name,debug)} 49 | -------------------------------------------------------------------------------- /10010/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 获取方式:打开 中国联通 app 【官方版】-> 首页的流量查询获取 Cookie 4 | =================== 5 | [MITM] 6 | hostname = m.client.10010.com 7 | 8 | 【Surge脚本配置】: 9 | =================== 10 | [Script] 11 | 联通组件 = type=http-request,pattern=https:\/\/m\.client\.10010\.com\/(.*)\/smartwisdomCommon,requires-body=1,max-size=0,script-path=https://raw.githubusercontent.com/dompling/Script/master/10010/index.js,script-update-interval=0 12 | 13 | =================== 14 | 【Loon脚本配置】: 15 | =================== 16 | [Script] 17 | http-request https:\/\/m\.client\.10010\.com\/(.*)\/smartwisdomCommon tag=联通 headers, script-path=https://raw.githubusercontent.com/dompling/Script/master/10010/index.js 18 | 19 | =================== 20 | 【 QX 脚本配置 】 : 21 | =================== 22 | 23 | [rewrite_local] 24 | https:\/\/m\.client\.10010\.com\/(.*)\/smartwisdomCommon url script-request-header https://raw.githubusercontent.com/dompling/Script/master/10010/index.js 25 | 26 | */ 27 | 28 | const APIKey = 'YaYa_10010'; 29 | $ = new API(APIKey, true); 30 | if ($request) GetCookie(); 31 | 32 | function GetCookie() { 33 | const cookie = $request.headers.Cookie || $request.headers.cookie; 34 | $.log($request.headers); 35 | if (cookie && cookie.indexOf('JSESSIONID') > -1) { 36 | $.write(cookie, 'cookie'); 37 | $.notify('中国联通','cookie 写入成功'); 38 | } 39 | $.done(); 40 | } 41 | 42 | /* prettier-ignore */ 43 | function ENV(){const isJSBox=typeof require=="function"&&typeof $jsbox!="undefined";return{isQX:typeof $task!=="undefined",isLoon:typeof $loon!=="undefined",isSurge:typeof $httpClient!=="undefined"&&typeof $utils!=="undefined",isBrowser:typeof document!=="undefined",isNode:typeof require=="function"&&!isJSBox,isJSBox,isRequest:typeof $request!=="undefined",isScriptable:typeof importModule!=="undefined",isShadowrocket:"undefined"!==typeof $rocket,isStash:"undefined"!==typeof $environment&&$environment["stash-version"]}} 44 | /* prettier-ignore */ 45 | function HTTP(defaultOptions={baseURL:""}){const{isQX,isLoon,isSurge,isScriptable,isNode,isBrowser,isShadowrocket,isStash,}=ENV();const methods=["GET","POST","PUT","DELETE","HEAD","OPTIONS","PATCH"];const URL_REGEX=/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;function send(method,options){options=typeof options==="string"?{url:options}:options;const baseURL=defaultOptions.baseURL;if(baseURL&&!URL_REGEX.test(options.url||"")){options.url=baseURL?baseURL+options.url:options.url}if(options.body&&options.headers&&!options.headers["Content-Type"]){options.headers["Content-Type"]="application/x-www-form-urlencoded"}options={...defaultOptions,...options};const timeout=options.timeout;const events={...{onRequest:()=>{},onResponse:(resp)=>resp,onTimeout:()=>{},},...options.events,};events.onRequest(method,options);let worker;if(isQX){worker=$task.fetch({method,...options})}else if(isLoon||isSurge||isNode||isShadowrocket||isStash){worker=new Promise((resolve,reject)=>{const request=isNode?require("request"):$httpClient;request[method.toLowerCase()](options,(err,response,body)=>{if(err)reject(err);else resolve({statusCode:response.status||response.statusCode,headers:response.headers,body,})})})}else if(isScriptable){const request=new Request(options.url);request.method=method;request.headers=options.headers;request.body=options.body;worker=new Promise((resolve,reject)=>{request.loadString().then((body)=>{resolve({statusCode:request.response.statusCode,headers:request.response.headers,body,})}).catch((err)=>reject(err))})}else if(isBrowser){worker=new Promise((resolve,reject)=>{fetch(options.url,{method,headers:options.headers,body:options.body,}).then((response)=>response.json()).then((response)=>resolve({statusCode:response.status,headers:response.headers,body:response.data,})).catch(reject)})}let timeoutid;const timer=timeout?new Promise((_,reject)=>{timeoutid=setTimeout(()=>{events.onTimeout();return reject(`${method}URL:${options.url}exceeds the timeout ${timeout}ms`)},timeout)}):null;return(timer?Promise.race([timer,worker]).then((res)=>{clearTimeout(timeoutid);return res}):worker).then((resp)=>events.onResponse(resp))}const http={};methods.forEach((method)=>(http[method.toLowerCase()]=(options)=>send(method,options)));return http} 46 | /* prettier-ignore */ 47 | function API(name="untitled",debug=false){const{isQX,isLoon,isSurge,isScriptable,isNode,isShadowrocket,isStash,}=ENV();return new(class{constructor(name,debug){this.name=name;this.debug=debug;this.http=HTTP();this.env=ENV();this.node=(()=>{if(isNode){const fs=require("fs");return{fs}}else{return null}})();this.initCache();const delay=(t,v)=>new Promise(function(resolve){setTimeout(resolve.bind(null,v),t)});Promise.prototype.delay=function(t){return this.then(function(v){return delay(t,v)})}}initCache(){if(isQX)this.cache=JSON.parse($prefs.valueForKey(this.name)||"{}");if(isLoon||isSurge||isStash||isShadowrocket)this.cache=JSON.parse($persistentStore.read(this.name)||"{}");if(isNode){let fpath="root.json";if(!this.node.fs.existsSync(fpath)){this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},(err)=>console.log(err))}this.root={};fpath=`${this.name}.json`;if(!this.node.fs.existsSync(fpath)){this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},(err)=>console.log(err));this.cache={}}else{this.cache=JSON.parse(this.node.fs.readFileSync(`${this.name}.json`))}}}persistCache(){const data=JSON.stringify(this.cache,null,2);if(isQX)$prefs.setValueForKey(data,this.name);if(isLoon||isSurge||isStash||isShadowrocket)$persistentStore.write(data,this.name);if(isNode){this.node.fs.writeFileSync(`${this.name}.json`,data,{flag:"w"},(err)=>console.log(err));this.node.fs.writeFileSync("root.json",JSON.stringify(this.root,null,2),{flag:"w"},(err)=>console.log(err))}}write(data,key){this.log(`SET ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.write(data,key)}if(isQX){return $prefs.setValueForKey(data,key)}if(isNode){this.root[key]=data}}else{this.cache[key]=data}this.persistCache()}read(key){this.log(`READ ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.read(key)}if(isQX){return $prefs.valueForKey(key)}if(isNode){return this.root[key]}}else{return this.cache[key]}}delete(key){this.log(`DELETE ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.write(null,key)}if(isQX){return $prefs.removeValueForKey(key)}if(isNode){delete this.root[key]}}else{delete this.cache[key]}this.persistCache()}notify(title,subtitle="",content="",options={}){const openURL=options["open-url"];const mediaURL=options["media-url"];if(isQX)$notify(title,subtitle,content,options);if(isSurge){$notification.post(title,subtitle,content+`${mediaURL?"\n多媒体:"+mediaURL:""}`,{url:openURL})}if(isLoon||isStash||isShadowrocket){let opts={};if(openURL)opts["openUrl"]=openURL;if(mediaURL)opts["mediaUrl"]=mediaURL;if(JSON.stringify(opts)==="{}"){$notification.post(title,subtitle,content)}else{$notification.post(title,subtitle,content,opts)}}if(isNode||isScriptable){const content_=content+(openURL?`\n点击跳转:${openURL}`:"")+(mediaURL?`\n多媒体:${mediaURL}`:"");if(isJSBox){const push=require("push");push.schedule({title:title,body:(subtitle?subtitle+"\n":"")+content_,})}else{console.log(`${title}\n${subtitle}\n${content_}\n\n`)}}}log(msg){if(this.debug)console.log(`[${this.name}]LOG:${this.stringify(msg)}`)}info(msg){console.log(`[${this.name}]INFO:${this.stringify(msg)}`)}error(msg){console.log(`[${this.name}]ERROR:${this.stringify(msg)}`)}wait(millisec){return new Promise((resolve)=>setTimeout(resolve,millisec))}done(value={}){if(isQX||isLoon||isSurge||isStash||isShadowrocket){$done(value)}else if(isNode&&!isJSBox){if(typeof $context!=="undefined"){$context.headers=value.headers;$context.statusCode=value.statusCode;$context.body=value.body}}}stringify(obj_or_str){if(typeof obj_or_str==="string"||obj_or_str instanceof String)return obj_or_str;else try{return JSON.stringify(obj_or_str,null,2)}catch(err){return"[object Object]"}}})(name,debug)} 48 | -------------------------------------------------------------------------------- /12123/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | 脚本名称:获取12123_token 5 | 获取方式:打开支付宝 交管12123 【官方版】-> 登录获取 6 | 更新时间:2022-11-08 7 | ==================================================================================================== 8 | 配置 (QuanX) 9 | [rewrite_local] 10 | ^https:\/\/miniappcsfw\.122\.gov\.cn:8443\/openapi\/invokeApi\/business\/biz url script-request-body https://raw.githubusercontent.com/dompling/Script/master/12123/index.js 11 | 12 | [MITM] 13 | hostname = miniappcsfw.122.gov.cn:8443 14 | ==================================================================================================== 15 | 配置 (Surge) 16 | [Script] 17 | 12123_Token = type=http-request,pattern=^https:\/\/miniappcsfw\.122\.gov\.cn:8443\/openapi\/invokeApi\/business\/biz,requires-body=1,max-size=0,timeout=1000,script-path=https://raw.githubusercontent.com/dompling/Script/master/12123/index.js,script-update-interval=0 18 | 19 | [MITM] 20 | hostname = %APPEND% miniappcsfw.122.gov.cn:8443 21 | ==================================================================================================== 22 | */ 23 | 24 | const APIKey = '12123'; 25 | const $ = new API(APIKey, true); 26 | if ($request) GetCookie(); 27 | 28 | function GetCookie() { 29 | console.log(`交管 12123:获取 token 开始`); 30 | if ($request.url.indexOf('openapi/invokeApi/business/biz') > -1) { 31 | const cookie = $request.body; 32 | $.log($request.body); 33 | if ( 34 | cookie.indexOf(`unhandledVioCount`) === -1 || 35 | cookie.indexOf(`authToken`) === -1 36 | ) 37 | return $.done(); 38 | $.write(cookie, '#wx_12123'); 39 | $.notify('交管 12123', 'cookie 写入成功'); 40 | } 41 | $.done(); 42 | } 43 | 44 | function ENV() { 45 | const isJSBox = typeof require == 'function' && typeof $jsbox != 'undefined'; 46 | return { 47 | isQX: typeof $task !== 'undefined', 48 | isLoon: typeof $loon !== 'undefined', 49 | isSurge: 50 | typeof $httpClient !== 'undefined' && typeof $utils !== 'undefined', 51 | isBrowser: typeof document !== 'undefined', 52 | isNode: typeof require == 'function' && !isJSBox, 53 | isJSBox, 54 | isRequest: typeof $request !== 'undefined', 55 | isScriptable: typeof importModule !== 'undefined', 56 | }; 57 | } 58 | 59 | function HTTP( 60 | defaultOptions = { 61 | baseURL: '', 62 | } 63 | ) { 64 | const { isQX, isLoon, isSurge, isScriptable, isNode, isBrowser } = ENV(); 65 | const methods = ['GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS', 'PATCH']; 66 | const URL_REGEX = 67 | /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/; 68 | 69 | function send(method, options) { 70 | options = 71 | typeof options === 'string' 72 | ? { 73 | url: options, 74 | } 75 | : options; 76 | const baseURL = defaultOptions.baseURL; 77 | if (baseURL && !URL_REGEX.test(options.url || '')) { 78 | options.url = baseURL ? baseURL + options.url : options.url; 79 | } 80 | if (options.body && options.headers && !options.headers['Content-Type']) { 81 | options.headers['Content-Type'] = 'application/x-www-form-urlencoded'; 82 | } 83 | options = { 84 | ...defaultOptions, 85 | ...options, 86 | }; 87 | const timeout = options.timeout; 88 | const events = { 89 | ...{ 90 | onRequest: () => {}, 91 | onResponse: (resp) => resp, 92 | onTimeout: () => {}, 93 | }, 94 | ...options.events, 95 | }; 96 | 97 | events.onRequest(method, options); 98 | 99 | let worker; 100 | if (isQX) { 101 | worker = $task.fetch({ 102 | method, 103 | ...options, 104 | }); 105 | } else if (isLoon || isSurge || isNode) { 106 | worker = new Promise((resolve, reject) => { 107 | const request = isNode ? require('request') : $httpClient; 108 | request[method.toLowerCase()](options, (err, response, body) => { 109 | if (err) reject(err); 110 | else 111 | resolve({ 112 | statusCode: response.status || response.statusCode, 113 | headers: response.headers, 114 | body, 115 | }); 116 | }); 117 | }); 118 | } else if (isScriptable) { 119 | const request = new Request(options.url); 120 | request.method = method; 121 | request.headers = options.headers; 122 | request.body = options.body; 123 | worker = new Promise((resolve, reject) => { 124 | request 125 | .loadString() 126 | .then((body) => { 127 | resolve({ 128 | statusCode: request.response.statusCode, 129 | headers: request.response.headers, 130 | body, 131 | }); 132 | }) 133 | .catch((err) => reject(err)); 134 | }); 135 | } else if (isBrowser) { 136 | worker = new Promise((resolve, reject) => { 137 | fetch(options.url, { 138 | method, 139 | headers: options.headers, 140 | body: options.body, 141 | }) 142 | .then((response) => response.json()) 143 | .then((response) => 144 | resolve({ 145 | statusCode: response.status, 146 | headers: response.headers, 147 | body: response.data, 148 | }) 149 | ) 150 | .catch(reject); 151 | }); 152 | } 153 | 154 | let timeoutid; 155 | const timer = timeout 156 | ? new Promise((_, reject) => { 157 | timeoutid = setTimeout(() => { 158 | events.onTimeout(); 159 | return reject( 160 | `${method} URL: ${options.url} exceeds the timeout ${timeout} ms` 161 | ); 162 | }, timeout); 163 | }) 164 | : null; 165 | 166 | return ( 167 | timer 168 | ? Promise.race([timer, worker]).then((res) => { 169 | clearTimeout(timeoutid); 170 | return res; 171 | }) 172 | : worker 173 | ).then((resp) => events.onResponse(resp)); 174 | } 175 | 176 | const http = {}; 177 | methods.forEach( 178 | (method) => 179 | (http[method.toLowerCase()] = (options) => send(method, options)) 180 | ); 181 | return http; 182 | } 183 | 184 | function API(name = 'untitled', debug = false) { 185 | const { isQX, isLoon, isSurge, isNode, isJSBox, isScriptable } = ENV(); 186 | return new (class { 187 | constructor(name, debug) { 188 | this.name = name; 189 | this.debug = debug; 190 | 191 | this.http = HTTP(); 192 | this.env = ENV(); 193 | 194 | this.node = (() => { 195 | if (isNode) { 196 | const fs = require('fs'); 197 | 198 | return { 199 | fs, 200 | }; 201 | } else { 202 | return null; 203 | } 204 | })(); 205 | this.initCache(); 206 | 207 | const delay = (t, v) => 208 | new Promise(function (resolve) { 209 | setTimeout(resolve.bind(null, v), t); 210 | }); 211 | 212 | Promise.prototype.delay = function (t) { 213 | return this.then(function (v) { 214 | return delay(t, v); 215 | }); 216 | }; 217 | } 218 | 219 | // persistence 220 | // initialize cache 221 | initCache() { 222 | if (isQX) this.cache = JSON.parse($prefs.valueForKey(this.name) || '{}'); 223 | if (isLoon || isSurge) 224 | this.cache = JSON.parse($persistentStore.read(this.name) || '{}'); 225 | 226 | if (isNode) { 227 | // create a json for root cache 228 | let fpath = 'root.json'; 229 | if (!this.node.fs.existsSync(fpath)) { 230 | this.node.fs.writeFileSync( 231 | fpath, 232 | JSON.stringify({}), 233 | { 234 | flag: 'wx', 235 | }, 236 | (err) => console.log(err) 237 | ); 238 | } 239 | this.root = {}; 240 | 241 | // create a json file with the given name if not exists 242 | fpath = `${this.name}.json`; 243 | if (!this.node.fs.existsSync(fpath)) { 244 | this.node.fs.writeFileSync( 245 | fpath, 246 | JSON.stringify({}), 247 | { 248 | flag: 'wx', 249 | }, 250 | (err) => console.log(err) 251 | ); 252 | this.cache = {}; 253 | } else { 254 | this.cache = JSON.parse( 255 | this.node.fs.readFileSync(`${this.name}.json`) 256 | ); 257 | } 258 | } 259 | } 260 | 261 | // store cache 262 | persistCache() { 263 | const data = JSON.stringify(this.cache, null, 2); 264 | if (isQX) $prefs.setValueForKey(data, this.name); 265 | if (isLoon || isSurge) $persistentStore.write(data, this.name); 266 | if (isNode) { 267 | this.node.fs.writeFileSync( 268 | `${this.name}.json`, 269 | data, 270 | { 271 | flag: 'w', 272 | }, 273 | (err) => console.log(err) 274 | ); 275 | this.node.fs.writeFileSync( 276 | 'root.json', 277 | JSON.stringify(this.root, null, 2), 278 | { 279 | flag: 'w', 280 | }, 281 | (err) => console.log(err) 282 | ); 283 | } 284 | } 285 | 286 | write(data, key) { 287 | this.log(`SET ${key}`); 288 | if (key.indexOf('#') !== -1) { 289 | key = key.substr(1); 290 | if (isSurge || isLoon) { 291 | return $persistentStore.write(data, key); 292 | } 293 | if (isQX) { 294 | return $prefs.setValueForKey(data, key); 295 | } 296 | if (isNode) { 297 | this.root[key] = data; 298 | } 299 | } else { 300 | this.cache[key] = data; 301 | } 302 | this.persistCache(); 303 | } 304 | 305 | read(key) { 306 | this.log(`READ ${key}`); 307 | if (key.indexOf('#') !== -1) { 308 | key = key.substr(1); 309 | if (isSurge || isLoon) { 310 | return $persistentStore.read(key); 311 | } 312 | if (isQX) { 313 | return $prefs.valueForKey(key); 314 | } 315 | if (isNode) { 316 | return this.root[key]; 317 | } 318 | } else { 319 | return this.cache[key]; 320 | } 321 | } 322 | 323 | delete(key) { 324 | this.log(`DELETE ${key}`); 325 | if (key.indexOf('#') !== -1) { 326 | key = key.substr(1); 327 | if (isSurge || isLoon) { 328 | return $persistentStore.write(null, key); 329 | } 330 | if (isQX) { 331 | return $prefs.removeValueForKey(key); 332 | } 333 | if (isNode) { 334 | delete this.root[key]; 335 | } 336 | } else { 337 | delete this.cache[key]; 338 | } 339 | this.persistCache(); 340 | } 341 | 342 | // notification 343 | notify(title, subtitle = '', content = '', options = {}) { 344 | const openURL = options['open-url']; 345 | const mediaURL = options['media-url']; 346 | 347 | if (isQX) $notify(title, subtitle, content, options); 348 | if (isSurge) { 349 | $notification.post( 350 | title, 351 | subtitle, 352 | content + `${mediaURL ? '\n多媒体:' + mediaURL : ''}`, 353 | { 354 | url: openURL, 355 | } 356 | ); 357 | } 358 | if (isLoon) { 359 | let opts = {}; 360 | if (openURL) opts['openUrl'] = openURL; 361 | if (mediaURL) opts['mediaUrl'] = mediaURL; 362 | if (JSON.stringify(opts) === '{}') { 363 | $notification.post(title, subtitle, content); 364 | } else { 365 | $notification.post(title, subtitle, content, opts); 366 | } 367 | } 368 | if (isNode || isScriptable) { 369 | const content_ = 370 | content + 371 | (openURL ? `\n点击跳转: ${openURL}` : '') + 372 | (mediaURL ? `\n多媒体: ${mediaURL}` : ''); 373 | if (isJSBox) { 374 | const push = require('push'); 375 | push.schedule({ 376 | title: title, 377 | body: (subtitle ? subtitle + '\n' : '') + content_, 378 | }); 379 | } else { 380 | console.log(`${title}\n${subtitle}\n${content_}\n\n`); 381 | } 382 | } 383 | } 384 | 385 | // other helper functions 386 | log(msg) { 387 | if (this.debug) console.log(`[${this.name}] LOG: ${this.stringify(msg)}`); 388 | } 389 | 390 | info(msg) { 391 | console.log(`[${this.name}] INFO: ${this.stringify(msg)}`); 392 | } 393 | 394 | error(msg) { 395 | console.log(`[${this.name}] ERROR: ${this.stringify(msg)}`); 396 | } 397 | 398 | wait(millisec) { 399 | return new Promise((resolve) => setTimeout(resolve, millisec)); 400 | } 401 | 402 | done(value = {}) { 403 | if (isQX || isLoon || isSurge) { 404 | $done(value); 405 | } else if (isNode && !isJSBox) { 406 | if (typeof $context !== 'undefined') { 407 | $context.headers = value.headers; 408 | $context.statusCode = value.statusCode; 409 | $context.body = value.body; 410 | } 411 | } 412 | } 413 | 414 | stringify(obj_or_str) { 415 | if (typeof obj_or_str === 'string' || obj_or_str instanceof String) 416 | return obj_or_str; 417 | else 418 | try { 419 | return JSON.stringify(obj_or_str, null, 2); 420 | } catch (err) { 421 | return '[object Object]'; 422 | } 423 | } 424 | })(name, debug); 425 | } 426 | -------------------------------------------------------------------------------- /12123/index.sgmodule: -------------------------------------------------------------------------------- 1 | #!name=交管12123 2 | #!desc=自动抓取 交管12123_Token,支持Surge和Quantumult-X(QX需要配合解析器) 3 | #!使用方法:打开 交管12123支付宝小程序 登录即可自动抓取Token。资源解析器:https://t.me/QuanXNews/110 4 | 5 | [Script] 6 | 交管12123 = type=http-request,pattern=^https:\/\/miniappcsfw\.122\.gov\.cn:8443\/openapi\/invokeApi\/business\/biz,requires-body=1,max-size=0,timeout=1000,script-path=https://raw.githubusercontent.com/dompling/Script/master/12123/index.js,script-update-interval=0 7 | 8 | [MITM] 9 | hostname = %APPEND% miniappcsfw.122.gov.cn:8443,miniappcsfw.122.gov.cn -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Script 2 | 3 | QuanX 4 | 5 | # 学习写一些小的东西,本地脚本 6 | 7 | ## 特别感谢 8 | 9 | 1. [Peng-YM](https://github.com/Peng-YM) 大佬提供的 OpenApi 10 | -------------------------------------------------------------------------------- /Widget/ftms/rewrite.js: -------------------------------------------------------------------------------- 1 | const $ = new API('ftms', true) 2 | const title = '一汽丰田' 3 | try { 4 | if ( 5 | $request.url.indexOf('getbmuservehicleinfo') > -1 && 6 | $request.url.indexOf('scriptable') === -1 7 | ) { 8 | $.write(JSON.stringify($request.headers), 'headers') 9 | if ($.read('mute') !== 'true') { 10 | $.notify(title, `Cookie 写入成功`) 11 | } 12 | } 13 | $.done({}) 14 | } catch (e) { 15 | console.log(`${title}cookie 写入失败` + e) 16 | $.notify(title, `Cookie 写入失败`) 17 | $.done({}) 18 | } 19 | 20 | /* prettier-ignore */ 21 | function ENV(){const isJSBox=typeof require=="function"&&typeof $jsbox!="undefined";return{isQX:typeof $task!=="undefined",isLoon:typeof $loon!=="undefined",isSurge:typeof $httpClient!=="undefined"&&typeof $utils!=="undefined",isBrowser:typeof document!=="undefined",isNode:typeof require=="function"&&!isJSBox,isJSBox,isRequest:typeof $request!=="undefined",isScriptable:typeof importModule!=="undefined",isShadowrocket:"undefined"!==typeof $rocket,isStash:"undefined"!==typeof $environment&&$environment["stash-version"]}} 22 | /* prettier-ignore */ 23 | function HTTP(defaultOptions={baseURL:""}){const{isQX,isLoon,isSurge,isScriptable,isNode,isBrowser,isShadowrocket,isStash,}=ENV();const methods=["GET","POST","PUT","DELETE","HEAD","OPTIONS","PATCH"];const URL_REGEX=/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;function send(method,options){options=typeof options==="string"?{url:options}:options;const baseURL=defaultOptions.baseURL;if(baseURL&&!URL_REGEX.test(options.url||"")){options.url=baseURL?baseURL+options.url:options.url}if(options.body&&options.headers&&!options.headers["Content-Type"]){options.headers["Content-Type"]="application/x-www-form-urlencoded"}options={...defaultOptions,...options};const timeout=options.timeout;const events={...{onRequest:()=>{},onResponse:(resp)=>resp,onTimeout:()=>{},},...options.events,};events.onRequest(method,options);let worker;if(isQX){worker=$task.fetch({method,...options})}else if(isLoon||isSurge||isNode||isShadowrocket||isStash){worker=new Promise((resolve,reject)=>{const request=isNode?require("request"):$httpClient;request[method.toLowerCase()](options,(err,response,body)=>{if(err)reject(err);else resolve({statusCode:response.status||response.statusCode,headers:response.headers,body,})})})}else if(isScriptable){const request=new Request(options.url);request.method=method;request.headers=options.headers;request.body=options.body;worker=new Promise((resolve,reject)=>{request.loadString().then((body)=>{resolve({statusCode:request.response.statusCode,headers:request.response.headers,body,})}).catch((err)=>reject(err))})}else if(isBrowser){worker=new Promise((resolve,reject)=>{fetch(options.url,{method,headers:options.headers,body:options.body,}).then((response)=>response.json()).then((response)=>resolve({statusCode:response.status,headers:response.headers,body:response.data,})).catch(reject)})}let timeoutid;const timer=timeout?new Promise((_,reject)=>{timeoutid=setTimeout(()=>{events.onTimeout();return reject(`${method}URL:${options.url}exceeds the timeout ${timeout}ms`)},timeout)}):null;return(timer?Promise.race([timer,worker]).then((res)=>{clearTimeout(timeoutid);return res}):worker).then((resp)=>events.onResponse(resp))}const http={};methods.forEach((method)=>(http[method.toLowerCase()]=(options)=>send(method,options)));return http} 24 | /* prettier-ignore */ 25 | function API(name="untitled",debug=false){const{isQX,isLoon,isSurge,isScriptable,isNode,isShadowrocket,isStash,}=ENV();return new(class{constructor(name,debug){this.name=name;this.debug=debug;this.http=HTTP();this.env=ENV();this.node=(()=>{if(isNode){const fs=require("fs");return{fs}}else{return null}})();this.initCache();const delay=(t,v)=>new Promise(function(resolve){setTimeout(resolve.bind(null,v),t)});Promise.prototype.delay=function(t){return this.then(function(v){return delay(t,v)})}}initCache(){if(isQX)this.cache=JSON.parse($prefs.valueForKey(this.name)||"{}");if(isLoon||isSurge||isStash||isShadowrocket)this.cache=JSON.parse($persistentStore.read(this.name)||"{}");if(isNode){let fpath="root.json";if(!this.node.fs.existsSync(fpath)){this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},(err)=>console.log(err))}this.root={};fpath=`${this.name}.json`;if(!this.node.fs.existsSync(fpath)){this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},(err)=>console.log(err));this.cache={}}else{this.cache=JSON.parse(this.node.fs.readFileSync(`${this.name}.json`))}}}persistCache(){const data=JSON.stringify(this.cache,null,2);if(isQX)$prefs.setValueForKey(data,this.name);if(isLoon||isSurge||isStash||isShadowrocket)$persistentStore.write(data,this.name);if(isNode){this.node.fs.writeFileSync(`${this.name}.json`,data,{flag:"w"},(err)=>console.log(err));this.node.fs.writeFileSync("root.json",JSON.stringify(this.root,null,2),{flag:"w"},(err)=>console.log(err))}}write(data,key){this.log(`SET ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.write(data,key)}if(isQX){return $prefs.setValueForKey(data,key)}if(isNode){this.root[key]=data}}else{this.cache[key]=data}this.persistCache()}read(key){this.log(`READ ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.read(key)}if(isQX){return $prefs.valueForKey(key)}if(isNode){return this.root[key]}}else{return this.cache[key]}}delete(key){this.log(`DELETE ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.write(null,key)}if(isQX){return $prefs.removeValueForKey(key)}if(isNode){delete this.root[key]}}else{delete this.cache[key]}this.persistCache()}notify(title,subtitle="",content="",options={}){const openURL=options["open-url"];const mediaURL=options["media-url"];if(isQX)$notify(title,subtitle,content,options);if(isSurge){$notification.post(title,subtitle,content+`${mediaURL?"\n多媒体:"+mediaURL:""}`,{url:openURL})}if(isLoon||isStash||isShadowrocket){let opts={};if(openURL)opts["openUrl"]=openURL;if(mediaURL)opts["mediaUrl"]=mediaURL;if(JSON.stringify(opts)==="{}"){$notification.post(title,subtitle,content)}else{$notification.post(title,subtitle,content,opts)}}if(isNode||isScriptable){const content_=content+(openURL?`\n点击跳转:${openURL}`:"")+(mediaURL?`\n多媒体:${mediaURL}`:"");if(isJSBox){const push=require("push");push.schedule({title:title,body:(subtitle?subtitle+"\n":"")+content_,})}else{console.log(`${title}\n${subtitle}\n${content_}\n\n`)}}}log(msg){if(this.debug)console.log(`[${this.name}]LOG:${this.stringify(msg)}`)}info(msg){console.log(`[${this.name}]INFO:${this.stringify(msg)}`)}error(msg){console.log(`[${this.name}]ERROR:${this.stringify(msg)}`)}wait(millisec){return new Promise((resolve)=>setTimeout(resolve,millisec))}done(value={}){if(isQX||isLoon||isSurge||isStash||isShadowrocket){$done(value)}else if(isNode&&!isJSBox){if(typeof $context!=="undefined"){$context.headers=value.headers;$context.statusCode=value.statusCode;$context.body=value.body}}}stringify(obj_or_str){if(typeof obj_or_str==="string"||obj_or_str instanceof String)return obj_or_str;else try{return JSON.stringify(obj_or_str,null,2)}catch(err){return"[object Object]"}}})(name,debug)} 26 | -------------------------------------------------------------------------------- /Widget/ftms/rewrite.sgmodule: -------------------------------------------------------------------------------- 1 | #!name=一汽丰田 2 | #!desc=一汽丰田抓包重写 3 | 4 | [Script] 5 | 一汽丰田 = type=http-request,pattern=^https?:\/\/superapp\.ftms\.com\.cn\/superapp\/users\/wt\/getbmuservehicleinfo,requires-body=1,max-size=0,timeout=1000,script-path=https://raw.githubusercontent.com/dompling/Script/master/Widget/ftms/rewrite.js,script-update-interval=0 6 | 7 | [MITM] 8 | hostname = %INSERT% ,superapp.ftms.com.cn 9 | -------------------------------------------------------------------------------- /gist/commit.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Author: 2Ya 4 | Github: https://www.github.com/dompling 5 | =========================== 6 | gist 恢复备份:请先去 boxjs 设置完善 gist 信息, 7 | token 获取方式 : 8 | 头像菜单-> 9 | Settings -> 10 | Developer settings -> 11 | Personal access tokens -> 12 | Generate new token -> 13 | 在里面找到 gist 勾选提交 14 | =========================== 15 | 16 | 17 | [task] 18 | 19 | # 备份 20 | 0 10 * * * https://raw.githubusercontent.com/dompling/Script/master/gist/backup.js 21 | 22 | # 缓存历史纪录 23 | 5 10 * * * https://raw.githubusercontent.com/dompling/Script/master/gist/commit.js 24 | 25 | # 恢复 26 | 5 10 * * * https://raw.githubusercontent.com/dompling/Script/master/gist/restore.js 27 | 28 | */ 29 | 30 | const $ = new API("gist"); 31 | 32 | $.token = $.read("token"); 33 | $.username = $.read("username"); 34 | $.desc = "BoxJS-Data Backup"; 35 | 36 | $.msg = ""; 37 | $.error = ""; 38 | 39 | $.http = new HTTP({ 40 | baseURL: `https://api.github.com`, 41 | headers: { 42 | Authorization: `token ${$.token}`, 43 | Accept: "application/vnd.github.v3+json", 44 | "User-Agent": 45 | "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1", 46 | }, 47 | }); 48 | 49 | (async () => { 50 | if (!$.token || !$.username) throw "请去 boxjs 完善信息"; 51 | const gistList = await getGist(); 52 | if (!gistList) throw new Error("请检查 Gist 账号配置"); 53 | if (gistList.message) 54 | throw new Error( 55 | `Gist 列表请求失败:${gistList.message}\n请检查 Gist 账号配置` 56 | ); 57 | 58 | const boxjsdata = gistList.find((item) => item.description === $.desc); 59 | if (!boxjsdata) throw "未找到 Gist 备份信息,请先备份"; 60 | 61 | const commits = await getGistCommit(boxjsdata.id); 62 | 63 | const checkboxs = {}; 64 | commits.forEach((item) => { 65 | const label = convertTimeToHumanReadable(item.committed_at); 66 | if (!checkboxs[label]) { 67 | checkboxs[label] = { key: item.version, label }; 68 | $.msg += `${label}\n${item.version}\n\n`; 69 | } 70 | }); 71 | 72 | $.write(Object.values(checkboxs), "revision_options"); 73 | $.info(`历史 Commit\n${$.msg}`); 74 | })() 75 | .catch((e) => { 76 | $.error(e); 77 | $.notify("GIST", "", `❌${e.message || e}`); 78 | }) 79 | .finally(() => { 80 | $.done(); 81 | }); 82 | 83 | function getGist() { 84 | return $.http 85 | .get({ url: `/users/${$.username}/gists` }) 86 | .then((response) => JSON.parse(response.body)); 87 | } 88 | 89 | function getGistCommit(gist_id) { 90 | return $.http 91 | .get({ url: `/gists/${gist_id}/commits?per_page=100` }) 92 | .then((response) => JSON.parse(response.body)); 93 | } 94 | 95 | Date.prototype.Format = function (fmt) { 96 | var o = { 97 | "M+": this.getMonth() + 1, //月份 98 | "d+": this.getDate(), //日 99 | "h+": this.getHours(), //小时 100 | "m+": this.getMinutes(), //分 101 | "s+": this.getSeconds(), //秒 102 | "q+": Math.floor((this.getMonth() + 3) / 3), //季度 103 | S: this.getMilliseconds(), //毫秒 104 | }; 105 | if (/(y+)/.test(fmt)) 106 | fmt = fmt.replace( 107 | RegExp.$1, 108 | (this.getFullYear() + "").substr(4 - RegExp.$1.length) 109 | ); 110 | for (var k in o) 111 | if (new RegExp("(" + k + ")").test(fmt)) 112 | fmt = fmt.replace( 113 | RegExp.$1, 114 | RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length) 115 | ); 116 | return fmt; 117 | }; 118 | 119 | function convertTimeToHumanReadable(dateTime) { 120 | return new Date(dateTime).Format("yyyy-MM-dd hh:mm"); 121 | } 122 | 123 | /* prettier-ignore */ 124 | function ENV(){const isJSBox=typeof require=="function"&&typeof $jsbox!="undefined";return{isQX:typeof $task!=="undefined",isLoon:typeof $loon!=="undefined",isSurge:typeof $httpClient!=="undefined"&&typeof $utils!=="undefined",isBrowser:typeof document!=="undefined",isNode:typeof require=="function"&&!isJSBox,isJSBox,isRequest:typeof $request!=="undefined",isScriptable:typeof importModule!=="undefined",isShadowrocket:"undefined"!==typeof $rocket,isStash:"undefined"!==typeof $environment&&$environment["stash-version"]}} 125 | /* prettier-ignore */ 126 | function HTTP(defaultOptions={baseURL:""}){const{isQX,isLoon,isSurge,isScriptable,isNode,isBrowser,isShadowrocket,isStash,}=ENV();const methods=["GET","POST","PUT","DELETE","HEAD","OPTIONS","PATCH"];const URL_REGEX=/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;function send(method,options){options=typeof options==="string"?{url:options}:options;const baseURL=defaultOptions.baseURL;if(baseURL&&!URL_REGEX.test(options.url||"")){options.url=baseURL?baseURL+options.url:options.url}if(options.body&&options.headers&&!options.headers["Content-Type"]){options.headers["Content-Type"]="application/x-www-form-urlencoded"}options={...defaultOptions,...options};const timeout=options.timeout;const events={...{onRequest:()=>{},onResponse:(resp)=>resp,onTimeout:()=>{},},...options.events,};events.onRequest(method,options);let worker;if(isQX){worker=$task.fetch({method,...options})}else if(isLoon||isSurge||isNode||isShadowrocket||isStash){worker=new Promise((resolve,reject)=>{const request=isNode?require("request"):$httpClient;request[method.toLowerCase()](options,(err,response,body)=>{if(err)reject(err);else resolve({statusCode:response.status||response.statusCode,headers:response.headers,body,})})})}else if(isScriptable){const request=new Request(options.url);request.method=method;request.headers=options.headers;request.body=options.body;worker=new Promise((resolve,reject)=>{request.loadString().then((body)=>{resolve({statusCode:request.response.statusCode,headers:request.response.headers,body,})}).catch((err)=>reject(err))})}else if(isBrowser){worker=new Promise((resolve,reject)=>{fetch(options.url,{method,headers:options.headers,body:options.body,}).then((response)=>response.json()).then((response)=>resolve({statusCode:response.status,headers:response.headers,body:response.data,})).catch(reject)})}let timeoutid;const timer=timeout?new Promise((_,reject)=>{timeoutid=setTimeout(()=>{events.onTimeout();return reject(`${method}URL:${options.url}exceeds the timeout ${timeout}ms`)},timeout)}):null;return(timer?Promise.race([timer,worker]).then((res)=>{clearTimeout(timeoutid);return res}):worker).then((resp)=>events.onResponse(resp))}const http={};methods.forEach((method)=>(http[method.toLowerCase()]=(options)=>send(method,options)));return http} 127 | /* prettier-ignore */ 128 | function API(name="untitled",debug=false){const{isQX,isLoon,isSurge,isScriptable,isNode,isShadowrocket,isStash,}=ENV();return new(class{constructor(name,debug){this.name=name;this.debug=debug;this.http=HTTP();this.env=ENV();this.node=(()=>{if(isNode){const fs=require("fs");return{fs}}else{return null}})();this.initCache();const delay=(t,v)=>new Promise(function(resolve){setTimeout(resolve.bind(null,v),t)});Promise.prototype.delay=function(t){return this.then(function(v){return delay(t,v)})}}initCache(){if(isQX)this.cache=JSON.parse($prefs.valueForKey(this.name)||"{}");if(isLoon||isSurge||isStash||isShadowrocket)this.cache=JSON.parse($persistentStore.read(this.name)||"{}");if(isNode){let fpath="root.json";if(!this.node.fs.existsSync(fpath)){this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},(err)=>console.log(err))}this.root={};fpath=`${this.name}.json`;if(!this.node.fs.existsSync(fpath)){this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},(err)=>console.log(err));this.cache={}}else{this.cache=JSON.parse(this.node.fs.readFileSync(`${this.name}.json`))}}}persistCache(){const data=JSON.stringify(this.cache,null,2);if(isQX)$prefs.setValueForKey(data,this.name);if(isLoon||isSurge||isStash||isShadowrocket)$persistentStore.write(data,this.name);if(isNode){this.node.fs.writeFileSync(`${this.name}.json`,data,{flag:"w"},(err)=>console.log(err));this.node.fs.writeFileSync("root.json",JSON.stringify(this.root,null,2),{flag:"w"},(err)=>console.log(err))}}write(data,key){this.log(`SET ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.write(data,key)}if(isQX){return $prefs.setValueForKey(data,key)}if(isNode){this.root[key]=data}}else{this.cache[key]=data}this.persistCache()}read(key){this.log(`READ ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.read(key)}if(isQX){return $prefs.valueForKey(key)}if(isNode){return this.root[key]}}else{return this.cache[key]}}delete(key){this.log(`DELETE ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.write(null,key)}if(isQX){return $prefs.removeValueForKey(key)}if(isNode){delete this.root[key]}}else{delete this.cache[key]}this.persistCache()}notify(title,subtitle="",content="",options={}){const openURL=options["open-url"];const mediaURL=options["media-url"];if(isQX)$notify(title,subtitle,content,options);if(isSurge){$notification.post(title,subtitle,content+`${mediaURL?"\n多媒体:"+mediaURL:""}`,{url:openURL})}if(isLoon||isStash||isShadowrocket){let opts={};if(openURL)opts["openUrl"]=openURL;if(mediaURL)opts["mediaUrl"]=mediaURL;if(JSON.stringify(opts)==="{}"){$notification.post(title,subtitle,content)}else{$notification.post(title,subtitle,content,opts)}}if(isNode||isScriptable){const content_=content+(openURL?`\n点击跳转:${openURL}`:"")+(mediaURL?`\n多媒体:${mediaURL}`:"");if(isJSBox){const push=require("push");push.schedule({title:title,body:(subtitle?subtitle+"\n":"")+content_,})}else{console.log(`${title}\n${subtitle}\n${content_}\n\n`)}}}log(msg){if(this.debug)console.log(`[${this.name}]LOG:${this.stringify(msg)}`)}info(msg){console.log(`[${this.name}]INFO:${this.stringify(msg)}`)}error(msg){console.log(`[${this.name}]ERROR:${this.stringify(msg)}`)}wait(millisec){return new Promise((resolve)=>setTimeout(resolve,millisec))}done(value={}){if(isQX||isLoon||isSurge||isStash||isShadowrocket){$done(value)}else if(isNode&&!isJSBox){if(typeof $context!=="undefined"){$context.headers=value.headers;$context.statusCode=value.statusCode;$context.body=value.body}}}stringify(obj_or_str){if(typeof obj_or_str==="string"||obj_or_str instanceof String)return obj_or_str;else try{return JSON.stringify(obj_or_str,null,2)}catch(err){return"[object Object]"}}})(name,debug)} 129 | -------------------------------------------------------------------------------- /gist/refreshApps.js: -------------------------------------------------------------------------------- 1 | const $ = new API("gist"); 2 | $.appSubCaches = JSON.parse($.read("#chavy_boxjs_app_subCaches")); 3 | $.gitKey = `https://raw.githubusercontent.com/dompling/Script/master/dompling.boxjs.json`; 4 | $.dompling = $.appSubCaches[$.gitKey]; 5 | 6 | $.appBlackIndex = $.dompling.apps.findIndex( 7 | (app) => app.id === "GistBackupBlackApp" 8 | ); 9 | 10 | $.appWhiteIndex = $.dompling.apps.findIndex( 11 | (app) => app.id === "GistBackupWhiteApp" 12 | ); 13 | 14 | $.settings = []; 15 | $.msg = ""; 16 | Object.values($.appSubCaches).forEach((sub) => { 17 | const setting = { 18 | id: `@gist.backup_black_apps.${sub.author}`, 19 | type: "checkboxes", 20 | val: "", 21 | name: `${sub.name}(${sub.apps.length})`, 22 | items: [], 23 | }; 24 | sub.apps.forEach((app) => { 25 | $.msg += `${app.name}\n\n`; 26 | setting.items.push({ 27 | label: app.name, 28 | key: `${app.id}`, 29 | }); 30 | }); 31 | $.settings.push(setting); 32 | }); 33 | $.info($.msg); 34 | if ($.appBlackIndex !== -1) { 35 | $.appSubCaches[$.gitKey].apps[$.appBlackIndex].settings = $.settings; 36 | $.write(JSON.stringify($.appSubCaches), "#chavy_boxjs_app_subCaches"); 37 | } 38 | 39 | if ($.appWhiteIndex !== -1) { 40 | $.appSubCaches[$.gitKey].apps[$.appWhiteIndex].settings = $.settings.map( 41 | (item) => { 42 | const id = item.id.replace("backup_black_apps", "backup_white_apps"); 43 | return { ...item, id }; 44 | } 45 | ); 46 | $.write(JSON.stringify($.appSubCaches), "#chavy_boxjs_app_subCaches"); 47 | } 48 | 49 | $.notify("数据黑白名", "", `刷新 Apps 成功`); 50 | $.done({}); 51 | 52 | /* prettier-ignore */ 53 | function ENV(){const isJSBox=typeof require=="function"&&typeof $jsbox!="undefined";return{isQX:typeof $task!=="undefined",isLoon:typeof $loon!=="undefined",isSurge:typeof $httpClient!=="undefined"&&typeof $utils!=="undefined",isBrowser:typeof document!=="undefined",isNode:typeof require=="function"&&!isJSBox,isJSBox,isRequest:typeof $request!=="undefined",isScriptable:typeof importModule!=="undefined",isShadowrocket:"undefined"!==typeof $rocket,isStash:"undefined"!==typeof $environment&&$environment["stash-version"]}} 54 | /* prettier-ignore */ 55 | function HTTP(defaultOptions={baseURL:""}){const{isQX,isLoon,isSurge,isScriptable,isNode,isBrowser,isShadowrocket,isStash,}=ENV();const methods=["GET","POST","PUT","DELETE","HEAD","OPTIONS","PATCH"];const URL_REGEX=/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;function send(method,options){options=typeof options==="string"?{url:options}:options;const baseURL=defaultOptions.baseURL;if(baseURL&&!URL_REGEX.test(options.url||"")){options.url=baseURL?baseURL+options.url:options.url}if(options.body&&options.headers&&!options.headers["Content-Type"]){options.headers["Content-Type"]="application/x-www-form-urlencoded"}options={...defaultOptions,...options};const timeout=options.timeout;const events={...{onRequest:()=>{},onResponse:(resp)=>resp,onTimeout:()=>{},},...options.events,};events.onRequest(method,options);let worker;if(isQX){worker=$task.fetch({method,...options})}else if(isLoon||isSurge||isNode||isShadowrocket||isStash){worker=new Promise((resolve,reject)=>{const request=isNode?require("request"):$httpClient;request[method.toLowerCase()](options,(err,response,body)=>{if(err)reject(err);else resolve({statusCode:response.status||response.statusCode,headers:response.headers,body,})})})}else if(isScriptable){const request=new Request(options.url);request.method=method;request.headers=options.headers;request.body=options.body;worker=new Promise((resolve,reject)=>{request.loadString().then((body)=>{resolve({statusCode:request.response.statusCode,headers:request.response.headers,body,})}).catch((err)=>reject(err))})}else if(isBrowser){worker=new Promise((resolve,reject)=>{fetch(options.url,{method,headers:options.headers,body:options.body,}).then((response)=>response.json()).then((response)=>resolve({statusCode:response.status,headers:response.headers,body:response.data,})).catch(reject)})}let timeoutid;const timer=timeout?new Promise((_,reject)=>{timeoutid=setTimeout(()=>{events.onTimeout();return reject(`${method}URL:${options.url}exceeds the timeout ${timeout}ms`)},timeout)}):null;return(timer?Promise.race([timer,worker]).then((res)=>{clearTimeout(timeoutid);return res}):worker).then((resp)=>events.onResponse(resp))}const http={};methods.forEach((method)=>(http[method.toLowerCase()]=(options)=>send(method,options)));return http} 56 | /* prettier-ignore */ 57 | function API(name="untitled",debug=false){const{isQX,isLoon,isSurge,isScriptable,isNode,isShadowrocket,isStash,}=ENV();return new(class{constructor(name,debug){this.name=name;this.debug=debug;this.http=HTTP();this.env=ENV();this.node=(()=>{if(isNode){const fs=require("fs");return{fs}}else{return null}})();this.initCache();const delay=(t,v)=>new Promise(function(resolve){setTimeout(resolve.bind(null,v),t)});Promise.prototype.delay=function(t){return this.then(function(v){return delay(t,v)})}}initCache(){if(isQX)this.cache=JSON.parse($prefs.valueForKey(this.name)||"{}");if(isLoon||isSurge||isStash||isShadowrocket)this.cache=JSON.parse($persistentStore.read(this.name)||"{}");if(isNode){let fpath="root.json";if(!this.node.fs.existsSync(fpath)){this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},(err)=>console.log(err))}this.root={};fpath=`${this.name}.json`;if(!this.node.fs.existsSync(fpath)){this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},(err)=>console.log(err));this.cache={}}else{this.cache=JSON.parse(this.node.fs.readFileSync(`${this.name}.json`))}}}persistCache(){const data=JSON.stringify(this.cache,null,2);if(isQX)$prefs.setValueForKey(data,this.name);if(isLoon||isSurge||isStash||isShadowrocket)$persistentStore.write(data,this.name);if(isNode){this.node.fs.writeFileSync(`${this.name}.json`,data,{flag:"w"},(err)=>console.log(err));this.node.fs.writeFileSync("root.json",JSON.stringify(this.root,null,2),{flag:"w"},(err)=>console.log(err))}}write(data,key){this.log(`SET ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.write(data,key)}if(isQX){return $prefs.setValueForKey(data,key)}if(isNode){this.root[key]=data}}else{this.cache[key]=data}this.persistCache()}read(key){this.log(`READ ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.read(key)}if(isQX){return $prefs.valueForKey(key)}if(isNode){return this.root[key]}}else{return this.cache[key]}}delete(key){this.log(`DELETE ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.write(null,key)}if(isQX){return $prefs.removeValueForKey(key)}if(isNode){delete this.root[key]}}else{delete this.cache[key]}this.persistCache()}notify(title,subtitle="",content="",options={}){const openURL=options["open-url"];const mediaURL=options["media-url"];if(isQX)$notify(title,subtitle,content,options);if(isSurge){$notification.post(title,subtitle,content+`${mediaURL?"\n多媒体:"+mediaURL:""}`,{url:openURL})}if(isLoon||isStash||isShadowrocket){let opts={};if(openURL)opts["openUrl"]=openURL;if(mediaURL)opts["mediaUrl"]=mediaURL;if(JSON.stringify(opts)==="{}"){$notification.post(title,subtitle,content)}else{$notification.post(title,subtitle,content,opts)}}if(isNode||isScriptable){const content_=content+(openURL?`\n点击跳转:${openURL}`:"")+(mediaURL?`\n多媒体:${mediaURL}`:"");if(isJSBox){const push=require("push");push.schedule({title:title,body:(subtitle?subtitle+"\n":"")+content_,})}else{console.log(`${title}\n${subtitle}\n${content_}\n\n`)}}}log(msg){if(this.debug)console.log(`[${this.name}]LOG:${this.stringify(msg)}`)}info(msg){console.log(`[${this.name}]INFO:${this.stringify(msg)}`)}error(msg){console.log(`[${this.name}]ERROR:${this.stringify(msg)}`)}wait(millisec){return new Promise((resolve)=>setTimeout(resolve,millisec))}done(value={}){if(isQX||isLoon||isSurge||isStash||isShadowrocket){$done(value)}else if(isNode&&!isJSBox){if(typeof $context!=="undefined"){$context.headers=value.headers;$context.statusCode=value.statusCode;$context.body=value.body}}}stringify(obj_or_str){if(typeof obj_or_str==="string"||obj_or_str instanceof String)return obj_or_str;else try{return JSON.stringify(obj_or_str,null,2)}catch(err){return"[object Object]"}}})(name,debug)} 58 | -------------------------------------------------------------------------------- /gist/restore.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Author: 2Ya 4 | Github: https://www.github.com/dompling 5 | =========================== 6 | gist 恢复备份:请先去 boxjs 设置完善 gist 信息, 7 | token 获取方式 : 8 | 头像菜单-> 9 | Settings -> 10 | Developer settings -> 11 | Personal access tokens -> 12 | Generate new token -> 13 | 在里面找到 gist 勾选提交 14 | =========================== 15 | 16 | 17 | [task] 18 | 19 | # 备份 20 | 0 10 * * * https://raw.githubusercontent.com/dompling/Script/master/gist/backup.js 21 | # 恢复 22 | 5 10 * * * https://raw.githubusercontent.com/dompling/Script/master/gist/restore.js 23 | 24 | */ 25 | 26 | const $ = new API("gist"); 27 | try { 28 | $.backup_black_apps = Object.values($.read("backup_black_apps") || {}) 29 | .join(",") 30 | .split(",") 31 | .filter((item) => !!item); 32 | 33 | $.backup_white_apps = Object.values($.read("backup_white_apps") || {}) 34 | .join(",") 35 | .split(",") 36 | .filter((item) => !!item); 37 | } catch (error) { 38 | $.backup_black_apps = []; 39 | $.backup_white_apps = []; 40 | } 41 | 42 | $.appSubCaches = JSON.parse($.read("#chavy_boxjs_app_subCaches") || "{}"); 43 | 44 | $.apps = []; 45 | $.black_restore = []; 46 | $.white_restore = []; 47 | Object.values($.appSubCaches).forEach((sub) => { 48 | if (!sub || !sub.apps) return; 49 | sub.apps.forEach((app) => { 50 | const key = `${app.id}`; 51 | if ($.backup_black_apps.indexOf(key) !== -1) { 52 | if (app.keys) { 53 | $.black_restore = [...app.keys, ...$.black_restore]; 54 | } 55 | if (app.settings) { 56 | const ids = app.settings.map((setting) => setting.id); 57 | $.black_restore = [...ids, ...$.black_restore]; 58 | } 59 | } 60 | if ($.backup_white_apps.indexOf(key) !== -1) { 61 | if (app.keys) { 62 | $.white_restore = [...app.keys, ...$.white_restore]; 63 | } 64 | if (app.settings) { 65 | const ids = app.settings.map((setting) => setting.id); 66 | $.white_restore = [...ids, ...$.white_restore]; 67 | } 68 | } 69 | }); 70 | }); 71 | 72 | // 存储`用户偏好` 73 | $.KEY_usercfgs = "chavy_boxjs_userCfgs"; 74 | // 存储`应用会话` 75 | $.KEY_sessions = "chavy_boxjs_sessions"; 76 | // 存储`应用订阅缓存` 77 | $.KEY_app_subCaches = "chavy_boxjs_app_subCaches"; 78 | // 存储`备份索引` 79 | $.KEY_backups = "chavy_boxjs_backups"; 80 | // 存储`当前会话` (配合切换会话, 记录当前切换到哪个会话) 81 | $.KEY_cursessions = "chavy_boxjs_cur_sessions"; 82 | 83 | $.token = $.read("token"); 84 | $.username = $.read("username"); 85 | $.versionId = $.read("revision_id"); 86 | 87 | $.cacheKey = "BoxJS-Data"; 88 | $.desc = "BoxJS-Data Backup"; 89 | $.msg = ""; 90 | 91 | const cacheArr = { 92 | usercfgs: { label: "用户偏好", key: $.KEY_usercfgs }, 93 | sessions: { label: "应用会话", key: $.KEY_sessions }, 94 | curSessions: { label: "当前会话", key: $.KEY_cursessions }, 95 | globalbaks: { label: "备份索引", key: $.KEY_backups }, 96 | appSubCaches: { label: "应用订阅缓存", key: $.KEY_app_subCaches }, 97 | }; 98 | 99 | $.backupType = 100 | $.read("backup_type") || [...Object.keys(cacheArr), "datas"].join(","); 101 | 102 | $.backupType = $.backupType.split(","); 103 | 104 | $.http = new HTTP({ 105 | baseURL: `https://api.github.com`, 106 | headers: { 107 | Authorization: `token ${$.token}`, 108 | Accept: "application/vnd.github.v3+json", 109 | "User-Agent": 110 | "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1", 111 | }, 112 | }); 113 | 114 | $.setval = (val, key) => { 115 | if ($.env.isQX) { 116 | return $prefs.setValueForKey(val, key); 117 | } else { 118 | return $persistentStore.write(val, key); 119 | } 120 | }; 121 | 122 | $.getval = (t) => { 123 | if ($.env.isQX) { 124 | return $prefs.valueForKey(t); 125 | } else { 126 | return $persistentStore.read(t); 127 | } 128 | }; 129 | 130 | $.setdata = (val, key) => { 131 | function lodash_set(obj, path, value) { 132 | if (Object(obj) !== obj) return obj; 133 | if (!Array.isArray(path)) path = path.toString().match(/[^.[\]]+/g) || []; 134 | path 135 | .slice(0, -1) 136 | .reduce( 137 | (a, c, i) => 138 | Object(a[c]) === a[c] 139 | ? a[c] 140 | : (a[c] = Math.abs(path[i + 1]) >> 0 === +path[i + 1] ? [] : {}), 141 | obj 142 | )[path[path.length - 1]] = value; 143 | return obj; 144 | } 145 | 146 | let issuc = false; 147 | if (/^@/.test(key)) { 148 | const [, objkey, paths] = /^@(.*?)\.(.*?)$/.exec(key); 149 | const objdat = $.getval(objkey); 150 | const objval = objkey ? (objdat === "null" ? null : objdat || "{}") : "{}"; 151 | try { 152 | const objedval = JSON.parse(objval); 153 | lodash_set(objedval, paths, val); 154 | issuc = $.setval(JSON.stringify(objedval), objkey); 155 | } catch (e) { 156 | const objedval = {}; 157 | lodash_set(objedval, paths, val); 158 | issuc = $.setval(JSON.stringify(objedval), objkey); 159 | } 160 | } else { 161 | issuc = $.setval(val, key); 162 | } 163 | return issuc; 164 | }; 165 | 166 | (async () => { 167 | if (!$.token || !$.username) throw "请去 boxjs 完善信息"; 168 | const gistList = await getGist(); 169 | if (!gistList) throw "请检查 Gist 账号配置"; 170 | if (gistList.message) 171 | throw `Gist 列表请求失败:${gistList.message}\n请检查 Gist 账号配置`; 172 | 173 | let boxjsdata = gistList.find((item) => item.description === $.desc); 174 | if (!boxjsdata) throw "未找到 Gist 备份信息,请先备份"; 175 | 176 | if ($.versionId) { 177 | boxjsdata = await getGistRevision(boxjsdata.id, $.versionId); 178 | } 179 | 180 | if ($.backupType.indexOf(`datas`) !== -1) { 181 | let datasIndex = 0; 182 | Object.keys(boxjsdata.files).forEach((key) => { 183 | if (key.indexOf("datas") !== -1) { 184 | datasIndex += 1; 185 | $.backupType.push(key.replace(".json", "")); 186 | cacheArr[key.replace(".json", "")] = { 187 | label: `用户数据第${datasIndex}段`, 188 | }; 189 | } 190 | }); 191 | } 192 | 193 | for (const cacheArrKey in cacheArr) { 194 | if ($.backupType.indexOf(cacheArrKey) === -1) continue; 195 | 196 | const item = cacheArr[cacheArrKey]; 197 | const saveKey = `${cacheArrKey}.json`; 198 | const fileUri = boxjsdata.files[saveKey].raw_url; 199 | const content = await getBackGist(fileUri); 200 | if (content) { 201 | try { 202 | $.info(fileUri); 203 | if (!item.key) { 204 | Object.keys(content || {}).forEach((key) => { 205 | const val = content[key]; 206 | if ($.white_restore.length) { 207 | if ($.white_restore.indexOf(key) > -1) { 208 | $.setdata(val, key); 209 | $.info(`${key}:白名单恢复`); 210 | } 211 | return; 212 | } 213 | if ($.black_restore.indexOf(key) === -1) { 214 | $.setdata(val, key); 215 | } else { 216 | $.info(`${key}:黑名单跳过恢复`); 217 | } 218 | }); 219 | } else { 220 | $.setdata(JSON.stringify(content), item.key); 221 | } 222 | $.msg += `${item.label}:备份恢复成功 \n`; 223 | $.info(`${item.label}:备份恢复成功`); 224 | } catch (e) { 225 | $.msg += `${item.label}:备份数据异常 \n`; 226 | } 227 | } else { 228 | $.msg += `${item.label}:未找到备份,请先备份 \n`; 229 | $.info(`${item.label}:未找到备份,请先备份`); 230 | } 231 | } 232 | })() 233 | .then(() => { 234 | $.write("", "revision_id"); 235 | if ($.versionId) { 236 | $.notify("gist 历史备份恢复", $.versionId, `${$.username}:\n${$.msg}`); 237 | } else { 238 | $.notify("gist 备份恢复", "", `${$.username}:\n${$.msg}`); 239 | } 240 | }) 241 | .catch((e) => { 242 | $.error(e); 243 | if ($.versionId) { 244 | $.notify("gist 历史备份恢复", $.versionId, `❌${e.message || e}`); 245 | } else { 246 | $.notify("gist 备份恢复", "", `❌${e.message || e}`); 247 | } 248 | }) 249 | .finally(() => { 250 | $.done(); 251 | }); 252 | 253 | function getGist() { 254 | return $.http 255 | .get({ url: `/users/${$.username}/gists` }) 256 | .then((response) => JSON.parse(response.body)); 257 | } 258 | 259 | function getBackGist(url) { 260 | return $.http.get({ url }).then((response) => JSON.parse(response.body)); 261 | } 262 | 263 | function getGistRevision(gist_id, revision_id) { 264 | return $.http 265 | .get({ url: `/gists/${gist_id}/${revision_id}` }) 266 | .then((response) => JSON.parse(response.body)); 267 | } 268 | 269 | /* prettier-ignore */ 270 | function ENV(){const isJSBox=typeof require=="function"&&typeof $jsbox!="undefined";return{isQX:typeof $task!=="undefined",isLoon:typeof $loon!=="undefined",isSurge:typeof $httpClient!=="undefined"&&typeof $utils!=="undefined",isBrowser:typeof document!=="undefined",isNode:typeof require=="function"&&!isJSBox,isJSBox,isRequest:typeof $request!=="undefined",isScriptable:typeof importModule!=="undefined",isShadowrocket:"undefined"!==typeof $rocket,isStash:"undefined"!==typeof $environment&&$environment["stash-version"]}} 271 | /* prettier-ignore */ 272 | function HTTP(defaultOptions={baseURL:""}){const{isQX,isLoon,isSurge,isScriptable,isNode,isBrowser,isShadowrocket,isStash,}=ENV();const methods=["GET","POST","PUT","DELETE","HEAD","OPTIONS","PATCH"];const URL_REGEX=/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;function send(method,options){options=typeof options==="string"?{url:options}:options;const baseURL=defaultOptions.baseURL;if(baseURL&&!URL_REGEX.test(options.url||"")){options.url=baseURL?baseURL+options.url:options.url}if(options.body&&options.headers&&!options.headers["Content-Type"]){options.headers["Content-Type"]="application/x-www-form-urlencoded"}options={...defaultOptions,...options};const timeout=options.timeout;const events={...{onRequest:()=>{},onResponse:(resp)=>resp,onTimeout:()=>{},},...options.events,};events.onRequest(method,options);let worker;if(isQX){worker=$task.fetch({method,...options})}else if(isLoon||isSurge||isNode||isShadowrocket||isStash){worker=new Promise((resolve,reject)=>{const request=isNode?require("request"):$httpClient;request[method.toLowerCase()](options,(err,response,body)=>{if(err)reject(err);else resolve({statusCode:response.status||response.statusCode,headers:response.headers,body,})})})}else if(isScriptable){const request=new Request(options.url);request.method=method;request.headers=options.headers;request.body=options.body;worker=new Promise((resolve,reject)=>{request.loadString().then((body)=>{resolve({statusCode:request.response.statusCode,headers:request.response.headers,body,})}).catch((err)=>reject(err))})}else if(isBrowser){worker=new Promise((resolve,reject)=>{fetch(options.url,{method,headers:options.headers,body:options.body,}).then((response)=>response.json()).then((response)=>resolve({statusCode:response.status,headers:response.headers,body:response.data,})).catch(reject)})}let timeoutid;const timer=timeout?new Promise((_,reject)=>{timeoutid=setTimeout(()=>{events.onTimeout();return reject(`${method}URL:${options.url}exceeds the timeout ${timeout}ms`)},timeout)}):null;return(timer?Promise.race([timer,worker]).then((res)=>{clearTimeout(timeoutid);return res}):worker).then((resp)=>events.onResponse(resp))}const http={};methods.forEach((method)=>(http[method.toLowerCase()]=(options)=>send(method,options)));return http} 273 | /* prettier-ignore */ 274 | function API(name="untitled",debug=false){const{isQX,isLoon,isSurge,isScriptable,isNode,isShadowrocket,isStash,}=ENV();return new(class{constructor(name,debug){this.name=name;this.debug=debug;this.http=HTTP();this.env=ENV();this.node=(()=>{if(isNode){const fs=require("fs");return{fs}}else{return null}})();this.initCache();const delay=(t,v)=>new Promise(function(resolve){setTimeout(resolve.bind(null,v),t)});Promise.prototype.delay=function(t){return this.then(function(v){return delay(t,v)})}}initCache(){if(isQX)this.cache=JSON.parse($prefs.valueForKey(this.name)||"{}");if(isLoon||isSurge||isStash||isShadowrocket)this.cache=JSON.parse($persistentStore.read(this.name)||"{}");if(isNode){let fpath="root.json";if(!this.node.fs.existsSync(fpath)){this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},(err)=>console.log(err))}this.root={};fpath=`${this.name}.json`;if(!this.node.fs.existsSync(fpath)){this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},(err)=>console.log(err));this.cache={}}else{this.cache=JSON.parse(this.node.fs.readFileSync(`${this.name}.json`))}}}persistCache(){const data=JSON.stringify(this.cache,null,2);if(isQX)$prefs.setValueForKey(data,this.name);if(isLoon||isSurge||isStash||isShadowrocket)$persistentStore.write(data,this.name);if(isNode){this.node.fs.writeFileSync(`${this.name}.json`,data,{flag:"w"},(err)=>console.log(err));this.node.fs.writeFileSync("root.json",JSON.stringify(this.root,null,2),{flag:"w"},(err)=>console.log(err))}}write(data,key){this.log(`SET ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.write(data,key)}if(isQX){return $prefs.setValueForKey(data,key)}if(isNode){this.root[key]=data}}else{this.cache[key]=data}this.persistCache()}read(key){this.log(`READ ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.read(key)}if(isQX){return $prefs.valueForKey(key)}if(isNode){return this.root[key]}}else{return this.cache[key]}}delete(key){this.log(`DELETE ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.write(null,key)}if(isQX){return $prefs.removeValueForKey(key)}if(isNode){delete this.root[key]}}else{delete this.cache[key]}this.persistCache()}notify(title,subtitle="",content="",options={}){const openURL=options["open-url"];const mediaURL=options["media-url"];if(isQX)$notify(title,subtitle,content,options);if(isSurge){$notification.post(title,subtitle,content+`${mediaURL?"\n多媒体:"+mediaURL:""}`,{url:openURL})}if(isLoon||isStash||isShadowrocket){let opts={};if(openURL)opts["openUrl"]=openURL;if(mediaURL)opts["mediaUrl"]=mediaURL;if(JSON.stringify(opts)==="{}"){$notification.post(title,subtitle,content)}else{$notification.post(title,subtitle,content,opts)}}if(isNode||isScriptable){const content_=content+(openURL?`\n点击跳转:${openURL}`:"")+(mediaURL?`\n多媒体:${mediaURL}`:"");if(isJSBox){const push=require("push");push.schedule({title:title,body:(subtitle?subtitle+"\n":"")+content_,})}else{console.log(`${title}\n${subtitle}\n${content_}\n\n`)}}}log(msg){if(this.debug)console.log(`[${this.name}]LOG:${this.stringify(msg)}`)}info(msg){console.log(`[${this.name}]INFO:${this.stringify(msg)}`)}error(msg){console.log(`[${this.name}]ERROR:${this.stringify(msg)}`)}wait(millisec){return new Promise((resolve)=>setTimeout(resolve,millisec))}done(value={}){if(isQX||isLoon||isSurge||isStash||isShadowrocket){$done(value)}else if(isNode&&!isJSBox){if(typeof $context!=="undefined"){$context.headers=value.headers;$context.statusCode=value.statusCode;$context.body=value.body}}}stringify(obj_or_str){if(typeof obj_or_str==="string"||obj_or_str instanceof String)return obj_or_str;else try{return JSON.stringify(obj_or_str,null,2)}catch(err){return"[object Object]"}}})(name,debug)} 275 | -------------------------------------------------------------------------------- /icon/github-black.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dompling/Script/5cc6c7b36072bc0d60f80a688ceddf2a87864f8b/icon/github-black.jpg -------------------------------------------------------------------------------- /icon/github-white.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dompling/Script/5cc6c7b36072bc0d60f80a688ceddf2a87864f8b/icon/github-white.jpg -------------------------------------------------------------------------------- /icon/setTime.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dompling/Script/5cc6c7b36072bc0d60f80a688ceddf2a87864f8b/icon/setTime.png -------------------------------------------------------------------------------- /image/1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dompling/Script/5cc6c7b36072bc0d60f80a688ceddf2a87864f8b/image/1.jpeg -------------------------------------------------------------------------------- /image/2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dompling/Script/5cc6c7b36072bc0d60f80a688ceddf2a87864f8b/image/2.jpeg -------------------------------------------------------------------------------- /image/3.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dompling/Script/5cc6c7b36072bc0d60f80a688ceddf2a87864f8b/image/3.jpeg -------------------------------------------------------------------------------- /image/ql.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dompling/Script/5cc6c7b36072bc0d60f80a688ceddf2a87864f8b/image/ql.png -------------------------------------------------------------------------------- /jd/JD_extra_cookie.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Author: 2Ya 4 | Github: https://github.com/domping 5 | Version: v1.1.0 6 | 7 | =================== 8 | 使用方式:复制 https://my.m.jd.com/jingdou/index.html 到浏览器打开 ,在 个人中心>京东豆数量页面 自动获取 cookie, 9 | 若弹出成功则正常使用。否则继续再此页面继续刷新一下试试 10 | =================== 11 | 12 | =================== 13 | [MITM] 14 | hostname = api.m.jd.com 15 | 16 | 【Surge脚本配置】: 17 | =================== 18 | [Script] 19 | 获取京东Cookie = type=http-request,pattern=https:\/\/api\.m\.jd\.com\/\?.*functionId=queryJDUserInfo,requires-body=1,max-size=0,script-path=https://raw.githubusercontent.com/dompling/Script/master/jd/JD_extra_cookie.js,script-update-interval=0 20 | 21 | =================== 22 | 【Loon脚本配置】: 23 | =================== 24 | [Script] 25 | http-request https:\/\/api\.m\.jd\.com\/\?.*functionId=queryJDUserInfo tag=获取京东Cookie, script-path=https://raw.githubusercontent.com/dompling/Script/master/jd/JD_extra_cookie.js 26 | 27 | =================== 28 | 【 QX 脚本配置 】 : 29 | =================== 30 | 31 | [rewrite_local] 32 | https:\/\/api\.m\.jd\.com\/\?.*functionId=queryJDUserInfo url script-request-header https://raw.githubusercontent.com/dompling/Script/master/jd/JD_extra_cookie.js 33 | 34 | */ 35 | 36 | const APIKey = "CookiesJD"; 37 | const $ = new API("ql", false); 38 | const CacheKey = `#${APIKey}`; 39 | $.KEY_sessions = "#chavy_boxjs_sessions"; 40 | 41 | const jdHelp = JSON.parse($.read("#jd_ck_remark") || "{}"); 42 | let remark = []; 43 | try { 44 | remark = JSON.parse(jdHelp.remark || "[]"); 45 | } catch (e) { 46 | console.log(e); 47 | } 48 | 49 | function getUsername(ck) { 50 | if (!ck) return ""; 51 | return decodeURIComponent(ck.match(/pt_pin=([^; ]+)(?=;?)/)[1]); 52 | } 53 | 54 | async function getScriptUrl() { 55 | const response = await $.http.get({ 56 | url: "https://raw.githubusercontent.com/dompling/Script/master/jd/ql_api.js", 57 | }); 58 | return response.body; 59 | } 60 | 61 | const mute = "#cks_get_mute"; 62 | $.mute = $.read(mute); 63 | 64 | (async () => { 65 | const ql_script = (await getScriptUrl()) || ""; 66 | eval(ql_script); 67 | await $.ql.initial(); 68 | 69 | if ($.ql) { 70 | $.ql.asyncCookie = async (cookieValue, name = "JD_WSCK") => { 71 | try { 72 | $.info(`青龙${name}登陆同步`); 73 | let qlCk = await $.ql.select(name); 74 | if (!qlCk.data) return; 75 | qlCk = qlCk.data; 76 | const DecodeName = getUsername(cookieValue); 77 | const current = qlCk.find( 78 | (item) => getUsername(item.value) === DecodeName 79 | ); 80 | if (current && current.value === cookieValue) { 81 | $.info("该账号无需更新"); 82 | return; 83 | } 84 | 85 | let remarks = ""; 86 | remarks = remark.find((item) => item.username === DecodeName); 87 | if (remarks) { 88 | remarks = 89 | name === "JD_WSCK" 90 | ? remarks.nickname 91 | : `${remarks.nickname}&${remarks.remark}&${remarks.qywxUserId}`; 92 | } 93 | let response; 94 | if (current) { 95 | current.value = cookieValue; 96 | response = await $.ql.edit({ 97 | name, 98 | remarks: current.remarks || remarks, 99 | value: cookieValue, 100 | id: current.id, 101 | }); 102 | if (response.data.status === 1) { 103 | response = await $.ql.enabled([current.id]); 104 | } 105 | } else { 106 | response = await $.ql.add([ 107 | { name: name, value: cookieValue, remarks: remarks }, 108 | ]); 109 | } 110 | $.info(JSON.stringify(response)); 111 | if ($.mute === "true" && response.code === 200) { 112 | return $.info("用户名: " + DecodeName + `同步${name}更新青龙成功🎉`); 113 | } else if (response.code === 200) { 114 | $.notify( 115 | "用户名: " + DecodeName, 116 | $.ql_config.ip, 117 | `同步${name}更新青龙成功🎉` 118 | ); 119 | } else { 120 | $.error("青龙同步失败"); 121 | } 122 | } catch (e) { 123 | $.error(e); 124 | } 125 | }; 126 | } 127 | if ($request) await GetCookie(); 128 | })() 129 | .catch((e) => { 130 | $.log(e); 131 | }) 132 | .finally(() => { 133 | $.done(); 134 | }); 135 | 136 | function getCache() { 137 | return JSON.parse($.read(CacheKey) || "[]"); 138 | } 139 | 140 | function updateJDHelp(username) { 141 | if (remark.length) { 142 | const newRemark = remark.map((item) => { 143 | if (item.username === username) { 144 | return { ...item, status: "正常" }; 145 | } 146 | return item; 147 | }); 148 | jdHelp.remark = JSON.stringify(newRemark, null, `\t`); 149 | $.write(JSON.stringify(jdHelp), "#jd_ck_remark"); 150 | } 151 | } 152 | 153 | async function GetCookie() { 154 | const CV = `${$request.headers["Cookie"] || $request.headers["cookie"]};`; 155 | 156 | if ( 157 | $request.url.indexOf("queryJDUserInfo") > -1 || 158 | $request.url.indexOf("openUpgrade") > -1 159 | ) { 160 | if (CV.match(/(pt_key=.+?pt_pin=|pt_pin=.+?pt_key=)/)) { 161 | const CookieValue = CV.match(/pt_key=.+?;/) + CV.match(/pt_pin=.+?;/); 162 | if (CookieValue.indexOf("fake_") > -1) return console.log("异常账号"); 163 | const DecodeName = getUsername(CookieValue); 164 | let updateIndex = null, 165 | CookieName, 166 | tipPrefix; 167 | 168 | const CookiesData = getCache(); 169 | const updateCookiesData = [...CookiesData]; 170 | 171 | CookiesData.forEach((item, index) => { 172 | if (getUsername(item.cookie) === DecodeName) updateIndex = index; 173 | }); 174 | 175 | if ($.ql) { 176 | $.ql.initial(); 177 | await $.ql.asyncCookie(CookieValue, "JD_COOKIE"); 178 | } 179 | 180 | if (updateIndex !== null) { 181 | updateCookiesData[updateIndex].cookie = CookieValue; 182 | CookieName = "【账号" + (updateIndex + 1) + "】"; 183 | tipPrefix = "更新京东"; 184 | } else { 185 | updateCookiesData.push({ 186 | userName: DecodeName, 187 | cookie: CookieValue, 188 | }); 189 | CookieName = "【账号" + updateCookiesData.length + "】"; 190 | tipPrefix = "首次写入京东"; 191 | } 192 | const cacheValue = JSON.stringify(updateCookiesData, null, `\t`); 193 | $.write(cacheValue, CacheKey); 194 | updateJDHelp(DecodeName); 195 | 196 | if ($.mute === "true") { 197 | return console.log( 198 | "用户名: " + DecodeName + tipPrefix + CookieName + "Cookie成功 🎉" 199 | ); 200 | } 201 | $.notify( 202 | "用户名: " + DecodeName, 203 | "", 204 | tipPrefix + CookieName + "Cookie成功 🎉", 205 | { "update-pasteboard": CookieValue } 206 | ); 207 | } else { 208 | console.log("ck 写入失败,未找到相关 ck"); 209 | } 210 | } else if ( 211 | $request.headers && 212 | ($request.url.indexOf("newUserInfo") > -1 || 213 | $request.url.indexOf("userBasicInfos") > -1) 214 | ) { 215 | if (CV.match(/wskey=([^=;]+?);/)[1]) { 216 | const wskey = CV.match(/wskey=([^=;]+?);/)[1]; 217 | 218 | const respBody = JSON.parse($response.body); 219 | let pin = ""; 220 | if (respBody.userInfoSns) { 221 | pin = respBody.userInfoSns.unickName; 222 | } 223 | if (respBody.basicUserInfo) { 224 | const nameInfo = respBody.basicUserInfo.find( 225 | (item) => item.functionId === "nameInfo" 226 | ); 227 | if (nameInfo) pin = nameInfo.content; 228 | } 229 | 230 | const code = `wskey=${wskey};pt_pin=${pin};`; 231 | 232 | const username = getUsername(code); 233 | const CookiesData = getCache(); 234 | let updateIndex = false; 235 | console.log(`用户名:${username}`); 236 | console.log(`同步 wskey: ${code}`); 237 | CookiesData.forEach((item, index) => { 238 | if (item.userName === username) { 239 | updateIndex = index; 240 | } 241 | }); 242 | 243 | if ($.ql) { 244 | $.ql.initial(); 245 | await $.ql.asyncCookie(code); 246 | } 247 | 248 | let text; 249 | if (updateIndex === false) { 250 | CookiesData.push({ 251 | userName: username, 252 | wskey: wskey, 253 | }); 254 | text = `新增`; 255 | } else { 256 | CookiesData[updateIndex].wskey = wskey; 257 | text = `修改`; 258 | } 259 | $.write(JSON.stringify(CookiesData, null, `\t`), CacheKey); 260 | if ($.mute === "true") { 261 | return console.log("用户名: " + username + `${text}wskey成功 🎉`); 262 | } 263 | return $.notify("用户名: " + username, "", `${text}wskey成功 🎉`, { 264 | "update-pasteboard": code, 265 | }); 266 | } 267 | } else { 268 | console.log("未匹配到相关信息,退出抓包"); 269 | } 270 | } 271 | 272 | /* prettier-ignore */ 273 | function ENV(){const isJSBox=typeof require=="function"&&typeof $jsbox!="undefined";return{isQX:typeof $task!=="undefined",isLoon:typeof $loon!=="undefined",isSurge:typeof $httpClient!=="undefined"&&typeof $utils!=="undefined",isBrowser:typeof document!=="undefined",isNode:typeof require=="function"&&!isJSBox,isJSBox,isRequest:typeof $request!=="undefined",isScriptable:typeof importModule!=="undefined",isShadowrocket:"undefined"!==typeof $rocket,isStash:"undefined"!==typeof $environment&&$environment["stash-version"]}} 274 | /* prettier-ignore */ 275 | function HTTP(defaultOptions={baseURL:""}){const{isQX,isLoon,isSurge,isScriptable,isNode,isBrowser,isShadowrocket,isStash,}=ENV();const methods=["GET","POST","PUT","DELETE","HEAD","OPTIONS","PATCH"];const URL_REGEX=/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;function send(method,options){options=typeof options==="string"?{url:options}:options;const baseURL=defaultOptions.baseURL;if(baseURL&&!URL_REGEX.test(options.url||"")){options.url=baseURL?baseURL+options.url:options.url}if(options.body&&options.headers&&!options.headers["Content-Type"]){options.headers["Content-Type"]="application/x-www-form-urlencoded"}options={...defaultOptions,...options};const timeout=options.timeout;const events={...{onRequest:()=>{},onResponse:(resp)=>resp,onTimeout:()=>{},},...options.events,};events.onRequest(method,options);let worker;if(isQX){worker=$task.fetch({method,...options})}else if(isLoon||isSurge||isNode||isShadowrocket||isStash){worker=new Promise((resolve,reject)=>{const request=isNode?require("request"):$httpClient;request[method.toLowerCase()](options,(err,response,body)=>{if(err)reject(err);else resolve({statusCode:response.status||response.statusCode,headers:response.headers,body,})})})}else if(isScriptable){const request=new Request(options.url);request.method=method;request.headers=options.headers;request.body=options.body;worker=new Promise((resolve,reject)=>{request.loadString().then((body)=>{resolve({statusCode:request.response.statusCode,headers:request.response.headers,body,})}).catch((err)=>reject(err))})}else if(isBrowser){worker=new Promise((resolve,reject)=>{fetch(options.url,{method,headers:options.headers,body:options.body,}).then((response)=>response.json()).then((response)=>resolve({statusCode:response.status,headers:response.headers,body:response.data,})).catch(reject)})}let timeoutid;const timer=timeout?new Promise((_,reject)=>{timeoutid=setTimeout(()=>{events.onTimeout();return reject(`${method}URL:${options.url}exceeds the timeout ${timeout}ms`)},timeout)}):null;return(timer?Promise.race([timer,worker]).then((res)=>{clearTimeout(timeoutid);return res}):worker).then((resp)=>events.onResponse(resp))}const http={};methods.forEach((method)=>(http[method.toLowerCase()]=(options)=>send(method,options)));return http} 276 | /* prettier-ignore */ 277 | function API(name="untitled",debug=false){const{isQX,isLoon,isSurge,isScriptable,isNode,isShadowrocket,isStash,isJSBox}=ENV();return new(class{constructor(name,debug){this.name=name;this.debug=debug;this.http=HTTP();this.env=ENV();this.node=(()=>{if(isNode){const fs=require("fs");return{fs}}else{return null}})();this.initCache();const delay=(t,v)=>new Promise(function(resolve){setTimeout(resolve.bind(null,v),t)});Promise.prototype.delay=function(t){return this.then(function(v){return delay(t,v)})}}initCache(){if(isQX)this.cache=JSON.parse($prefs.valueForKey(this.name)||"{}");if(isLoon||isSurge||isStash||isShadowrocket)this.cache=JSON.parse($persistentStore.read(this.name)||"{}");if(isNode){let fpath="root.json";if(!this.node.fs.existsSync(fpath)){this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},(err)=>console.log(err))}this.root={};fpath=`${this.name}.json`;if(!this.node.fs.existsSync(fpath)){this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},(err)=>console.log(err));this.cache={}}else{this.cache=JSON.parse(this.node.fs.readFileSync(`${this.name}.json`))}}}persistCache(){const data=JSON.stringify(this.cache,null,2);if(isQX)$prefs.setValueForKey(data,this.name);if(isLoon||isSurge||isStash||isShadowrocket)$persistentStore.write(data,this.name);if(isNode){this.node.fs.writeFileSync(`${this.name}.json`,data,{flag:"w"},(err)=>console.log(err));this.node.fs.writeFileSync("root.json",JSON.stringify(this.root,null,2),{flag:"w"},(err)=>console.log(err))}}write(data,key){this.log(`SET ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.write(data,key)}if(isQX){return $prefs.setValueForKey(data,key)}if(isNode){this.root[key]=data}}else{this.cache[key]=data}this.persistCache()}read(key){this.log(`READ ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.read(key)}if(isQX){return $prefs.valueForKey(key)}if(isNode){return this.root[key]}}else{return this.cache[key]}}delete(key){this.log(`DELETE ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.write(null,key)}if(isQX){return $prefs.removeValueForKey(key)}if(isNode){delete this.root[key]}}else{delete this.cache[key]}this.persistCache()}notify(title,subtitle="",content="",options={}){const openURL=options["open-url"];const mediaURL=options["media-url"];if(isQX)$notify(title,subtitle,content,options);if(isSurge){$notification.post(title,subtitle,content+`${mediaURL?"\n多媒体:"+mediaURL:""}`,{url:openURL})}if(isLoon||isStash||isShadowrocket){let opts={};if(openURL)opts["openUrl"]=openURL;if(mediaURL)opts["mediaUrl"]=mediaURL;if(JSON.stringify(opts)==="{}"){$notification.post(title,subtitle,content)}else{$notification.post(title,subtitle,content,opts)}}if(isNode||isScriptable){const content_=content+(openURL?`\n点击跳转:${openURL}`:"")+(mediaURL?`\n多媒体:${mediaURL}`:"");if(isJSBox){const push=require("push");push.schedule({title:title,body:(subtitle?subtitle+"\n":"")+content_,})}else{console.log(`${title}\n${subtitle}\n${content_}\n\n`)}}}log(msg){if(this.debug)console.log(`[${this.name}]LOG:${this.stringify(msg)}`)}info(msg){console.log(`[${this.name}]INFO:${this.stringify(msg)}`)}error(msg){console.log(`[${this.name}]ERROR:${this.stringify(msg)}`)}wait(millisec){return new Promise((resolve)=>setTimeout(resolve,millisec))}done(value={}){if(isQX||isLoon||isSurge||isStash||isShadowrocket){$done(value)}else if(isNode&&!isJSBox){if(typeof $context!=="undefined"){$context.headers=value.headers;$context.statusCode=value.statusCode;$context.body=value.body}}}stringify(obj_or_str){if(typeof obj_or_str==="string"||obj_or_str instanceof String)return obj_or_str;else try{return JSON.stringify(obj_or_str,null,2)}catch(err){return"[object Object]"}}})(name,debug)} 278 | -------------------------------------------------------------------------------- /jd/JD_extra_sign.js: -------------------------------------------------------------------------------- 1 | /* 2 | Author: 2Ya 3 | Description: 本脚本使用的野比大佬的多合一签到 原脚本地址:https://raw.githubusercontent.com/NobyDa/Script/master/JD-DailyBonus/JD_DailyBonus.js 4 | Github: https://github.com/domping 5 | =================== 6 | 【task】 7 | =================== 8 | 1 0 * * * https://raw.githubusercontent.com/dompling/Script/master/jd/JD_extra_sign.js 9 | 10 | [获取 ck] 11 | 使用方式:复制 https://home.m.jd.com/myJd/newhome.action 到浏览器打开 ,在个人中心自动获取 cookie, 12 | 若弹出成功则正常使用。否则继续再此页面继续刷新一下试试 13 | =================== 14 | [MITM] 15 | hostname = wq.jd.com 16 | 17 | 【Surge脚本配置】: 18 | =================== 19 | [Script] 20 | 获取京东Cookie = type=http-request,pattern=^https:\/\/wq\.jd\.com\/user_new\/info\/GetJDUserInfoUnion,requires-body=1,max-size=0,script-path=https://raw.githubusercontent.com/dompling/Script/master/jd/JD_extra_cookie.js,script-update-interval=0 21 | 22 | =================== 23 | 【Loon脚本配置】: 24 | =================== 25 | [Script] 26 | http-request https:\/\/wq\.jd\.com\/user_new\/info\/GetJDUserInfoUnion tag=获取京东Cookie, script-path=https://raw.githubusercontent.com/dompling/Script/master/jd/JD_extra_cookie.js 27 | 28 | =================== 29 | 【 QX 脚本配置 】 : 30 | =================== 31 | 32 | [rewrite_local] 33 | https:\/\/wq\.jd\.com\/user_new\/info\/GetJDUserInfoUnion url script-request-header https://raw.githubusercontent.com/dompling/Script/master/jd/JD_extra_cookie.js 34 | 35 | */ 36 | const scriptURL = 37 | 'https://raw.githubusercontent.com/NobyDa/Script/master/JD-DailyBonus/JD_DailyBonus.js'; 38 | const APIKey = 'CookiesJD'; 39 | const CookieJD = '#CookieJD'; 40 | const CookieJD2 = '#CookieJD2'; 41 | let boxjs = 'boxjs.net'; 42 | const $ = new API(APIKey, true); 43 | const CacheKey = `#${APIKey}`; 44 | let cookies = []; 45 | let cookie1 = $.read(CookieJD) || ''; 46 | let cookie2 = $.read(CookieJD2) || ''; 47 | let script = '', 48 | script_text = ''; 49 | try { 50 | cookies = getCache(); 51 | boxjs = $.read('#BoxJSDomain') || boxjs; 52 | const ck1Name = getUsername(cookie1); 53 | const ck2Name = getUsername(cookie2); 54 | if (ck1Name) { 55 | const push1 = cookies.find((item) => { 56 | const u = getUsername(item.cookie); 57 | return u === ck1Name; 58 | }); 59 | if (!push1) { 60 | cookies.push({ 61 | userName: ck1Name, 62 | cookie: push1, 63 | }); 64 | } 65 | } 66 | if (ck2Name) { 67 | const push2 = cookies.find((item) => { 68 | const u = getUsername(item.cookie); 69 | return u === ck2Name; 70 | }); 71 | if (!push2) { 72 | cookies.push({ 73 | userName: ck2Name, 74 | cookie: push2, 75 | }); 76 | } 77 | } 78 | } catch (e) { 79 | $.log(e); 80 | } 81 | 82 | (async () => { 83 | const saveCookies = []; 84 | const len = cookies.length; 85 | const n = 2; //假设每行显示4个 86 | const lineNum = len % n === 0 ? len / n : Math.floor(len / n + 1); 87 | for (let i = 0; i < lineNum; i++) { 88 | saveCookies.push(cookies.slice(i * n, i * n + n)); 89 | } 90 | script = (await getScriptUrl(scriptURL)) || ''; 91 | for (let index = 0; index < saveCookies.length; index++) { 92 | const item = saveCookies[index]; 93 | $.write(item[0].cookie, CookieJD); 94 | $.log(`京东账号:${item[0].userName}`); 95 | if (item.length > 1) { 96 | $.write(item[1].cookie, CookieJD2); 97 | $.log(`京东账号:${item[1].userName}`); 98 | } 99 | const cached_logs = []; 100 | await new Promise((rslve) => { 101 | script_text = script 102 | .replace(/\$done/g, 'rslve') 103 | .replace(/\$\.done/g, 'rslve'); 104 | $.log('执行多合一签到'); 105 | try { 106 | eval(script_text); 107 | } catch (e) { 108 | cached_logs.push(e); 109 | rslve(e); 110 | } 111 | }); 112 | $.log(cached_logs); 113 | } 114 | })() 115 | .catch((e) => { 116 | $.log(JSON.stringify(e)); 117 | }) 118 | .finally(() => { 119 | $.write(cookie1, CookieJD); 120 | $.write(cookie2, CookieJD2); 121 | $.done(); 122 | }); 123 | 124 | async function getScriptUrl(uri) { 125 | const response = await $.http.get({ url: uri }); 126 | return response.body; 127 | } 128 | 129 | function getCache() { 130 | var cache = $.read(CacheKey) || '[]'; 131 | return JSON.parse(cache); 132 | } 133 | 134 | function getUsername(ck) { 135 | if (!ck) return ''; 136 | return ck.match(/pin=(.+?);/)[1]; 137 | } 138 | 139 | /* prettier-ignore */ 140 | function ENV(){const isJSBox=typeof require=="function"&&typeof $jsbox!="undefined";return{isQX:typeof $task!=="undefined",isLoon:typeof $loon!=="undefined",isSurge:typeof $httpClient!=="undefined"&&typeof $utils!=="undefined",isBrowser:typeof document!=="undefined",isNode:typeof require=="function"&&!isJSBox,isJSBox,isRequest:typeof $request!=="undefined",isScriptable:typeof importModule!=="undefined",isShadowrocket:"undefined"!==typeof $rocket,isStash:"undefined"!==typeof $environment&&$environment["stash-version"]}} 141 | /* prettier-ignore */ 142 | function HTTP(defaultOptions={baseURL:""}){const{isQX,isLoon,isSurge,isScriptable,isNode,isBrowser,isShadowrocket,isStash,}=ENV();const methods=["GET","POST","PUT","DELETE","HEAD","OPTIONS","PATCH"];const URL_REGEX=/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;function send(method,options){options=typeof options==="string"?{url:options}:options;const baseURL=defaultOptions.baseURL;if(baseURL&&!URL_REGEX.test(options.url||"")){options.url=baseURL?baseURL+options.url:options.url}if(options.body&&options.headers&&!options.headers["Content-Type"]){options.headers["Content-Type"]="application/x-www-form-urlencoded"}options={...defaultOptions,...options};const timeout=options.timeout;const events={...{onRequest:()=>{},onResponse:(resp)=>resp,onTimeout:()=>{},},...options.events,};events.onRequest(method,options);let worker;if(isQX){worker=$task.fetch({method,...options})}else if(isLoon||isSurge||isNode||isShadowrocket||isStash){worker=new Promise((resolve,reject)=>{const request=isNode?require("request"):$httpClient;request[method.toLowerCase()](options,(err,response,body)=>{if(err)reject(err);else resolve({statusCode:response.status||response.statusCode,headers:response.headers,body,})})})}else if(isScriptable){const request=new Request(options.url);request.method=method;request.headers=options.headers;request.body=options.body;worker=new Promise((resolve,reject)=>{request.loadString().then((body)=>{resolve({statusCode:request.response.statusCode,headers:request.response.headers,body,})}).catch((err)=>reject(err))})}else if(isBrowser){worker=new Promise((resolve,reject)=>{fetch(options.url,{method,headers:options.headers,body:options.body,}).then((response)=>response.json()).then((response)=>resolve({statusCode:response.status,headers:response.headers,body:response.data,})).catch(reject)})}let timeoutid;const timer=timeout?new Promise((_,reject)=>{timeoutid=setTimeout(()=>{events.onTimeout();return reject(`${method}URL:${options.url}exceeds the timeout ${timeout}ms`)},timeout)}):null;return(timer?Promise.race([timer,worker]).then((res)=>{clearTimeout(timeoutid);return res}):worker).then((resp)=>events.onResponse(resp))}const http={};methods.forEach((method)=>(http[method.toLowerCase()]=(options)=>send(method,options)));return http} 143 | /* prettier-ignore */ 144 | function API(name="untitled",debug=false){const{isQX,isLoon,isSurge,isScriptable,isNode,isShadowrocket,isStash,isJSBox}=ENV();return new(class{constructor(name,debug){this.name=name;this.debug=debug;this.http=HTTP();this.env=ENV();this.node=(()=>{if(isNode){const fs=require("fs");return{fs}}else{return null}})();this.initCache();const delay=(t,v)=>new Promise(function(resolve){setTimeout(resolve.bind(null,v),t)});Promise.prototype.delay=function(t){return this.then(function(v){return delay(t,v)})}}initCache(){if(isQX)this.cache=JSON.parse($prefs.valueForKey(this.name)||"{}");if(isLoon||isSurge||isStash||isShadowrocket)this.cache=JSON.parse($persistentStore.read(this.name)||"{}");if(isNode){let fpath="root.json";if(!this.node.fs.existsSync(fpath)){this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},(err)=>console.log(err))}this.root={};fpath=`${this.name}.json`;if(!this.node.fs.existsSync(fpath)){this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},(err)=>console.log(err));this.cache={}}else{this.cache=JSON.parse(this.node.fs.readFileSync(`${this.name}.json`))}}}persistCache(){const data=JSON.stringify(this.cache,null,2);if(isQX)$prefs.setValueForKey(data,this.name);if(isLoon||isSurge||isStash||isShadowrocket)$persistentStore.write(data,this.name);if(isNode){this.node.fs.writeFileSync(`${this.name}.json`,data,{flag:"w"},(err)=>console.log(err));this.node.fs.writeFileSync("root.json",JSON.stringify(this.root,null,2),{flag:"w"},(err)=>console.log(err))}}write(data,key){this.log(`SET ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.write(data,key)}if(isQX){return $prefs.setValueForKey(data,key)}if(isNode){this.root[key]=data}}else{this.cache[key]=data}this.persistCache()}read(key){this.log(`READ ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.read(key)}if(isQX){return $prefs.valueForKey(key)}if(isNode){return this.root[key]}}else{return this.cache[key]}}delete(key){this.log(`DELETE ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.write(null,key)}if(isQX){return $prefs.removeValueForKey(key)}if(isNode){delete this.root[key]}}else{delete this.cache[key]}this.persistCache()}notify(title,subtitle="",content="",options={}){const openURL=options["open-url"];const mediaURL=options["media-url"];if(isQX)$notify(title,subtitle,content,options);if(isSurge){$notification.post(title,subtitle,content+`${mediaURL?"\n多媒体:"+mediaURL:""}`,{url:openURL})}if(isLoon||isStash||isShadowrocket){let opts={};if(openURL)opts["openUrl"]=openURL;if(mediaURL)opts["mediaUrl"]=mediaURL;if(JSON.stringify(opts)==="{}"){$notification.post(title,subtitle,content)}else{$notification.post(title,subtitle,content,opts)}}if(isNode||isScriptable){const content_=content+(openURL?`\n点击跳转:${openURL}`:"")+(mediaURL?`\n多媒体:${mediaURL}`:"");if(isJSBox){const push=require("push");push.schedule({title:title,body:(subtitle?subtitle+"\n":"")+content_,})}else{console.log(`${title}\n${subtitle}\n${content_}\n\n`)}}}log(msg){if(this.debug)console.log(`[${this.name}]LOG:${this.stringify(msg)}`)}info(msg){console.log(`[${this.name}]INFO:${this.stringify(msg)}`)}error(msg){console.log(`[${this.name}]ERROR:${this.stringify(msg)}`)}wait(millisec){return new Promise((resolve)=>setTimeout(resolve,millisec))}done(value={}){if(isQX||isLoon||isSurge||isStash||isShadowrocket){$done(value)}else if(isNode&&!isJSBox){if(typeof $context!=="undefined"){$context.headers=value.headers;$context.statusCode=value.statusCode;$context.body=value.body}}}stringify(obj_or_str){if(typeof obj_or_str==="string"||obj_or_str instanceof String)return obj_or_str;else try{return JSON.stringify(obj_or_str,null,2)}catch(err){return"[object Object]"}}})(name,debug)} 145 | -------------------------------------------------------------------------------- /jd/README.md: -------------------------------------------------------------------------------- 1 | # Script 2 | 3 | > 修改 [野比大佬](https://github.com/NobyDa/Script/tree/master)的,自用代码。额外的账号签到 4 | > 修改 [lxk0301](https://github.com/lxk0301/scripts)大佬代码 818,自用代码。额外的账号签到 5 | 6 | # 特别感谢 7 | 8 | 1. [@NobyDa](https://github.com/NobyDa/Script/tree/master) 9 | 2. [@lxk0301](https://github.com/lxk0301/scripts) 10 | -------------------------------------------------------------------------------- /jd/boxjs_env_to_ql.js: -------------------------------------------------------------------------------- 1 | /* 2 | 青龙 docker 每日自动同步 boxjs cookie 3 | 40 * * * https://raw.githubusercontent.com/dompling/Script/master/jd/boxjs_env_to_ql.js 4 | */ 5 | 6 | const $ = new API("ql", true); 7 | 8 | $.getval = (t) => { 9 | if ($.env.isQX) { 10 | return $prefs.valueForKey(t); 11 | } else { 12 | return $persistentStore.read(t); 13 | } 14 | }; 15 | 16 | $.getdata = (t) => { 17 | function lodash_get(t, s, e) { 18 | const i = s.replace(/\[(\d+)\]/g, ".$1").split("."); 19 | let r = t; 20 | for (const t of i) if (((r = Object(r)[t]), void 0 === r)) return e; 21 | return r; 22 | } 23 | 24 | let s = $.getval(t); 25 | if (/^@/.test(t)) { 26 | const [, e, i] = /^@(.*?)\.(.*?)$/.exec(t), 27 | r = e ? $.getval(e) : ""; 28 | if (r) 29 | try { 30 | const t = JSON.parse(r); 31 | s = t ? lodash_get(t, i, "") : s; 32 | } catch (t) { 33 | s = ""; 34 | } 35 | } 36 | return s; 37 | }; 38 | 39 | const title = "🐉 通知提示"; 40 | const notifyMsg = []; 41 | let envsSync = $.read("ENV_KEY") || `[]`; 42 | 43 | try { 44 | envsSync = JSON.parse(envsSync); 45 | } catch (error) { 46 | envsSync = []; 47 | $.info(error); 48 | } 49 | 50 | try { 51 | envsSync = [JSON.parse($argument)]; 52 | $.info(`传入参数:${$argument}`); 53 | } catch (error) {} 54 | 55 | const envsData = {}; 56 | envsSync.forEach((item) => { 57 | const qlValue = $.getdata(item.BoxJsKey) || ""; 58 | if (!qlValue) return $.error("环境变量值不能为空"); 59 | notifyMsg.push(`${item.BoxJsKey}->${item.qlKey}`); 60 | 61 | envsData[item.BoxJsKey] = { 62 | name: item.qlKey, 63 | value: qlValue, 64 | remarks: item.remark || `BoxJS 上传 Key${item.BoxJsKey}`, 65 | }; 66 | }); 67 | 68 | async function getScriptUrl() { 69 | const response = await $.http.get({ 70 | url: "https://raw.githubusercontent.com/dompling/Script/master/jd/ql_api.js", 71 | }); 72 | return response.body; 73 | } 74 | 75 | (async () => { 76 | const qlData = Object.values(envsData); 77 | if (!qlData.length) return $.notify(title, "同步失败", "环境变量不能为空"); 78 | 79 | const ql_script = (await getScriptUrl()) || ""; 80 | eval(ql_script); 81 | await $.ql.initial(); 82 | 83 | for (let index = 0; index < qlData.length; index++) { 84 | const element = qlData[index]; 85 | const response = await $.ql.select(element.name); 86 | if ( 87 | element.remarks && 88 | element.remarks !== `BoxJS 上传 Key${element.name}` 89 | ) { 90 | response.data = response.data.filter( 91 | (item) => item.remarks === element.remarks 92 | ); 93 | } else { 94 | response.data = response.data.filter( 95 | (item) => item.remarks === `BoxJS 上传 Key${element.name}` 96 | ); 97 | } 98 | if (response.data.length > 0) { 99 | const delIds = response.data.map((item) => item.id); 100 | await $.ql.delete(delIds); 101 | $.log(`清空环境变量${element.name}`); 102 | } 103 | } 104 | 105 | const res = await $.ql.add(qlData); 106 | 107 | if (res.error) { 108 | return $.notify( 109 | title, 110 | "同步失败", 111 | `青龙【${qlKey}】名称只能输入字母数字下划线,且不能以数字开头` 112 | ); 113 | } 114 | 115 | $.info(`上传环境变量`); 116 | $.info(notifyMsg.join(`\n`)); 117 | 118 | if ($.read("mute") !== "true") { 119 | return $.notify(title, `已同步${notifyMsg.length}条`, notifyMsg.join(`\n`)); 120 | } 121 | })() 122 | .catch((e) => { 123 | $.log(JSON.stringify(e)); 124 | }) 125 | .finally(() => { 126 | $.done(); 127 | }); 128 | 129 | /* prettier-ignore */ 130 | function ENV(){const isJSBox=typeof require=="function"&&typeof $jsbox!="undefined";return{isQX:typeof $task!=="undefined",isLoon:typeof $loon!=="undefined",isSurge:typeof $httpClient!=="undefined"&&typeof $utils!=="undefined",isBrowser:typeof document!=="undefined",isNode:typeof require=="function"&&!isJSBox,isJSBox,isRequest:typeof $request!=="undefined",isScriptable:typeof importModule!=="undefined",isShadowrocket:"undefined"!==typeof $rocket,isStash:"undefined"!==typeof $environment&&$environment["stash-version"]}} 131 | /* prettier-ignore */ 132 | function HTTP(defaultOptions={baseURL:""}){const{isQX,isLoon,isSurge,isScriptable,isNode,isBrowser,isShadowrocket,isStash,}=ENV();const methods=["GET","POST","PUT","DELETE","HEAD","OPTIONS","PATCH"];const URL_REGEX=/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;function send(method,options){options=typeof options==="string"?{url:options}:options;const baseURL=defaultOptions.baseURL;if(baseURL&&!URL_REGEX.test(options.url||"")){options.url=baseURL?baseURL+options.url:options.url}if(options.body&&options.headers&&!options.headers["Content-Type"]){options.headers["Content-Type"]="application/x-www-form-urlencoded"}options={...defaultOptions,...options};const timeout=options.timeout;const events={...{onRequest:()=>{},onResponse:(resp)=>resp,onTimeout:()=>{},},...options.events,};events.onRequest(method,options);let worker;if(isQX){worker=$task.fetch({method,...options})}else if(isLoon||isSurge||isNode||isShadowrocket||isStash){worker=new Promise((resolve,reject)=>{const request=isNode?require("request"):$httpClient;request[method.toLowerCase()](options,(err,response,body)=>{if(err)reject(err);else resolve({statusCode:response.status||response.statusCode,headers:response.headers,body,})})})}else if(isScriptable){const request=new Request(options.url);request.method=method;request.headers=options.headers;request.body=options.body;worker=new Promise((resolve,reject)=>{request.loadString().then((body)=>{resolve({statusCode:request.response.statusCode,headers:request.response.headers,body,})}).catch((err)=>reject(err))})}else if(isBrowser){worker=new Promise((resolve,reject)=>{fetch(options.url,{method,headers:options.headers,body:options.body,}).then((response)=>response.json()).then((response)=>resolve({statusCode:response.status,headers:response.headers,body:response.data,})).catch(reject)})}let timeoutid;const timer=timeout?new Promise((_,reject)=>{timeoutid=setTimeout(()=>{events.onTimeout();return reject(`${method}URL:${options.url}exceeds the timeout ${timeout}ms`)},timeout)}):null;return(timer?Promise.race([timer,worker]).then((res)=>{clearTimeout(timeoutid);return res}):worker).then((resp)=>events.onResponse(resp))}const http={};methods.forEach((method)=>(http[method.toLowerCase()]=(options)=>send(method,options)));return http} 133 | /* prettier-ignore */ 134 | function API(name="untitled",debug=false){const{isQX,isLoon,isSurge,isScriptable,isNode,isShadowrocket,isStash,isJSBox}=ENV();return new(class{constructor(name,debug){this.name=name;this.debug=debug;this.http=HTTP();this.env=ENV();this.node=(()=>{if(isNode){const fs=require("fs");return{fs}}else{return null}})();this.initCache();const delay=(t,v)=>new Promise(function(resolve){setTimeout(resolve.bind(null,v),t)});Promise.prototype.delay=function(t){return this.then(function(v){return delay(t,v)})}}initCache(){if(isQX)this.cache=JSON.parse($prefs.valueForKey(this.name)||"{}");if(isLoon||isSurge||isStash||isShadowrocket)this.cache=JSON.parse($persistentStore.read(this.name)||"{}");if(isNode){let fpath="root.json";if(!this.node.fs.existsSync(fpath)){this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},(err)=>console.log(err))}this.root={};fpath=`${this.name}.json`;if(!this.node.fs.existsSync(fpath)){this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},(err)=>console.log(err));this.cache={}}else{this.cache=JSON.parse(this.node.fs.readFileSync(`${this.name}.json`))}}}persistCache(){const data=JSON.stringify(this.cache,null,2);if(isQX)$prefs.setValueForKey(data,this.name);if(isLoon||isSurge||isStash||isShadowrocket)$persistentStore.write(data,this.name);if(isNode){this.node.fs.writeFileSync(`${this.name}.json`,data,{flag:"w"},(err)=>console.log(err));this.node.fs.writeFileSync("root.json",JSON.stringify(this.root,null,2),{flag:"w"},(err)=>console.log(err))}}write(data,key){this.log(`SET ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.write(data,key)}if(isQX){return $prefs.setValueForKey(data,key)}if(isNode){this.root[key]=data}}else{this.cache[key]=data}this.persistCache()}read(key){this.log(`READ ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.read(key)}if(isQX){return $prefs.valueForKey(key)}if(isNode){return this.root[key]}}else{return this.cache[key]}}delete(key){this.log(`DELETE ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.write(null,key)}if(isQX){return $prefs.removeValueForKey(key)}if(isNode){delete this.root[key]}}else{delete this.cache[key]}this.persistCache()}notify(title,subtitle="",content="",options={}){const openURL=options["open-url"];const mediaURL=options["media-url"];if(isQX)$notify(title,subtitle,content,options);if(isSurge){$notification.post(title,subtitle,content+`${mediaURL?"\n多媒体:"+mediaURL:""}`,{url:openURL})}if(isLoon||isStash||isShadowrocket){let opts={};if(openURL)opts["openUrl"]=openURL;if(mediaURL)opts["mediaUrl"]=mediaURL;if(JSON.stringify(opts)==="{}"){$notification.post(title,subtitle,content)}else{$notification.post(title,subtitle,content,opts)}}if(isNode||isScriptable){const content_=content+(openURL?`\n点击跳转:${openURL}`:"")+(mediaURL?`\n多媒体:${mediaURL}`:"");if(isJSBox){const push=require("push");push.schedule({title:title,body:(subtitle?subtitle+"\n":"")+content_,})}else{console.log(`${title}\n${subtitle}\n${content_}\n\n`)}}}log(msg){if(this.debug)console.log(`[${this.name}]LOG:${this.stringify(msg)}`)}info(msg){console.log(`[${this.name}]INFO:${this.stringify(msg)}`)}error(msg){console.log(`[${this.name}]ERROR:${this.stringify(msg)}`)}wait(millisec){return new Promise((resolve)=>setTimeout(resolve,millisec))}done(value={}){if(isQX||isLoon||isSurge||isStash||isShadowrocket){$done(value)}else if(isNode&&!isJSBox){if(typeof $context!=="undefined"){$context.headers=value.headers;$context.statusCode=value.statusCode;$context.body=value.body}}}stringify(obj_or_str){if(typeof obj_or_str==="string"||obj_or_str instanceof String)return obj_or_str;else try{return JSON.stringify(obj_or_str,null,2)}catch(err){return"[object Object]"}}})(name,debug)} 135 | -------------------------------------------------------------------------------- /jd/jd_ck_del.js: -------------------------------------------------------------------------------- 1 | const $ = new API('jd_ck_remark', true) 2 | const delKey = '#del_condition' 3 | let condition = $.read(delKey) 4 | const CacheKey = `#CookiesJD` 5 | let jdHelp = [] 6 | let cookies = [] 7 | try { 8 | cookies = JSON.parse($.read(CacheKey) || '[]') 9 | jdHelp = JSON.parse($.read('remark') || '[]') 10 | } catch (e) { 11 | $.error(e) 12 | } 13 | try { 14 | if (condition) { 15 | condition = condition.split(',') 16 | $.log('当前删除条件') 17 | $.log(JSON.stringify(condition, null, `\t`)) 18 | 19 | const delData = [] 20 | const newData = cookies.filter((item, index) => { 21 | const where = 22 | condition.indexOf(`${index + 1}`) !== -1 || 23 | condition.indexOf(item.userName) !== -1 24 | if (where) delData.push(item.userName) 25 | return !where 26 | }) 27 | const newJDHelp = jdHelp.filter((item) => { 28 | return delData.indexOf(item.username) === -1 29 | }) 30 | 31 | if (cookies.length !== newData.length) { 32 | $.log('=============删除信息=============') 33 | $.info(JSON.stringify(delData, null, `\t`)) 34 | $.log('=================================') 35 | $.write(JSON.stringify(newData, null, `\t`), CacheKey) 36 | $.write(JSON.stringify(newJDHelp, null, `\t`), 'remark') 37 | $.notify( 38 | '删除成功', 39 | '', 40 | `已删除 CK ${cookies.length - newData.length} 条\n${delData.join(',')}` 41 | ) 42 | $.write('', delKey) 43 | } 44 | } 45 | } catch (e) { 46 | $.error(e) 47 | $.notify('删除失败', '', '删除条件异常') 48 | } 49 | $.done({}) 50 | 51 | 52 | 53 | /* prettier-ignore */ 54 | function ENV(){const isJSBox=typeof require=="function"&&typeof $jsbox!="undefined";return{isQX:typeof $task!=="undefined",isLoon:typeof $loon!=="undefined",isSurge:typeof $httpClient!=="undefined"&&typeof $utils!=="undefined",isBrowser:typeof document!=="undefined",isNode:typeof require=="function"&&!isJSBox,isJSBox,isRequest:typeof $request!=="undefined",isScriptable:typeof importModule!=="undefined",isShadowrocket:"undefined"!==typeof $rocket,isStash:"undefined"!==typeof $environment&&$environment["stash-version"]}} 55 | /* prettier-ignore */ 56 | function HTTP(defaultOptions={baseURL:""}){const{isQX,isLoon,isSurge,isScriptable,isNode,isBrowser,isShadowrocket,isStash,}=ENV();const methods=["GET","POST","PUT","DELETE","HEAD","OPTIONS","PATCH"];const URL_REGEX=/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;function send(method,options){options=typeof options==="string"?{url:options}:options;const baseURL=defaultOptions.baseURL;if(baseURL&&!URL_REGEX.test(options.url||"")){options.url=baseURL?baseURL+options.url:options.url}if(options.body&&options.headers&&!options.headers["Content-Type"]){options.headers["Content-Type"]="application/x-www-form-urlencoded"}options={...defaultOptions,...options};const timeout=options.timeout;const events={...{onRequest:()=>{},onResponse:(resp)=>resp,onTimeout:()=>{},},...options.events,};events.onRequest(method,options);let worker;if(isQX){worker=$task.fetch({method,...options})}else if(isLoon||isSurge||isNode||isShadowrocket||isStash){worker=new Promise((resolve,reject)=>{const request=isNode?require("request"):$httpClient;request[method.toLowerCase()](options,(err,response,body)=>{if(err)reject(err);else resolve({statusCode:response.status||response.statusCode,headers:response.headers,body,})})})}else if(isScriptable){const request=new Request(options.url);request.method=method;request.headers=options.headers;request.body=options.body;worker=new Promise((resolve,reject)=>{request.loadString().then((body)=>{resolve({statusCode:request.response.statusCode,headers:request.response.headers,body,})}).catch((err)=>reject(err))})}else if(isBrowser){worker=new Promise((resolve,reject)=>{fetch(options.url,{method,headers:options.headers,body:options.body,}).then((response)=>response.json()).then((response)=>resolve({statusCode:response.status,headers:response.headers,body:response.data,})).catch(reject)})}let timeoutid;const timer=timeout?new Promise((_,reject)=>{timeoutid=setTimeout(()=>{events.onTimeout();return reject(`${method}URL:${options.url}exceeds the timeout ${timeout}ms`)},timeout)}):null;return(timer?Promise.race([timer,worker]).then((res)=>{clearTimeout(timeoutid);return res}):worker).then((resp)=>events.onResponse(resp))}const http={};methods.forEach((method)=>(http[method.toLowerCase()]=(options)=>send(method,options)));return http} 57 | /* prettier-ignore */ 58 | function API(name="untitled",debug=false){const{isQX,isLoon,isSurge,isScriptable,isNode,isShadowrocket,isStash,isJSBox}=ENV();return new(class{constructor(name,debug){this.name=name;this.debug=debug;this.http=HTTP();this.env=ENV();this.node=(()=>{if(isNode){const fs=require("fs");return{fs}}else{return null}})();this.initCache();const delay=(t,v)=>new Promise(function(resolve){setTimeout(resolve.bind(null,v),t)});Promise.prototype.delay=function(t){return this.then(function(v){return delay(t,v)})}}initCache(){if(isQX)this.cache=JSON.parse($prefs.valueForKey(this.name)||"{}");if(isLoon||isSurge||isStash||isShadowrocket)this.cache=JSON.parse($persistentStore.read(this.name)||"{}");if(isNode){let fpath="root.json";if(!this.node.fs.existsSync(fpath)){this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},(err)=>console.log(err))}this.root={};fpath=`${this.name}.json`;if(!this.node.fs.existsSync(fpath)){this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},(err)=>console.log(err));this.cache={}}else{this.cache=JSON.parse(this.node.fs.readFileSync(`${this.name}.json`))}}}persistCache(){const data=JSON.stringify(this.cache,null,2);if(isQX)$prefs.setValueForKey(data,this.name);if(isLoon||isSurge||isStash||isShadowrocket)$persistentStore.write(data,this.name);if(isNode){this.node.fs.writeFileSync(`${this.name}.json`,data,{flag:"w"},(err)=>console.log(err));this.node.fs.writeFileSync("root.json",JSON.stringify(this.root,null,2),{flag:"w"},(err)=>console.log(err))}}write(data,key){this.log(`SET ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.write(data,key)}if(isQX){return $prefs.setValueForKey(data,key)}if(isNode){this.root[key]=data}}else{this.cache[key]=data}this.persistCache()}read(key){this.log(`READ ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.read(key)}if(isQX){return $prefs.valueForKey(key)}if(isNode){return this.root[key]}}else{return this.cache[key]}}delete(key){this.log(`DELETE ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.write(null,key)}if(isQX){return $prefs.removeValueForKey(key)}if(isNode){delete this.root[key]}}else{delete this.cache[key]}this.persistCache()}notify(title,subtitle="",content="",options={}){const openURL=options["open-url"];const mediaURL=options["media-url"];if(isQX)$notify(title,subtitle,content,options);if(isSurge){$notification.post(title,subtitle,content+`${mediaURL?"\n多媒体:"+mediaURL:""}`,{url:openURL})}if(isLoon||isStash||isShadowrocket){let opts={};if(openURL)opts["openUrl"]=openURL;if(mediaURL)opts["mediaUrl"]=mediaURL;if(JSON.stringify(opts)==="{}"){$notification.post(title,subtitle,content)}else{$notification.post(title,subtitle,content,opts)}}if(isNode||isScriptable){const content_=content+(openURL?`\n点击跳转:${openURL}`:"")+(mediaURL?`\n多媒体:${mediaURL}`:"");if(isJSBox){const push=require("push");push.schedule({title:title,body:(subtitle?subtitle+"\n":"")+content_,})}else{console.log(`${title}\n${subtitle}\n${content_}\n\n`)}}}log(msg){if(this.debug)console.log(`[${this.name}]LOG:${this.stringify(msg)}`)}info(msg){console.log(`[${this.name}]INFO:${this.stringify(msg)}`)}error(msg){console.log(`[${this.name}]ERROR:${this.stringify(msg)}`)}wait(millisec){return new Promise((resolve)=>setTimeout(resolve,millisec))}done(value={}){if(isQX||isLoon||isSurge||isStash||isShadowrocket){$done(value)}else if(isNode&&!isJSBox){if(typeof $context!=="undefined"){$context.headers=value.headers;$context.statusCode=value.statusCode;$context.body=value.body}}}stringify(obj_or_str){if(typeof obj_or_str==="string"||obj_or_str instanceof String)return obj_or_str;else try{return JSON.stringify(obj_or_str,null,2)}catch(err){return"[object Object]"}}})(name,debug)} 59 | -------------------------------------------------------------------------------- /jd/jd_cookie_rewrite.sgmodule: -------------------------------------------------------------------------------- 1 | #!name=🟢 京东账号 2 | #!desc=京东 Cookies 模块配置 3 | 4 | [Script] 5 | # > 获取多账号京东Cookie 6 | 7 | 获取多账号京东Cookie = type=http-request,pattern=https:\/\/api\.m\.jd\.com\/api\?.*functionId=queryJDUserInfo,requires-body=1,max-size=0,script-path=https://raw.githubusercontent.com/dompling/Script/master/jd/JD_extra_cookie.js,script-update-interval=0 8 | #app京东Cookie = type=http-request,pattern=https:\/\/api\.m\.jd\.com\/openUpgrade,script-path=https://raw.githubusercontent.com/dompling/Script/master/jd/JD_extra_cookie.js 9 | app京东Wskey = type=http-response,pattern=^https:\/\/api\.m\.jd\.com\/client\.action\?functionId=(newUserInfo|userBasicInfos),requires-body=1,max-size=0,timeout=1000,script-path=https://raw.githubusercontent.com/dompling/Script/master/jd/JD_extra_cookie.js,script-update-interval=0 10 | 11 | [MITM] 12 | hostname = %APPEND% me-api.jd.com,api-dd.jd.com,api.m.jd.com -------------------------------------------------------------------------------- /jd/jd_cookie_search.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Author: 2Ya 4 | Github: https://github.com/domping 5 | ScriptName:京东 ck 多账号备注 + 搜索 6 | ================================== 7 | 给京东账号添加一个备注吧 O(∩_∩)O哈哈~ (适合账号多账号昵称混乱的用户) 8 | ================================== 9 | 使用方法: 10 | 1.添加 boxjs 订阅:https://raw.githubusercontent.com/dompling/Script/master/dompling.boxjs.json 11 | 2.在应用中找到 dompling -> 京东账号 ck 检索 12 | 3.点击右上角运行按钮初始化京东 ck 数据 13 | 4.初始完成之后,给各个账号添加备注就能愉快的搜索你的京东 ck 了。 14 | 5.搜索方式:设置关键字 下标(数组下标从 0 开始)、username(京东 ck 的 pin)、nickname(给京东账号设置的备注昵称), status(正常|未登录) 15 | 搜索示例:0,2Y,正常 16 | 返回结果:返回下标为 0 的,返回 2Y (username|nickname),返回正常状态的 17 | task : 每日九点检查 ck 过期状态 18 | 0 9 * * * https://raw.githubusercontent.com/dompling/Script/master/jd/jd_cookie_search.js 19 | 20 | */ 21 | const noTitle = "登录助手"; 22 | const $ = new API("jd_ck_remark"); 23 | $.msg = ""; 24 | const APIKey = "CookiesJD"; 25 | const CacheKey = `#${APIKey}`; 26 | const remark_key = `remark`; 27 | const searchKey = "keyword"; 28 | const keyword = ($.read(searchKey) || "").split(","); 29 | const cookiesRemark = JSON.parse($.read(remark_key) || "[]"); 30 | const CookiesJD = JSON.parse($.read(CacheKey) || "[]"); 31 | const CookieJD = $.read("#CookieJD"); 32 | const CookieJD2 = $.read("#CookieJD2"); 33 | const ckData = CookiesJD.map((item) => item.cookie); 34 | if (CookieJD) ckData.unshift(CookieJD); 35 | if (CookieJD2) ckData.unshift(CookieJD2); 36 | 37 | console.log("初始化备注开始"); 38 | console.log(`=========== 检测到京东账号:【${ckData.length}】个 ===========`); 39 | 40 | const ckRemarkFormat = {}; 41 | cookiesRemark.forEach((item) => { 42 | ckRemarkFormat[item.username] = item; 43 | }); 44 | (async () => { 45 | const ckFormat = []; 46 | const notLogin = []; 47 | let ckIndex = 1; 48 | for (const cookie of ckData) { 49 | try { 50 | let username = cookie.match(/pt_pin=(.+?);/)[1]; 51 | username = decodeURIComponent(username); 52 | console.log("==================================="); 53 | console.log(`检查开始:账号 ${username} 【登陆状态】`); 54 | const response = await isLogin(cookie); 55 | const status = response.retcode === "0" ? "正常" : "未登录"; 56 | 57 | let avatar = "", 58 | nickname = "", 59 | isPlusVip = 0, 60 | beanNum = 0, 61 | fruit = "", 62 | jdPet = "", 63 | mobile = ckRemarkFormat[username] 64 | ? ckRemarkFormat[username].mobile 65 | : ""; 66 | if (response.retcode === "0") { 67 | isPlusVip = response.data.userInfo.isPlusVip; 68 | beanNum = response.data.assetInfo.beanNum; 69 | avatar = response.data.userInfo.baseInfo.headImageUrl; 70 | nickname = response.data.userInfo.baseInfo.nickname; 71 | console.log("帐号昵称:" + nickname); 72 | if (!mobile) mobile = await getPhoneNumber(cookie); 73 | fruit = await getFruit(cookie); 74 | // jdPet = await PetRequest('energyCollect', cookie) 75 | } 76 | 77 | console.log(`检查结束:账号【${ckIndex}】 ${username}【${status}】`); 78 | console.log("==================================="); 79 | let newRemark = 80 | nickname || 81 | (ckRemarkFormat[username] ? ckRemarkFormat[username].remark : ""); 82 | 83 | const item = { 84 | index: ckIndex, 85 | username, 86 | nickname, 87 | qywxUserId: "", 88 | cardId: "", 89 | paymentCode: "", 90 | avatar, 91 | ...ckRemarkFormat[username], 92 | jdPet, 93 | fruit, 94 | beanNum, 95 | mobile, 96 | isPlusVip, 97 | status, 98 | remark: newRemark, 99 | }; 100 | if (status === "未登录") notLogin.push(item); 101 | ckFormat.push(item); 102 | ckIndex++; 103 | } catch (error) { 104 | console.log(error); 105 | } 106 | } 107 | $.msg = "检索完成,所有账号状态正常!"; 108 | console.log($.msg); 109 | if (notLogin.length) { 110 | console.log( 111 | `----------------未登录账号【${notLogin.length}】----------------` 112 | ); 113 | console.log( 114 | notLogin.map((item) => `${item.username}【${item.nickname}】`).join(`\n`) 115 | ); 116 | $.msg = `未登录账号:\n ${notLogin 117 | .map((item) => `账号【${item.index}】:${item.nickname || item.username}`) 118 | .join(`\n`)}`; 119 | } 120 | $.write(JSON.stringify(ckFormat, null, `\t`), remark_key); 121 | console.log(`检测到${keyword.length - 1}个搜索条件:${keyword.join(",")}`); 122 | if (keyword && keyword[0]) { 123 | console.log("开始搜索中"); 124 | const searchValue = ckFormat.filter((item, index) => { 125 | return ( 126 | keyword.indexOf(`${index}`) > -1 || 127 | keyword.indexOf(item.username) > -1 || 128 | keyword.indexOf(item.nickname) > -1 || 129 | keyword.indexOf(item.status) > -1 130 | ); 131 | }); 132 | if (searchValue.length) { 133 | $.msg = `已找到搜索结果:\n`; 134 | searchValue.forEach((item) => { 135 | $.msg += `${item.nickname || item.username}:${item.mobile} 【${ 136 | item.status 137 | }】\n`; 138 | }); 139 | } else { 140 | $.msg = "未找到相关 ck"; 141 | } 142 | console.log($.msg); 143 | if ($.read("mute") !== "true") { 144 | $.notify(noTitle, `关键字:${keyword}`, $.msg); 145 | } 146 | } else { 147 | if ($.read("mute") !== "true") { 148 | $.notify(noTitle, ``, $.msg); 149 | } 150 | } 151 | })() 152 | .catch((e) => { 153 | console.log(e); 154 | }) 155 | .finally(() => { 156 | $.done(); 157 | }); 158 | 159 | async function isLogin(Cookie) { 160 | const opt = { 161 | url: "https://me-api.jd.com/user_new/info/GetJDUserInfoUnion?sceneval=2&sceneval=2&g_login_type=1&g_ty=ls", 162 | headers: { 163 | cookie: Cookie, 164 | Referer: "https://home.m.jd.com/", 165 | }, 166 | }; 167 | return $.http.get(opt).then((response) => { 168 | try { 169 | return JSON.parse(response.body); 170 | } catch (e) { 171 | return {}; 172 | } 173 | }); 174 | } 175 | 176 | async function getPhoneNumber(cookie) { 177 | const opt = { 178 | url: `https://crmsam.jd.com/union/bindingPhoneNumber`, 179 | headers: { 180 | cookie: cookie, 181 | }, 182 | }; 183 | 184 | return $.http.get(opt).then((response) => { 185 | try { 186 | const data = JSON.parse(response.body); 187 | if (data.code === 200) return data.data; 188 | return ""; 189 | } catch (e) { 190 | return ""; 191 | } 192 | }); 193 | } 194 | 195 | function taskPetUrl(function_id, body = {}, cookie) { 196 | body["version"] = 2; 197 | body["channel"] = "app"; 198 | return { 199 | url: `https://api.m.jd.com/client.action?functionId=${function_id}`, 200 | body: `body=${escape( 201 | JSON.stringify(body) 202 | )}&appid=wh5&loginWQBiz=pet-town&clientVersion=9.0.4`, 203 | headers: { 204 | cookie: cookie, 205 | host: "api.m.jd.com", 206 | "content-type": "application/x-www-form-urlencoded", 207 | }, 208 | }; 209 | } 210 | 211 | async function PetRequest(function_id, cookie, body = {}) { 212 | return $.http.post(taskPetUrl(function_id, body, cookie)).then((response) => { 213 | try { 214 | const data = JSON.parse(response.body); 215 | if (data.code === "0") return data.result.medalPercent.toFixed(1); 216 | return ""; 217 | } catch (e) { 218 | return ""; 219 | } 220 | }); 221 | } 222 | 223 | async function getFruit(cookie) { 224 | const option = { 225 | url: `https://api.m.jd.com/client.action?functionId=initForFarm&body=%7B%22version%22%3A21%2C%22channel%22%3A1%2C%22babelChannel%22%3A0%2C%22lat%22%3A%220%22%2C%22lng%22%3A%220%22%7D&appid=signed_wh5&area=0_0_0_0&osVersion=&screen=375*667&networkType=×tamp=1681177626558&d_brand=&d_model=&wqDefault=false&client=apple&clientVersion=9.3.0&partner=&build=&openudid=&uemps=0-2-999`, 226 | headers: { 227 | accept: "*/*", 228 | cookie: cookie, 229 | origin: "https://h5.m.jd.com", 230 | referer: "https://h5.m.jd.com/", 231 | "content-type": "application/x-www-form-urlencoded", 232 | "user-agent": 233 | "jdapp;iPhone;9.3.0;14.3;%E4%BA%AC%E4%B8%9C/9.3.0 CFNetwork/1209 Darwin/20.2.0;", 234 | }, 235 | }; 236 | 237 | return $.http.post(option).then((response) => { 238 | try { 239 | const data = JSON.parse(response.body); 240 | if (!data.farmUserPro) console.log(data); 241 | if (data.code === "0") 242 | return ( 243 | (data.farmUserPro.treeEnergy / data.farmUserPro.treeTotalEnergy) * 244 | 100 245 | ).toFixed(2); 246 | return ""; 247 | } catch (e) { 248 | return ""; 249 | } 250 | }); 251 | } 252 | 253 | /* prettier-ignore */ 254 | function ENV(){const isJSBox=typeof require=="function"&&typeof $jsbox!="undefined";return{isQX:typeof $task!=="undefined",isLoon:typeof $loon!=="undefined",isSurge:typeof $httpClient!=="undefined"&&typeof $utils!=="undefined",isBrowser:typeof document!=="undefined",isNode:typeof require=="function"&&!isJSBox,isJSBox,isRequest:typeof $request!=="undefined",isScriptable:typeof importModule!=="undefined",isShadowrocket:"undefined"!==typeof $rocket,isStash:"undefined"!==typeof $environment&&$environment["stash-version"]}} 255 | /* prettier-ignore */ 256 | function HTTP(defaultOptions={baseURL:""}){const{isQX,isLoon,isSurge,isScriptable,isNode,isBrowser,isShadowrocket,isStash,}=ENV();const methods=["GET","POST","PUT","DELETE","HEAD","OPTIONS","PATCH"];const URL_REGEX=/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;function send(method,options){options=typeof options==="string"?{url:options}:options;const baseURL=defaultOptions.baseURL;if(baseURL&&!URL_REGEX.test(options.url||"")){options.url=baseURL?baseURL+options.url:options.url}if(options.body&&options.headers&&!options.headers["Content-Type"]){options.headers["Content-Type"]="application/x-www-form-urlencoded"}options={...defaultOptions,...options};const timeout=options.timeout;const events={...{onRequest:()=>{},onResponse:(resp)=>resp,onTimeout:()=>{},},...options.events,};events.onRequest(method,options);let worker;if(isQX){worker=$task.fetch({method,...options})}else if(isLoon||isSurge||isNode||isShadowrocket||isStash){worker=new Promise((resolve,reject)=>{const request=isNode?require("request"):$httpClient;request[method.toLowerCase()](options,(err,response,body)=>{if(err)reject(err);else resolve({statusCode:response.status||response.statusCode,headers:response.headers,body,})})})}else if(isScriptable){const request=new Request(options.url);request.method=method;request.headers=options.headers;request.body=options.body;worker=new Promise((resolve,reject)=>{request.loadString().then((body)=>{resolve({statusCode:request.response.statusCode,headers:request.response.headers,body,})}).catch((err)=>reject(err))})}else if(isBrowser){worker=new Promise((resolve,reject)=>{fetch(options.url,{method,headers:options.headers,body:options.body,}).then((response)=>response.json()).then((response)=>resolve({statusCode:response.status,headers:response.headers,body:response.data,})).catch(reject)})}let timeoutid;const timer=timeout?new Promise((_,reject)=>{timeoutid=setTimeout(()=>{events.onTimeout();return reject(`${method}URL:${options.url}exceeds the timeout ${timeout}ms`)},timeout)}):null;return(timer?Promise.race([timer,worker]).then((res)=>{clearTimeout(timeoutid);return res}):worker).then((resp)=>events.onResponse(resp))}const http={};methods.forEach((method)=>(http[method.toLowerCase()]=(options)=>send(method,options)));return http} 257 | /* prettier-ignore */ 258 | function API(name="untitled",debug=false){const{isQX,isLoon,isSurge,isScriptable,isNode,isShadowrocket,isStash,isJSBox}=ENV();return new(class{constructor(name,debug){this.name=name;this.debug=debug;this.http=HTTP();this.env=ENV();this.node=(()=>{if(isNode){const fs=require("fs");return{fs}}else{return null}})();this.initCache();const delay=(t,v)=>new Promise(function(resolve){setTimeout(resolve.bind(null,v),t)});Promise.prototype.delay=function(t){return this.then(function(v){return delay(t,v)})}}initCache(){if(isQX)this.cache=JSON.parse($prefs.valueForKey(this.name)||"{}");if(isLoon||isSurge||isStash||isShadowrocket)this.cache=JSON.parse($persistentStore.read(this.name)||"{}");if(isNode){let fpath="root.json";if(!this.node.fs.existsSync(fpath)){this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},(err)=>console.log(err))}this.root={};fpath=`${this.name}.json`;if(!this.node.fs.existsSync(fpath)){this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},(err)=>console.log(err));this.cache={}}else{this.cache=JSON.parse(this.node.fs.readFileSync(`${this.name}.json`))}}}persistCache(){const data=JSON.stringify(this.cache,null,2);if(isQX)$prefs.setValueForKey(data,this.name);if(isLoon||isSurge||isStash||isShadowrocket)$persistentStore.write(data,this.name);if(isNode){this.node.fs.writeFileSync(`${this.name}.json`,data,{flag:"w"},(err)=>console.log(err));this.node.fs.writeFileSync("root.json",JSON.stringify(this.root,null,2),{flag:"w"},(err)=>console.log(err))}}write(data,key){this.log(`SET ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.write(data,key)}if(isQX){return $prefs.setValueForKey(data,key)}if(isNode){this.root[key]=data}}else{this.cache[key]=data}this.persistCache()}read(key){this.log(`READ ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.read(key)}if(isQX){return $prefs.valueForKey(key)}if(isNode){return this.root[key]}}else{return this.cache[key]}}delete(key){this.log(`DELETE ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.write(null,key)}if(isQX){return $prefs.removeValueForKey(key)}if(isNode){delete this.root[key]}}else{delete this.cache[key]}this.persistCache()}notify(title,subtitle="",content="",options={}){const openURL=options["open-url"];const mediaURL=options["media-url"];if(isQX)$notify(title,subtitle,content,options);if(isSurge){$notification.post(title,subtitle,content+`${mediaURL?"\n多媒体:"+mediaURL:""}`,{url:openURL})}if(isLoon||isStash||isShadowrocket){let opts={};if(openURL)opts["openUrl"]=openURL;if(mediaURL)opts["mediaUrl"]=mediaURL;if(JSON.stringify(opts)==="{}"){$notification.post(title,subtitle,content)}else{$notification.post(title,subtitle,content,opts)}}if(isNode||isScriptable){const content_=content+(openURL?`\n点击跳转:${openURL}`:"")+(mediaURL?`\n多媒体:${mediaURL}`:"");if(isJSBox){const push=require("push");push.schedule({title:title,body:(subtitle?subtitle+"\n":"")+content_,})}else{console.log(`${title}\n${subtitle}\n${content_}\n\n`)}}}log(msg){if(this.debug)console.log(`[${this.name}]LOG:${this.stringify(msg)}`)}info(msg){console.log(`[${this.name}]INFO:${this.stringify(msg)}`)}error(msg){console.log(`[${this.name}]ERROR:${this.stringify(msg)}`)}wait(millisec){return new Promise((resolve)=>setTimeout(resolve,millisec))}done(value={}){if(isQX||isLoon||isSurge||isStash||isShadowrocket){$done(value)}else if(isNode&&!isJSBox){if(typeof $context!=="undefined"){$context.headers=value.headers;$context.statusCode=value.statusCode;$context.body=value.body}}}stringify(obj_or_str){if(typeof obj_or_str==="string"||obj_or_str instanceof String)return obj_or_str;else try{return JSON.stringify(obj_or_str,null,2)}catch(err){return"[object Object]"}}})(name,debug)} 259 | -------------------------------------------------------------------------------- /jd/jd_login_help.loon.conf: -------------------------------------------------------------------------------- 1 | #!name=登录助手 2 | #!desc=网页端快速切换 BoxJS 中的缓存账号 3 | #!openUrl=https://github.com/dompling/Script/blob/master/jd/jd_login_help.js 4 | #!author=dompling 5 | #!homepage=https://github.com/dompling 6 | #!icon=https://raw.githubusercontent.com/chavyleung/scripts/master/box/icons/BoxJs.png 7 | 8 | [Script] 9 | 10 | http-response ^https?:\/\/.*\.?jd\.(com|hk)\/?((?!\.(js|json|gif|webp|dpg|flv|mp3|mp4)).)*$ script-path=https://raw.githubusercontent.com/dompling/Script/master/jd/jd_login_help.js, requires-body=true, timeout=5000, tag=京东全站 11 | http-response ^https?:\/\/.*\.jingxi\.com\/?((?!\.(js|json|gif|flv|mp3|mp4)).)*$ script-path=https://raw.githubusercontent.com/dompling/Script/master/jd/jd_login_help.js, requires-body=true, timeout=5000, tag=京喜全站 12 | 13 | #http-response ^https?:\/\/m\.jd\.com script-path=https://raw.githubusercontent.com/dompling/Script/master/jd/jd_login_help.js, requires-body=true, timeout=5000, tag=京东首页 14 | #http-response ^https?:\/\/plogin\.m\.jd\.com\/login\/login script-path=https://raw.githubusercontent.com/dompling/Script/master/jd/jd_login_help.js, requires-body=true, timeout=5000, tag=京东登录 15 | 16 | [MITM] 17 | hostname = -ap-dd*.jd.com, -ddms.jd.com, -imio.jd.com, -jdcs.m.jd.com, -jdpaycert.jd.com, -jdpaysdk.jd.com, -jtk.jd.com, -lite-msg.m.jd.com, -msjdpay.jd.com, -payfinish.jd.com, -payfinish.m.jd.com, -poly-merchant.jd.com, -redpoint-msg.m.jd.com, *.*.jd.com, *.*.jingxi.com, *.*.jkcsjd.com, *.jd.com, *.jingxi.com, *.jkcsjd.com 18 | -------------------------------------------------------------------------------- /jd/jd_login_help.sgmodule: -------------------------------------------------------------------------------- 1 | #!name=登录助手 2 | #!desc=京东+京喜账号CK登陆辅助 3 | 4 | [Script] 5 | # > 京东系列 6 | 京东登录辅助 = type=http-response,pattern=^https?:\/\/.*\.?jd\.(com|hk)\/?((?!\.(js|json|gif|webp|dpg|flv|mp3|mp4)).)*$,requires-body=1,max-size=0,timeout=1000,script-path=https://raw.githubusercontent.com/dompling/Script/master/jd/jd_login_help.js 7 | # > 京喜系列 8 | 京喜登录辅助 = type=http-response,pattern=^https?:\/\/.*\.jingxi\.com\/?((?!\.(js|json|gif|flv|mp3|mp4)).)*$,requires-body=1,max-size=0,timeout=1000,script-path=https://raw.githubusercontent.com/dompling/Script/master/jd/jd_login_help.js 9 | 10 | [MITM] 11 | hostname = %APPEND% -ap-dd*.jd.com, -ddms.jd.com, -imio.jd.com, -jdcs.m.jd.com, -jdpaycert.jd.com, -jdpaysdk.jd.com, -jtk.jd.com, -lite-msg.m.jd.com, -msjdpay.jd.com, -payfinish.jd.com, -payfinish.m.jd.com, -poly-merchant.jd.com, -redpoint-msg.m.jd.com, *.*.jd.com, *.*.jingxi.com, *.*.jkcsjd.com, *.jd.com, *.jingxi.com, *.jkcsjd.com 12 | -------------------------------------------------------------------------------- /jd/ql_api.js: -------------------------------------------------------------------------------- 1 | try { 2 | $.ql_config = JSON.parse($.read("#ql")); 3 | } catch (e) { 4 | $.ql_config = {}; 5 | } 6 | $.ql_url = $.ql_config.ip; 7 | 8 | $.log(`地址:${$.ql_url}`); 9 | 10 | $.ql = { 11 | type: "api", 12 | headers: { 13 | "Content-Type": `application/json;charset=UTF-8`, 14 | Authorization: "", 15 | }, 16 | disabled(ids) { 17 | if (!this.headers.Authorization) return; 18 | const opt = { 19 | url: `${$.ql_url}/${this.type}/envs/disable`, 20 | headers: this.headers, 21 | body: JSON.stringify(ids), 22 | }; 23 | return $.http.put(opt).then((response) => JSON.parse(response.body)); 24 | }, 25 | enabled(ids) { 26 | if (!this.headers.Authorization) return; 27 | const opt = { 28 | url: `${$.ql_url}/${this.type}/envs/enable`, 29 | headers: this.headers, 30 | body: JSON.stringify(ids), 31 | }; 32 | return $.http.put(opt).then((response) => JSON.parse(response.body)); 33 | }, 34 | delete(ids) { 35 | if (!this.headers.Authorization) return; 36 | const opt = { 37 | url: `${$.ql_url}/${this.type}/envs`, 38 | headers: this.headers, 39 | body: JSON.stringify(ids), 40 | }; 41 | return $.http.delete(opt).then((response) => JSON.parse(response.body)); 42 | }, 43 | add(records) { 44 | if (!this.headers.Authorization) return; 45 | const opt = { 46 | url: `${$.ql_url}/${this.type}/envs`, 47 | headers: this.headers, 48 | body: JSON.stringify(records), 49 | }; 50 | return $.http.post(opt).then((response) => JSON.parse(response.body)); 51 | }, 52 | edit(records) { 53 | if (!this.headers.Authorization) return; 54 | const opt = { 55 | url: `${$.ql_url}/${this.type}/envs`, 56 | headers: this.headers, 57 | body: JSON.stringify(records), 58 | }; 59 | return $.http.put(opt).then((response) => JSON.parse(response.body)); 60 | }, 61 | select(searchValue = "JD_COOKIE") { 62 | if (!this.headers.Authorization) return; 63 | const opt = { 64 | url: `${$.ql_url}/${this.type}/envs?searchValue=${searchValue}`, 65 | headers: this.headers, 66 | }; 67 | return $.http.get(opt).then((response) => JSON.parse(response.body)); 68 | }, 69 | initial: async () => { 70 | if ($.ql_url && !$.ql_url.match(/^(http|https)/)) 71 | $.ql_url = `http://${$.ql_url}`; 72 | 73 | $.application = { 74 | client_id: $.ql_config.client_id, 75 | client_secret: $.ql_config.client_secret, 76 | }; 77 | 78 | $.ql_account = { 79 | username: $.ql_config.username, 80 | password: $.ql_config.password, 81 | }; 82 | 83 | if ($.ql_config.is_pwd === "true") { 84 | const options = { 85 | url: `${$.ql_url}/api/user/login`, 86 | body: JSON.stringify($.ql_account), 87 | headers: { 88 | "Content-Type": `application/json;charset=UTF-8`, 89 | }, 90 | }; 91 | let response = await $.http.post(options); 92 | response = JSON.parse(response.body); 93 | if (response.code === 200) { 94 | $.ql.type = "api"; 95 | $.ql.headers.Authorization = `Bearer ${response.data.token}`; 96 | $.log(`登陆成功:${response.data.lastaddr}`); 97 | $.log(`ip:${response.data.lastip}`); 98 | } else { 99 | $.log(response); 100 | $.log(`登陆失败:${response.message}`); 101 | } 102 | } else { 103 | const options = { 104 | url: `${$.ql_url}/open/auth/token?client_id=${$.application.client_id}&client_secret=${$.application.client_secret}`, 105 | headers: { 106 | "Content-Type": `application/json;charset=UTF-8`, 107 | }, 108 | }; 109 | let response = await $.http.get(options); 110 | response = JSON.parse(response.body); 111 | if (response.code === 200) { 112 | $.ql.type = "open"; 113 | $.ql.headers.Authorization = `Bearer ${response.data.token}`; 114 | $.log(`登陆成功`); 115 | } else { 116 | $.log(response); 117 | $.log(`登陆失败:${response.message}`); 118 | } 119 | } 120 | }, 121 | }; 122 | -------------------------------------------------------------------------------- /jd/ql_cookie_sync.js: -------------------------------------------------------------------------------- 1 | /* 2 | 青龙 docker 每日自动同步 boxjs cookie 3 | 40 * * * https://raw.githubusercontent.com/dompling/Script/master/jd/ql_cookie_sync.js 4 | */ 5 | 6 | const $ = new API("ql", true); 7 | 8 | const title = "🐉 通知提示"; 9 | 10 | const jd_cookies = JSON.parse($.read("#CookiesJD") || "[]"); 11 | 12 | let remark = {}; 13 | try { 14 | const _remark = JSON.parse( 15 | JSON.parse($.read("#jd_ck_remark") || "{}").remark || "[]" 16 | ); 17 | 18 | _remark.forEach((item) => { 19 | remark[item.username] = item; 20 | }); 21 | } catch (e) { 22 | console.log(e); 23 | } 24 | 25 | 26 | function getUsername(ck) { 27 | if (!ck) return ""; 28 | return decodeURIComponent(ck.match(/pt_pin=([^; ]+)(?=;?)/)[1]); 29 | } 30 | 31 | async function getScriptUrl() { 32 | const response = await $.http.get({ 33 | url: "https://raw.githubusercontent.com/dompling/Script/master/jd/ql_api.js", 34 | }); 35 | return response.body; 36 | } 37 | 38 | (async () => { 39 | const ql_script = (await getScriptUrl()) || ""; 40 | eval(ql_script); 41 | await $.ql.initial(); 42 | 43 | const cookiesRes = await $.ql.select(); 44 | const ids = cookiesRes.data.map((item) => item.id); 45 | await $.ql.delete(ids); 46 | const wskeyRes = await $.ql.select("JD_WSCK"); 47 | await $.ql.delete(wskeyRes.data.map((item) => item.id)); 48 | $.log("清空 cookie 和 wskey"); 49 | 50 | const addData = []; 51 | const wsCookie = []; 52 | for (const jd_cookie of jd_cookies) { 53 | const username = getUsername(jd_cookie.cookie); 54 | let remarks = ""; 55 | if (remark[username]) { 56 | remarks = remark[username].nickname; 57 | 58 | remarks += `&${remark[username].remark}`; 59 | if (remark[username].qywxUserId) 60 | remarks += `&${remark[username].qywxUserId}`; 61 | } else { 62 | remarks = username; 63 | } 64 | addData.push({ name: "JD_COOKIE", value: jd_cookie.cookie, remarks }); 65 | if (jd_cookie.wskey) { 66 | wsCookie.push({ 67 | name: "JD_WSCK", 68 | remarks: remarks.split("&")[0], 69 | value: 70 | jd_cookie.wskey.indexOf("pt_pin") !== -1 71 | ? jd_cookie.wskey 72 | : `${jd_cookie.wskey}pt_pin=${encodeURI(username)};`, 73 | }); 74 | } 75 | } 76 | if (addData.length) await $.ql.add(addData); 77 | if (wsCookie.length) await $.ql.add(wsCookie); 78 | 79 | const _cookiesRes = await $.ql.select(); 80 | const _ids = []; 81 | for (let index = 0; index < _cookiesRes.data.length; index++) { 82 | const item = _cookiesRes.data[index]; 83 | const response = await TotalBean(item.value); 84 | if (response.retcode !== "0") _ids.push(item); 85 | } 86 | 87 | if (_ids.length > 0) { 88 | const ids = _ids.map((item) => item.id); 89 | $.error( 90 | `过期账号:${_ids 91 | .map((item) => item.remarks || getUsername(item.value)) 92 | .join(`\n`)}` 93 | ); 94 | await $.ql.disabled(ids); 95 | } 96 | 97 | const cookieText = jd_cookies.map((item) => item.userName).join(`\n`); 98 | if ($.read("mute") !== "true") { 99 | return $.notify(title, "", `已同步账号: ${cookieText}`); 100 | } 101 | })() 102 | .catch((e) => { 103 | $.log(JSON.stringify(e)); 104 | }) 105 | .finally(() => { 106 | $.done(); 107 | }); 108 | 109 | async function TotalBean(Cookie) { 110 | const opt = { 111 | url: "https://me-api.jd.com/user_new/info/GetJDUserInfoUnion?sceneval=2&sceneval=2&g_login_type=1&g_ty=ls", 112 | headers: { 113 | cookie: Cookie, 114 | Referer: "https://home.m.jd.com/", 115 | }, 116 | }; 117 | return $.http.get(opt).then((response) => { 118 | try { 119 | return JSON.parse(response.body); 120 | } catch (e) { 121 | return {}; 122 | } 123 | }); 124 | } 125 | 126 | /* prettier-ignore */ 127 | function ENV(){const isJSBox=typeof require=="function"&&typeof $jsbox!="undefined";return{isQX:typeof $task!=="undefined",isLoon:typeof $loon!=="undefined",isSurge:typeof $httpClient!=="undefined"&&typeof $utils!=="undefined",isBrowser:typeof document!=="undefined",isNode:typeof require=="function"&&!isJSBox,isJSBox,isRequest:typeof $request!=="undefined",isScriptable:typeof importModule!=="undefined",isShadowrocket:"undefined"!==typeof $rocket,isStash:"undefined"!==typeof $environment&&$environment["stash-version"]}} 128 | /* prettier-ignore */ 129 | function HTTP(defaultOptions={baseURL:""}){const{isQX,isLoon,isSurge,isScriptable,isNode,isBrowser,isShadowrocket,isStash,}=ENV();const methods=["GET","POST","PUT","DELETE","HEAD","OPTIONS","PATCH"];const URL_REGEX=/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;function send(method,options){options=typeof options==="string"?{url:options}:options;const baseURL=defaultOptions.baseURL;if(baseURL&&!URL_REGEX.test(options.url||"")){options.url=baseURL?baseURL+options.url:options.url}if(options.body&&options.headers&&!options.headers["Content-Type"]){options.headers["Content-Type"]="application/x-www-form-urlencoded"}options={...defaultOptions,...options};const timeout=options.timeout;const events={...{onRequest:()=>{},onResponse:(resp)=>resp,onTimeout:()=>{},},...options.events,};events.onRequest(method,options);let worker;if(isQX){worker=$task.fetch({method,...options})}else if(isLoon||isSurge||isNode||isShadowrocket||isStash){worker=new Promise((resolve,reject)=>{const request=isNode?require("request"):$httpClient;request[method.toLowerCase()](options,(err,response,body)=>{if(err)reject(err);else resolve({statusCode:response.status||response.statusCode,headers:response.headers,body,})})})}else if(isScriptable){const request=new Request(options.url);request.method=method;request.headers=options.headers;request.body=options.body;worker=new Promise((resolve,reject)=>{request.loadString().then((body)=>{resolve({statusCode:request.response.statusCode,headers:request.response.headers,body,})}).catch((err)=>reject(err))})}else if(isBrowser){worker=new Promise((resolve,reject)=>{fetch(options.url,{method,headers:options.headers,body:options.body,}).then((response)=>response.json()).then((response)=>resolve({statusCode:response.status,headers:response.headers,body:response.data,})).catch(reject)})}let timeoutid;const timer=timeout?new Promise((_,reject)=>{timeoutid=setTimeout(()=>{events.onTimeout();return reject(`${method}URL:${options.url}exceeds the timeout ${timeout}ms`)},timeout)}):null;return(timer?Promise.race([timer,worker]).then((res)=>{clearTimeout(timeoutid);return res}):worker).then((resp)=>events.onResponse(resp))}const http={};methods.forEach((method)=>(http[method.toLowerCase()]=(options)=>send(method,options)));return http} 130 | /* prettier-ignore */ 131 | function API(name="untitled",debug=false){const{isQX,isLoon,isSurge,isScriptable,isNode,isShadowrocket,isStash,isJSBox}=ENV();return new(class{constructor(name,debug){this.name=name;this.debug=debug;this.http=HTTP();this.env=ENV();this.node=(()=>{if(isNode){const fs=require("fs");return{fs}}else{return null}})();this.initCache();const delay=(t,v)=>new Promise(function(resolve){setTimeout(resolve.bind(null,v),t)});Promise.prototype.delay=function(t){return this.then(function(v){return delay(t,v)})}}initCache(){if(isQX)this.cache=JSON.parse($prefs.valueForKey(this.name)||"{}");if(isLoon||isSurge||isStash||isShadowrocket)this.cache=JSON.parse($persistentStore.read(this.name)||"{}");if(isNode){let fpath="root.json";if(!this.node.fs.existsSync(fpath)){this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},(err)=>console.log(err))}this.root={};fpath=`${this.name}.json`;if(!this.node.fs.existsSync(fpath)){this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},(err)=>console.log(err));this.cache={}}else{this.cache=JSON.parse(this.node.fs.readFileSync(`${this.name}.json`))}}}persistCache(){const data=JSON.stringify(this.cache,null,2);if(isQX)$prefs.setValueForKey(data,this.name);if(isLoon||isSurge||isStash||isShadowrocket)$persistentStore.write(data,this.name);if(isNode){this.node.fs.writeFileSync(`${this.name}.json`,data,{flag:"w"},(err)=>console.log(err));this.node.fs.writeFileSync("root.json",JSON.stringify(this.root,null,2),{flag:"w"},(err)=>console.log(err))}}write(data,key){this.log(`SET ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.write(data,key)}if(isQX){return $prefs.setValueForKey(data,key)}if(isNode){this.root[key]=data}}else{this.cache[key]=data}this.persistCache()}read(key){this.log(`READ ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.read(key)}if(isQX){return $prefs.valueForKey(key)}if(isNode){return this.root[key]}}else{return this.cache[key]}}delete(key){this.log(`DELETE ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.write(null,key)}if(isQX){return $prefs.removeValueForKey(key)}if(isNode){delete this.root[key]}}else{delete this.cache[key]}this.persistCache()}notify(title,subtitle="",content="",options={}){const openURL=options["open-url"];const mediaURL=options["media-url"];if(isQX)$notify(title,subtitle,content,options);if(isSurge){$notification.post(title,subtitle,content+`${mediaURL?"\n多媒体:"+mediaURL:""}`,{url:openURL})}if(isLoon||isStash||isShadowrocket){let opts={};if(openURL)opts["openUrl"]=openURL;if(mediaURL)opts["mediaUrl"]=mediaURL;if(JSON.stringify(opts)==="{}"){$notification.post(title,subtitle,content)}else{$notification.post(title,subtitle,content,opts)}}if(isNode||isScriptable){const content_=content+(openURL?`\n点击跳转:${openURL}`:"")+(mediaURL?`\n多媒体:${mediaURL}`:"");if(isJSBox){const push=require("push");push.schedule({title:title,body:(subtitle?subtitle+"\n":"")+content_,})}else{console.log(`${title}\n${subtitle}\n${content_}\n\n`)}}}log(msg){if(this.debug)console.log(`[${this.name}]LOG:${this.stringify(msg)}`)}info(msg){console.log(`[${this.name}]INFO:${this.stringify(msg)}`)}error(msg){console.log(`[${this.name}]ERROR:${this.stringify(msg)}`)}wait(millisec){return new Promise((resolve)=>setTimeout(resolve,millisec))}done(value={}){if(isQX||isLoon||isSurge||isStash||isShadowrocket){$done(value)}else if(isNode&&!isJSBox){if(typeof $context!=="undefined"){$context.headers=value.headers;$context.statusCode=value.statusCode;$context.body=value.body}}}stringify(obj_or_str){if(typeof obj_or_str==="string"||obj_or_str instanceof String)return obj_or_str;else try{return JSON.stringify(obj_or_str,null,2)}catch(err){return"[object Object]"}}})(name,debug)} 132 | -------------------------------------------------------------------------------- /jd/ql_env_back.js: -------------------------------------------------------------------------------- 1 | /* 2 | 青龙 docker 每日自动同步 boxjs cookie 3 | 40 * * * https://raw.githubusercontent.com/dompling/Script/master/jd/ql_cookie_sync.js 4 | */ 5 | 6 | const $ = new API('ql', true); 7 | 8 | const title = '🐉 通知提示'; 9 | 10 | async function getScriptUrl() { 11 | const response = await $.http.get({ 12 | url: 'https://raw.githubusercontent.com/dompling/Script/master/jd/ql_api.js', 13 | }); 14 | return response.body; 15 | } 16 | 17 | (async () => { 18 | const ql_script = (await getScriptUrl()) || ''; 19 | eval(ql_script); 20 | await $.ql.initial(); 21 | 22 | const envs = await $.ql.select(''); 23 | $.write(JSON.stringify(envs.data), 'env'); 24 | if ($.read('mute') !== 'true') { 25 | return $.notify( 26 | title, 27 | '已备份环境变量', 28 | `备份个数:${envs.data.length} 个`, 29 | ); 30 | } 31 | })() 32 | .catch((e) => { 33 | $.error(JSON.stringify(e)); 34 | }) 35 | .finally(() => { 36 | $.done(); 37 | }); 38 | 39 | /* prettier-ignore */ 40 | function ENV(){const isJSBox=typeof require=="function"&&typeof $jsbox!="undefined";return{isQX:typeof $task!=="undefined",isLoon:typeof $loon!=="undefined",isSurge:typeof $httpClient!=="undefined"&&typeof $utils!=="undefined",isBrowser:typeof document!=="undefined",isNode:typeof require=="function"&&!isJSBox,isJSBox,isRequest:typeof $request!=="undefined",isScriptable:typeof importModule!=="undefined",isShadowrocket:"undefined"!==typeof $rocket,isStash:"undefined"!==typeof $environment&&$environment["stash-version"]}} 41 | /* prettier-ignore */ 42 | function HTTP(defaultOptions={baseURL:""}){const{isQX,isLoon,isSurge,isScriptable,isNode,isBrowser,isShadowrocket,isStash,}=ENV();const methods=["GET","POST","PUT","DELETE","HEAD","OPTIONS","PATCH"];const URL_REGEX=/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;function send(method,options){options=typeof options==="string"?{url:options}:options;const baseURL=defaultOptions.baseURL;if(baseURL&&!URL_REGEX.test(options.url||"")){options.url=baseURL?baseURL+options.url:options.url}if(options.body&&options.headers&&!options.headers["Content-Type"]){options.headers["Content-Type"]="application/x-www-form-urlencoded"}options={...defaultOptions,...options};const timeout=options.timeout;const events={...{onRequest:()=>{},onResponse:(resp)=>resp,onTimeout:()=>{},},...options.events,};events.onRequest(method,options);let worker;if(isQX){worker=$task.fetch({method,...options})}else if(isLoon||isSurge||isNode||isShadowrocket||isStash){worker=new Promise((resolve,reject)=>{const request=isNode?require("request"):$httpClient;request[method.toLowerCase()](options,(err,response,body)=>{if(err)reject(err);else resolve({statusCode:response.status||response.statusCode,headers:response.headers,body,})})})}else if(isScriptable){const request=new Request(options.url);request.method=method;request.headers=options.headers;request.body=options.body;worker=new Promise((resolve,reject)=>{request.loadString().then((body)=>{resolve({statusCode:request.response.statusCode,headers:request.response.headers,body,})}).catch((err)=>reject(err))})}else if(isBrowser){worker=new Promise((resolve,reject)=>{fetch(options.url,{method,headers:options.headers,body:options.body,}).then((response)=>response.json()).then((response)=>resolve({statusCode:response.status,headers:response.headers,body:response.data,})).catch(reject)})}let timeoutid;const timer=timeout?new Promise((_,reject)=>{timeoutid=setTimeout(()=>{events.onTimeout();return reject(`${method}URL:${options.url}exceeds the timeout ${timeout}ms`)},timeout)}):null;return(timer?Promise.race([timer,worker]).then((res)=>{clearTimeout(timeoutid);return res}):worker).then((resp)=>events.onResponse(resp))}const http={};methods.forEach((method)=>(http[method.toLowerCase()]=(options)=>send(method,options)));return http} 43 | /* prettier-ignore */ 44 | function API(name="untitled",debug=false){const{isQX,isLoon,isSurge,isScriptable,isNode,isShadowrocket,isStash,isJSBox}=ENV();return new(class{constructor(name,debug){this.name=name;this.debug=debug;this.http=HTTP();this.env=ENV();this.node=(()=>{if(isNode){const fs=require("fs");return{fs}}else{return null}})();this.initCache();const delay=(t,v)=>new Promise(function(resolve){setTimeout(resolve.bind(null,v),t)});Promise.prototype.delay=function(t){return this.then(function(v){return delay(t,v)})}}initCache(){if(isQX)this.cache=JSON.parse($prefs.valueForKey(this.name)||"{}");if(isLoon||isSurge||isStash||isShadowrocket)this.cache=JSON.parse($persistentStore.read(this.name)||"{}");if(isNode){let fpath="root.json";if(!this.node.fs.existsSync(fpath)){this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},(err)=>console.log(err))}this.root={};fpath=`${this.name}.json`;if(!this.node.fs.existsSync(fpath)){this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},(err)=>console.log(err));this.cache={}}else{this.cache=JSON.parse(this.node.fs.readFileSync(`${this.name}.json`))}}}persistCache(){const data=JSON.stringify(this.cache,null,2);if(isQX)$prefs.setValueForKey(data,this.name);if(isLoon||isSurge||isStash||isShadowrocket)$persistentStore.write(data,this.name);if(isNode){this.node.fs.writeFileSync(`${this.name}.json`,data,{flag:"w"},(err)=>console.log(err));this.node.fs.writeFileSync("root.json",JSON.stringify(this.root,null,2),{flag:"w"},(err)=>console.log(err))}}write(data,key){this.log(`SET ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.write(data,key)}if(isQX){return $prefs.setValueForKey(data,key)}if(isNode){this.root[key]=data}}else{this.cache[key]=data}this.persistCache()}read(key){this.log(`READ ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.read(key)}if(isQX){return $prefs.valueForKey(key)}if(isNode){return this.root[key]}}else{return this.cache[key]}}delete(key){this.log(`DELETE ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.write(null,key)}if(isQX){return $prefs.removeValueForKey(key)}if(isNode){delete this.root[key]}}else{delete this.cache[key]}this.persistCache()}notify(title,subtitle="",content="",options={}){const openURL=options["open-url"];const mediaURL=options["media-url"];if(isQX)$notify(title,subtitle,content,options);if(isSurge){$notification.post(title,subtitle,content+`${mediaURL?"\n多媒体:"+mediaURL:""}`,{url:openURL})}if(isLoon||isStash||isShadowrocket){let opts={};if(openURL)opts["openUrl"]=openURL;if(mediaURL)opts["mediaUrl"]=mediaURL;if(JSON.stringify(opts)==="{}"){$notification.post(title,subtitle,content)}else{$notification.post(title,subtitle,content,opts)}}if(isNode||isScriptable){const content_=content+(openURL?`\n点击跳转:${openURL}`:"")+(mediaURL?`\n多媒体:${mediaURL}`:"");if(isJSBox){const push=require("push");push.schedule({title:title,body:(subtitle?subtitle+"\n":"")+content_,})}else{console.log(`${title}\n${subtitle}\n${content_}\n\n`)}}}log(msg){if(this.debug)console.log(`[${this.name}]LOG:${this.stringify(msg)}`)}info(msg){console.log(`[${this.name}]INFO:${this.stringify(msg)}`)}error(msg){console.log(`[${this.name}]ERROR:${this.stringify(msg)}`)}wait(millisec){return new Promise((resolve)=>setTimeout(resolve,millisec))}done(value={}){if(isQX||isLoon||isSurge||isStash||isShadowrocket){$done(value)}else if(isNode&&!isJSBox){if(typeof $context!=="undefined"){$context.headers=value.headers;$context.statusCode=value.statusCode;$context.body=value.body}}}stringify(obj_or_str){if(typeof obj_or_str==="string"||obj_or_str instanceof String)return obj_or_str;else try{return JSON.stringify(obj_or_str,null,2)}catch(err){return"[object Object]"}}})(name,debug)} 45 | -------------------------------------------------------------------------------- /jd/ql_env_upload.js: -------------------------------------------------------------------------------- 1 | /* 2 | 青龙 docker 每日自动同步 boxjs cookie 3 | 40 * * * https://raw.githubusercontent.com/dompling/Script/master/jd/ql_cookie_sync.js 4 | */ 5 | 6 | const $ = new API('ql', true); 7 | 8 | const title = '🐉 通知提示'; 9 | 10 | let envs = []; 11 | try { 12 | envs = JSON.parse($.read('env') || '[]'); 13 | } catch (e) { 14 | console.log(e); 15 | } 16 | 17 | async function getScriptUrl() { 18 | const response = await $.http.get({ 19 | url: 'https://raw.githubusercontent.com/dompling/Script/master/jd/ql_api.js', 20 | }); 21 | return response.body; 22 | } 23 | 24 | (async () => { 25 | if (!envs.length) return $.notify(title, '同步失败', '环境变量错误'); 26 | 27 | const ql_script = (await getScriptUrl()) || ''; 28 | eval(ql_script); 29 | await $.ql.initial(); 30 | 31 | const response = await $.ql.select(''); 32 | const delIds = response.data.map((item) => item.id); 33 | await $.ql.delete(delIds); 34 | console.log(`=======================清空环境变量=======================`); 35 | 36 | await $.ql.add( 37 | envs 38 | .filter((item) => item.status === 0) 39 | .map((env) => ({ 40 | name: `${env.name}`, 41 | value: `${env.value}`, 42 | remarks: `${env.remarks || ''}`, 43 | })) 44 | ); 45 | console.log(`=======================恢复环境变量=======================`); 46 | if ($.read('mute') !== 'true') { 47 | return $.notify(title, '同步成功', `同步个数:${envs.length} 个`); 48 | } 49 | })() 50 | .catch((e) => { 51 | $.error(JSON.stringify(e)); 52 | }) 53 | .finally(() => { 54 | $.done(); 55 | }); 56 | 57 | /* prettier-ignore */ 58 | function ENV(){const isJSBox=typeof require=="function"&&typeof $jsbox!="undefined";return{isQX:typeof $task!=="undefined",isLoon:typeof $loon!=="undefined",isSurge:typeof $httpClient!=="undefined"&&typeof $utils!=="undefined",isBrowser:typeof document!=="undefined",isNode:typeof require=="function"&&!isJSBox,isJSBox,isRequest:typeof $request!=="undefined",isScriptable:typeof importModule!=="undefined",isShadowrocket:"undefined"!==typeof $rocket,isStash:"undefined"!==typeof $environment&&$environment["stash-version"]}} 59 | /* prettier-ignore */ 60 | function HTTP(defaultOptions={baseURL:""}){const{isQX,isLoon,isSurge,isScriptable,isNode,isBrowser,isShadowrocket,isStash,}=ENV();const methods=["GET","POST","PUT","DELETE","HEAD","OPTIONS","PATCH"];const URL_REGEX=/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;function send(method,options){options=typeof options==="string"?{url:options}:options;const baseURL=defaultOptions.baseURL;if(baseURL&&!URL_REGEX.test(options.url||"")){options.url=baseURL?baseURL+options.url:options.url}if(options.body&&options.headers&&!options.headers["Content-Type"]){options.headers["Content-Type"]="application/x-www-form-urlencoded"}options={...defaultOptions,...options};const timeout=options.timeout;const events={...{onRequest:()=>{},onResponse:(resp)=>resp,onTimeout:()=>{},},...options.events,};events.onRequest(method,options);let worker;if(isQX){worker=$task.fetch({method,...options})}else if(isLoon||isSurge||isNode||isShadowrocket||isStash){worker=new Promise((resolve,reject)=>{const request=isNode?require("request"):$httpClient;request[method.toLowerCase()](options,(err,response,body)=>{if(err)reject(err);else resolve({statusCode:response.status||response.statusCode,headers:response.headers,body,})})})}else if(isScriptable){const request=new Request(options.url);request.method=method;request.headers=options.headers;request.body=options.body;worker=new Promise((resolve,reject)=>{request.loadString().then((body)=>{resolve({statusCode:request.response.statusCode,headers:request.response.headers,body,})}).catch((err)=>reject(err))})}else if(isBrowser){worker=new Promise((resolve,reject)=>{fetch(options.url,{method,headers:options.headers,body:options.body,}).then((response)=>response.json()).then((response)=>resolve({statusCode:response.status,headers:response.headers,body:response.data,})).catch(reject)})}let timeoutid;const timer=timeout?new Promise((_,reject)=>{timeoutid=setTimeout(()=>{events.onTimeout();return reject(`${method}URL:${options.url}exceeds the timeout ${timeout}ms`)},timeout)}):null;return(timer?Promise.race([timer,worker]).then((res)=>{clearTimeout(timeoutid);return res}):worker).then((resp)=>events.onResponse(resp))}const http={};methods.forEach((method)=>(http[method.toLowerCase()]=(options)=>send(method,options)));return http} 61 | /* prettier-ignore */ 62 | function API(name="untitled",debug=false){const{isQX,isLoon,isSurge,isScriptable,isNode,isShadowrocket,isStash,isJSBox}=ENV();return new(class{constructor(name,debug){this.name=name;this.debug=debug;this.http=HTTP();this.env=ENV();this.node=(()=>{if(isNode){const fs=require("fs");return{fs}}else{return null}})();this.initCache();const delay=(t,v)=>new Promise(function(resolve){setTimeout(resolve.bind(null,v),t)});Promise.prototype.delay=function(t){return this.then(function(v){return delay(t,v)})}}initCache(){if(isQX)this.cache=JSON.parse($prefs.valueForKey(this.name)||"{}");if(isLoon||isSurge||isStash||isShadowrocket)this.cache=JSON.parse($persistentStore.read(this.name)||"{}");if(isNode){let fpath="root.json";if(!this.node.fs.existsSync(fpath)){this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},(err)=>console.log(err))}this.root={};fpath=`${this.name}.json`;if(!this.node.fs.existsSync(fpath)){this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},(err)=>console.log(err));this.cache={}}else{this.cache=JSON.parse(this.node.fs.readFileSync(`${this.name}.json`))}}}persistCache(){const data=JSON.stringify(this.cache,null,2);if(isQX)$prefs.setValueForKey(data,this.name);if(isLoon||isSurge||isStash||isShadowrocket)$persistentStore.write(data,this.name);if(isNode){this.node.fs.writeFileSync(`${this.name}.json`,data,{flag:"w"},(err)=>console.log(err));this.node.fs.writeFileSync("root.json",JSON.stringify(this.root,null,2),{flag:"w"},(err)=>console.log(err))}}write(data,key){this.log(`SET ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.write(data,key)}if(isQX){return $prefs.setValueForKey(data,key)}if(isNode){this.root[key]=data}}else{this.cache[key]=data}this.persistCache()}read(key){this.log(`READ ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.read(key)}if(isQX){return $prefs.valueForKey(key)}if(isNode){return this.root[key]}}else{return this.cache[key]}}delete(key){this.log(`DELETE ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.write(null,key)}if(isQX){return $prefs.removeValueForKey(key)}if(isNode){delete this.root[key]}}else{delete this.cache[key]}this.persistCache()}notify(title,subtitle="",content="",options={}){const openURL=options["open-url"];const mediaURL=options["media-url"];if(isQX)$notify(title,subtitle,content,options);if(isSurge){$notification.post(title,subtitle,content+`${mediaURL?"\n多媒体:"+mediaURL:""}`,{url:openURL})}if(isLoon||isStash||isShadowrocket){let opts={};if(openURL)opts["openUrl"]=openURL;if(mediaURL)opts["mediaUrl"]=mediaURL;if(JSON.stringify(opts)==="{}"){$notification.post(title,subtitle,content)}else{$notification.post(title,subtitle,content,opts)}}if(isNode||isScriptable){const content_=content+(openURL?`\n点击跳转:${openURL}`:"")+(mediaURL?`\n多媒体:${mediaURL}`:"");if(isJSBox){const push=require("push");push.schedule({title:title,body:(subtitle?subtitle+"\n":"")+content_,})}else{console.log(`${title}\n${subtitle}\n${content_}\n\n`)}}}log(msg){if(this.debug)console.log(`[${this.name}]LOG:${this.stringify(msg)}`)}info(msg){console.log(`[${this.name}]INFO:${this.stringify(msg)}`)}error(msg){console.log(`[${this.name}]ERROR:${this.stringify(msg)}`)}wait(millisec){return new Promise((resolve)=>setTimeout(resolve,millisec))}done(value={}){if(isQX||isLoon||isSurge||isStash||isShadowrocket){$done(value)}else if(isNode&&!isJSBox){if(typeof $context!=="undefined"){$context.headers=value.headers;$context.statusCode=value.statusCode;$context.body=value.body}}}stringify(obj_or_str){if(typeof obj_or_str==="string"||obj_or_str instanceof String)return obj_or_str;else try{return JSON.stringify(obj_or_str,null,2)}catch(err){return"[object Object]"}}})(name,debug)} -------------------------------------------------------------------------------- /jd/ql_sync_box.js: -------------------------------------------------------------------------------- 1 | /* 2 | 青龙 docker 每日自动同步 boxjs cookie 3 | 40 * * * https://raw.githubusercontent.com/dompling/Script/master/jd/ql_cookie_sync.js 4 | */ 5 | 6 | const $ = new API('ql', true); 7 | 8 | const title = '🐉 通知提示'; 9 | const cookiesKey = '#CookiesJD'; 10 | let jd_reamrk = $.read('#jd_ck_remark'); 11 | let jd_cookies = []; 12 | try { 13 | jd_cookies = JSON.parse($.read(cookiesKey) || '[]'); 14 | jd_reamrk = JSON.parse(jd_reamrk || '[]'); 15 | } catch (e) { 16 | $.error(e); 17 | } 18 | 19 | function getUsername(ck) { 20 | if (!ck) return ""; 21 | return decodeURIComponent(ck.match(/pt_pin=([^; ]+)(?=;?)/)[1]); 22 | } 23 | 24 | async function getScriptUrl() { 25 | const response = await $.http.get({ 26 | url: 'https://raw.githubusercontent.com/dompling/Script/master/jd/ql_api.js', 27 | }); 28 | return response.body; 29 | } 30 | 31 | (async () => { 32 | const ql_script = (await getScriptUrl()) || ''; 33 | eval(ql_script); 34 | await $.ql.initial(); 35 | 36 | const cookiesRes = await $.ql.select(); 37 | const wskeyRes = await $.ql.select('JD_WSCK'); 38 | 39 | const JD_CACHE_INFO = await $.ql.select('JD_CACHE_INFO'); 40 | 41 | const wskey = {}; 42 | wskeyRes.data.forEach((item) => { 43 | const pin = getUsername(item.value); 44 | wskey[pin] = item.value; 45 | }); 46 | 47 | const cookies = cookiesRes.data.map((item) => { 48 | const key = getUsername(item.value); 49 | return { userName: key, cookie: item.value }; 50 | }); 51 | const saveCookie = jd_cookies.map((item) => { 52 | const qlCk = cookies.find((ql) => ql.userName === item.userName); 53 | let temp = { ...item }; 54 | if (qlCk) { 55 | temp = { ...temp, ...qlCk }; 56 | if (wskey[item.userName]) temp.wskey = wskey[item.userName]; 57 | } 58 | return temp; 59 | }); 60 | const userNames = saveCookie.map((item) => item.userName); 61 | cookies.forEach((ql) => { 62 | if (userNames.indexOf(ql.userName) === -1) saveCookie.push(ql); 63 | }); 64 | 65 | if (JD_CACHE_INFO.data.length) { 66 | const cache_info = JSON.parse(JD_CACHE_INFO.data[0].value); 67 | jd_reamrk.remark = JSON.parse(jd_reamrk.remark || '[]'); 68 | 69 | if (jd_reamrk.remark.length) { 70 | jd_reamrk.remark = jd_reamrk.remark.map((item, index) => { 71 | if (cache_info[item.username]) { 72 | return { ...item, ...cache_info[item.username], index }; 73 | } 74 | return item; 75 | }); 76 | jd_reamrk.remark = JSON.stringify(jd_reamrk.remark, null, `\t`); 77 | $.write(JSON.stringify(jd_reamrk), `#jd_ck_remark`); 78 | } 79 | 80 | } 81 | 82 | $.write(JSON.stringify(saveCookie, null, `\t`), cookiesKey); 83 | if ($.read('mute') !== 'true') { 84 | return $.notify( 85 | title, 86 | '已同步账号', 87 | `${cookies.map((item) => item.userName).join(`\n`)}` 88 | ); 89 | } 90 | })() 91 | .catch((e) => { 92 | $.log(JSON.stringify(e)); 93 | }) 94 | .finally(() => { 95 | $.done(); 96 | }); 97 | 98 | /* prettier-ignore */ 99 | function ENV(){const isJSBox=typeof require=="function"&&typeof $jsbox!="undefined";return{isQX:typeof $task!=="undefined",isLoon:typeof $loon!=="undefined",isSurge:typeof $httpClient!=="undefined"&&typeof $utils!=="undefined",isBrowser:typeof document!=="undefined",isNode:typeof require=="function"&&!isJSBox,isJSBox,isRequest:typeof $request!=="undefined",isScriptable:typeof importModule!=="undefined",isShadowrocket:"undefined"!==typeof $rocket,isStash:"undefined"!==typeof $environment&&$environment["stash-version"]}} 100 | /* prettier-ignore */ 101 | function HTTP(defaultOptions={baseURL:""}){const{isQX,isLoon,isSurge,isScriptable,isNode,isBrowser,isShadowrocket,isStash,}=ENV();const methods=["GET","POST","PUT","DELETE","HEAD","OPTIONS","PATCH"];const URL_REGEX=/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;function send(method,options){options=typeof options==="string"?{url:options}:options;const baseURL=defaultOptions.baseURL;if(baseURL&&!URL_REGEX.test(options.url||"")){options.url=baseURL?baseURL+options.url:options.url}if(options.body&&options.headers&&!options.headers["Content-Type"]){options.headers["Content-Type"]="application/x-www-form-urlencoded"}options={...defaultOptions,...options};const timeout=options.timeout;const events={...{onRequest:()=>{},onResponse:(resp)=>resp,onTimeout:()=>{},},...options.events,};events.onRequest(method,options);let worker;if(isQX){worker=$task.fetch({method,...options})}else if(isLoon||isSurge||isNode||isShadowrocket||isStash){worker=new Promise((resolve,reject)=>{const request=isNode?require("request"):$httpClient;request[method.toLowerCase()](options,(err,response,body)=>{if(err)reject(err);else resolve({statusCode:response.status||response.statusCode,headers:response.headers,body,})})})}else if(isScriptable){const request=new Request(options.url);request.method=method;request.headers=options.headers;request.body=options.body;worker=new Promise((resolve,reject)=>{request.loadString().then((body)=>{resolve({statusCode:request.response.statusCode,headers:request.response.headers,body,})}).catch((err)=>reject(err))})}else if(isBrowser){worker=new Promise((resolve,reject)=>{fetch(options.url,{method,headers:options.headers,body:options.body,}).then((response)=>response.json()).then((response)=>resolve({statusCode:response.status,headers:response.headers,body:response.data,})).catch(reject)})}let timeoutid;const timer=timeout?new Promise((_,reject)=>{timeoutid=setTimeout(()=>{events.onTimeout();return reject(`${method}URL:${options.url}exceeds the timeout ${timeout}ms`)},timeout)}):null;return(timer?Promise.race([timer,worker]).then((res)=>{clearTimeout(timeoutid);return res}):worker).then((resp)=>events.onResponse(resp))}const http={};methods.forEach((method)=>(http[method.toLowerCase()]=(options)=>send(method,options)));return http} 102 | /* prettier-ignore */ 103 | function API(name="untitled",debug=false){const{isQX,isLoon,isSurge,isScriptable,isNode,isShadowrocket,isStash,isJSBox}=ENV();return new(class{constructor(name,debug){this.name=name;this.debug=debug;this.http=HTTP();this.env=ENV();this.node=(()=>{if(isNode){const fs=require("fs");return{fs}}else{return null}})();this.initCache();const delay=(t,v)=>new Promise(function(resolve){setTimeout(resolve.bind(null,v),t)});Promise.prototype.delay=function(t){return this.then(function(v){return delay(t,v)})}}initCache(){if(isQX)this.cache=JSON.parse($prefs.valueForKey(this.name)||"{}");if(isLoon||isSurge||isStash||isShadowrocket)this.cache=JSON.parse($persistentStore.read(this.name)||"{}");if(isNode){let fpath="root.json";if(!this.node.fs.existsSync(fpath)){this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},(err)=>console.log(err))}this.root={};fpath=`${this.name}.json`;if(!this.node.fs.existsSync(fpath)){this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},(err)=>console.log(err));this.cache={}}else{this.cache=JSON.parse(this.node.fs.readFileSync(`${this.name}.json`))}}}persistCache(){const data=JSON.stringify(this.cache,null,2);if(isQX)$prefs.setValueForKey(data,this.name);if(isLoon||isSurge||isStash||isShadowrocket)$persistentStore.write(data,this.name);if(isNode){this.node.fs.writeFileSync(`${this.name}.json`,data,{flag:"w"},(err)=>console.log(err));this.node.fs.writeFileSync("root.json",JSON.stringify(this.root,null,2),{flag:"w"},(err)=>console.log(err))}}write(data,key){this.log(`SET ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.write(data,key)}if(isQX){return $prefs.setValueForKey(data,key)}if(isNode){this.root[key]=data}}else{this.cache[key]=data}this.persistCache()}read(key){this.log(`READ ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.read(key)}if(isQX){return $prefs.valueForKey(key)}if(isNode){return this.root[key]}}else{return this.cache[key]}}delete(key){this.log(`DELETE ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.write(null,key)}if(isQX){return $prefs.removeValueForKey(key)}if(isNode){delete this.root[key]}}else{delete this.cache[key]}this.persistCache()}notify(title,subtitle="",content="",options={}){const openURL=options["open-url"];const mediaURL=options["media-url"];if(isQX)$notify(title,subtitle,content,options);if(isSurge){$notification.post(title,subtitle,content+`${mediaURL?"\n多媒体:"+mediaURL:""}`,{url:openURL})}if(isLoon||isStash||isShadowrocket){let opts={};if(openURL)opts["openUrl"]=openURL;if(mediaURL)opts["mediaUrl"]=mediaURL;if(JSON.stringify(opts)==="{}"){$notification.post(title,subtitle,content)}else{$notification.post(title,subtitle,content,opts)}}if(isNode||isScriptable){const content_=content+(openURL?`\n点击跳转:${openURL}`:"")+(mediaURL?`\n多媒体:${mediaURL}`:"");if(isJSBox){const push=require("push");push.schedule({title:title,body:(subtitle?subtitle+"\n":"")+content_,})}else{console.log(`${title}\n${subtitle}\n${content_}\n\n`)}}}log(msg){if(this.debug)console.log(`[${this.name}]LOG:${this.stringify(msg)}`)}info(msg){console.log(`[${this.name}]INFO:${this.stringify(msg)}`)}error(msg){console.log(`[${this.name}]ERROR:${this.stringify(msg)}`)}wait(millisec){return new Promise((resolve)=>setTimeout(resolve,millisec))}done(value={}){if(isQX||isLoon||isSurge||isStash||isShadowrocket){$done(value)}else if(isNode&&!isJSBox){if(typeof $context!=="undefined"){$context.headers=value.headers;$context.statusCode=value.statusCode;$context.body=value.body}}}stringify(obj_or_str){if(typeof obj_or_str==="string"||obj_or_str instanceof String)return obj_or_str;else try{return JSON.stringify(obj_or_str,null,2)}catch(err){return"[object Object]"}}})(name,debug)} -------------------------------------------------------------------------------- /shortcut/sgmodule.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "dompling", 3 | "name": "模块管理器", 4 | "version": "1.2", 5 | "desc": "增加指定文件下载", 6 | "url": "https://www.icloud.com/shortcuts/cc3e949106af4414b1d813fcfcb4c0b3" 7 | } 8 | -------------------------------------------------------------------------------- /spotify/spotify-lyric.request.js: -------------------------------------------------------------------------------- 1 | const $ = new API("Spotify"); 2 | 3 | let trackId = $request.url.replace( 4 | "https://spclient.wg.spotify.com/color-lyrics/v2/track/", 5 | "" 6 | ); 7 | 8 | const randomIds = [ 9 | "7ptLu9jaGwjeJCYItMK1LY", 10 | "5bcbAT32LJS87hklgOxUqM", 11 | "1VcwIxoUBHE2RPL87sDBUy", 12 | "61ZqMVbR9GlvKJ06AiQE1B", 13 | "5bRt9Vs7UPznXM6EfBhiZ1", 14 | "09TnsucrKhbEU4qQI5dkV0", 15 | "0sFTMZdnVtnmqj9rymmCDU", 16 | "6Zl8uPNEcnHpHC0sVZhScU", 17 | "1b8ZybIufxmpDQszin5yPt", 18 | "7gmSd6MBDNHJpMBl4gM3N2", 19 | ]; 20 | const random_index = Math.floor(Math.random() * randomIds.length); 21 | const randomId = randomIds[random_index]; 22 | 23 | if ($request.url.indexOf("clientLanguage=zh") != -1) { 24 | trackId = trackId.replace("?clientLanguage=zh", ""); 25 | $request.url = $request.url.replace( 26 | /track\/.*\/?/, 27 | `track/${randomId}?clientLanguage=zh` 28 | ); 29 | $request.url = $request.url + `&trackId=${trackId}`; 30 | } 31 | 32 | $.done($request); 33 | 34 | /* prettier-ignore */ 35 | function ENV(){const isJSBox=typeof require=="function"&&typeof $jsbox!="undefined";return{isQX:typeof $task!=="undefined",isLoon:typeof $loon!=="undefined",isSurge:typeof $httpClient!=="undefined"&&typeof $utils!=="undefined",isBrowser:typeof document!=="undefined",isNode:typeof require=="function"&&!isJSBox,isJSBox,isRequest:typeof $request!=="undefined",isScriptable:typeof importModule!=="undefined",isShadowrocket:"undefined"!==typeof $rocket,isStash:"undefined"!==typeof $environment&&$environment["stash-version"]}} 36 | /* prettier-ignore */ 37 | function HTTP(defaultOptions={baseURL:""}){const{isQX,isLoon,isSurge,isScriptable,isNode,isBrowser,isShadowrocket,isStash,}=ENV();const methods=["GET","POST","PUT","DELETE","HEAD","OPTIONS","PATCH"];const URL_REGEX=/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;function send(method,options){options=typeof options==="string"?{url:options}:options;const baseURL=defaultOptions.baseURL;if(baseURL&&!URL_REGEX.test(options.url||"")){options.url=baseURL?baseURL+options.url:options.url}if(options.body&&options.headers&&!options.headers["Content-Type"]){options.headers["Content-Type"]="application/x-www-form-urlencoded"}options={...defaultOptions,...options};const timeout=options.timeout;const events={...{onRequest:()=>{},onResponse:(resp)=>resp,onTimeout:()=>{},},...options.events,};events.onRequest(method,options);let worker;if(isQX){worker=$task.fetch({method,...options})}else if(isLoon||isSurge||isNode||isShadowrocket||isStash){worker=new Promise((resolve,reject)=>{const request=isNode?require("request"):$httpClient;request[method.toLowerCase()](options,(err,response,body)=>{if(err)reject(err);else resolve({statusCode:response.status||response.statusCode,headers:response.headers,body,})})})}else if(isScriptable){const request=new Request(options.url);request.method=method;request.headers=options.headers;request.body=options.body;worker=new Promise((resolve,reject)=>{request.loadString().then((body)=>{resolve({statusCode:request.response.statusCode,headers:request.response.headers,body,})}).catch((err)=>reject(err))})}else if(isBrowser){worker=new Promise((resolve,reject)=>{fetch(options.url,{method,headers:options.headers,body:options.body,}).then((response)=>response.json()).then((response)=>resolve({statusCode:response.status,headers:response.headers,body:response.data,})).catch(reject)})}let timeoutid;const timer=timeout?new Promise((_,reject)=>{timeoutid=setTimeout(()=>{events.onTimeout();return reject(`${method}URL:${options.url}exceeds the timeout ${timeout}ms`)},timeout)}):null;return(timer?Promise.race([timer,worker]).then((res)=>{clearTimeout(timeoutid);return res}):worker).then((resp)=>events.onResponse(resp))}const http={};methods.forEach((method)=>(http[method.toLowerCase()]=(options)=>send(method,options)));return http} 38 | /* prettier-ignore */ 39 | function API(name="untitled",debug=false){const{isQX,isLoon,isSurge,isScriptable,isNode,isShadowrocket,isStash,}=ENV();return new(class{constructor(name,debug){this.name=name;this.debug=debug;this.http=HTTP();this.env=ENV();this.node=(()=>{if(isNode){const fs=require("fs");return{fs}}else{return null}})();this.initCache();const delay=(t,v)=>new Promise(function(resolve){setTimeout(resolve.bind(null,v),t)});Promise.prototype.delay=function(t){return this.then(function(v){return delay(t,v)})}}initCache(){if(isQX)this.cache=JSON.parse($prefs.valueForKey(this.name)||"{}");if(isLoon||isSurge||isStash||isShadowrocket)this.cache=JSON.parse($persistentStore.read(this.name)||"{}");if(isNode){let fpath="root.json";if(!this.node.fs.existsSync(fpath)){this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},(err)=>console.log(err))}this.root={};fpath=`${this.name}.json`;if(!this.node.fs.existsSync(fpath)){this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},(err)=>console.log(err));this.cache={}}else{this.cache=JSON.parse(this.node.fs.readFileSync(`${this.name}.json`))}}}persistCache(){const data=JSON.stringify(this.cache,null,2);if(isQX)$prefs.setValueForKey(data,this.name);if(isLoon||isSurge||isStash||isShadowrocket)$persistentStore.write(data,this.name);if(isNode){this.node.fs.writeFileSync(`${this.name}.json`,data,{flag:"w"},(err)=>console.log(err));this.node.fs.writeFileSync("root.json",JSON.stringify(this.root,null,2),{flag:"w"},(err)=>console.log(err))}}write(data,key){this.log(`SET ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.write(data,key)}if(isQX){return $prefs.setValueForKey(data,key)}if(isNode){this.root[key]=data}}else{this.cache[key]=data}this.persistCache()}read(key){this.log(`READ ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.read(key)}if(isQX){return $prefs.valueForKey(key)}if(isNode){return this.root[key]}}else{return this.cache[key]}}delete(key){this.log(`DELETE ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.write(null,key)}if(isQX){return $prefs.removeValueForKey(key)}if(isNode){delete this.root[key]}}else{delete this.cache[key]}this.persistCache()}notify(title,subtitle="",content="",options={}){const openURL=options["open-url"];const mediaURL=options["media-url"];if(isQX)$notify(title,subtitle,content,options);if(isSurge){$notification.post(title,subtitle,content+`${mediaURL?"\n多媒体:"+mediaURL:""}`,{url:openURL})}if(isLoon||isStash||isShadowrocket){let opts={};if(openURL)opts["openUrl"]=openURL;if(mediaURL)opts["mediaUrl"]=mediaURL;if(JSON.stringify(opts)==="{}"){$notification.post(title,subtitle,content)}else{$notification.post(title,subtitle,content,opts)}}if(isNode||isScriptable){const content_=content+(openURL?`\n点击跳转:${openURL}`:"")+(mediaURL?`\n多媒体:${mediaURL}`:"");if(isJSBox){const push=require("push");push.schedule({title:title,body:(subtitle?subtitle+"\n":"")+content_,})}else{console.log(`${title}\n${subtitle}\n${content_}\n\n`)}}}log(msg){if(this.debug)console.log(`[${this.name}]LOG:${this.stringify(msg)}`)}info(msg){console.log(`[${this.name}]INFO:${this.stringify(msg)}`)}error(msg){console.log(`[${this.name}]ERROR:${this.stringify(msg)}`)}wait(millisec){return new Promise((resolve)=>setTimeout(resolve,millisec))}done(value={}){if(isQX||isLoon||isSurge||isStash||isShadowrocket){$done(value)}else if(isNode&&!isJSBox){if(typeof $context!=="undefined"){$context.headers=value.headers;$context.statusCode=value.statusCode;$context.body=value.body}}}stringify(obj_or_str){if(typeof obj_or_str==="string"||obj_or_str instanceof String)return obj_or_str;else try{return JSON.stringify(obj_or_str,null,2)}catch(err){return"[object Object]"}}})(name,debug)} 40 | -------------------------------------------------------------------------------- /spotify/歌词搜索.ios.online.sgmodule: -------------------------------------------------------------------------------- 1 | #!name=🟢 歌词翻译 2 | #!desc=Spotify IOS 歌词翻译 3 | 4 | 5 | [Script] 6 | 7 | spotify歌词翻译 = type=http-response,pattern=^https:\/\/spclient\.wg\.spotify\.com\/color-lyrics\/v2\/track\/,requires-body=1,binary-body-mode=1,max-size=0,script-path=https://raw.githubusercontent.com/dompling/Script/master/spotify/spotify-lyric.search.js 8 | 9 | [MITM] 10 | 11 | hostname = %APPEND% spclient.wg.spotify.com -------------------------------------------------------------------------------- /spotify/歌词搜索.mac.online.sgmodule: -------------------------------------------------------------------------------- 1 | #!name=🟢 歌词搜索 2 | #!desc=Spotify 歌词翻译 3 | #!system=mac 4 | 5 | [Script] 6 | 7 | # 修改下方argument中的appid和securityKey,填入自己的appid和密钥 8 | spotify歌词翻译 = type=http-request,pattern=^https:\/\/spclient\.wg\.spotify\.com\/color-lyrics\/v2\/track\/,requires-body=1,max-size=0,script-path=https://raw.githubusercontent.com/dompling/Script/master/spotify/spotify-lyric.search.js 9 | 10 | [General] 11 | force-http-engine-hosts = %APPEND% spclient.wg.spotify.com 12 | 13 | [MITM] 14 | 15 | hostname = %APPEND% spclient.wg.spotify.com -------------------------------------------------------------------------------- /spotify/歌词翻译.ios.online.sgmodule: -------------------------------------------------------------------------------- 1 | #!name=🟢 歌词翻译.IOS 2 | #!desc=Spotify IOS 歌词翻译 3 | #!system=ios 4 | 5 | [Script] 6 | spotify歌词翻译 = type=http-response,pattern=^https:\/\/spclient\.wg\.spotify\.com\/color-lyrics\/v2\/track\/,requires-body=1,binary-body-mode=1,max-size=0,script-path=https://raw.githubusercontent.com/dompling/Script/master/spotify/spotify-lyric.ios.js 7 | 8 | 9 | [MITM] 10 | 11 | hostname = %APPEND% spclient.wg.spotify.com -------------------------------------------------------------------------------- /spotify/歌词翻译.mac.online.sgmodule: -------------------------------------------------------------------------------- 1 | #!name=🟢 歌词翻译.MAC 2 | #!desc=Spotify MAC 歌词翻译 3 | #!system=mac 4 | 5 | [Script] 6 | 7 | spotify歌词翻译 = type=http-response,pattern=^https:\/\/spclient\.wg\.spotify\.com\/color-lyrics\/v2\/track\/,requires-body=1,max-size=0,script-path=https://raw.githubusercontent.com/dompling/Script/master/spotify/spotify-lyric.mac.js 8 | 9 | 10 | [MITM] 11 | 12 | hostname = %APPEND% spclient.wg.spotify.com -------------------------------------------------------------------------------- /tools/open-api.js: -------------------------------------------------------------------------------- 1 | function Tools(name) { 2 | /* prettier-ignore */ 3 | function ENV(){const isJSBox=typeof require=="function"&&typeof $jsbox!="undefined";return{isQX:typeof $task!=="undefined",isLoon:typeof $loon!=="undefined",isSurge:typeof $httpClient!=="undefined"&&typeof $utils!=="undefined",isBrowser:typeof document!=="undefined",isNode:typeof require=="function"&&!isJSBox,isJSBox,isRequest:typeof $request!=="undefined",isScriptable:typeof importModule!=="undefined",isShadowrocket:"undefined"!==typeof $rocket,isStash:"undefined"!==typeof $environment&&$environment["stash-version"]}} 4 | /* prettier-ignore */ 5 | function HTTP(defaultOptions={baseURL:""}){const{isQX,isLoon,isSurge,isScriptable,isNode,isBrowser,isShadowrocket,isStash,}=ENV();const methods=["GET","POST","PUT","DELETE","HEAD","OPTIONS","PATCH"];const URL_REGEX=/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;function send(method,options){options=typeof options==="string"?{url:options}:options;const baseURL=defaultOptions.baseURL;if(baseURL&&!URL_REGEX.test(options.url||"")){options.url=baseURL?baseURL+options.url:options.url}if(options.body&&options.headers&&!options.headers["Content-Type"]){options.headers["Content-Type"]="application/x-www-form-urlencoded"}options={...defaultOptions,...options};const timeout=options.timeout;const events={...{onRequest:()=>{},onResponse:(resp)=>resp,onTimeout:()=>{},},...options.events,};events.onRequest(method,options);let worker;if(isQX){worker=$task.fetch({method,...options})}else if(isLoon||isSurge||isNode||isShadowrocket||isStash){worker=new Promise((resolve,reject)=>{const request=isNode?require("request"):$httpClient;request[method.toLowerCase()](options,(err,response,body)=>{if(err)reject(err);else resolve({statusCode:response.status||response.statusCode,headers:response.headers,body,})})})}else if(isScriptable){const request=new Request(options.url);request.method=method;request.headers=options.headers;request.body=options.body;worker=new Promise((resolve,reject)=>{request.loadString().then((body)=>{resolve({statusCode:request.response.statusCode,headers:request.response.headers,body,})}).catch((err)=>reject(err))})}else if(isBrowser){worker=new Promise((resolve,reject)=>{fetch(options.url,{method,headers:options.headers,body:options.body,}).then((response)=>response.json()).then((response)=>resolve({statusCode:response.status,headers:response.headers,body:response.data,})).catch(reject)})}let timeoutid;const timer=timeout?new Promise((_,reject)=>{timeoutid=setTimeout(()=>{events.onTimeout();return reject(`${method}URL:${options.url}exceeds the timeout ${timeout}ms`)},timeout)}):null;return(timer?Promise.race([timer,worker]).then((res)=>{clearTimeout(timeoutid);return res}):worker).then((resp)=>events.onResponse(resp))}const http={};methods.forEach((method)=>(http[method.toLowerCase()]=(options)=>send(method,options)));return http} 6 | /* prettier-ignore */ 7 | function API(name="untitled",debug=false){const{isQX,isLoon,isSurge,isScriptable,isNode,isShadowrocket,isStash,}=ENV();return new(class{constructor(name,debug){this.name=name;this.debug=debug;this.http=HTTP();this.env=ENV();this.node=(()=>{if(isNode){const fs=require("fs");return{fs}}else{return null}})();this.initCache();const delay=(t,v)=>new Promise(function(resolve){setTimeout(resolve.bind(null,v),t)});Promise.prototype.delay=function(t){return this.then(function(v){return delay(t,v)})}}initCache(){if(isQX)this.cache=JSON.parse($prefs.valueForKey(this.name)||"{}");if(isLoon||isSurge||isStash||isShadowrocket)this.cache=JSON.parse($persistentStore.read(this.name)||"{}");if(isNode){let fpath="root.json";if(!this.node.fs.existsSync(fpath)){this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},(err)=>console.log(err))}this.root={};fpath=`${this.name}.json`;if(!this.node.fs.existsSync(fpath)){this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},(err)=>console.log(err));this.cache={}}else{this.cache=JSON.parse(this.node.fs.readFileSync(`${this.name}.json`))}}}persistCache(){const data=JSON.stringify(this.cache,null,2);if(isQX)$prefs.setValueForKey(data,this.name);if(isLoon||isSurge||isStash||isShadowrocket)$persistentStore.write(data,this.name);if(isNode){this.node.fs.writeFileSync(`${this.name}.json`,data,{flag:"w"},(err)=>console.log(err));this.node.fs.writeFileSync("root.json",JSON.stringify(this.root,null,2),{flag:"w"},(err)=>console.log(err))}}lodash_set(obj,path,value){if(Object(obj)!==obj)return obj;if(!Array.isArray(path))path=path.toString().match(/[^.[\]]+/g)||[];path.slice(0,-1).reduce((a,c,i)=>Object(a[c])===a[c]?a[c]:(a[c]=Math.abs(path[i+1])>>0===+path[i+1]?[]:{}),obj)[path[path.length-1]]=value;return obj}lodash_get(t,s,e){const i=s.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(((r=Object(r)[t]),void 0===r))return e;return r}middlewareVal=(key)=>{if(/^@/.test(key)){const[,objkey,paths]=/^@(.*?)\.(.*?)$/.exec(key);return[objkey,paths]}else if(key.indexOf("#")!==-1){const objkey=key.substring(1);return[objkey]}return[key]};write(data,key){const[objkey,paths]=this.middlewareVal(key);if(paths){const objdat=$.read(objkey);const objval=objkey?objdat==="null"?null:objdat||"{}":"{}";try{const objedval=JSON.parse(objval);this.lodash_set(objedval,paths,data);this.root[objkey]=objedval}catch(e){const objedval={};this.lodash_set(objedval,paths,data);this.root[objkey]=objedval}}else{this.root[objkey]=data}this.persistCache()}read(key,defaultValue){this.log(`READ ${key}`);const[objkey,paths]=this.middlewareVal(key);let result;if(paths){let obj;try{obj=objkey?JSON.parse(this.root[objkey]):""}catch{obj=objkey?this.root[objkey]:""}result=this.lodash_get(obj,paths,"")||defaultValue}else{result=this.root[objkey]||defaultValue}return result}delete(key){this.log(`DELETE ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.write(null,key)}if(isQX){return $prefs.removeValueForKey(key)}if(isNode){delete this.root[key]}}else{delete this.cache[key]}this.persistCache()}notify(title,subtitle="",content="",options={}){const openURL=options["open-url"];const mediaURL=options["media-url"];if(isQX)$notify(title,subtitle,content,options);if(isSurge){$notification.post(title,subtitle,content+`${mediaURL?"\n多媒体:"+mediaURL:""}`,{url:openURL})}if(isLoon||isStash||isShadowrocket){let opts={};if(openURL)opts["openUrl"]=openURL;if(mediaURL)opts["mediaUrl"]=mediaURL;if(JSON.stringify(opts)==="{}"){$notification.post(title,subtitle,content)}else{$notification.post(title,subtitle,content,opts)}}if(isNode||isScriptable){const content_=content+(openURL?`\n点击跳转:${openURL}`:"")+(mediaURL?`\n多媒体:${mediaURL}`:"");if(isJSBox){const push=require("push");push.schedule({title:title,body:(subtitle?subtitle+"\n":"")+content_,})}else{console.log(`${title}\n${subtitle}\n${content_}\n\n`)}}}log(msg){if(this.debug)console.log(`[${this.name}]LOG:${this.stringify(msg)}`)}info(msg){console.log(`[${this.name}]INFO:${this.stringify(msg)}`)}error(msg){console.log(`[${this.name}]ERROR:${this.stringify(msg)}`)}wait(millisec){return new Promise((resolve)=>setTimeout(resolve,millisec))}done(value={}){if(isQX||isLoon||isSurge||isStash||isShadowrocket){$done(value)}else if(isNode&&!isJSBox){if(typeof $context!=="undefined"){$context.headers=value.headers;$context.statusCode=value.statusCode;$context.body=value.body}}}stringify(obj_or_str){if(typeof obj_or_str==="string"||obj_or_str instanceof String)return obj_or_str;else try{return JSON.stringify(obj_or_str,null,2)}catch(err){return"[object Object]"}}})(name,debug)} 8 | return new API(name); 9 | } 10 | -------------------------------------------------------------------------------- /tools/task.js: -------------------------------------------------------------------------------- 1 | const $ = new API("SET_TIME"); 2 | const subs = $.read("SUB"); 3 | 4 | let task = subs.map((item) => item.url); 5 | try { 6 | task = [JSON.parse($argument)]; 7 | } catch {} 8 | 9 | (async () => { 10 | const cacheTask = []; 11 | for (const url of task) { 12 | try { 13 | const result = await $.http.get(url); 14 | const res = JSON.parse(result.body); 15 | $.info(res.name); 16 | const item = dealTask(res.task, res.name); 17 | cacheTask.push({ name: res.name, task: item }); 18 | } catch (e) { 19 | $.error(e); 20 | } 21 | } 22 | $.write(cacheTask, "CACHE"); 23 | $.info("缓存完成"); 24 | })().finally(() => { 25 | $.done({}); 26 | }); 27 | 28 | function dealTask(taskList, name) { 29 | const dataSource = {}; 30 | taskList.forEach((item) => { 31 | const rows = item.config.split(",").map((t) => t.split("=")); 32 | let value = { url: "", cron: "", tag: "", ["img-url"]: "" }; 33 | rows.forEach((type) => { 34 | if (type.length === 1) { 35 | const [cron, url] = type[0].split(/(https?:\/\/[^\s]+)/); 36 | value.cron = cron; 37 | value.url = url; 38 | } else { 39 | let [label, val] = type; 40 | val = val.replace(/\s*/g, ""); 41 | label = label.replace(/\s*/g, ""); 42 | value[label] = val; 43 | } 44 | }); 45 | if (value.url && value.cron) dataSource[`${name}_${value.tag}`] = value; 46 | }); 47 | return dataSource; 48 | } 49 | 50 | /* prettier-ignore */ 51 | function ENV(){const isJSBox=typeof require=="function"&&typeof $jsbox!="undefined";return{isQX:typeof $task!=="undefined",isLoon:typeof $loon!=="undefined",isSurge:typeof $httpClient!=="undefined"&&typeof $utils!=="undefined",isBrowser:typeof document!=="undefined",isNode:typeof require=="function"&&!isJSBox,isJSBox,isRequest:typeof $request!=="undefined",isScriptable:typeof importModule!=="undefined",isShadowrocket:"undefined"!==typeof $rocket,isStash:"undefined"!==typeof $environment&&$environment["stash-version"]}} 52 | /* prettier-ignore */ 53 | function HTTP(defaultOptions={baseURL:""}){const{isQX,isLoon,isSurge,isScriptable,isNode,isBrowser,isShadowrocket,isStash,}=ENV();const methods=["GET","POST","PUT","DELETE","HEAD","OPTIONS","PATCH"];const URL_REGEX=/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;function send(method,options){options=typeof options==="string"?{url:options}:options;const baseURL=defaultOptions.baseURL;if(baseURL&&!URL_REGEX.test(options.url||"")){options.url=baseURL?baseURL+options.url:options.url}if(options.body&&options.headers&&!options.headers["Content-Type"]){options.headers["Content-Type"]="application/x-www-form-urlencoded"}options={...defaultOptions,...options};const timeout=options.timeout;const events={...{onRequest:()=>{},onResponse:(resp)=>resp,onTimeout:()=>{},},...options.events,};events.onRequest(method,options);let worker;if(isQX){worker=$task.fetch({method,...options})}else if(isLoon||isSurge||isNode||isShadowrocket||isStash){worker=new Promise((resolve,reject)=>{const request=isNode?require("request"):$httpClient;request[method.toLowerCase()](options,(err,response,body)=>{if(err)reject(err);else resolve({statusCode:response.status||response.statusCode,headers:response.headers,body,})})})}else if(isScriptable){const request=new Request(options.url);request.method=method;request.headers=options.headers;request.body=options.body;worker=new Promise((resolve,reject)=>{request.loadString().then((body)=>{resolve({statusCode:request.response.statusCode,headers:request.response.headers,body,})}).catch((err)=>reject(err))})}else if(isBrowser){worker=new Promise((resolve,reject)=>{fetch(options.url,{method,headers:options.headers,body:options.body,}).then((response)=>response.json()).then((response)=>resolve({statusCode:response.status,headers:response.headers,body:response.data,})).catch(reject)})}let timeoutid;const timer=timeout?new Promise((_,reject)=>{timeoutid=setTimeout(()=>{events.onTimeout();return reject(`${method}URL:${options.url}exceeds the timeout ${timeout}ms`)},timeout)}):null;return(timer?Promise.race([timer,worker]).then((res)=>{clearTimeout(timeoutid);return res}):worker).then((resp)=>events.onResponse(resp))}const http={};methods.forEach((method)=>(http[method.toLowerCase()]=(options)=>send(method,options)));return http} 54 | /* prettier-ignore */ 55 | function API(name="untitled",debug=false){const{isQX,isLoon,isSurge,isScriptable,isNode,isShadowrocket,isStash,}=ENV();return new(class{constructor(name,debug){this.name=name;this.debug=debug;this.http=HTTP();this.env=ENV();this.node=(()=>{if(isNode){const fs=require("fs");return{fs}}else{return null}})();this.initCache();const delay=(t,v)=>new Promise(function(resolve){setTimeout(resolve.bind(null,v),t)});Promise.prototype.delay=function(t){return this.then(function(v){return delay(t,v)})}}initCache(){if(isQX)this.cache=JSON.parse($prefs.valueForKey(this.name)||"{}");if(isLoon||isSurge||isStash||isShadowrocket)this.cache=JSON.parse($persistentStore.read(this.name)||"{}");if(isNode){let fpath="root.json";if(!this.node.fs.existsSync(fpath)){this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},(err)=>console.log(err))}this.root={};fpath=`${this.name}.json`;if(!this.node.fs.existsSync(fpath)){this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},(err)=>console.log(err));this.cache={}}else{this.cache=JSON.parse(this.node.fs.readFileSync(`${this.name}.json`))}}}persistCache(){const data=JSON.stringify(this.cache,null,2);if(isQX)$prefs.setValueForKey(data,this.name);if(isLoon||isSurge||isStash||isShadowrocket)$persistentStore.write(data,this.name);if(isNode){this.node.fs.writeFileSync(`${this.name}.json`,data,{flag:"w"},(err)=>console.log(err));this.node.fs.writeFileSync("root.json",JSON.stringify(this.root,null,2),{flag:"w"},(err)=>console.log(err))}}write(data,key){this.log(`SET ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.write(data,key)}if(isQX){return $prefs.setValueForKey(data,key)}if(isNode){this.root[key]=data}}else{this.cache[key]=data}this.persistCache()}read(key){this.log(`READ ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.read(key)}if(isQX){return $prefs.valueForKey(key)}if(isNode){return this.root[key]}}else{return this.cache[key]}}delete(key){this.log(`DELETE ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.write(null,key)}if(isQX){return $prefs.removeValueForKey(key)}if(isNode){delete this.root[key]}}else{delete this.cache[key]}this.persistCache()}notify(title,subtitle="",content="",options={}){const openURL=options["open-url"];const mediaURL=options["media-url"];if(isQX)$notify(title,subtitle,content,options);if(isSurge){$notification.post(title,subtitle,content+`${mediaURL?"\n多媒体:"+mediaURL:""}`,{url:openURL})}if(isLoon||isStash||isShadowrocket){let opts={};if(openURL)opts["openUrl"]=openURL;if(mediaURL)opts["mediaUrl"]=mediaURL;if(JSON.stringify(opts)==="{}"){$notification.post(title,subtitle,content)}else{$notification.post(title,subtitle,content,opts)}}if(isNode||isScriptable){const content_=content+(openURL?`\n点击跳转:${openURL}`:"")+(mediaURL?`\n多媒体:${mediaURL}`:"");if(isJSBox){const push=require("push");push.schedule({title:title,body:(subtitle?subtitle+"\n":"")+content_,})}else{console.log(`${title}\n${subtitle}\n${content_}\n\n`)}}}log(msg){if(this.debug)console.log(`[${this.name}]LOG:${this.stringify(msg)}`)}info(msg){console.log(`[${this.name}]INFO:${this.stringify(msg)}`)}error(msg){console.log(`[${this.name}]ERROR:${this.stringify(msg)}`)}wait(millisec){return new Promise((resolve)=>setTimeout(resolve,millisec))}done(value={}){if(isQX||isLoon||isSurge||isStash||isShadowrocket){$done(value)}else if(isNode&&!isJSBox){if(typeof $context!=="undefined"){$context.headers=value.headers;$context.statusCode=value.statusCode;$context.body=value.body}}}stringify(obj_or_str){if(typeof obj_or_str==="string"||obj_or_str instanceof String)return obj_or_str;else try{return JSON.stringify(obj_or_str,null,2)}catch(err){return"[object Object]"}}})(name,debug)} 56 | -------------------------------------------------------------------------------- /wsgw/wsgw.sgmodule: -------------------------------------------------------------------------------- 1 | #!name =🔴 网上国网 2 | #!category=通用重写 3 | #!desc=95598 4 | 5 | [Script] 6 | 接口重写 = type=http-request, pattern=^https?:\/\/api\.wsgw-rewrite\.com\/electricity\/bill\/all, script-path=https://raw.githubusercontent.com/dompling/Script/master/wsgw/index.js, requires-body=true, max-size=-1, timeout=60 7 | 8 | [MITM] 9 | hostname = %APPEND% api.wsgw-rewrite.com 10 | 11 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | ajv@^6.12.3: 6 | version "6.12.4" 7 | resolved "https://registry.npm.taobao.org/ajv/download/ajv-6.12.4.tgz?cache=0&sync_timestamp=1597480893665&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fajv%2Fdownload%2Fajv-6.12.4.tgz#0614facc4522127fa713445c6bfd3ebd376e2234" 8 | integrity sha1-BhT6zEUiEn+nE0Rca/0+vTduIjQ= 9 | dependencies: 10 | fast-deep-equal "^3.1.1" 11 | fast-json-stable-stringify "^2.0.0" 12 | json-schema-traverse "^0.4.1" 13 | uri-js "^4.2.2" 14 | 15 | asn1@~0.2.3: 16 | version "0.2.4" 17 | resolved "https://registry.npm.taobao.org/asn1/download/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" 18 | integrity sha1-jSR136tVO7M+d7VOWeiAu4ziMTY= 19 | dependencies: 20 | safer-buffer "~2.1.0" 21 | 22 | assert-plus@1.0.0, assert-plus@^1.0.0: 23 | version "1.0.0" 24 | resolved "https://registry.npm.taobao.org/assert-plus/download/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" 25 | integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= 26 | 27 | asynckit@^0.4.0: 28 | version "0.4.0" 29 | resolved "https://registry.npm.taobao.org/asynckit/download/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" 30 | integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= 31 | 32 | aws-sign2@~0.7.0: 33 | version "0.7.0" 34 | resolved "https://registry.npm.taobao.org/aws-sign2/download/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" 35 | integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= 36 | 37 | aws4@^1.8.0: 38 | version "1.10.1" 39 | resolved "https://registry.npm.taobao.org/aws4/download/aws4-1.10.1.tgz?cache=0&sync_timestamp=1597237018736&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Faws4%2Fdownload%2Faws4-1.10.1.tgz#e1e82e4f3e999e2cfd61b161280d16a111f86428" 40 | integrity sha1-4eguTz6Zniz9YbFhKA0WoRH4ZCg= 41 | 42 | bcrypt-pbkdf@^1.0.0: 43 | version "1.0.2" 44 | resolved "https://registry.npm.taobao.org/bcrypt-pbkdf/download/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" 45 | integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= 46 | dependencies: 47 | tweetnacl "^0.14.3" 48 | 49 | caseless@~0.12.0: 50 | version "0.12.0" 51 | resolved "https://registry.npm.taobao.org/caseless/download/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" 52 | integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= 53 | 54 | combined-stream@^1.0.6, combined-stream@~1.0.6: 55 | version "1.0.8" 56 | resolved "https://registry.npm.taobao.org/combined-stream/download/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" 57 | integrity sha1-w9RaizT9cwYxoRCoolIGgrMdWn8= 58 | dependencies: 59 | delayed-stream "~1.0.0" 60 | 61 | core-util-is@1.0.2: 62 | version "1.0.2" 63 | resolved "https://registry.npm.taobao.org/core-util-is/download/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" 64 | integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= 65 | 66 | dashdash@^1.12.0: 67 | version "1.14.1" 68 | resolved "https://registry.npm.taobao.org/dashdash/download/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" 69 | integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= 70 | dependencies: 71 | assert-plus "^1.0.0" 72 | 73 | delayed-stream@~1.0.0: 74 | version "1.0.0" 75 | resolved "https://registry.npm.taobao.org/delayed-stream/download/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" 76 | integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= 77 | 78 | ecc-jsbn@~0.1.1: 79 | version "0.1.2" 80 | resolved "https://registry.npm.taobao.org/ecc-jsbn/download/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" 81 | integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= 82 | dependencies: 83 | jsbn "~0.1.0" 84 | safer-buffer "^2.1.0" 85 | 86 | extend@~3.0.2: 87 | version "3.0.2" 88 | resolved "https://registry.npm.taobao.org/extend/download/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" 89 | integrity sha1-+LETa0Bx+9jrFAr/hYsQGewpFfo= 90 | 91 | extsprintf@1.3.0: 92 | version "1.3.0" 93 | resolved "https://registry.npm.taobao.org/extsprintf/download/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" 94 | integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= 95 | 96 | extsprintf@^1.2.0: 97 | version "1.4.0" 98 | resolved "https://registry.npm.taobao.org/extsprintf/download/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" 99 | integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= 100 | 101 | fast-deep-equal@^3.1.1: 102 | version "3.1.3" 103 | resolved "https://registry.npm.taobao.org/fast-deep-equal/download/fast-deep-equal-3.1.3.tgz?cache=0&sync_timestamp=1591599604977&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffast-deep-equal%2Fdownload%2Ffast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" 104 | integrity sha1-On1WtVnWy8PrUSMlJE5hmmXGxSU= 105 | 106 | fast-json-stable-stringify@^2.0.0: 107 | version "2.1.0" 108 | resolved "https://registry.npm.taobao.org/fast-json-stable-stringify/download/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" 109 | integrity sha1-h0v2nG9ATCtdmcSBNBOZ/VWJJjM= 110 | 111 | forever-agent@~0.6.1: 112 | version "0.6.1" 113 | resolved "https://registry.npm.taobao.org/forever-agent/download/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" 114 | integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= 115 | 116 | form-data@~2.3.2: 117 | version "2.3.3" 118 | resolved "https://registry.npm.taobao.org/form-data/download/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" 119 | integrity sha1-3M5SwF9kTymManq5Nr1yTO/786Y= 120 | dependencies: 121 | asynckit "^0.4.0" 122 | combined-stream "^1.0.6" 123 | mime-types "^2.1.12" 124 | 125 | getpass@^0.1.1: 126 | version "0.1.7" 127 | resolved "https://registry.npm.taobao.org/getpass/download/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" 128 | integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= 129 | dependencies: 130 | assert-plus "^1.0.0" 131 | 132 | har-schema@^2.0.0: 133 | version "2.0.0" 134 | resolved "https://registry.npm.taobao.org/har-schema/download/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" 135 | integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= 136 | 137 | har-validator@~5.1.3: 138 | version "5.1.5" 139 | resolved "https://registry.npm.taobao.org/har-validator/download/har-validator-5.1.5.tgz?cache=0&sync_timestamp=1596082605533&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhar-validator%2Fdownload%2Fhar-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" 140 | integrity sha1-HwgDufjLIMD6E4It8ezds2veHv0= 141 | dependencies: 142 | ajv "^6.12.3" 143 | har-schema "^2.0.0" 144 | 145 | http-signature@~1.2.0: 146 | version "1.2.0" 147 | resolved "https://registry.npm.taobao.org/http-signature/download/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" 148 | integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= 149 | dependencies: 150 | assert-plus "^1.0.0" 151 | jsprim "^1.2.2" 152 | sshpk "^1.7.0" 153 | 154 | is-typedarray@~1.0.0: 155 | version "1.0.0" 156 | resolved "https://registry.npm.taobao.org/is-typedarray/download/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" 157 | integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= 158 | 159 | isstream@~0.1.2: 160 | version "0.1.2" 161 | resolved "https://registry.npm.taobao.org/isstream/download/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" 162 | integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= 163 | 164 | jsbn@~0.1.0: 165 | version "0.1.1" 166 | resolved "https://registry.npm.taobao.org/jsbn/download/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" 167 | integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= 168 | 169 | json-schema-traverse@^0.4.1: 170 | version "0.4.1" 171 | resolved "https://registry.npm.taobao.org/json-schema-traverse/download/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" 172 | integrity sha1-afaofZUTq4u4/mO9sJecRI5oRmA= 173 | 174 | json-schema@0.2.3: 175 | version "0.2.3" 176 | resolved "https://registry.npm.taobao.org/json-schema/download/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" 177 | integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= 178 | 179 | json-stringify-safe@~5.0.1: 180 | version "5.0.1" 181 | resolved "https://registry.npm.taobao.org/json-stringify-safe/download/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" 182 | integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= 183 | 184 | jsprim@^1.2.2: 185 | version "1.4.1" 186 | resolved "https://registry.npm.taobao.org/jsprim/download/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" 187 | integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= 188 | dependencies: 189 | assert-plus "1.0.0" 190 | extsprintf "1.3.0" 191 | json-schema "0.2.3" 192 | verror "1.10.0" 193 | 194 | mime-db@1.44.0: 195 | version "1.44.0" 196 | resolved "https://registry.npm.taobao.org/mime-db/download/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" 197 | integrity sha1-+hHF6wrKEzS0Izy01S8QxaYnL5I= 198 | 199 | mime-types@^2.1.12, mime-types@~2.1.19: 200 | version "2.1.27" 201 | resolved "https://registry.npm.taobao.org/mime-types/download/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f" 202 | integrity sha1-R5SfmOJ56lMRn1ci4PNOUpvsAJ8= 203 | dependencies: 204 | mime-db "1.44.0" 205 | 206 | oauth-sign@~0.9.0: 207 | version "0.9.0" 208 | resolved "https://registry.npm.taobao.org/oauth-sign/download/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" 209 | integrity sha1-R6ewFrqmi1+g7PPe4IqFxnmsZFU= 210 | 211 | performance-now@^2.1.0: 212 | version "2.1.0" 213 | resolved "https://registry.npm.taobao.org/performance-now/download/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" 214 | integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= 215 | 216 | psl@^1.1.28: 217 | version "1.8.0" 218 | resolved "https://registry.npm.taobao.org/psl/download/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" 219 | integrity sha1-kyb4vPsBOtzABf3/BWrM4CDlHCQ= 220 | 221 | punycode@^2.1.0, punycode@^2.1.1: 222 | version "2.1.1" 223 | resolved "https://registry.npm.taobao.org/punycode/download/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" 224 | integrity sha1-tYsBCsQMIsVldhbI0sLALHv0eew= 225 | 226 | qs@~6.5.2: 227 | version "6.5.2" 228 | resolved "https://registry.npm.taobao.org/qs/download/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" 229 | integrity sha1-yzroBuh0BERYTvFUzo7pjUA/PjY= 230 | 231 | request@^2.88.2: 232 | version "2.88.2" 233 | resolved "https://registry.npm.taobao.org/request/download/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" 234 | integrity sha1-1zyRhzHLWofaBH4gcjQUb2ZNErM= 235 | dependencies: 236 | aws-sign2 "~0.7.0" 237 | aws4 "^1.8.0" 238 | caseless "~0.12.0" 239 | combined-stream "~1.0.6" 240 | extend "~3.0.2" 241 | forever-agent "~0.6.1" 242 | form-data "~2.3.2" 243 | har-validator "~5.1.3" 244 | http-signature "~1.2.0" 245 | is-typedarray "~1.0.0" 246 | isstream "~0.1.2" 247 | json-stringify-safe "~5.0.1" 248 | mime-types "~2.1.19" 249 | oauth-sign "~0.9.0" 250 | performance-now "^2.1.0" 251 | qs "~6.5.2" 252 | safe-buffer "^5.1.2" 253 | tough-cookie "~2.5.0" 254 | tunnel-agent "^0.6.0" 255 | uuid "^3.3.2" 256 | 257 | safe-buffer@^5.0.1, safe-buffer@^5.1.2: 258 | version "5.2.1" 259 | resolved "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" 260 | integrity sha1-Hq+fqb2x/dTsdfWPnNtOa3gn7sY= 261 | 262 | safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: 263 | version "2.1.2" 264 | resolved "https://registry.npm.taobao.org/safer-buffer/download/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" 265 | integrity sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo= 266 | 267 | sshpk@^1.7.0: 268 | version "1.16.1" 269 | resolved "https://registry.npm.taobao.org/sshpk/download/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" 270 | integrity sha1-+2YcC+8ps520B2nuOfpwCT1vaHc= 271 | dependencies: 272 | asn1 "~0.2.3" 273 | assert-plus "^1.0.0" 274 | bcrypt-pbkdf "^1.0.0" 275 | dashdash "^1.12.0" 276 | ecc-jsbn "~0.1.1" 277 | getpass "^0.1.1" 278 | jsbn "~0.1.0" 279 | safer-buffer "^2.0.2" 280 | tweetnacl "~0.14.0" 281 | 282 | tough-cookie@~2.5.0: 283 | version "2.5.0" 284 | resolved "https://registry.npm.taobao.org/tough-cookie/download/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" 285 | integrity sha1-zZ+yoKodWhK0c72fuW+j3P9lreI= 286 | dependencies: 287 | psl "^1.1.28" 288 | punycode "^2.1.1" 289 | 290 | tunnel-agent@^0.6.0: 291 | version "0.6.0" 292 | resolved "https://registry.npm.taobao.org/tunnel-agent/download/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" 293 | integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= 294 | dependencies: 295 | safe-buffer "^5.0.1" 296 | 297 | tweetnacl@^0.14.3, tweetnacl@~0.14.0: 298 | version "0.14.5" 299 | resolved "https://registry.npm.taobao.org/tweetnacl/download/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" 300 | integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= 301 | 302 | uri-js@^4.2.2: 303 | version "4.2.2" 304 | resolved "https://registry.npm.taobao.org/uri-js/download/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" 305 | integrity sha1-lMVA4f93KVbiKZUHwBCupsiDjrA= 306 | dependencies: 307 | punycode "^2.1.0" 308 | 309 | uuid@^3.3.2: 310 | version "3.4.0" 311 | resolved "https://registry.npm.taobao.org/uuid/download/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" 312 | integrity sha1-sj5DWK+oogL+ehAK8fX4g/AgB+4= 313 | 314 | verror@1.10.0: 315 | version "1.10.0" 316 | resolved "https://registry.npm.taobao.org/verror/download/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" 317 | integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= 318 | dependencies: 319 | assert-plus "^1.0.0" 320 | core-util-is "1.0.2" 321 | extsprintf "^1.2.0" 322 | -------------------------------------------------------------------------------- /解析脚本.offline.sgmodule: -------------------------------------------------------------------------------- 1 | #!name=🔴 解析脚本 2 | #!category=通用重写 3 | #!desc=依赖于 https://script.hub 4 | #!arguments=SURGE_SUFFIX:sg,STASH_SUFFIX:stash,LOON_SUFFIX:loon 5 | #!arguments-desc=[参数设置]\nSURGE_SUFFIX: 自定义Surge链接的后戳参数\nSTASH_SUFFIX: 自定义Stash链接的后戳参数\nLOON_SUFFIX: 自定义Loon链接的后戳参数\n\n[模块说明]\n▎模块依赖于 https://script.hub 环境运行;\n▎模块限Surge使用, Loon或Stash可复制相关重写至本地使用;\n▎Surge用户只需修改SURGE_SUFFIX参数即可, 另外两个参数仅供格式预览; 6 | 7 | [URL Rewrite] 8 | # 搭配 【快捷指令】【模块管理器】 https://www.icloud.com/shortcuts/5703d8a26a6644ebab34aaeca8b37902 9 | # ^https:\/\/(.*git.*)\/(.*)\.(js|conf|snippet|plugin|list)$ http://script.hub/file/_start_/https://$1/$2.$3/_end_/$2.sgmodule?type=surge-module&target=surge-module&del=true 10 | 11 | # 转为Surge 12 | ^https:\/\/(.*git.*)\/(.*\.)(js|conf|snippet|plugin|list).*(sg)$ http://script.hub/file/_start_/https://$1/$2$3/_end_/$2.sgmodule?type=surge-module&target=surge-module&del=true 13 | 14 | # 转为Stash 15 | ^https:\/\/(.*git.*)\/(.*\.)(js|conf|snippet|plugin|list).*(stash)$ http://script.hub/file/_start_/https://$1/$2$3/_end_/$2.sgmodule?type=qx-rewrite&target=stash-stoverride&del=true 16 | 17 | # 转为Loon 18 | ^https:\/\/(.*git.*)\/(.*\.)(js|conf|snippet|plugin|list).*(loon)$ http://script.hub/file/_start_/https://$1/$2$3/_end_/$2.sgmodule?type=loon-plugin&target=loon-plugin&del=true 19 | --------------------------------------------------------------------------------