├── Advertise ├── 10099_Advertise.js ├── 10099_Advertise.plugin ├── 10099_Advertise.sgmodule ├── 10099_Advertise.snippet └── README.md ├── JSBox ├── 10099 │ └── scripts │ │ └── widgets │ │ ├── accessoryRec.js │ │ └── small.js ├── HARToJS.js └── README.md ├── README.md ├── Rule ├── AppleDirect.list ├── AppleProxy.list ├── Crypto.list ├── Direct.list ├── Openai.list ├── Pay.list ├── Proxy.list └── README.md ├── Scriptable ├── ChinaBroadnet.js ├── ExchangeRate.js ├── HARToJS.js ├── JSDown.js ├── README.md ├── src │ ├── ChinaBroadnet.Medium.png │ └── ChinaBroadnet.Small.png └── wuhuhuuuu.scriptable.json ├── Scripts ├── ChinaBroadnet │ ├── ChinaBroadnet.cookie.js │ ├── ChinaBroadnet.js │ ├── ChinaBroadnet.panel.js │ ├── ChinaBroadnet.png │ ├── ChinaBroadnet.sgmodule │ └── README.md ├── README.md ├── TencentComic │ ├── README.md │ ├── Tencent.Comic.cookie.js │ ├── Tencent.Comic.js │ └── Tencent.Comic.png └── wuhuhuuuu.boxjs.json └── wuhuhuuuu.PNG /Advertise/10099_Advertise.js: -------------------------------------------------------------------------------- 1 | let resp = JSON.parse($response.body); 2 | const postersToExclude = [ 3 | "首页-轮播图-新版", 4 | "首页-甄选推荐", 5 | "首页-底部广告位", 6 | "分类-轮播图", 7 | "我的-非广电轮播图", 8 | "我的-轮播图", 9 | "新首页-顶部轮播图", 10 | "新首页-甄选推荐", 11 | "新首页-底部轮播图", 12 | "新首页-模板A-增值业务-1" 13 | ]; 14 | const result = resp.data.filter(item => !postersToExclude.includes(item.posterStandName)); 15 | resp.data = result; 16 | $done({ body: JSON.stringify(resp) }); -------------------------------------------------------------------------------- /Advertise/10099_Advertise.plugin: -------------------------------------------------------------------------------- 1 | #!name=10099_Advertise 2 | #!desc=Ban advertise!! 3 | #!author=wuhuhuuuu 4 | #!homepage=https://github.com/wuhuhuuuu 5 | #!icon=https://github.com/wuhuhuuuu/study/raw/main/Scripts/10099/10099.png 6 | 7 | 8 | [Rewrite] 9 | https://app.10099.com.cn/contact-web/api/version/getFlashScreenPage reject 10 | 11 | [Script] 12 | http-response https://app.10099.com.cn/contact-web/api/content/qryPosterStand script-path=https://github.com/wuhuhuuuu/study/raw/main/Advertise/10099_Advertise.js, requires-body=true, timeout=10, tag=10099_Advertise, img-url=https://github.com/wuhuhuuuu/study/raw/main/Scripts/10099/10099.png 13 | 14 | [MITM] 15 | hostname = app.10099.com.cn -------------------------------------------------------------------------------- /Advertise/10099_Advertise.sgmodule: -------------------------------------------------------------------------------- 1 | #!name=10099_Advertise 2 | #!desc=Ban advertise!! 3 | #!author=wuhuhuuuu 4 | #!homepage=https://github.com/wuhuhuuuu 5 | #!icon=https://github.com/wuhuhuuuu/study/raw/main/Scripts/10099/10099.png 6 | 7 | 8 | [URL Rewrite] 9 | https://app.10099.com.cn/contact-web/api/version/getFlashScreenPage - reject 10 | 11 | [Script] 12 | 10099_Advertise = type=http-response,pattern=https://app.10099.com.cn/contact-web/api/content/qryPosterStand,requires-body=1,max-size=0,script-path=10099_Advertise.js 13 | 14 | [MITM] 15 | hostname= %APPEND% app.10099.com.cn -------------------------------------------------------------------------------- /Advertise/10099_Advertise.snippet: -------------------------------------------------------------------------------- 1 | #!name=10099_Advertise 2 | #!desc=Ban advertise!! 3 | #!author=wuhuhuuuu 4 | #!homepage=https://github.com/wuhuhuuuu 5 | #!icon=https://github.com/wuhuhuuuu/study/raw/main/Scripts/10099/10099.png 6 | 7 | https://app.10099.com.cn/contact-web/api/version/getFlashScreenPage url reject 8 | https://app.10099.com.cn/contact-web/api/content/qryPosterStand url script-response-body https://github.com/wuhuhuuuu/study/raw/main/Advertise/10099_Advertise.js 9 | 10 | hostname = app.10099.com.cn -------------------------------------------------------------------------------- /Advertise/README.md: -------------------------------------------------------------------------------- 1 | # 授人以鱼不如授人以渔 2 | 3 | 学一手去广告。 -------------------------------------------------------------------------------- /JSBox/10099/scripts/widgets/accessoryRec.js: -------------------------------------------------------------------------------- 1 | function setLayout(data) { 2 | return { 3 | type: "hstack", 4 | props: {}, 5 | views: [ 6 | { 7 | type: "image", 8 | props: { 9 | symbol: { 10 | glyph: data.icon, 11 | size: 11, 12 | weight: "bold" 13 | }, 14 | color: $color(data.iconColor), 15 | frame: { 16 | width: 15, 17 | height: 15 18 | } 19 | } 20 | }, 21 | { 22 | type: "text", 23 | props: { 24 | text: data.title, 25 | font: { 26 | name: "default", 27 | size: 12 28 | }, 29 | lineLimit: 1, 30 | frame: { 31 | width: 50, 32 | height: 15 33 | } 34 | } 35 | }, 36 | { 37 | type: "text", 38 | props: { 39 | text: data.number + data.unit, 40 | font: { 41 | name: "default", 42 | size: 12 43 | }, 44 | lineLimit: 1, 45 | frame: { 46 | width: 60, 47 | height: 15, 48 | alignment: $widget.alignment.trailing 49 | } 50 | } 51 | } 52 | ] 53 | }; 54 | } 55 | 56 | module.exports = info => { 57 | return { 58 | type: "vstack", 59 | props: { 60 | alignment: $widget.horizontalAlignment.center 61 | }, 62 | views: [setLayout(info.fee), setLayout(info.flow), setLayout(info.voice)] 63 | }; 64 | }; 65 | -------------------------------------------------------------------------------- /JSBox/10099/scripts/widgets/small.js: -------------------------------------------------------------------------------- 1 | function setLayout(data) { 2 | return { 3 | type: "hstack", 4 | props: {}, 5 | views: [ 6 | { 7 | type: "image", 8 | props: { 9 | symbol: { 10 | glyph: data.icon, 11 | size: 11, 12 | weight: "bold" 13 | }, 14 | color: $color(data.iconColor), 15 | frame: { 16 | width: 15, 17 | height: 15 18 | } 19 | } 20 | }, 21 | { 22 | type: "text", 23 | props: { 24 | text: data.title, 25 | font: { 26 | name: "default", 27 | size: 12 28 | }, 29 | lineLimit: 1, 30 | frame: { 31 | width: 50, 32 | height: 15 33 | } 34 | } 35 | }, 36 | { 37 | type: "text", 38 | props: { 39 | text: data.number + data.unit, 40 | font: { 41 | name: "default", 42 | size: 12 43 | }, 44 | lineLimit: 1, 45 | frame: { 46 | width: 60, 47 | height: 15, 48 | alignment: $widget.alignment.trailing 49 | } 50 | } 51 | } 52 | ] 53 | }; 54 | } 55 | 56 | module.exports = (info, ctx) => { 57 | return { 58 | type: "vstack", 59 | props: { 60 | frame: { 61 | width: ctx.displaySize.width, 62 | height: ctx.displaySize.height 63 | }, 64 | background: $color("white", "black") 65 | }, 66 | views: [ 67 | { 68 | type: "image", 69 | props: { 70 | path: "assets/10099.png", 71 | resizable: true, 72 | scaledToFit: true, 73 | frame: { 74 | width: 120, 75 | height: 40 76 | } 77 | } 78 | }, 79 | { 80 | type: "text", 81 | props: { 82 | text: "¥ " + info.fee.number, 83 | font: { 84 | name: "bold", 85 | size: 23 86 | } 87 | } 88 | }, 89 | { 90 | type: "vstack", 91 | props: { 92 | alignment: $widget.horizontalAlignment.trailing 93 | }, 94 | views: [ 95 | setLayout(info.flow), 96 | setLayout(info.voice), 97 | setLayout(info.updateTime) 98 | ] 99 | } 100 | ] 101 | }; 102 | }; 103 | -------------------------------------------------------------------------------- /JSBox/HARToJS.js: -------------------------------------------------------------------------------- 1 | $app.strings = { 2 | en: { 3 | app: "Please run in Action Extension!", 4 | failure: "failure to save the script!" 5 | }, 6 | "zh-Hans": { 7 | app: "请在分享面板中运行!", 8 | failure: "保存脚本失败!" 9 | } 10 | }; 11 | function writeJs() { 12 | const data = $context.data; 13 | const json = JSON.parse($data(data).string); 14 | const request = json.log.entries[0].request; 15 | const headers = request.headers; 16 | const postData = request?.postData.text; 17 | const result = { 18 | url: "", 19 | method: "", 20 | header: {}, 21 | body: null 22 | }; 23 | 24 | result.url = request.url; 25 | result.method = request.method; 26 | headers.forEach(item => { 27 | result.header[item.name] = item.value; 28 | }); 29 | result.body = ifJSON(postData); 30 | 31 | const name = request.url.split("/")[2]; 32 | $addin.save({ 33 | name: name, 34 | data: $data({ 35 | string: `let resp = await $http.request(${JSON.stringify( 36 | result 37 | )})\nconsole.log(resp.data)` 38 | }), 39 | handler: function (success) { 40 | success 41 | ? $app.openURL(`jsbox://open?name=${name}`) 42 | : $ui.toast($l10n("failure")); 43 | } 44 | }); 45 | } 46 | 47 | function ifJSON(json) { 48 | let result = null; 49 | try { 50 | result = JSON.parse(json); 51 | } catch (e) { 52 | result = json; 53 | } 54 | return result; 55 | } 56 | 57 | $app.env == $env.action ? writeJs() : $ui.toast($l10n("app")); 58 | -------------------------------------------------------------------------------- /JSBox/README.md: -------------------------------------------------------------------------------- 1 | # 授人以鱼不如授人以渔 2 | 3 | 学一手JSBox。 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 授人以鱼不如授人以渔 2 | 3 | 学习学习学习,小小学一手。 -------------------------------------------------------------------------------- /Rule/AppleDirect.list: -------------------------------------------------------------------------------- 1 | # NAME:Apple Direct 2 | # Author: wuhuhuuuu 3 | 4 | 5 | DOMAIN-SUFFIX,apple.com 6 | DOMAIN-SUFFIX,digicert.com 7 | DOMAIN-SUFFIX,icloud.com 8 | DOMAIN-SUFFIX,autonavi.com 9 | DOMAIN-SUFFIX,mzstatic.com 10 | DOMAIN-SUFFIX,mail.me.com -------------------------------------------------------------------------------- /Rule/AppleProxy.list: -------------------------------------------------------------------------------- 1 | # NAME:Apple Proxy 2 | # Author: wuhuhuuuu 3 | 4 | 5 | # -> App Download Speed 6 | DOMAIN,iosapps.itunes.apple.com 7 | # -> TestFlight 8 | DOMAIN,testflight.apple.com 9 | # -> iCloud 10 | DOMAIN-SUFFIX,icloud.com 11 | # -> Email 12 | DOMAIN-SUFFIX,mail.me.com 13 | # -> iMessage 14 | DOMAIN-SUFFIX,ess.apple.com 15 | # -> identify 16 | DOMAIN-KEYWORD,cdn-apple -------------------------------------------------------------------------------- /Rule/Crypto.list: -------------------------------------------------------------------------------- 1 | # Binance 2 | DOMAIN-SUFFIX,binance.com 3 | DOMAIN-SUFFIX,binance.info 4 | DOMAIN-SUFFIX,bnbstatic.com 5 | DOMAIN,www.binancecnt.com 6 | 7 | # Bybit 8 | 9 | DOMAIN-SUFFIX,bybit.com 10 | DOMAIN-SUFFIX,bybit.biz 11 | DOMAIN-SUFFIX,byabcde.com 12 | DOMAIN,api3.bybdc6.com 13 | DOMAIN,api.ffbbbdc6d3c353211fe2ba39c9f744cd.com -------------------------------------------------------------------------------- /Rule/Direct.list: -------------------------------------------------------------------------------- 1 | # NAME:Direct 2 | # Author: wuhuhuuuu 3 | 4 | 5 | # -> 腾讯 6 | # -------> 微信 7 | DOMAIN-SUFFIX,wechat.com 8 | USER-AGENT,MicroMessenger Client 9 | 10 | # -------> QQ 11 | DOMAIN-SUFFIX,qq.com 12 | DOMAIN-SUFFIX,tencent.com 13 | 14 | # -> 阿里 15 | DOMAIN-SUFFIX,alipay.com 16 | DOMAIN-SUFFIX,alipayobjects.com 17 | 18 | # -> 京东 19 | DOMAIN-SUFFIX,360buyimg.com 20 | DOMAIN-SUFFIX,300hu.com 21 | DOMAIN-KEYWORD,jd 22 | 23 | # -> 百度 24 | DOMAIN-SUFFIX,baidu.com 25 | 26 | # -> 抖音 27 | DOMAIN-SUFFIX,douyinvod.com 28 | DOMAIN-SUFFIX,douyinpic.com 29 | DOMAIN-SUFFIX,zijieapi.com 30 | DOMAIN-SUFFIX,amemv.com 31 | DOMAIN-SUFFIX,bytegecko.com 32 | DOMAIN-SUFFIX,volcsirius.com 33 | 34 | # -> 12306 35 | DOMAIN-SUFFIX,12306.cn 36 | 37 | # -> 哔哩哔哩 38 | DOMAIN-SUFFIX,bilivideo.com 39 | DOMAIN-SUFFIX,biliapi.net 40 | DOMAIN-SUFFIX,bilibili.com 41 | DOMAIN-SUFFIX,hdslb.com 42 | 43 | # -> ChinaUnicom 44 | DOMAIN-SUFFIX,chinaunicom.cn 45 | DOMAIN-SUFFIX,10010.com -------------------------------------------------------------------------------- /Rule/Openai.list: -------------------------------------------------------------------------------- 1 | # NAME:Openai 2 | # Author: wuhuhuuuu 3 | 4 | 5 | DOMAIN-SUFFIX,openai.com 6 | DOMAIN-SUFFIX,chatgpt.com 7 | DOMAIN-SUFFIX,oaistatic.com 8 | DOMAIN-SUFFIX,ingest.sentry.io 9 | DOMAIN-SUFFIX,browser-intake-datadoghq.com -------------------------------------------------------------------------------- /Rule/Pay.list: -------------------------------------------------------------------------------- 1 | # NAME:Pay 2 | # Author: wuhuhuuuu 3 | 4 | 5 | DOMAIN-SUFFIX,redotpay.com 6 | DOMAIN-SUFFIX,zendesk.com 7 | DOMAIN-KEYWORD,paypal -------------------------------------------------------------------------------- /Rule/Proxy.list: -------------------------------------------------------------------------------- 1 | # NAME:Proxy 2 | # Author: wuhuhuuuu 3 | 4 | 5 | # -> Microsoft 6 | DOMAIN-SUFFIX,microsoft.com 7 | DOMAIN-SUFFIX,microsoftonline.com 8 | DOMAIN-SUFFIX,live.com 9 | DOMAIN-SUFFIX,msftauth.net 10 | DOMAIN-SUFFIX,msauth.net 11 | DOMAIN-SUFFIX,office.com 12 | DOMAIN-SUFFIX,office365.com 13 | DOMAIN-SUFFIX,skype.com 14 | 15 | # -> Google 16 | DOMAIN-SUFFIX,googleapis.com 17 | DOMAIN-SUFFIX,youtube.com 18 | 19 | # -> Github 20 | DOMAIN-SUFFIX,github.com 21 | DOMAIN-SUFFIX,githubusercontent.com 22 | 23 | # -> Bark 24 | DOMAIN,api.day.app 25 | 26 | # -> T-Mobile 27 | DOMAIN-KEYWORD,t-mobile 28 | DOMAIN-KEYWORD,tmobile 29 | 30 | # -> Notion 31 | DOMAIN-SUFFIX,notion.site 32 | 33 | # -> Twitter 34 | DOMAIN-SUFFIX,twitter.com 35 | DOMAIN-SUFFIX,twimg.com 36 | 37 | # -> Spotify 38 | DOMAIN-SUFFIX,spotify.com 39 | 40 | # -> Duolingo 41 | DOMAIN-SUFFIX,duolingo.com 42 | DOMAIN-SUFFIX,cloudfront.net -------------------------------------------------------------------------------- /Rule/README.md: -------------------------------------------------------------------------------- 1 | # 授人以鱼不如授人以渔 2 | 3 | 学一手规则。 -------------------------------------------------------------------------------- /Scriptable/ChinaBroadnet.js: -------------------------------------------------------------------------------- 1 | // Variables used by Scriptable. 2 | // These must be at the very top of the file. Do not edit. 3 | // icon-color: deep-brown; icon-glyph: phone-square; 4 | // Author: wuhu. 5 | // 该脚本小尺寸组件支持两种模式,默认为圆环进度条模式,主屏幕长按小组件-->编辑小组件-->Parameter,输入1,使用文字模式 6 | // 渐变进度条为试验性功能,默认关闭 7 | 8 | if (typeof require === 'undefined') require = importModule; 9 | const {DmYY, Runing} = require('./DmYY'); 10 | 11 | class Widget extends DmYY { 12 | constructor(arg) { 13 | super(arg); 14 | this.name = '中国广电'; 15 | this.en = 'ChinaBroadnet'; 16 | this.logo = 'https://github.com/wuhuhuuuu/study/raw/main/Scriptable/src/ChinaBroadnet.Medium.png'; 17 | this.verticalLogo = 'https://github.com/wuhuhuuuu/study/raw/main/Scriptable/src/ChinaBroadnet.Small.png'; 18 | this.Run(); 19 | } 20 | 21 | widgetParam = args.widgetParameter; 22 | // 推荐使用Boxjs代理缓存,若无请自行手动抓包后在此输入中国联通access、body数据。 23 | access = ''; 24 | body = ''; 25 | 26 | gradient = false; 27 | 28 | flowColorHex = '12A6E4'; 29 | voiceColorHex = 'F86527'; 30 | 31 | ringStackSize = 61; 32 | ringTextSize = 14; 33 | feeTextSize = 21; 34 | textSize = 13; 35 | smallPadding = 16; 36 | padding = 10; 37 | logoScale = 0.24; 38 | 39 | canvSize = 178; 40 | canvWidth = 18; 41 | canvRadius = 80; 42 | 43 | format = (str) => { 44 | return parseInt(str) >= 10 ? str : `0${str}`; 45 | }; 46 | 47 | date = new Date(); 48 | arrUpdateTime = [ 49 | this.format(this.date.getMonth() + 1), 50 | this.format(this.date.getDate()), 51 | this.format(this.date.getHours()), 52 | this.format(this.date.getMinutes()), 53 | ]; 54 | 55 | fee = { 56 | title: '话费剩余', 57 | number: 0, 58 | unit: '元', 59 | en: '¥', 60 | }; 61 | 62 | flow = { 63 | percent: 0, 64 | title: '流量剩余', 65 | number: 0, 66 | unit: 'GB', 67 | en: 'GB', 68 | icon: 'antenna.radiowaves.left.and.right', 69 | iconColor: new Color('1ab6f8'), 70 | FGColor: new Color(this.flowColorHex), 71 | BGColor: new Color(this.flowColorHex, 0.2), 72 | colors: [], 73 | }; 74 | 75 | voice = { 76 | percent: 0, 77 | title: '语音剩余', 78 | number: 0, 79 | unit: '分钟', 80 | en: 'MIN', 81 | icon: 'phone.fill', 82 | iconColor: new Color('30d15b'), 83 | FGColor: new Color(this.voiceColorHex), 84 | BGColor: new Color(this.voiceColorHex, 0.2), 85 | colors: [], 86 | }; 87 | 88 | point = { 89 | title: '剩余积分', 90 | number: 0, 91 | unit: '', 92 | icon: 'tag.fill', 93 | iconColor: new Color('fc6d6d'), 94 | } 95 | 96 | init = async () => { 97 | try { 98 | await this.getData(); 99 | } catch (e) { 100 | console.log(e); 101 | } 102 | }; 103 | 104 | async getData() { 105 | const url= 'https://wx.10099.com.cn/contact-web/api/busi/qryUserInfo'; 106 | const bodyData = { 107 | "data": this.body 108 | } 109 | try { 110 | const req = new Request(url); 111 | req.headers = { 112 | 'access': this.access, 113 | 'content-type': 'application/json' 114 | }; 115 | req.body = JSON.stringify(bodyData) 116 | req.method = 'POST' 117 | const userInfo = await req.loadJSON(); 118 | 119 | if (userInfo.status === '000000') { 120 | console.log('获取信息成功'); 121 | console.log(userInfo.data); 122 | const data = userInfo.data.userData; 123 | this.fee.number = data.fee / 100; 124 | this.flow.number = (data.flow / 1048576).toFixed(2); 125 | this.flow.percent = ((data.flow / data.flowAll) * 100).toFixed(2); 126 | this.voice.number = data.voice; 127 | this.voice.percent = ((data.voice / data.voiceAll) * 100).toFixed(2); 128 | } else { 129 | throw 'cookie错误/服务器维护'; 130 | } 131 | } catch (e) { 132 | console.log('获取信息失败:' + e); 133 | } 134 | } 135 | 136 | async smallHeader(stack) { 137 | const headerStack = stack.addStack(); 138 | headerStack.addSpacer(); 139 | const logo = headerStack.addImage(await this.$request.get(this.logo, 'IMG')); 140 | logo.imageSize = new Size(415 * this.logoScale, 125 * this.logoScale); 141 | headerStack.addSpacer(); 142 | stack.addSpacer(); 143 | 144 | const feeStack = stack.addStack(); 145 | feeStack.centerAlignContent(); 146 | feeStack.addSpacer(); 147 | const feeValue = feeStack.addText("¥"+`${this.fee.number}`); 148 | feeValue.font = Font.mediumRoundedSystemFont(this.feeTextSize); 149 | feeValue.textColor = this.widgetColor; 150 | feeStack.addSpacer(); 151 | stack.addSpacer(); 152 | } 153 | 154 | textLayout(stack, data) { 155 | const rowStack = stack.addStack(); 156 | rowStack.centerAlignContent(); 157 | const icon = SFSymbol.named(data.icon); 158 | icon.applyHeavyWeight(); 159 | let iconElement = rowStack.addImage(icon.image); 160 | iconElement.imageSize = new Size(this.textSize, this.textSize); 161 | iconElement.tintColor = data.iconColor; 162 | rowStack.addSpacer(4); 163 | let title = rowStack.addText(data.title); 164 | rowStack.addSpacer(); 165 | let number = rowStack.addText(data.number + data.unit); 166 | ;[title, number].map(t => t.textColor = this.widgetColor); 167 | ;[title, number].map(t => t.font = Font.systemFont(this.textSize)); 168 | } 169 | 170 | async mediumCell(canvas, stack, data, color, fee = false, percent) { 171 | const bg = new LinearGradient(); 172 | bg.locations = [0, 1]; 173 | bg.colors = [ 174 | new Color(color, 0.03), 175 | new Color(color, 0.1) 176 | ]; 177 | const dataStack = stack.addStack(); 178 | dataStack.backgroundGradient = bg; 179 | dataStack.cornerRadius = 20; 180 | dataStack.layoutVertically(); 181 | dataStack.addSpacer(); 182 | 183 | const topStack = dataStack.addStack(); 184 | topStack.addSpacer(); 185 | await this.imageCell(canvas, topStack, data, fee, percent); 186 | topStack.addSpacer(); 187 | 188 | if (fee) { 189 | dataStack.addSpacer(5); 190 | const updateStack = dataStack.addStack(); 191 | updateStack.addSpacer(); 192 | updateStack.centerAlignContent(); 193 | const updataIcon = SFSymbol.named('arrow.2.circlepath'); 194 | updataIcon.applyHeavyWeight(); 195 | const updateImg = updateStack.addImage(updataIcon.image); 196 | updateImg.tintColor = new Color(color, 0.6); 197 | updateImg.imageSize = new Size(10, 10); 198 | updateStack.addSpacer(3); 199 | const updateText = updateStack.addText(`${this.arrUpdateTime[2]}:${this.arrUpdateTime[3]}`) 200 | updateText.font = Font.mediumSystemFont(10); 201 | updateText.textColor = new Color(color, 0.6); 202 | updateStack.addSpacer(); 203 | /* 204 | let tempStack = dataStack.addStack(); 205 | tempStack.layoutVertically() 206 | let tempStack1 = tempStack.addStack() 207 | tempStack1.addSpacer() 208 | let tempText1 = tempStack1.addText(this.flow.colors.toString()) 209 | tempStack1.addSpacer() 210 | let tempStack2 = tempStack.addStack() 211 | tempStack2.addSpacer() 212 | let tempText2 = tempStack2.addText(this.voice.colors.toString()) 213 | tempStack2.addSpacer() 214 | ;[tempText1, tempText2].map(t => t.font = Font.systemFont(6)); 215 | ;[tempText1, tempText2].map(t => t.textColor = updateText.textColor); 216 | */ 217 | } 218 | 219 | dataStack.addSpacer(); 220 | 221 | const numberStack = dataStack.addStack(); 222 | numberStack.addSpacer(); 223 | const number = numberStack.addText(`${data.number} ${data.en}`); 224 | number.font = Font.semiboldSystemFont(15); 225 | numberStack.addSpacer(); 226 | 227 | dataStack.addSpacer(3); 228 | 229 | const titleStack = dataStack.addStack(); 230 | titleStack.addSpacer(); 231 | const title = titleStack.addText(data.title); 232 | title.font = Font.mediumSystemFont(11); 233 | title.textOpacity = 0.7; 234 | titleStack.addSpacer(); 235 | 236 | dataStack.addSpacer(15); 237 | ;[title, number].map(t => t.textColor = new Color(color)); 238 | } 239 | 240 | async imageCell(canvas, stack, data, fee, percent) { 241 | const canvaStack = stack.addStack(); 242 | canvaStack.layoutVertically(); 243 | if (!fee) { 244 | this.drawArc(canvas, data.percent * 3.6, data.FGColor, data.BGColor); 245 | canvaStack.size = new Size(this.ringStackSize, this.ringStackSize); 246 | canvaStack.backgroundImage = canvas.getImage(); 247 | this.ringContent(canvaStack, data, percent); 248 | } else { 249 | canvaStack.addSpacer(10); 250 | const smallLogo = await this.$request.get(this.verticalLogo, 'IMG'); 251 | const logoStack = canvaStack.addStack(); 252 | logoStack.size = new Size(40, 40); 253 | logoStack.backgroundImage = smallLogo; 254 | } 255 | } 256 | 257 | ringContent(stack, data, percent = false) { 258 | const rowIcon = stack.addStack(); 259 | rowIcon.addSpacer(); 260 | const icon = SFSymbol.named(data.icon); 261 | icon.applyHeavyWeight(); 262 | const iconElement = rowIcon.addImage(icon.image); 263 | iconElement.tintColor = this.gradient ? new Color(data.colors[1]) : data.FGColor; 264 | iconElement.imageSize = new Size(12, 12); 265 | iconElement.imageOpacity = 0.7; 266 | rowIcon.addSpacer(); 267 | 268 | stack.addSpacer(1); 269 | 270 | const rowNumber = stack.addStack(); 271 | rowNumber.addSpacer(); 272 | const number = rowNumber.addText(percent ? `${data.percent}` : `${data.number}`); 273 | number.font = percent ? Font.systemFont(this.ringTextSize - 2) : Font.mediumSystemFont(this.ringTextSize); 274 | rowNumber.addSpacer(); 275 | 276 | const rowUnit = stack.addStack(); 277 | rowUnit.addSpacer(); 278 | const unit = rowUnit.addText(percent ? '%' : data.unit); 279 | unit.font = Font.boldSystemFont(8); 280 | unit.textOpacity = 0.5; 281 | rowUnit.addSpacer(); 282 | 283 | if (percent) { 284 | if (this.gradient) { 285 | ;[unit, number].map(t => t.textColor = new Color(data.colors[1])); 286 | } else { 287 | ;[unit, number].map(t => t.textColor = data.FGColor); 288 | } 289 | } else { 290 | ;[unit, number].map(t => t.textColor = this.widgetColor); 291 | } 292 | } 293 | 294 | makeCanvas() { 295 | const canvas = new DrawContext(); 296 | canvas.opaque = false; 297 | canvas.respectScreenScale = true; 298 | canvas.size = new Size(this.canvSize, this.canvSize); 299 | return canvas; 300 | } 301 | 302 | sinDeg(deg) { 303 | return Math.sin((deg * Math.PI) / 180); 304 | } 305 | 306 | cosDeg(deg) { 307 | return Math.cos((deg * Math.PI) / 180); 308 | } 309 | 310 | drawArc(canvas, deg, fillColor, strokeColor) { 311 | let ctr = new Point(this.canvSize / 2, this.canvSize / 2); 312 | let bgx = ctr.x - this.canvRadius; 313 | let bgy = ctr.y - this.canvRadius; 314 | let bgd = 2 * this.canvRadius; 315 | let bgr = new Rect(bgx, bgy, bgd, bgd) 316 | 317 | canvas.setStrokeColor(strokeColor); 318 | canvas.setLineWidth(this.canvWidth); 319 | canvas.strokeEllipse(bgr); 320 | 321 | for (let t = 0; t < deg; t++) { 322 | let rect_x = ctr.x + this.canvRadius * this.sinDeg(t) - this.canvWidth / 2; 323 | let rect_y = ctr.y - this.canvRadius * this.cosDeg(t) - this.canvWidth / 2; 324 | let rect_r = new Rect(rect_x, rect_y, this.canvWidth, this.canvWidth); 325 | canvas.setFillColor(this.gradient ? new Color(fillColor[t]) : fillColor); 326 | canvas.setStrokeColor(strokeColor) 327 | canvas.fillEllipse(rect_r); 328 | } 329 | } 330 | 331 | arrColor() { 332 | let colorArr = [['#FFF000', '#E62490'], ['#ABDCFF', '#0396FF'], ['#FEB692', '#EA5455'], ['#FEB692', '#EA5455'], ['#CE9FFC', '#7367F0'], ['#90F7EC', '#32CCBC'], ['#FFF6B7', '#F6416C'], ['#E2B0FF', '#9F44D3'], ['#F97794', '#F072B6'], ['#FCCF31', '#F55555'], ['#5EFCE8', '#736EFE'], ['#FAD7A1', '#E96D71'], ['#FFFF1C', '#00C3FF'], ['#FEC163', '#DE4313'], ['#F6CEEC', '#D939CD'], ['#FDD819', '#E80505'], ['#FFF3B0', '#CA26FF'], ['#EECDA3', '#EF629F'], ['#C2E59C', '#64B3F4'], ['#FFF886', '#F072B6'], ['#F5CBFF', '#C346C2'], ['#FFF720', '#3CD500'], ['#FFC371', '#FF5F6D'], ['#FFD3A5', '#FD6585'], ['#C2FFD8', '#465EFB'], ['#FFC600', '#FD6E6A'], ['#FFC600', '#FD6E6A'], ['#92FE9D', '#00C9FF'], ['#FFDDE1', '#EE9CA7'], ['#F0FF00', '#58CFFB'], ['#FFE985', '#FA742B'], ['#72EDF2', '#5151E5'], ['#F6D242', '#FF52E5'], ['#F9D423', '#FF4E50'], ['#00EAFF', '#3C8CE7'], ['#FCFF00', '#FFA8A8'], ['#FF96F9', '#C32BAC'], ['#FFDD94', '#FA897B'], ['#FFCC4B', '#FF7D58'], ['#D0E6A5', '#86E3CE'], ['#F0D5B6', '#F16238'], ['#C4E86B', '#00BCB4'], ['#FFC446', '#FA0874'], ['#E1EE32', '#FFB547'], ['#E9A6D2', '#E9037B'], ['#F8EC70', '#49E2F6'], ['#A2F8CD', '#00C3FF'], ['#FDEFE2', '#FE214F'], ['#FFB7D1', '#E4B7FF'], ['#D0E6A5', '#86E3CE'], ['#E8E965', '#64C5C7']]; 333 | let colors = colorArr[Math.floor(Math.random() * colorArr.length)]; 334 | return colors; 335 | } 336 | 337 | gradientColor(colors, step) { 338 | var startRGB = this.colorToRgb(colors[0]), 339 | startR = startRGB[0], 340 | startG = startRGB[1], 341 | startB = startRGB[2]; 342 | 343 | var endRGB = this.colorToRgb(colors[1]), 344 | endR = endRGB[0], 345 | endG = endRGB[1], 346 | endB = endRGB[2]; 347 | 348 | var sR = (endR - startR) / step, 349 | sG = (endG - startG) / step, 350 | sB = (endB - startB) / step; 351 | 352 | var colorArr = []; 353 | for (var i = 0;i < step; i++) { 354 | var hex = this.colorToHex('rgb(' + parseInt((sR * i + startR)) + ',' + parseInt((sG * i + startG)) + ',' + parseInt((sB * i + startB)) + ')'); 355 | colorArr.push(hex); 356 | } 357 | return colorArr; 358 | } 359 | 360 | colorToRgb(sColor) { 361 | var reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/; 362 | var sColor = sColor.toLowerCase(); 363 | if (sColor && reg.test(sColor)) { 364 | if (sColor.length === 4) { 365 | var sColorNew = "#"; 366 | for (var i = 1; i < 4; i += 1) { 367 | sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1)); 368 | } 369 | sColor = sColorNew; 370 | } 371 | var sColorChange = []; 372 | for (var i = 1; i < 7; i += 2) { 373 | sColorChange.push(parseInt("0x" + sColor.slice(i, i + 2))); 374 | } 375 | return sColorChange; 376 | } else { 377 | return sColor; 378 | } 379 | }; 380 | 381 | colorToHex(rgb) { 382 | var _this = rgb; 383 | var reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/; 384 | if (/^(rgb|RGB)/.test(_this)) { 385 | var aColor = _this.replace(/(?:\(|\)|rgb|RGB)*/g,"").split(","); 386 | var strHex = "#"; 387 | for (var i = 0; i < aColor.length; i++) { 388 | var hex = Number(aColor[i]).toString(16); 389 | hex = hex.length < 2 ? 0 + '' + hex : hex; 390 | if (hex === "0") { 391 | hex += hex; 392 | } 393 | strHex += hex; 394 | } 395 | if (strHex.length !== 7) { 396 | strHex = _this; 397 | } 398 | 399 | return strHex; 400 | } else if (reg.test(_this)) { 401 | var aNum = _this.replace(/#/,"").split(""); 402 | if (aNum.length === 6) { 403 | return _this; 404 | } else if (aNum.length === 3) { 405 | var numHex = "#"; 406 | for (var i = 0; i < aNum.length; i+=1) { 407 | numHex += (aNum[i] + aNum[i]); 408 | } 409 | return numHex; 410 | } 411 | } else { 412 | return _this; 413 | } 414 | } 415 | 416 | renderSmall = async (w) => { 417 | w.setPadding(this.smallPadding, this.smallPadding, this.smallPadding, this.smallPadding); 418 | await this.smallHeader(w); 419 | const bodyStack = w.addStack(); 420 | bodyStack.layoutVertically(); 421 | if (this.widgetParam == "1"){ 422 | bodyStack.addSpacer() 423 | this.textLayout(bodyStack, this.flow); 424 | bodyStack.addSpacer(); 425 | this.textLayout(bodyStack, this.voice); 426 | // bodyStack.addSpacer(7); 427 | // this.textLayout(bodyStack, this.point); 428 | } else { 429 | const canvas = this.makeCanvas(); 430 | const ringStack = bodyStack.addStack(); 431 | this.imageCell(canvas, ringStack, this.flow); 432 | ringStack.addSpacer(); 433 | this.imageCell(canvas, ringStack, this.voice); 434 | } 435 | return w; 436 | }; 437 | 438 | renderMedium = async (w) => { 439 | w.setPadding(this.padding, this.padding, this.padding, this.padding); 440 | const canvas = this.makeCanvas(); 441 | const bodyStack = w.addStack(); 442 | await this.mediumCell(canvas, bodyStack, this.fee, 'd7000f', true); 443 | bodyStack.addSpacer(this.padding); 444 | await this.mediumCell(canvas, bodyStack, this.flow, this.flowColorHex, false, true); 445 | bodyStack.addSpacer(this.padding); 446 | await this.mediumCell(canvas, bodyStack, this.voice, this.voiceColorHex, false,true); 447 | return w; 448 | }; 449 | 450 | renderLarge = async (w) => { 451 | w.addText('暂不支持') 452 | return w; 453 | }; 454 | 455 | Run() { 456 | if (config.runsInApp) { 457 | const widgetInitConfig = { 458 | access: '@wuhuhu.ChinaBroadnet.access', 459 | body: '@wuhuhu.ChinaBroadnet.body' 460 | }; 461 | this.registerAction('颜色配置', async () => { 462 | await this.setAlertInput( 463 | `${this.name}颜色配置`, 464 | '进度条颜色|底圈颜色\n底圈颜色留空将跟随进度条颜色并淡显', 465 | { 466 | gradient: '是否开启渐变进度条,缺省:false', 467 | step1: '流量进度条颜色', 468 | step2: '语音进度条颜色', 469 | inner1: '流量进度条底圈颜色', 470 | inner2: '语音进度条底圈颜色', 471 | }, 472 | ); 473 | }, 'https://pic1.imgdb.cn/item/63315c1e16f2c2beb1a27363.png'); 474 | this.registerAction('尺寸设置', async () => { 475 | await this.setAlertInput( 476 | `${this.name}尺寸设置`, 477 | '进度条大小|文字大小', 478 | { 479 | logoScale: '小组件logo缩放,缺省:0.24', 480 | ringStackSize: '圆环大小,缺省:61', 481 | ringTextSize: '圆环中心文字大小,缺省:14', 482 | feeTextSize: '话费文字大小,缺省:21', 483 | textSize: '文字模式下文字大小,缺省:13', 484 | smallPadding: '小尺寸组件边距,缺省:16', 485 | padding: '中尺寸组件边距,缺省:10', 486 | }, 487 | ); 488 | }, 'https://pic1.imgdb.cn/item/63315c2c16f2c2beb1a28726.png'); 489 | this.registerAction('账号设置', async () => { 490 | await this.setAlertInput( 491 | `${this.name}账号`, 492 | '读取 BoxJS 缓存信息', 493 | {access: 'access', 494 | body: 'body.data'}, 495 | ); 496 | }, 'https://raw.githubusercontent.com/githubdulong/Script/master/Images/account.png'); 497 | this.registerAction('代理缓存', async () => { 498 | await this.setCacheBoxJSData(widgetInitConfig); 499 | }, 'https://raw.githubusercontent.com/githubdulong/Script/master/Images/boxjs.png'); 500 | this.registerAction('基础设置', this.setWidgetConfig, 'https://raw.githubusercontent.com/githubdulong/Script/master/Images/preferences.png'); 501 | } 502 | 503 | try { 504 | const { 505 | access, 506 | body, 507 | step1, 508 | step2, 509 | inner1, 510 | inner2, 511 | logoScale, 512 | ringStackSize, 513 | ringTextSize, 514 | feeTextSize, 515 | textSize, 516 | smallPadding, 517 | padding, 518 | gradient, 519 | } = this.settings; 520 | this.access = access ? access : this.access; 521 | this.body = body ? body : this.body; 522 | this.gradient = gradient === 'true' ? true : this.gradient; 523 | this.flowColorHex = step1 ? step1 : this.flowColorHex; 524 | this.voiceColorHex = step2 ? step2 : this.voiceColorHex; 525 | this.flow.BGColor = inner1 ? new Color(inner1) : new Color(this.flowColorHex, 0.2); 526 | this.voice.BGColor = inner2 ? new Color(inner2) : new Color(this.voiceColorHex, 0.2); 527 | this.flow.FGColor = new Color(this.flowColorHex); 528 | this.voice.FGColor = new Color(this.voiceColorHex); 529 | 530 | this.logoScale = logoScale ? parseFloat(logoScale) : this.logoScale; 531 | this.ringStackSize = ringStackSize ? parseFloat(ringStackSize) : this.ringStackSize; 532 | this.ringTextSize = ringTextSize ? parseFloat(ringTextSize) : this.ringTextSize; 533 | this.feeTextSize = feeTextSize ? parseFloat(feeTextSize) : this.feeTextSize; 534 | this.textSize = textSize ? parseFloat(textSize) : this.textSize; 535 | this.smallPadding = smallPadding ? parseFloat(smallPadding) : this.smallPadding; 536 | this.padding = padding ? parseFloat(padding) : this.padding; 537 | 538 | if (this.gradient) { 539 | this.flow.colors = this.arrColor(); 540 | this.voice.colors = this.arrColor(); 541 | this.flow.BGColor = inner1 ? new Color(inner1) : new Color(this.flow.colors[1], 0.2); 542 | this.voice.BGColor = inner2 ? new Color(inner2) : new Color(this.voice.colors[1], 0.2); 543 | this.flow.FGColor = this.gradientColor(this.flow.colors, 360); 544 | this.voice.FGColor = this.gradientColor(this.voice.colors, 360); 545 | this.flowColorHex = this.flow.colors[1]; 546 | this.voiceColorHex = this.voice.colors[1]; 547 | } 548 | 549 | } catch (e) { 550 | console.log(e); 551 | } 552 | } 553 | 554 | async render() { 555 | await this.init(); 556 | const widget = new ListWidget(); 557 | await this.getWidgetBackgroundImage(widget); 558 | if (this.widgetFamily === 'medium') { 559 | return await this.renderMedium(widget); 560 | } else if (this.widgetFamily === 'large') { 561 | return await this.renderLarge(widget); 562 | } else { 563 | return await this.renderSmall(widget); 564 | } 565 | } 566 | } 567 | 568 | await Runing(Widget, args.widgetParameter, false); -------------------------------------------------------------------------------- /Scriptable/ExchangeRate.js: -------------------------------------------------------------------------------- 1 | // Variables used by Scriptable. 2 | // These must be at the very top of the file. Do not edit. 3 | // icon-color: deep-green; icon-glyph: signature; 4 | /* 5 | Author: wuhu. 6 | 2023.9.7 7 | refer "https://github.com/vikiboss/60s" 8 | */ 9 | 10 | let params = args.widgetParameter 11 | let currencys 12 | if (params) { 13 | currencys = params.includes(",") ? params.split(",") : params.includes(",") ? params.split(",") : null 14 | } 15 | 16 | async function getInfo() { 17 | try { 18 | let url = "https://60s.viki.moe/ex-rates?c=cny" 19 | let request = new Request(url) 20 | let resp = await request.loadJSON() 21 | return resp.data 22 | } catch (e) { 23 | console.error(e) 24 | } 25 | 26 | } 27 | 28 | let widget = new ListWidget() 29 | let stackAll = widget.addStack() 30 | stackAll.layoutVertically() 31 | stackAll.setPadding(-2, 0, -2, 0) 32 | let titleStack = stackAll.addStack() 33 | let date = new Date() 34 | let updateTime = date.getHours() + ":" + date.getMinutes() 35 | let time = titleStack.addStack().addText("更新" + updateTime) 36 | time.font = Font.thinRoundedSystemFont(13) 37 | titleStack.addSpacer() 38 | let CNY = titleStack.addStack().addText("CNY") 39 | CNY.font = Font.italicSystemFont(13) 40 | stackAll.addSpacer() 41 | 42 | let message = await getInfo() 43 | 44 | addEachInfo("🇺🇸", "USD") 45 | stackAll.addSpacer() 46 | addEachInfo("🇭🇰", "HKD") 47 | stackAll.addSpacer() 48 | addEachInfo("🇯🇵", "JPY") 49 | stackAll.addSpacer() 50 | addEachInfo("🇪🇺", "EUR") 51 | await widget.presentSmall() 52 | 53 | function addEachInfo(icon, name) { 54 | let rowStack = stackAll.addStack() 55 | let iconStack = rowStack.addStack().addText(icon) 56 | iconStack.font = Font.mediumSystemFont(15) 57 | rowStack.addSpacer(10) 58 | let nameStack = rowStack.addStack().addText(name) 59 | nameStack.font = Font.blackSystemFont(12) 60 | rowStack.addSpacer() 61 | let rate = message ? (100/message[name]).toFixed(2) : "0.00" 62 | let rateStack = rowStack.addStack().addText(rate) 63 | rateStack.font = Font.blackMonospacedSystemFont(12) 64 | } -------------------------------------------------------------------------------- /Scriptable/HARToJS.js: -------------------------------------------------------------------------------- 1 | // Variables used by Scriptable. 2 | // These must be at the very top of the file. Do not edit. 3 | // icon-color: yellow; icon-glyph: screwdriver; 4 | // share-sheet-inputs: file-url; 5 | function writeJs() { 6 | let url = args.fileURLs[0] 7 | let string = FileManager.local().readString(url) 8 | const json = JSON.parse(string) 9 | const request = json.log.entries[0].request; 10 | const headers = request.headers; 11 | const postData = request?.postData.text; 12 | const header = {}; 13 | headers.forEach(item => { 14 | header[item.name] = item.value; 15 | }); 16 | 17 | let body = ifJSON(postData) 18 | let script = ` let request = new Request("${request.url}") 19 | request.method = "${request.method}" 20 | request.headers = ${JSON.stringify(header)} 21 | request.body = ${body} 22 | let resp = await request.loadString() 23 | console.log(resp)` 24 | 25 | const name = request.url.split("/")[2]; 26 | let fm = icloudOrNot() ? FileManager.iCloud() : FileManager.local() 27 | let dict = fm.documentsDirectory() 28 | fm.writeString(`${dict}/${name}.js`, script) 29 | } 30 | 31 | function icloudOrNot() { 32 | let fm = FileManager 33 | let result = 1 34 | try { 35 | let fm_icloud = fm.iCloud().documentsDirectory() 36 | } catch (e) { 37 | result = e ? 0 : 1 38 | } 39 | return result 40 | } 41 | 42 | function ifJSON(json) { 43 | let result = null; 44 | try { 45 | const test = JSON.parse(json); 46 | result = JSON.stringify(json) 47 | } catch (e) { 48 | result = json; 49 | } 50 | return result; 51 | } 52 | 53 | 54 | config.runsInActionExtension ? writeJs() : console.log("Please run in ActionExtension") -------------------------------------------------------------------------------- /Scriptable/JSDown.js: -------------------------------------------------------------------------------- 1 | // Variables used by Scriptable. 2 | // These must be at the very top of the file. Do not edit. 3 | // icon-color: purple; icon-glyph: file-download; 4 | // share-sheet-inputs: url; 5 | 6 | let link = "" 7 | if (config.runsInApp) { 8 | let text = Pasteboard.pasteString() ? Pasteboard.pasteString() : "" 9 | let alert = new Alert() 10 | alert.title = "Input URL!!" 11 | alert.addAction("OK") 12 | alert.addDestructiveAction("Cancel") 13 | alert.addTextField("", text) 14 | let result = await alert.present() 15 | if (result == 0) { 16 | link = alert.textFieldValue(0) 17 | } 18 | } else if (config.runsInActionExtension) { 19 | link = args.urls[0] 20 | } 21 | if (link) { 22 | let url = urlParse(link) 23 | if (url) await download(url) 24 | } 25 | Script.complete() 26 | 27 | function urlParse(url) { 28 | let match = url.match(/^https:\/\/github\.com\/(.+)\/blob\/(.+\.js$)/) 29 | if (match) { 30 | let uri = url.replace(/^https:\/\/github\.com\/(.+)\/blob\/(.+\.js$)/, "https://raw.githubusercontent.com/$1/$2") 31 | return uri 32 | } 33 | } 34 | 35 | function downWhere() { 36 | let fm = FileManager.iCloud() 37 | let result = 1 38 | try { 39 | let dict = fm.documentsDirectory() 40 | } catch (e) { 41 | result = e ? 0 : 1 42 | } 43 | return result 44 | } 45 | 46 | async function download(url) { 47 | let request = new Request(url) 48 | let content = await request.loadString() 49 | let jsName = url.substring(url.lastIndexOf("/") + 1) 50 | let fileName = decodeURIComponent(jsName) 51 | let fm = downWhere() ? FileManager.iCloud() : FileManager.local() 52 | let dict = fm.documentsDirectory() 53 | let filePath = fm.joinPath(dict, fileName) 54 | fm.writeString(filePath, content) 55 | console.log("Done!!!") 56 | } -------------------------------------------------------------------------------- /Scriptable/README.md: -------------------------------------------------------------------------------- 1 | # 授人以鱼不如授人以渔 2 | 3 | 学一手Scriptable。 -------------------------------------------------------------------------------- /Scriptable/src/ChinaBroadnet.Medium.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuhuuuu/study/106ed3b788d4bc3dce0587f3a3e7acc47682fe7d/Scriptable/src/ChinaBroadnet.Medium.png -------------------------------------------------------------------------------- /Scriptable/src/ChinaBroadnet.Small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuhuuuu/study/106ed3b788d4bc3dce0587f3a3e7acc47682fe7d/Scriptable/src/ChinaBroadnet.Small.png -------------------------------------------------------------------------------- /Scriptable/wuhuhuuuu.scriptable.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "wuhuhuuuu", 3 | "scriptable": true, 4 | "icon": "https://github.com/wuhuhuuuu/study/raw/main/wuhuhuuuu.PNG", 5 | "repo": "https://github.com/wuhuhuuuu/study/tree/main/Scriptable", 6 | "apps": [ 7 | { 8 | "scriptURL": "https://github.com/wuhuhuuuu/study/raw/main/Scriptable/10099/10099.js", 9 | "title": "中国广电", 10 | "thumb": "https://github.com/wuhuhuuuu/study/raw/main/Scripts/10099/10099.png", 11 | "name": "中国广电", 12 | "description": "中国广电套餐信息展示", 13 | "version": "1.2" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /Scripts/ChinaBroadnet/ChinaBroadnet.cookie.js: -------------------------------------------------------------------------------- 1 | const $ = new Env('wuhuhu.ChinaBroadnet') 2 | $.KEY_url = '@wuhuhu.ChinaBroadnet.url' 3 | $.KEY_access = '@wuhuhu.ChinaBroadnet.access' 4 | $.KEY_body = '@wuhuhu.ChinaBroadnet.body' 5 | 6 | !(async () => { 7 | const url = $request.url 8 | const access = $request.headers['access'] || $request.headers['Access'] 9 | const body = JSON.parse($request.body).data 10 | if ($.setdata(url, $.KEY_url) && $.setdata(access, $.KEY_access) && $.setdata(body, $.KEY_body)) { 11 | $.subt = `获取会话: 成功!` 12 | } else { 13 | $.subt = `获取会话: 失败!` 14 | } 15 | $.msg($.name, $.subt) 16 | })() 17 | .catch((e) => $.logErr(e)) 18 | .finally(() => $.done()) 19 | 20 | // prettier-ignore 21 | function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,a)=>{s.call(this,t,(t,s,r)=>{t?a(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.encoding="utf-8",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}getEnv(){return"undefined"!=typeof $environment&&$environment["surge-version"]?"Surge":"undefined"!=typeof $environment&&$environment["stash-version"]?"Stash":"undefined"!=typeof module&&module.exports?"Node.js":"undefined"!=typeof $task?"Quantumult X":"undefined"!=typeof $loon?"Loon":"undefined"!=typeof $rocket?"Shadowrocket":void 0}isNode(){return"Node.js"===this.getEnv()}isQuanX(){return"Quantumult X"===this.getEnv()}isSurge(){return"Surge"===this.getEnv()}isLoon(){return"Loon"===this.getEnv()}isShadowrocket(){return"Shadowrocket"===this.getEnv()}isStash(){return"Stash"===this.getEnv()}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const a=this.getdata(t);if(a)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,a)=>e(a))})}runScript(t,e){return new Promise(s=>{let a=this.getdata("@chavy_boxjs_userCfgs.httpapi");a=a?a.replace(/\n/g,"").trim():a;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[i,o]=a.split("@"),n={url:`http://${o}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":i,Accept:"*/*"},timeout:r};this.post(n,(t,e,a)=>s(a))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),a=!s&&this.fs.existsSync(e);if(!s&&!a)return{};{const a=s?t:e;try{return JSON.parse(this.fs.readFileSync(a))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),a=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):a?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const a=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of a)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,a)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[a+1])>>0==+e[a+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,a]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,a,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,a,r]=/^@(.*?)\.(.*?)$/.exec(e),i=this.getval(a),o=a?"null"===i?null:i||"{}":"{}";try{const e=JSON.parse(o);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),a)}catch(e){const i={};this.lodash_set(i,r,t),s=this.setval(JSON.stringify(i),a)}}else s=this.setval(t,e);return s}getval(t){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":return $persistentStore.read(t);case"Quantumult X":return $prefs.valueForKey(t);case"Node.js":return this.data=this.loaddata(),this.data[t];default:return this.data&&this.data[t]||null}}setval(t,e){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":return $persistentStore.write(t,e);case"Quantumult X":return $prefs.setValueForKey(t,e);case"Node.js":return this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0;default:return this.data&&this.data[e]||null}}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){switch(t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"],delete t.headers["content-type"],delete t.headers["content-length"]),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,a)=>{!t&&s&&(s.body=a,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,a)});break;case"Quantumult X":this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:a,headers:r,body:i,bodyBytes:o}=t;e(null,{status:s,statusCode:a,headers:r,body:i,bodyBytes:o},i,o)},t=>e(t&&t.error||"UndefinedError"));break;case"Node.js":let s=require("iconv-lite");this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:a,statusCode:r,headers:i,rawBody:o}=t,n=s.decode(o,this.encoding);e(null,{status:a,statusCode:r,headers:i,rawBody:o,body:n},n)},t=>{const{message:a,response:r}=t;e(a,r,r&&s.decode(r.rawBody,this.encoding))})}}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";switch(t.body&&t.headers&&!t.headers["Content-Type"]&&!t.headers["content-type"]&&(t.headers["content-type"]="application/x-www-form-urlencoded"),t.headers&&(delete t.headers["Content-Length"],delete t.headers["content-length"]),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,(t,s,a)=>{!t&&s&&(s.body=a,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,a)});break;case"Quantumult X":t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:a,headers:r,body:i,bodyBytes:o}=t;e(null,{status:s,statusCode:a,headers:r,body:i,bodyBytes:o},i,o)},t=>e(t&&t.error||"UndefinedError"));break;case"Node.js":let a=require("iconv-lite");this.initGotEnv(t);const{url:r,...i}=t;this.got[s](r,i).then(t=>{const{statusCode:s,statusCode:r,headers:i,rawBody:o}=t,n=a.decode(o,this.encoding);e(null,{status:s,statusCode:r,headers:i,rawBody:o,body:n},n)},t=>{const{message:s,response:r}=t;e(s,r,r&&a.decode(r.rawBody,this.encoding))})}}time(t,e=null){const s=e?new Date(e):new Date;let a={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in a)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?a[e]:("00"+a[e]).substr((""+a[e]).length)));return t}queryStr(t){let e="";for(const s in t){let a=t[s];null!=a&&""!==a&&("object"==typeof a&&(a=JSON.stringify(a)),e+=`${s}=${a}&`)}return e=e.substring(0,e.length-1),e}msg(e=t,s="",a="",r){const i=t=>{switch(typeof t){case void 0:return t;case"string":switch(this.getEnv()){case"Surge":case"Stash":default:return{url:t};case"Loon":case"Shadowrocket":return t;case"Quantumult X":return{"open-url":t};case"Node.js":return}case"object":switch(this.getEnv()){case"Surge":case"Stash":case"Shadowrocket":default:{let e=t.url||t.openUrl||t["open-url"];return{url:e}}case"Loon":{let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}case"Quantumult X":{let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl,a=t["update-pasteboard"]||t.updatePasteboard;return{"open-url":e,"media-url":s,"update-pasteboard":a}}case"Node.js":return}default:return}};if(!this.isMute)switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:$notification.post(e,s,a,i(r));break;case"Quantumult X":$notify(e,s,a,i(r));break;case"Node.js":}if(!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),a&&t.push(a),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Quantumult X":default:this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t);break;case"Node.js":this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack)}}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;switch(this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Quantumult X":default:$done(t);break;case"Node.js":process.exit(1)}}}(t,e)} -------------------------------------------------------------------------------- /Scripts/ChinaBroadnet/ChinaBroadnet.js: -------------------------------------------------------------------------------- 1 | const $ = new Env('wuhuhu.ChinaBroadnet') 2 | $.KEY_url = '@wuhuhu.ChinaBroadnet.url' 3 | $.KEY_access = '@wuhuhu.ChinaBroadnet.access' 4 | $.KEY_body = '@wuhuhu.ChinaBroadnet.body' 5 | 6 | !(async () => { 7 | await login() 8 | await showmsg() 9 | })() 10 | .catch((e) => $.logErr(e)) 11 | .finally(() => $.done()) 12 | 13 | function login() { 14 | return new Promise((resolve) => { 15 | const url = $.getdata($.KEY_url) 16 | const access = $.getdata($.KEY_access) 17 | const body = $.getdata($.KEY_body) 18 | const opts = {} 19 | const data = { 20 | "data": body 21 | } 22 | opts.url = url 23 | opts.headers = { 24 | 'access': access, 25 | 'content-type': 'application/json' 26 | } 27 | opts.body = JSON.stringify(data) 28 | $.post(opts, (err, resp, data) => { 29 | try { 30 | $.Info = JSON.parse(data) 31 | } catch (e) { 32 | $.logErr(e, resp) 33 | } finally { 34 | resolve() 35 | } 36 | }) 37 | }) 38 | } 39 | function showmsg() { 40 | return new Promise((resolve) => { 41 | console.log($.Info['data']) 42 | $.subt = '查询' 43 | if ($.Info.status === '000000') { 44 | fee = $.Info.data.userData.fee/100 45 | flow = ($.Info.data.userData.flow/1048576).toFixed(2) 46 | $.subt += '成功' 47 | $.desc = `🎉 剩余话费:${fee}元\n` + `🎉 剩余流量:${flow}GB` 48 | } else $.subt += '失败' 49 | $.msg($.name, $.subt, $.desc) 50 | resolve() 51 | }) 52 | } 53 | 54 | // prettier-ignore 55 | function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,a)=>{s.call(this,t,(t,s,r)=>{t?a(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.encoding="utf-8",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}getEnv(){return"undefined"!=typeof $environment&&$environment["surge-version"]?"Surge":"undefined"!=typeof $environment&&$environment["stash-version"]?"Stash":"undefined"!=typeof module&&module.exports?"Node.js":"undefined"!=typeof $task?"Quantumult X":"undefined"!=typeof $loon?"Loon":"undefined"!=typeof $rocket?"Shadowrocket":void 0}isNode(){return"Node.js"===this.getEnv()}isQuanX(){return"Quantumult X"===this.getEnv()}isSurge(){return"Surge"===this.getEnv()}isLoon(){return"Loon"===this.getEnv()}isShadowrocket(){return"Shadowrocket"===this.getEnv()}isStash(){return"Stash"===this.getEnv()}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const a=this.getdata(t);if(a)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,a)=>e(a))})}runScript(t,e){return new Promise(s=>{let a=this.getdata("@chavy_boxjs_userCfgs.httpapi");a=a?a.replace(/\n/g,"").trim():a;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[i,o]=a.split("@"),n={url:`http://${o}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":i,Accept:"*/*"},timeout:r};this.post(n,(t,e,a)=>s(a))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),a=!s&&this.fs.existsSync(e);if(!s&&!a)return{};{const a=s?t:e;try{return JSON.parse(this.fs.readFileSync(a))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),a=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):a?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const a=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of a)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,a)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[a+1])>>0==+e[a+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,a]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,a,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,a,r]=/^@(.*?)\.(.*?)$/.exec(e),i=this.getval(a),o=a?"null"===i?null:i||"{}":"{}";try{const e=JSON.parse(o);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),a)}catch(e){const i={};this.lodash_set(i,r,t),s=this.setval(JSON.stringify(i),a)}}else s=this.setval(t,e);return s}getval(t){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":return $persistentStore.read(t);case"Quantumult X":return $prefs.valueForKey(t);case"Node.js":return this.data=this.loaddata(),this.data[t];default:return this.data&&this.data[t]||null}}setval(t,e){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":return $persistentStore.write(t,e);case"Quantumult X":return $prefs.setValueForKey(t,e);case"Node.js":return this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0;default:return this.data&&this.data[e]||null}}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){switch(t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"],delete t.headers["content-type"],delete t.headers["content-length"]),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,a)=>{!t&&s&&(s.body=a,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,a)});break;case"Quantumult X":this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:a,headers:r,body:i,bodyBytes:o}=t;e(null,{status:s,statusCode:a,headers:r,body:i,bodyBytes:o},i,o)},t=>e(t&&t.error||"UndefinedError"));break;case"Node.js":let s=require("iconv-lite");this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:a,statusCode:r,headers:i,rawBody:o}=t,n=s.decode(o,this.encoding);e(null,{status:a,statusCode:r,headers:i,rawBody:o,body:n},n)},t=>{const{message:a,response:r}=t;e(a,r,r&&s.decode(r.rawBody,this.encoding))})}}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";switch(t.body&&t.headers&&!t.headers["Content-Type"]&&!t.headers["content-type"]&&(t.headers["content-type"]="application/x-www-form-urlencoded"),t.headers&&(delete t.headers["Content-Length"],delete t.headers["content-length"]),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,(t,s,a)=>{!t&&s&&(s.body=a,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,a)});break;case"Quantumult X":t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:a,headers:r,body:i,bodyBytes:o}=t;e(null,{status:s,statusCode:a,headers:r,body:i,bodyBytes:o},i,o)},t=>e(t&&t.error||"UndefinedError"));break;case"Node.js":let a=require("iconv-lite");this.initGotEnv(t);const{url:r,...i}=t;this.got[s](r,i).then(t=>{const{statusCode:s,statusCode:r,headers:i,rawBody:o}=t,n=a.decode(o,this.encoding);e(null,{status:s,statusCode:r,headers:i,rawBody:o,body:n},n)},t=>{const{message:s,response:r}=t;e(s,r,r&&a.decode(r.rawBody,this.encoding))})}}time(t,e=null){const s=e?new Date(e):new Date;let a={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in a)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?a[e]:("00"+a[e]).substr((""+a[e]).length)));return t}queryStr(t){let e="";for(const s in t){let a=t[s];null!=a&&""!==a&&("object"==typeof a&&(a=JSON.stringify(a)),e+=`${s}=${a}&`)}return e=e.substring(0,e.length-1),e}msg(e=t,s="",a="",r){const i=t=>{switch(typeof t){case void 0:return t;case"string":switch(this.getEnv()){case"Surge":case"Stash":default:return{url:t};case"Loon":case"Shadowrocket":return t;case"Quantumult X":return{"open-url":t};case"Node.js":return}case"object":switch(this.getEnv()){case"Surge":case"Stash":case"Shadowrocket":default:{let e=t.url||t.openUrl||t["open-url"];return{url:e}}case"Loon":{let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}case"Quantumult X":{let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl,a=t["update-pasteboard"]||t.updatePasteboard;return{"open-url":e,"media-url":s,"update-pasteboard":a}}case"Node.js":return}default:return}};if(!this.isMute)switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:$notification.post(e,s,a,i(r));break;case"Quantumult X":$notify(e,s,a,i(r));break;case"Node.js":}if(!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),a&&t.push(a),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Quantumult X":default:this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t);break;case"Node.js":this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack)}}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;switch(this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Quantumult X":default:$done(t);break;case"Node.js":process.exit(1)}}}(t,e)} -------------------------------------------------------------------------------- /Scripts/ChinaBroadnet/ChinaBroadnet.panel.js: -------------------------------------------------------------------------------- 1 | const $ = new Env('wuhuhu.ChinaBroadnet') 2 | $.KEY_url = '@wuhuhu.ChinaBroadnet.url' 3 | $.KEY_access = '@wuhuhu.ChinaBroadnet.access' 4 | $.KEY_body = '@wuhuhu.ChinaBroadnet.body' 5 | 6 | !(async () => { 7 | await login() 8 | await showmsg() 9 | })() 10 | .catch((e) => $.logErr(e)) 11 | .finally(() => $.done()) 12 | 13 | function login() { 14 | return new Promise((resolve) => { 15 | const url = $.getdata($.KEY_url) 16 | const access = $.getdata($.KEY_access) 17 | const body = $.getdata($.KEY_body) 18 | const opts = {} 19 | const data = { 20 | "data": body 21 | } 22 | opts.url = url 23 | opts.headers = { 24 | 'access': access, 25 | 'content-type': 'application/json' 26 | } 27 | opts.body = JSON.stringify(data) 28 | $.post(opts, (err, resp, data) => { 29 | try { 30 | $.Info = JSON.parse(data) 31 | } catch (e) { 32 | $.logErr(e, resp) 33 | } finally { 34 | resolve() 35 | } 36 | }) 37 | }) 38 | } 39 | function showmsg() { 40 | return new Promise((resolve) => { 41 | console.log($.Info['data']) 42 | $.subt = '查询' 43 | if ($.Info.status === '000000') { 44 | const fee = $.Info.data.userData.fee/100 45 | const flow = ($.Info.data.userData.flow/1048576).toFixed(2) 46 | const voice = $.Info.data.userData.voice 47 | $done({title: "10099", 48 | content: `📲 剩余话费:${fee} 元\n\n` + `🌐 剩余流量:${flow} GB\n\n`+ `📞 剩余语音:${voice} 分钟`}) 49 | } else $done({title: "10099", 50 | content: "Cookie已过期,请重新获取!!"}) 51 | resolve() 52 | }) 53 | } 54 | 55 | // prettier-ignore 56 | function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,a)=>{s.call(this,t,(t,s,r)=>{t?a(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.encoding="utf-8",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}getEnv(){return"undefined"!=typeof $environment&&$environment["surge-version"]?"Surge":"undefined"!=typeof $environment&&$environment["stash-version"]?"Stash":"undefined"!=typeof module&&module.exports?"Node.js":"undefined"!=typeof $task?"Quantumult X":"undefined"!=typeof $loon?"Loon":"undefined"!=typeof $rocket?"Shadowrocket":void 0}isNode(){return"Node.js"===this.getEnv()}isQuanX(){return"Quantumult X"===this.getEnv()}isSurge(){return"Surge"===this.getEnv()}isLoon(){return"Loon"===this.getEnv()}isShadowrocket(){return"Shadowrocket"===this.getEnv()}isStash(){return"Stash"===this.getEnv()}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const a=this.getdata(t);if(a)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,a)=>e(a))})}runScript(t,e){return new Promise(s=>{let a=this.getdata("@chavy_boxjs_userCfgs.httpapi");a=a?a.replace(/\n/g,"").trim():a;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[i,o]=a.split("@"),n={url:`http://${o}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":i,Accept:"*/*"},timeout:r};this.post(n,(t,e,a)=>s(a))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),a=!s&&this.fs.existsSync(e);if(!s&&!a)return{};{const a=s?t:e;try{return JSON.parse(this.fs.readFileSync(a))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),a=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):a?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const a=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of a)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,a)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[a+1])>>0==+e[a+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,a]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,a,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,a,r]=/^@(.*?)\.(.*?)$/.exec(e),i=this.getval(a),o=a?"null"===i?null:i||"{}":"{}";try{const e=JSON.parse(o);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),a)}catch(e){const i={};this.lodash_set(i,r,t),s=this.setval(JSON.stringify(i),a)}}else s=this.setval(t,e);return s}getval(t){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":return $persistentStore.read(t);case"Quantumult X":return $prefs.valueForKey(t);case"Node.js":return this.data=this.loaddata(),this.data[t];default:return this.data&&this.data[t]||null}}setval(t,e){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":return $persistentStore.write(t,e);case"Quantumult X":return $prefs.setValueForKey(t,e);case"Node.js":return this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0;default:return this.data&&this.data[e]||null}}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){switch(t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"],delete t.headers["content-type"],delete t.headers["content-length"]),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,a)=>{!t&&s&&(s.body=a,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,a)});break;case"Quantumult X":this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:a,headers:r,body:i,bodyBytes:o}=t;e(null,{status:s,statusCode:a,headers:r,body:i,bodyBytes:o},i,o)},t=>e(t&&t.error||"UndefinedError"));break;case"Node.js":let s=require("iconv-lite");this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:a,statusCode:r,headers:i,rawBody:o}=t,n=s.decode(o,this.encoding);e(null,{status:a,statusCode:r,headers:i,rawBody:o,body:n},n)},t=>{const{message:a,response:r}=t;e(a,r,r&&s.decode(r.rawBody,this.encoding))})}}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";switch(t.body&&t.headers&&!t.headers["Content-Type"]&&!t.headers["content-type"]&&(t.headers["content-type"]="application/x-www-form-urlencoded"),t.headers&&(delete t.headers["Content-Length"],delete t.headers["content-length"]),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,(t,s,a)=>{!t&&s&&(s.body=a,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,a)});break;case"Quantumult X":t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:a,headers:r,body:i,bodyBytes:o}=t;e(null,{status:s,statusCode:a,headers:r,body:i,bodyBytes:o},i,o)},t=>e(t&&t.error||"UndefinedError"));break;case"Node.js":let a=require("iconv-lite");this.initGotEnv(t);const{url:r,...i}=t;this.got[s](r,i).then(t=>{const{statusCode:s,statusCode:r,headers:i,rawBody:o}=t,n=a.decode(o,this.encoding);e(null,{status:s,statusCode:r,headers:i,rawBody:o,body:n},n)},t=>{const{message:s,response:r}=t;e(s,r,r&&a.decode(r.rawBody,this.encoding))})}}time(t,e=null){const s=e?new Date(e):new Date;let a={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in a)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?a[e]:("00"+a[e]).substr((""+a[e]).length)));return t}queryStr(t){let e="";for(const s in t){let a=t[s];null!=a&&""!==a&&("object"==typeof a&&(a=JSON.stringify(a)),e+=`${s}=${a}&`)}return e=e.substring(0,e.length-1),e}msg(e=t,s="",a="",r){const i=t=>{switch(typeof t){case void 0:return t;case"string":switch(this.getEnv()){case"Surge":case"Stash":default:return{url:t};case"Loon":case"Shadowrocket":return t;case"Quantumult X":return{"open-url":t};case"Node.js":return}case"object":switch(this.getEnv()){case"Surge":case"Stash":case"Shadowrocket":default:{let e=t.url||t.openUrl||t["open-url"];return{url:e}}case"Loon":{let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}case"Quantumult X":{let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl,a=t["update-pasteboard"]||t.updatePasteboard;return{"open-url":e,"media-url":s,"update-pasteboard":a}}case"Node.js":return}default:return}};if(!this.isMute)switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:$notification.post(e,s,a,i(r));break;case"Quantumult X":$notify(e,s,a,i(r));break;case"Node.js":}if(!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),a&&t.push(a),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Quantumult X":default:this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t);break;case"Node.js":this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack)}}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;switch(this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Quantumult X":default:$done(t);break;case"Node.js":process.exit(1)}}}(t,e)} -------------------------------------------------------------------------------- /Scripts/ChinaBroadnet/ChinaBroadnet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuhuuuu/study/106ed3b788d4bc3dce0587f3a3e7acc47682fe7d/Scripts/ChinaBroadnet/ChinaBroadnet.png -------------------------------------------------------------------------------- /Scripts/ChinaBroadnet/ChinaBroadnet.sgmodule: -------------------------------------------------------------------------------- 1 | #!name=ChinaBroadnet 2 | #!desc=Cookie 3 | #!category=Cookie 4 | 5 | [MITM] 6 | hostname = %APPEND% wx.10099.com.cn 7 | 8 | [Script] 9 | ChinaBroadnet.cookie = type=http-request,pattern=https://wx.10099.com.cn/contact-web/api/busi/qryUserInfo,requires-body=1,max-size=0,script-path=https://github.com/wuhuhuuuu/study/raw/main/Scripts/ChinaBroadnet/ChinaBroadnet.cookie.js,script-update-interval=0 -------------------------------------------------------------------------------- /Scripts/ChinaBroadnet/README.md: -------------------------------------------------------------------------------- 1 | # ChinaBroadnet 2 | 3 | ## 配置 (Surge) 4 | 5 | ```properties 6 | [MITM] 7 | hostname = wx.10099.com.cn 8 | 9 | [Script] 10 | ChinaBroadnet.cookie = type=http-request,pattern=https://wx.10099.com.cn/contact-web/api/busi/qryUserInfo,requires-body=1,max-size=0,script-path=https://github.com/wuhuhuuuu/study/raw/main/Scripts/ChinaBroadnet/ChinaBroadnet.cookie.js,script-update-interval=0 11 | ChinaBroadnet = type=cron,cronexp=3 0 * * *,script-path=https://github.com/wuhuhuuuu/study/raw/main/Scripts/ChinaBroadnet/ChinaBroadnet.js,wake-system=1,script-update-interval=0 12 | ``` 13 | ```properties 14 | Panel 配置 15 | 16 | [Panel] 17 | ChinaBroadnet = script-name=ChinaBroadnet.Panel,update-interval=3600 18 | 19 | [Script] 20 | ChinaBroadnet.Panel = type=generic,script-path=https://github.com/wuhuhuuuu/study/raw/main/Scripts/ChinaBroadnet/ChinaBroadnet.panel.js 21 | ``` 22 | ## 配置(Loon) 23 | 24 | ```properties 25 | [MITM] 26 | hostname = wx.10099.com.cn 27 | 28 | [Script] 29 | http-request https://wx.10099.com.cn/contact-web/api/busi/qryUserInfo script-path=https://github.com/wuhuhuuuu/study/raw/main/Scripts/ChinaBroadnet/ChinaBroadnet.cookie.js, requires-body=true, timeout=10, tag=ChinaBroadnet.cookie, img-url=https://github.com/wuhuhuuuu/study/raw/main/Scripts/ChinaBroadnet/ChinaBroadnet.png 30 | cron "3 0 * * *" script-path=https://github.com/wuhuhuuuu/study/raw/main/Scripts/ChinaBroadnet/ChinaBroadnet.js, timeout=10, tag=ChinaBroadnet, img-url=https://github.com/wuhuhuuuu/study/raw/main/Scripts/ChinaBroadnet/ChinaBroadnet.png 31 | ``` 32 | ## 配置 (QuanX) 33 | 34 | ```properties 35 | [mitm] 36 | hostname = wx.10099.com.cn 37 | 38 | [rewrite_local] 39 | https://wx.10099.com.cn/contact-web/api/busi/qryUserInfo url script-request-body https://github.com/wuhuhuuuu/study/raw/main/Scripts/ChinaBroadnet/ChinaBroadnet.cookie.js 40 | 41 | [task_local] 42 | 3 0 * * * https://github.com/wuhuhuuuu/study/raw/main/Scripts/ChinaBroadnet/ChinaBroadnet.js, tag=ChinaBroadnet, img-url=https://github.com/wuhuhuuuu/study/raw/main/Scripts/ChinaBroadnet/ChinaBroadnet.png 43 | ``` 44 | 45 | ## 说明 46 | 47 | > 先在登录成功后, 再打开获取 Cookie 的脚本 48 | 49 | 1. 先复制相关信息到对应字段 50 | 2. 打开 小程序 刷新一次 51 | 3. 系统提示: `获取Cookie: 成功` 52 | 4. 最后就可以获取cookie脚本注释掉了 53 | 54 | > 第 1 条脚本是用来获取 cookie 的, 用浏览器访问一次获取 cookie 成功后就可以删掉或注释掉了, 但请确保在`登录成功`后再获取 cookie. 55 | 56 | > 第 2 条脚本是通知信息脚本, 每天`00:03:00`执行一次. 57 | 58 | ## 感谢 59 | 60 | [@chavyleung](https://github.com/chavyleung) 61 | -------------------------------------------------------------------------------- /Scripts/README.md: -------------------------------------------------------------------------------- 1 | # 授人以鱼不如授人以渔 2 | 3 | 学一手JavaScript。 -------------------------------------------------------------------------------- /Scripts/TencentComic/README.md: -------------------------------------------------------------------------------- 1 | # 腾讯动漫 2 | 3 | ## 配置 (Surge) 4 | 5 | ```properties 6 | [MITM] 7 | hostname = i.ac.qq.com 8 | 9 | [Script] 10 | 腾讯动漫Cookie = type=http-request,pattern=^https:\/\/i.ac.qq.com\/.+\/SignIn\/signIn$,requires-body=0,script-path=https://github.com/wuhuhuuuu/study/raw/main/Scripts/Tencent_Comic/Tencent.Comic.cookie.js 11 | 腾讯动漫 = type=cron,cronexp=3 0 * * *,script-path=https://github.com/wuhuhuuuu/study/raw/main/Scripts/Tencent_Comic/Tencent.Comic.js,wake-system=1,script-update-interval=0 12 | ``` 13 | 14 | ## 配置(Loon) 15 | 16 | ```properties 17 | [MITM] 18 | hostname = i.ac.qq.com 19 | 20 | [Script] 21 | http-request ^https:\/\/i.ac.qq.com\/.+\/SignIn\/signIn$ script-path=https://github.com/wuhuhuuuu/study/raw/main/Scripts/Tencent_Comic/Tencent.Comic.cookie.js, timeout=10, tag=腾讯动漫Cookie, img-url=https://github.com/wuhuhuuuu/study/raw/main/Scripts/Tencent_Comic/Tencent.Comic.png 22 | cron "3 0 * * *" script-path=https://github.com/wuhuhuuuu/study/raw/main/Scripts/Tencent_Comic/Tencent.Comic.js, timeout=10, tag=腾讯动漫, img-url=https://github.com/wuhuhuuuu/study/raw/main/Scripts/Tencent_Comic/Tencent.Comic.png 23 | ``` 24 | ## 配置 (QuanX) 25 | 26 | ```properties 27 | [mitm] 28 | hostname = i.ac.qq.com 29 | 30 | [rewrite_local] 31 | ^https:\/\/i.ac.qq.com\/.+\/SignIn\/signIn$ url script-request-header https://github.com/wuhuhuuuu/study/raw/main/Scripts/Tencent_Comic/Tencent.Comic.cookie.js 32 | 33 | [task_local] 34 | 3 0 * * * https://github.com/wuhuhuuuu/study/raw/main/Scripts/Tencent_Comic/Tencent.Comic.js, tag=腾讯动漫签到, img-url=https://github.com/wuhuhuuuu/study/raw/main/Scripts/Tencent_Comic/Tencent.Comic.png 35 | ``` 36 | 37 | ## 说明 38 | 39 | > 先在登录成功后, 再打开获取 Cookie 的脚本 40 | 41 | 1. 先复制相关信息到对应字段 42 | 2. 打开 APP 手动签到一次 43 | 3. 系统提示: `获取Cookie: 成功` 44 | 4. 最后就可以获取cookie脚本注释掉了 45 | 46 | > 第 1 条脚本是用来获取 cookie 的, 用浏览器访问一次获取 cookie 成功后就可以删掉或注释掉了, 但请确保在`登录成功`后再获取 cookie. 47 | 48 | > 第 2 条脚本是签到脚本, 每天`00:03:00`执行一次. 49 | 50 | ## 感谢 51 | 52 | [@chavyleung](https://github.com/chavyleung) -------------------------------------------------------------------------------- /Scripts/TencentComic/Tencent.Comic.cookie.js: -------------------------------------------------------------------------------- 1 | const $ = new Env('腾讯动漫') 2 | $.KEY_sign = 'Tencent_Comic' 3 | 4 | !(async () => { 5 | const session = {} 6 | session.url = $request.url 7 | session.headers = $request.headers 8 | if ($.setdata(JSON.stringify(session), $.KEY_sign)) { 9 | $.subt = `获取会话: 成功!` 10 | } else { 11 | $.subt = `获取会话: 失败!` 12 | } 13 | $.msg($.name, $.subt) 14 | })() 15 | .catch((e) => $.logErr(e)) 16 | .finally(() => $.done()) 17 | 18 | // prettier-ignore 19 | function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,a)=>{s.call(this,t,(t,s,r)=>{t?a(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.encoding="utf-8",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}getEnv(){return"undefined"!=typeof $environment&&$environment["surge-version"]?"Surge":"undefined"!=typeof $environment&&$environment["stash-version"]?"Stash":"undefined"!=typeof module&&module.exports?"Node.js":"undefined"!=typeof $task?"Quantumult X":"undefined"!=typeof $loon?"Loon":"undefined"!=typeof $rocket?"Shadowrocket":void 0}isNode(){return"Node.js"===this.getEnv()}isQuanX(){return"Quantumult X"===this.getEnv()}isSurge(){return"Surge"===this.getEnv()}isLoon(){return"Loon"===this.getEnv()}isShadowrocket(){return"Shadowrocket"===this.getEnv()}isStash(){return"Stash"===this.getEnv()}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const a=this.getdata(t);if(a)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,a)=>e(a))})}runScript(t,e){return new Promise(s=>{let a=this.getdata("@chavy_boxjs_userCfgs.httpapi");a=a?a.replace(/\n/g,"").trim():a;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[i,o]=a.split("@"),n={url:`http://${o}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":i,Accept:"*/*"},timeout:r};this.post(n,(t,e,a)=>s(a))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),a=!s&&this.fs.existsSync(e);if(!s&&!a)return{};{const a=s?t:e;try{return JSON.parse(this.fs.readFileSync(a))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),a=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):a?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const a=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of a)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,a)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[a+1])>>0==+e[a+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,a]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,a,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,a,r]=/^@(.*?)\.(.*?)$/.exec(e),i=this.getval(a),o=a?"null"===i?null:i||"{}":"{}";try{const e=JSON.parse(o);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),a)}catch(e){const i={};this.lodash_set(i,r,t),s=this.setval(JSON.stringify(i),a)}}else s=this.setval(t,e);return s}getval(t){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":return $persistentStore.read(t);case"Quantumult X":return $prefs.valueForKey(t);case"Node.js":return this.data=this.loaddata(),this.data[t];default:return this.data&&this.data[t]||null}}setval(t,e){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":return $persistentStore.write(t,e);case"Quantumult X":return $prefs.setValueForKey(t,e);case"Node.js":return this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0;default:return this.data&&this.data[e]||null}}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){switch(t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"],delete t.headers["content-type"],delete t.headers["content-length"]),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,a)=>{!t&&s&&(s.body=a,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,a)});break;case"Quantumult X":this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:a,headers:r,body:i,bodyBytes:o}=t;e(null,{status:s,statusCode:a,headers:r,body:i,bodyBytes:o},i,o)},t=>e(t&&t.error||"UndefinedError"));break;case"Node.js":let s=require("iconv-lite");this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:a,statusCode:r,headers:i,rawBody:o}=t,n=s.decode(o,this.encoding);e(null,{status:a,statusCode:r,headers:i,rawBody:o,body:n},n)},t=>{const{message:a,response:r}=t;e(a,r,r&&s.decode(r.rawBody,this.encoding))})}}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";switch(t.body&&t.headers&&!t.headers["Content-Type"]&&!t.headers["content-type"]&&(t.headers["content-type"]="application/x-www-form-urlencoded"),t.headers&&(delete t.headers["Content-Length"],delete t.headers["content-length"]),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,(t,s,a)=>{!t&&s&&(s.body=a,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,a)});break;case"Quantumult X":t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:a,headers:r,body:i,bodyBytes:o}=t;e(null,{status:s,statusCode:a,headers:r,body:i,bodyBytes:o},i,o)},t=>e(t&&t.error||"UndefinedError"));break;case"Node.js":let a=require("iconv-lite");this.initGotEnv(t);const{url:r,...i}=t;this.got[s](r,i).then(t=>{const{statusCode:s,statusCode:r,headers:i,rawBody:o}=t,n=a.decode(o,this.encoding);e(null,{status:s,statusCode:r,headers:i,rawBody:o,body:n},n)},t=>{const{message:s,response:r}=t;e(s,r,r&&a.decode(r.rawBody,this.encoding))})}}time(t,e=null){const s=e?new Date(e):new Date;let a={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in a)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?a[e]:("00"+a[e]).substr((""+a[e]).length)));return t}queryStr(t){let e="";for(const s in t){let a=t[s];null!=a&&""!==a&&("object"==typeof a&&(a=JSON.stringify(a)),e+=`${s}=${a}&`)}return e=e.substring(0,e.length-1),e}msg(e=t,s="",a="",r){const i=t=>{switch(typeof t){case void 0:return t;case"string":switch(this.getEnv()){case"Surge":case"Stash":default:return{url:t};case"Loon":case"Shadowrocket":return t;case"Quantumult X":return{"open-url":t};case"Node.js":return}case"object":switch(this.getEnv()){case"Surge":case"Stash":case"Shadowrocket":default:{let e=t.url||t.openUrl||t["open-url"];return{url:e}}case"Loon":{let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}case"Quantumult X":{let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl,a=t["update-pasteboard"]||t.updatePasteboard;return{"open-url":e,"media-url":s,"update-pasteboard":a}}case"Node.js":return}default:return}};if(!this.isMute)switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:$notification.post(e,s,a,i(r));break;case"Quantumult X":$notify(e,s,a,i(r));break;case"Node.js":}if(!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),a&&t.push(a),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Quantumult X":default:this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t);break;case"Node.js":this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack)}}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;switch(this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Quantumult X":default:$done(t);break;case"Node.js":process.exit(1)}}}(t,e)} -------------------------------------------------------------------------------- /Scripts/TencentComic/Tencent.Comic.js: -------------------------------------------------------------------------------- 1 | const $ = new Env('腾讯动漫') 2 | $.KEY_sign = 'Tencent_Comic' 3 | 4 | !(async () => { 5 | await login() 6 | await showmsg() 7 | })() 8 | .catch((e) => $.logErr(e)) 9 | .finally(() => $.done()) 10 | 11 | function login() { 12 | return new Promise((resolve) => { 13 | const opts = JSON.parse($.getdata($.KEY_sign)) 14 | $.post(opts, (err, resp, data) => { 15 | try { 16 | $.loginInfo = resp 17 | } catch (e) { 18 | $.logErr(e, resp) 19 | } finally { 20 | resolve() 21 | } 22 | }) 23 | }) 24 | } 25 | function showmsg() { 26 | return new Promise((resolve) => { 27 | const getday = new Date().getDay() 28 | const week = { 29 | '0': '星期日', 30 | '1': '星期一', 31 | '2': '星期二', 32 | '3': '星期三', 33 | '4': '星期四', 34 | '5': '星期五', 35 | '6': '星期六', 36 | } 37 | const day = week[getday] 38 | $.subt = `${day} 签到: ` 39 | if ($.loginInfo.statusCode == '200') $.subt += '成功' 40 | else $.subt += '失败' 41 | $.msg($.name, $.subt, $.desc) 42 | resolve() 43 | }) 44 | } 45 | 46 | // prettier-ignore 47 | function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,a)=>{s.call(this,t,(t,s,r)=>{t?a(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.encoding="utf-8",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}getEnv(){return"undefined"!=typeof $environment&&$environment["surge-version"]?"Surge":"undefined"!=typeof $environment&&$environment["stash-version"]?"Stash":"undefined"!=typeof module&&module.exports?"Node.js":"undefined"!=typeof $task?"Quantumult X":"undefined"!=typeof $loon?"Loon":"undefined"!=typeof $rocket?"Shadowrocket":void 0}isNode(){return"Node.js"===this.getEnv()}isQuanX(){return"Quantumult X"===this.getEnv()}isSurge(){return"Surge"===this.getEnv()}isLoon(){return"Loon"===this.getEnv()}isShadowrocket(){return"Shadowrocket"===this.getEnv()}isStash(){return"Stash"===this.getEnv()}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const a=this.getdata(t);if(a)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,a)=>e(a))})}runScript(t,e){return new Promise(s=>{let a=this.getdata("@chavy_boxjs_userCfgs.httpapi");a=a?a.replace(/\n/g,"").trim():a;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[i,o]=a.split("@"),n={url:`http://${o}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":i,Accept:"*/*"},timeout:r};this.post(n,(t,e,a)=>s(a))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),a=!s&&this.fs.existsSync(e);if(!s&&!a)return{};{const a=s?t:e;try{return JSON.parse(this.fs.readFileSync(a))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),a=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):a?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const a=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of a)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,a)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[a+1])>>0==+e[a+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,a]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,a,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,a,r]=/^@(.*?)\.(.*?)$/.exec(e),i=this.getval(a),o=a?"null"===i?null:i||"{}":"{}";try{const e=JSON.parse(o);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),a)}catch(e){const i={};this.lodash_set(i,r,t),s=this.setval(JSON.stringify(i),a)}}else s=this.setval(t,e);return s}getval(t){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":return $persistentStore.read(t);case"Quantumult X":return $prefs.valueForKey(t);case"Node.js":return this.data=this.loaddata(),this.data[t];default:return this.data&&this.data[t]||null}}setval(t,e){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":return $persistentStore.write(t,e);case"Quantumult X":return $prefs.setValueForKey(t,e);case"Node.js":return this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0;default:return this.data&&this.data[e]||null}}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){switch(t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"],delete t.headers["content-type"],delete t.headers["content-length"]),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,a)=>{!t&&s&&(s.body=a,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,a)});break;case"Quantumult X":this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:a,headers:r,body:i,bodyBytes:o}=t;e(null,{status:s,statusCode:a,headers:r,body:i,bodyBytes:o},i,o)},t=>e(t&&t.error||"UndefinedError"));break;case"Node.js":let s=require("iconv-lite");this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:a,statusCode:r,headers:i,rawBody:o}=t,n=s.decode(o,this.encoding);e(null,{status:a,statusCode:r,headers:i,rawBody:o,body:n},n)},t=>{const{message:a,response:r}=t;e(a,r,r&&s.decode(r.rawBody,this.encoding))})}}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";switch(t.body&&t.headers&&!t.headers["Content-Type"]&&!t.headers["content-type"]&&(t.headers["content-type"]="application/x-www-form-urlencoded"),t.headers&&(delete t.headers["Content-Length"],delete t.headers["content-length"]),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,(t,s,a)=>{!t&&s&&(s.body=a,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,a)});break;case"Quantumult X":t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:a,headers:r,body:i,bodyBytes:o}=t;e(null,{status:s,statusCode:a,headers:r,body:i,bodyBytes:o},i,o)},t=>e(t&&t.error||"UndefinedError"));break;case"Node.js":let a=require("iconv-lite");this.initGotEnv(t);const{url:r,...i}=t;this.got[s](r,i).then(t=>{const{statusCode:s,statusCode:r,headers:i,rawBody:o}=t,n=a.decode(o,this.encoding);e(null,{status:s,statusCode:r,headers:i,rawBody:o,body:n},n)},t=>{const{message:s,response:r}=t;e(s,r,r&&a.decode(r.rawBody,this.encoding))})}}time(t,e=null){const s=e?new Date(e):new Date;let a={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in a)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?a[e]:("00"+a[e]).substr((""+a[e]).length)));return t}queryStr(t){let e="";for(const s in t){let a=t[s];null!=a&&""!==a&&("object"==typeof a&&(a=JSON.stringify(a)),e+=`${s}=${a}&`)}return e=e.substring(0,e.length-1),e}msg(e=t,s="",a="",r){const i=t=>{switch(typeof t){case void 0:return t;case"string":switch(this.getEnv()){case"Surge":case"Stash":default:return{url:t};case"Loon":case"Shadowrocket":return t;case"Quantumult X":return{"open-url":t};case"Node.js":return}case"object":switch(this.getEnv()){case"Surge":case"Stash":case"Shadowrocket":default:{let e=t.url||t.openUrl||t["open-url"];return{url:e}}case"Loon":{let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}case"Quantumult X":{let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl,a=t["update-pasteboard"]||t.updatePasteboard;return{"open-url":e,"media-url":s,"update-pasteboard":a}}case"Node.js":return}default:return}};if(!this.isMute)switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:$notification.post(e,s,a,i(r));break;case"Quantumult X":$notify(e,s,a,i(r));break;case"Node.js":}if(!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),a&&t.push(a),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Quantumult X":default:this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t);break;case"Node.js":this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack)}}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;switch(this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Quantumult X":default:$done(t);break;case"Node.js":process.exit(1)}}}(t,e)} -------------------------------------------------------------------------------- /Scripts/TencentComic/Tencent.Comic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuhuuuu/study/106ed3b788d4bc3dce0587f3a3e7acc47682fe7d/Scripts/TencentComic/Tencent.Comic.png -------------------------------------------------------------------------------- /Scripts/wuhuhuuuu.boxjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "wuhuhuuuu.app.sub", 3 | "name": "wuhuhuuuu", 4 | "author": "@wuhuhuuuu", 5 | "icon": "https://github.com/wuhuhuuuu/study/raw/main/wuhuhuuuu.PNG", 6 | "repo": "https://github.com/wuhuhuuuu/study", 7 | "apps": [ 8 | { 9 | "id": "Tencent.Comic", 10 | "name": "腾讯动漫", 11 | "keys": ["Tencent_Comic"], 12 | "author": "@wuhuhuuuu", 13 | "script": "https://github.com/wuhuhuuuu/study/raw/main/Scripts/Tencent_Comic/Tencent.Comic.js", 14 | "repo": "https://github.com/wuhuhuuuu/study/tree/main/Scripts/Tencent_Comic", 15 | "icons": [ 16 | "https://github.com/wuhuhuuuu/study/raw/main/Scripts/Tencent_Comic/Tencent.Comic.png", 17 | "https://github.com/wuhuhuuuu/study/raw/main/Scripts/Tencent_Comic/Tencent.Comic.png" 18 | ] 19 | }, 20 | { 21 | "id": "wuhuhu.ChinaBroadnet", 22 | "name": "中国广电", 23 | "keys": ["@wuhuhu.ChinaBroadnet.url", "@wuhuhu.ChinaBroadnet.access", "@wuhuhu.ChinaBroadnet.body"], 24 | "author": "@wuhuhuuuu", 25 | "script": "https://github.com/wuhuhuuuu/study/raw/main/Scripts/ChinaBroadnet/ChinaBroadnet.js", 26 | "repo": "https://github.com/wuhuhuuuu/study/tree/main/Scripts/ChinaBroadnet", 27 | "icons": [ 28 | "https://github.com/wuhuhuuuu/study/raw/main/Scripts/ChinaBroadnet/ChinaBroadnet.png", 29 | "https://github.com/wuhuhuuuu/study/raw/main/Scripts/ChinaBroadnet/ChinaBroadnet.png" 30 | ] 31 | } 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /wuhuhuuuu.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuhuuuu/study/106ed3b788d4bc3dce0587f3a3e7acc47682fe7d/wuhuhuuuu.PNG --------------------------------------------------------------------------------