From 548e6802cf59fcc349be178a35ac8cb5e7e85d82 Mon Sep 17 00:00:00 2001
From: blackmatrix7 <27717518+blackmatrix7@users.noreply.github.com>
Date: Wed, 14 Sep 2022 23:27:19 +0800
Subject: [PATCH] =?UTF-8?q?[Apple=20Store]=20=E6=94=AF=E6=8C=81iPhone=2014?=
=?UTF-8?q?=20=E7=B3=BB=E5=88=97=E5=BA=93=E5=AD=98=E7=9B=91=E6=8E=A7?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
script/applestore/README.md | 118 ++++++++++++++++++++++----
script/applestore/applestore.js | 100 +++++++++++++---------
script/applestore/applestore.lnplugin | 10 +++
script/applestore/applestore.lnscript | 1 -
script/applestore/images/01.png | Bin 0 -> 21429 bytes
script/applestore/images/02.png | Bin 0 -> 52648 bytes
script/applestore/images/03.png | Bin 0 -> 85873 bytes
script/applestore/images/04..jpg | Bin 0 -> 97059 bytes
script/applestore/images/04.png | Bin 0 -> 70285 bytes
9 files changed, 171 insertions(+), 58 deletions(-)
create mode 100644 script/applestore/applestore.lnplugin
delete mode 100644 script/applestore/applestore.lnscript
create mode 100644 script/applestore/images/01.png
create mode 100644 script/applestore/images/02.png
create mode 100644 script/applestore/images/03.png
create mode 100644 script/applestore/images/04..jpg
create mode 100644 script/applestore/images/04.png
diff --git a/script/applestore/README.md b/script/applestore/README.md
index ca72179d6..6d6da9a20 100644
--- a/script/applestore/README.md
+++ b/script/applestore/README.md
@@ -1,10 +1,10 @@
-# Apple Store 库存监控
+# 🧸 Apple Store 库存监控
## 前言
-脚本用来监控线下AppleStore指定商品库存,目前验证过iPhone13、AppleWatch7系列。
+脚本用来监控线下AppleStore指定商品库存,已经支持iPhone14全系列。
长话短说,需要做一些准备:
@@ -16,25 +16,88 @@
### 确认型号
-iPhone13
+##### iPhone 14 系列
-https://www.apple.com.cn/shop/buy-iphone/iphone-13/MLDH3CH/A
+https://www.apple.com.cn/shop/buy-iphone/iphone-14
-iPhone 13 Pro
+##### iPhone 14 Pro 系列
-https://www.apple.com.cn/shop/buy-iphone/iphone-13-pro/MLTE3CH/A
+https://www.apple.com.cn/shop/buy-iphone/iphone-14-pro
-在上面的链接中选择需要的型号、颜色、容量,然后把地址中类似MLDH3CH/A的文本复制下来,就是需要监控的型号
+在上面的链接中选择需要的型号、颜色、容量,然后把浏览器地址中类似 `MLDH3CH/A` 的文本复制下来,就是需要监控的型号。
-AppleWatch
+如下图:
-https://www.apple.com.cn/shop/buy-watch/apple-watch/45mm-cellular-graphite-stainless-steel-pride-edition-braided-solo-loop-size-5
+![](https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/script/applestore/images/01.png)
-AppleWatch因为有选项,所以会稍微麻烦,需要在浏览器的“开发人员工具”中,找到“网络”,在“筛选器”中输入`https://www.apple.com.cn/shop/fulfillment-messages`,找到网络请求,将`parts.0=xxxxx`和`option.0=xxxxxxxxxxx`中xxxxx部分复制出来保存。
+##### Apple Watch 系列
-将两个拼接在一起,如 `Z0YQ#MKMR3CH/A,MJXA3FE/A`,就是需要监控的型号。
+Apple Watch 因为有选项,所以会稍微麻烦,请以下步骤操作:
-AppleWatch目前没办法自动获取标题,所以可以自定义标题,如`Z0YQ#MKMR3CH/A,MJXA3FE/A#AppleWatch 7 石墨色不锈钢`,把这部分输入到BoxJs的监控型号中。
+1. 在浏览器中选择你所需的型号,得到类似 `https://www.apple.com.cn/shop/buy-watch/apple-watch-ultra/49mm-cellular-titanium-black-gray-trail-loop-m-l` 的地址。
+2. 在浏览器中按下`F12`,打开“开发人员工具”,在顶部的标签中选择“网络”或“network”。
+3. 在一堆网络请求中找到类似 `fulfillment-messages` 的地址,如果没有找到,保持“开发人员工具”打开的情况下,再刷新一次页面。
+4. 把含有 `https://www.apple.com.cn/shop/fulfillment-messages` 的链接复制下来,里面有我们需要的信息。
+
+> 如果你对上述步骤感到比较疑惑,建议在搜索引擎中以“`Chrome 开发人员 工具 教程`”为关键词,搜索相关资料。如何查看浏览器的网络请求,并不在本项目的说明范围内。
+
+###### Apple Watch Ultra
+
+如果你需要监控的是Apple Watch Ultra,事情就很简单,把链接中类似parts.0=MNHT3CH/A的内容记录下来,`MNHT3CH/A`就是你需要监控的型号,保存好它!
+
+###### Apple Watch 8
+
+Apple Watch 8 中地址存在类似的格式 `parts.0=Z0YQ&option.0=MNNQ3CH/A,MPLE3FE/A` 。我们需要的是`parts.0` 和 `option.0` 之后的数据。
+
+以上面的地址为例,我们需要的是 `Z0YQ` 和 `MNNQ3CH/A,MPLE3FE/A`。
+
+至此,完成所需监控的iPhone或Apple Watch型号收集。
+
+### 型号拼接
+
+这步是把获取的型号,拼接成字符串,填写到BoxJS中,让脚本知道你要监控什么商品的库存。
+
+#### iPhone 14、iPhone 14 Pro
+
+采用如下格式
+
+```
+<型号>##<名称>
+```
+
+型号就是获取的设备型号,名称可以自己取,便于在通知中识别。
+
+假设上面获取的型号是MLDH3CH/A,那拼接后的字符串就是
+
+```
+MLDH3CH/A##小黑紫
+```
+
+注意有两个##
+
+#### Apple Watch
+
+##### Apple Watch Ultra
+
+和iPhone相似
+
+```
+MNHT3CH/A##Apple Watch Ultra
+```
+
+##### Apple Watch 8
+
+```
+Z0YQ#MNNQ3CH/A,MPLE3FE/A#Apple Watch 8
+```
+
+#### 多个型号
+
+如下拼接
+
+```
+MLDH3CH/A##小黑紫;MNHT3CH/A##Apple Watch Ultra;Z0YQ#MNNQ3CH/A,MPLE3FE/A#Apple Watch 8
+```
### 确认地区
@@ -42,11 +105,19 @@ AppleWatch目前没办法自动获取标题,所以可以自定义标题,如`
直辖市示例:北京 北京 昌平区
+如果搞不定的话,在Apple官网选择查看取货情况,把下面的字保存下来,每个间隔一个空格。
+
+![](https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/script/applestore/images/03.png)
+
+## BoxJS填写效果
+
+![](https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/script/applestore/images/04.png)
+
## 进阶问题
### 脏数据
-每次配置型号和地区,都必须在BoxJS中把`iphone_stock`的值清理掉,避免脏数据导致脚本异常。
+每次配置型号和地区,都必须在BoxJS中把库存的数据清理掉,避免脏数据导致脚本异常。
### 监控间隔
@@ -81,7 +152,7 @@ AppleWatch目前没办法自动获取标题,所以可以自定义标题,如`
使用模块
```ini
-https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/script/applestore/iphone.sgmodule
+https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/script/applestore/applestore.sgmodule
```
### Loon
@@ -89,7 +160,7 @@ https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/script/app
使用插件
```ini
-https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/script/applestore/iphone.lnplugin
+https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/script/applestore/applestore.lnplugin
```
### Quantumult X
@@ -98,6 +169,21 @@ https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/script/app
```ini
[task_local]
-0/5 * 6-23 * * * https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/script/applestore/iphone.js, tag=AppleStore_商品库存监控, enabled=true
+0/5 * 6-23 * * * https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/script/applestore/applestore.js, tag=AppleStore_商品库存监控, enabled=true
```
+## 变量说明
+
+NodeJS(含青龙面板),请根据下表配置magic.json的变量。
+
+更新详细的配置说明,请访问:https://github.com/blackmatrix7/ios_rule_script/blob/master/script/README.md。
+
+| 变量 | 类型 | 说明 |
+| ---------------------------------- | ------ | ------------------------------------------------------------ |
+| applestore_goods_model | string | 监控的商品型号,类似`MPU93CH/A##iPhone 14 午夜色 128G` 。 |
+| applestore_region | string | 监控的地区,类似`北京 北京 昌平区`、`吉林 长春 朝阳区` 。 |
+| applestore_settings_notify_soldout | bool | 售罄也进行推送,建议为`false` 。 |
+| applestore_run_forever | bool | NodeJS环境下只运行一次或无限次运行。只运行一次适合在青龙面板设置定时任务;无限运行适合用NodeJS直接启动脚本。 |
+| applestore_watch_interval | number | NodeJS无限运行时,库存监控间隔,单位毫秒,最小2000。 |
+| applestore_goods_stock | json | 监控的库存数据,自动生成,不要修改。 |
+
diff --git a/script/applestore/applestore.js b/script/applestore/applestore.js
index 3ca70b877..6608da756 100644
--- a/script/applestore/applestore.js
+++ b/script/applestore/applestore.js
@@ -1,10 +1,11 @@
const SCRIPT_NAME = "AppleStore";
-const APPLESTORE_MODEL_KEY = "goods_model";
+const APPLESTORE_MODEL_KEY = "applestore_goods_model";
const APPLESTORE_REGION_KEY = "applestore_region";
-const APPLESTORE_STOCK_KEY = "goods_stock";
+const APPLESTORE_STOCK_KEY = "applestore_goods_stock";
+const APPLESTORE_RUN_FOREVER_KEY = "applestore_run_forever";
+const APPLESTORE_WATCH_INTERVAL = "applestore_watch_interval";
-let magicJS = MagicJS(SCRIPT_NAME);
-magicJS.barkUrl = magicJS.read("applestore_bark_url") || magicJS.read("magicjs_bark_url");
+const $ = MagicJS(SCRIPT_NAME);
function getGoodsStock(parts, location, option = "") {
return new Promise((resolve) => {
@@ -14,40 +15,36 @@ function getGoodsStock(parts, location, option = "") {
} else {
url = encodeURI(`https://www.apple.com.cn/shop/fulfillment-messages?pl=true&mt=compact&parts.0=${parts}&location=${location}&_=${new Date().getTime()}`);
}
- magicJS.get(url, (err, resp, data) => {
- try{
- let obj = JSON.parse(data);
- let stores = obj["body"]["content"]["pickupMessage"]["stores"];
- if (stores) {
- resolve(stores);
- } else {
- magicJS.notify("查询库存失败,请检查配置是否正确。");
- resolve([]);
- }
- }
- catch (err){
- magicJS.logError(`解析库存数据失败,异常信息:${err}`);
+ $.http.get(url).then(resp => {
+ const obj = resp.body;
+ let stores = obj["body"]["content"]["pickupMessage"]["stores"];
+ if (stores) {
+ resolve(stores);
+ } else {
+ $.logger.error("查询库存失败,请检查配置是否正确。");
resolve([]);
}
- });
+ }).catch(err => {
+ $.logger.error(`查询库存出现异常,${err}`);
+ })
});
}
async function watchStock(goods_models, applestore_region) {
- let stock = magicJS.read(APPLESTORE_STOCK_KEY);
- stock = !!stock ? stock : {};
+ let stock = $.data.read(APPLESTORE_STOCK_KEY);
+ stock = stock || {};
let len = goods_models.length;
let tasks = [];
for (let i = 0; i < len; i++) {
- const wrap = async () =>{
+ const wrap = async () => {
let partsConfig = goods_models[i].split("#");
let parts = partsConfig[0];
let option = partsConfig.length >= 2 ? partsConfig[1] : "";
let name = partsConfig.length == 3 ? partsConfig[2] : "";
let subObj = { watch: 0, pickup: 0, soldout: 0, changed: 0 };
let availability = await getGoodsStock(parts, applestore_region, option);
-
+
if (availability && availability.length > 0) {
// 获取AppleStore取货信息
for (let store of availability) {
@@ -69,7 +66,7 @@ async function watchStock(goods_models, applestore_region) {
stock[parts]["stores"][storeNumber]["notify"] = false;
}
}
-
+
let now = new Date();
if (!stock[parts]["title"] && !name) {
name = "未命名商品";
@@ -81,7 +78,7 @@ async function watchStock(goods_models, applestore_region) {
let soldOutContent = ""; // 售罄的型号与店铺
let unchangContent = ""; // 没有变化的型号与店铺
let content = "";
-
+
// 整理通知内容
for (let storeStock of Object.values(stock[parts]["stores"])) {
subObj["watch"] += 1;
@@ -99,7 +96,7 @@ async function watchStock(goods_models, applestore_region) {
}
logStr += `${storeStock["name"]} - ${storeStock["msg"]}\n`;
}
-
+
// 售罄
else {
subObj["soldout"] += 1;
@@ -118,14 +115,14 @@ async function watchStock(goods_models, applestore_region) {
content = stockInContent;
}
// 配置为无货通知且存在无货情况时
- if (magicJS.read("applestore_settings_notify_soldout") == true) {
+ if ($.data.read("applestore_settings_notify_soldout") == true) {
content = !!stockInContent ? stockInContent + `\n${soldOutContent}\n${unchangContent}` : !!soldOutContent ? `${soldOutContent}\n${unchangContent}` : unchangContent;
}
if (!!content) {
let subTitle = `监控: ${subObj.watch} 售罄: ${subObj.soldout} 有货: ${subObj.pickup} ${watchResult}`;
- magicJS.notify(title, subTitle, content, "applestore://");
+ $.notification.post(title, subTitle, content, "applestore://");
}
- magicJS.logInfo(logStr);
+ $.logger.info(logStr);
}
}
tasks.push(wrap());
@@ -133,17 +130,17 @@ async function watchStock(goods_models, applestore_region) {
await Promise.all(tasks);
// 存储本次库存检查结果
- magicJS.write(APPLESTORE_STOCK_KEY, stock);
+ $.data.write(APPLESTORE_STOCK_KEY, stock);
}
(async () => {
- let goods_model = magicJS.read(APPLESTORE_MODEL_KEY).trim();
- let applestore_region = magicJS.read(APPLESTORE_REGION_KEY).trim();
+ let goods_model = $.data.read(APPLESTORE_MODEL_KEY).trim();
+ let applestore_region = $.data.read(APPLESTORE_REGION_KEY).trim();
if (!goods_model || !applestore_region) {
let msg = "请先在BoxJS中配置心仪的商品型号及购买地区";
- magicJS.logWarning(msg);
- magicJS.notify(msg);
+ $.logger.warning(msg);
+ $.notification.post(msg);
return;
}
@@ -152,16 +149,37 @@ async function watchStock(goods_models, applestore_region) {
// 监控库存
await watchStock(goods_models, applestore_region);
- while (magicJS.isNode) {
- let hours = new Date().getHours()
- if (hours <= 1 || hours >= 6){
- await watchStock(goods_models, applestore_region);
+ // NodeJS环境只运行一次或无限监控库存
+ if ($.env.isNode) {
+ let interval = Number($.data.read(APPLESTORE_WATCH_INTERVAL, 5000));
+ interval = interval <= 2000? 5000: interval;
+ const runForever = $.data.read(APPLESTORE_RUN_FOREVER_KEY, false);
+ while (runForever === true) {
+ let hours = new Date().getHours()
+ if (hours <= 1 || hours >= 6) {
+ await watchStock(goods_models, applestore_region);
+ }
+ await $.utils.sleep(interval);
}
- await magicJS.sleep(5000);
}
- magicJS.done();
+ $.done();
})();
-// prettier-ignore
-function MagicJS(scriptName="MagicJS",logLevel="INFO"){return new class{constructor(){if(this._startTime=Date.now(),this.version="2.2.3.6",this.scriptName=scriptName,this.logLevels={DEBUG:5,INFO:4,NOTIFY:3,WARNING:2,ERROR:1,CRITICAL:0,NONE:-1},this.isLoon="undefined"!=typeof $loon,this.isQuanX="undefined"!=typeof $task,this.isJSBox="undefined"!=typeof $drive,this.isNode="undefined"!=typeof module&&!this.isJSBox,this.isSurge="undefined"!=typeof $httpClient&&!this.isLoon,this.node={request:void 0,fs:void 0,data:{}},this.iOSUserAgent="Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.5 Mobile/15E148 Safari/604.1",this.pcUserAgent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36 Edg/84.0.522.59",this._logLevel="INFO",this.logLevel=logLevel,this._barkUrl="",this._barkKey="",this.isNode){this.node.fs=require("fs"),this.node.request=require("request");try{this.node.fs.accessSync("./magic.json",this.node.fs.constants.R_OK|this.node.fs.constants.W_OK)}catch(err){this.node.fs.writeFileSync("./magic.json","{}",{encoding:"utf8"})}this.node.data=require("./magic.json")}else this.isJSBox&&($file.exists("drive://MagicJS")||$file.mkdir("drive://MagicJS"),$file.exists("drive://MagicJS/magic.json")||$file.write({data:$data({string:"{}"}),path:"drive://MagicJS/magic.json"}))}set barkUrl(url){try{let _url=url.replace(/\/+$/g,"");this._barkUrl=`${/^https?:\/\/([^/]*)/.exec(_url)[0]}/push`,this._barkKey=/\/([^\/]+)\/?$/.exec(_url)[1]}catch(err){this.logDebug("Bark config error.")}}set logLevel(level){let magic_loglevel=this.read("magicjs_loglevel");this._logLevel=magic_loglevel||level.toUpperCase()}get logLevel(){return this._logLevel}get isRequest(){return"undefined"!=typeof $request&&"undefined"==typeof $response}get isResponse(){return"undefined"!=typeof $response}get isDebug(){return"DEBUG"===this.logLevel}get request(){return"undefined"!=typeof $request?$request:void 0}get response(){return"undefined"!=typeof $response?($response.hasOwnProperty("status")&&($response.statusCode=$response.status),$response.hasOwnProperty("statusCode")&&($response.status=$response.statusCode),$response):void 0}get platform(){return this.isSurge?"Surge":this.isQuanX?"Quantumult X":this.isLoon?"Loon":this.isJSBox?"JSBox":this.isNode?"Node.js":"Unknown"}read(key,session=""){let val="";this.isSurge||this.isLoon?val=$persistentStore.read(key):this.isQuanX?val=$prefs.valueForKey(key):this.isNode?val=this.node.data:this.isJSBox&&(val=$file.read("drive://MagicJS/magic.json").string);try{this.isNode&&(val=val[key]),this.isJSBox&&(val=JSON.parse(val)[key]),session&&("string"==typeof val&&(val=JSON.parse(val)),val=val&&"object"==typeof val?val[session]:null)}catch(err){this.logError(err),val=session?{}:null,this.del(key)}void 0===val&&(val=null);try{val&&"string"==typeof val&&(val=JSON.parse(val))}catch(err){}return this.logDebug(`READ DATA [${key}]${session?`[${session}]`:""}(${typeof val})\n${JSON.stringify(val)}`),val}write(key,val,session=""){let data=session?{}:"";if(session&&(this.isSurge||this.isLoon)?data=$persistentStore.read(key):session&&this.isQuanX?data=$prefs.valueForKey(key):this.isNode?data=this.node.data:this.isJSBox&&(data=JSON.parse($file.read("drive://MagicJS/magic.json").string)),session){try{"string"==typeof data&&(data=JSON.parse(data)),data="object"==typeof data&&data?data:{}}catch(err){this.logError(err),this.del(key),data={}}this.isJSBox||this.isNode?(data[key]&&"object"==typeof data[key]||(data[key]={}),data[key].hasOwnProperty(session)||(data[key][session]=null),void 0===val?delete data[key][session]:data[key][session]=val):void 0===val?delete data[session]:data[session]=val}else this.isNode||this.isJSBox?void 0===val?delete data[key]:data[key]=val:data=void 0===val?null:val;"object"==typeof data&&(data=JSON.stringify(data)),this.isSurge||this.isLoon?$persistentStore.write(data,key):this.isQuanX?$prefs.setValueForKey(data,key):this.isNode?this.node.fs.writeFileSync("./magic.json",data):this.isJSBox&&$file.write({data:$data({string:data}),path:"drive://MagicJS/magic.json"}),this.logDebug(`WRITE DATA [${key}]${session?`[${session}]`:""}(${typeof val})\n${JSON.stringify(val)}`)}del(key,session=""){this.logDebug(`DELETE KEY [${key}]${session?`[${session}]`:""}`),this.write(key,null,session)}notify(title=this.scriptName,subTitle="",body="",opts=""){let convertOptions;if(opts=(_opts=>{let newOpts={};if("string"==typeof _opts)this.isLoon?newOpts={openUrl:_opts}:this.isQuanX?newOpts={"open-url":_opts}:this.isSurge&&(newOpts={url:_opts});else if("object"==typeof _opts)if(this.isLoon)newOpts.openUrl=_opts["open-url"]?_opts["open-url"]:"",newOpts.mediaUrl=_opts["media-url"]?_opts["media-url"]:"";else if(this.isQuanX)newOpts=_opts["open-url"]||_opts["media-url"]?_opts:{};else if(this.isSurge){let openUrl=_opts["open-url"]||_opts.openUrl;newOpts=openUrl?{url:openUrl}:{}}return newOpts})(opts),1==arguments.length&&(title=this.scriptName,subTitle="",body=arguments[0]),this.logNotify(`title:${title}\nsubTitle:${subTitle}\nbody:${body}\noptions:${"object"==typeof opts?JSON.stringify(opts):opts}`),this.isSurge)$notification.post(title,subTitle,body,opts);else if(this.isLoon)opts?$notification.post(title,subTitle,body,opts):$notification.post(title,subTitle,body);else if(this.isQuanX)$notify(title,subTitle,body,opts);else if(this.isJSBox){let push={title:title,body:subTitle?`${subTitle}\n${body}`:body};$push.schedule(push)}this._barkUrl&&this._barkKey&&this.notifyBark(title,subTitle,body)}notifyDebug(title=this.scriptName,subTitle="",body="",opts=""){"DEBUG"===this.logLevel&&(1==arguments.length&&(title=this.scriptName,subTitle="",body=arguments[0]),this.notify(title,subTitle,body,opts))}notifyBark(title=this.scriptName,subTitle="",body="",opts=""){let options={url:this._barkUrl,headers:{"Content-Type":"application/json; charset=utf-8"},body:{title:title,body:subTitle?`${subTitle}\n${body}`:body,device_key:this._barkKey}};this.post(options,err=>{})}log(msg,level="INFO"){this.logLevels[this._logLevel]void 0===_options.body?"":`${encodeURIComponent(key)}=${encodeURIComponent(_options.body[key])}`).join("&");_options.url.indexOf("?")<0&&(_options.url+="?"),_options.url.lastIndexOf("&")+1!=_options.url.length&&_options.url.lastIndexOf("?")+1!=_options.url.length&&(_options.url+="&"),_options.url+=qs,delete _options.body}return this.isQuanX?(_options.hasOwnProperty("body")&&"string"!=typeof _options.body&&(_options.body=JSON.stringify(_options.body)),_options.method=method):this.isNode?(delete _options.headers["Accept-Encoding"],"object"==typeof _options.body&&("GET"===method?(_options.qs=_options.body,delete _options.body):"POST"===method&&(_options.json=!0,_options.body=_options.body))):this.isJSBox&&(_options.header=_options.headers,delete _options.headers),_options}adapterHttpResponse(resp){let _resp={body:resp.body,headers:resp.headers,json:()=>JSON.parse(_resp.body)};return resp.hasOwnProperty("statusCode")&&resp.statusCode&&(_resp.status=resp.statusCode),_resp}get(options,callback){let _options=this.adapterHttpOptions(options,"GET");this.logDebug(`HTTP GET: ${JSON.stringify(_options)}`),this.isSurge||this.isLoon?$httpClient.get(_options,callback):this.isQuanX?$task.fetch(_options).then(resp=>{resp.status=resp.statusCode,callback(null,resp,resp.body)},reason=>callback(reason.error,null,null)):this.isNode?this.node.request.get(_options,(err,resp,data)=>{resp=this.adapterHttpResponse(resp),callback(err,resp,data)}):this.isJSBox&&(_options.handler=resp=>{let err=resp.error?JSON.stringify(resp.error):void 0,data="object"==typeof resp.data?JSON.stringify(resp.data):resp.data;callback(err,resp.response,data)},$http.get(_options))}getPromise(options){return new Promise((resolve,reject)=>{magicJS.get(options,(err,resp)=>{err?reject(err):resolve(resp)})})}post(options,callback){let _options=this.adapterHttpOptions(options,"POST");if(this.logDebug(`HTTP POST: ${JSON.stringify(_options)}`),this.isSurge||this.isLoon)$httpClient.post(_options,callback);else if(this.isQuanX)$task.fetch(_options).then(resp=>{resp.status=resp.statusCode,callback(null,resp,resp.body)},reason=>{callback(reason.error,null,null)});else if(this.isNode){let resp=this.node.request.post(_options,callback);resp.status=resp.statusCode,delete resp.statusCode}else this.isJSBox&&(_options.handler=resp=>{let err=resp.error?JSON.stringify(resp.error):void 0,data="object"==typeof resp.data?JSON.stringify(resp.data):resp.data;callback(err,resp.response,data)},$http.post(_options,{}))}done(value={}){this._endTime=Date.now();let span=(this._endTime-this._startTime)/1e3;magicJS.logDebug(`SCRIPT COMPLETED: ${span}S.`),"undefined"!=typeof $done&&$done(value)}isToday(day){if(null==day)return!1;{let today=new Date;return"string"==typeof day&&(day=new Date(day)),today.getFullYear()==day.getFullYear()&&today.getMonth()==day.getMonth()&&today.getDay()==day.getDay()}}isNumber(val){return"NaN"!==parseFloat(val).toString()}attempt(promise,defaultValue=null){return promise.then(args=>[null,args]).catch(ex=>(this.logError(ex),[ex,defaultValue]))}retry(fn,retries=5,interval=0,callback=null){return(...args)=>new Promise((resolve,reject)=>{function _retry(...args){Promise.resolve().then(()=>fn.apply(this,args)).then(result=>{"function"==typeof callback?Promise.resolve().then(()=>callback(result)).then(()=>{resolve(result)}).catch(ex=>{retries>=1?interval>0?setTimeout(()=>_retry.apply(this,args),interval):_retry.apply(this,args):reject(ex),retries--}):resolve(result)}).catch(ex=>{this.logRetry(ex),retries>=1&&interval>0?setTimeout(()=>_retry.apply(this,args),interval):retries>=1?_retry.apply(this,args):reject(ex),retries--})}_retry.apply(this,args)})}formatTime(time,fmt="yyyy-MM-dd hh:mm:ss"){var o={"M+":time.getMonth()+1,"d+":time.getDate(),"h+":time.getHours(),"m+":time.getMinutes(),"s+":time.getSeconds(),"q+":Math.floor((time.getMonth()+3)/3),S:time.getMilliseconds()};/(y+)/.test(fmt)&&(fmt=fmt.replace(RegExp.$1,(time.getFullYear()+"").substr(4-RegExp.$1.length)));for(let k in o)new RegExp("("+k+")").test(fmt)&&(fmt=fmt.replace(RegExp.$1,1==RegExp.$1.length?o[k]:("00"+o[k]).substr((""+o[k]).length)));return fmt}now(){return this.formatTime(new Date,"yyyy-MM-dd hh:mm:ss")}today(){return this.formatTime(new Date,"yyyy-MM-dd")}sleep(time){return new Promise(resolve=>setTimeout(resolve,time))}}(scriptName)}
+
+/**
+ *
+ * $$\ $$\ $$\ $$$$$\ $$$$$$\ $$$$$$\
+ * $$$\ $$$ | \__| \__$$ |$$ __$$\ $$ ___$$\
+ * $$$$\ $$$$ | $$$$$$\ $$$$$$\ $$\ $$$$$$$\ $$ |$$ / \__| \_/ $$ |
+ * $$\$$\$$ $$ | \____$$\ $$ __$$\ $$ |$$ _____| $$ |\$$$$$$\ $$$$$ /
+ * $$ \$$$ $$ | $$$$$$$ |$$ / $$ |$$ |$$ / $$\ $$ | \____$$\ \___$$\
+ * $$ |\$ /$$ |$$ __$$ |$$ | $$ |$$ |$$ | $$ | $$ |$$\ $$ | $$\ $$ |
+ * $$ | \_/ $$ |\$$$$$$$ |\$$$$$$$ |$$ |\$$$$$$$\\$$$$$$ |\$$$$$$ | \$$$$$$ |
+ * \__| \__| \_______| \____$$ |\__| \_______|\______/ \______/ \______/
+ * $$\ $$ |
+ * \$$$$$$ |
+ * \______/
+ *
+*/
+function MagicJS(e="MagicJS",t="INFO"){const r=()=>{const e=typeof $loon!=="undefined";const t=typeof $task!=="undefined";const n=typeof module!=="undefined";const r=typeof $httpClient!=="undefined"&&!e;const s=typeof $storm!=="undefined";const i=typeof $environment!=="undefined"&&typeof $environment["stash-build"]!=="undefined";const o=r||e||s||i;const l=typeof importModule!=="undefined";return{isLoon:e,isQuanX:t,isNode:n,isSurge:r,isStorm:s,isStash:i,isSurgeLike:o,isScriptable:l,get name(){if(e){return"Loon"}else if(t){return"QuantumultX"}else if(n){return"NodeJS"}else if(r){return"Surge"}else if(l){return"Scriptable"}else{return"unknown"}},get build(){if(r){return $environment["surge-build"]}else if(i){return $environment["stash-build"]}else if(s){return $storm.buildVersion}},get language(){if(r||i){return $environment["language"]}},get version(){if(r){return $environment["surge-version"]}else if(i){return $environment["stash-version"]}else if(s){return $storm.appVersion}else if(n){return process.version}},get system(){if(r){return $environment["system"]}else if(n){return process.platform}},get systemVersion(){if(s){return $storm.systemVersion}},get deviceName(){if(s){return $storm.deviceName}}}};const s=(n,e="INFO")=>{let r=e;const s={SNIFFER:6,DEBUG:5,INFO:4,NOTIFY:3,WARNING:2,ERROR:1,CRITICAL:0,NONE:-1};const i={SNIFFER:"",DEBUG:"",INFO:"",NOTIFY:"",WARNING:"❗ ",ERROR:"❌ ",CRITICAL:"❌ ",NONE:""};const t=(e,t="INFO")=>{if(!(s[r]{r=e};return{setLevel:o,sniffer:e=>{t(e,"SNIFFER")},debug:e=>{t(e,"DEBUG")},info:e=>{t(e,"INFO")},notify:e=>{t(e,"NOTIFY")},warning:e=>{t(e,"WARNING")},error:e=>{t(e,"ERROR")},retry:e=>{t(e,"RETRY")}}};return new class{constructor(e,t){this._startTime=Date.now();this.version="3.0.0";this.scriptName=e;this.env=r();this.logger=s(e,t);this.http=typeof MagicHttp==="function"?MagicHttp(this.env,this.logger):undefined;this.data=typeof MagicData==="function"?MagicData(this.env,this.logger):undefined;this.notification=typeof MagicNotification==="function"?MagicNotification(this.scriptName,this.env,this.logger,this.http):undefined;this.utils=typeof MagicUtils==="function"?MagicUtils(this.env,this.logger):undefined;this.qinglong=typeof MagicQingLong==="function"?MagicQingLong(this.env,this.data,this.logger):undefined;if(typeof this.data!=="undefined"){let e=this.data.read("magic_loglevel");const n=this.data.read("magic_bark_url");if(e){this.logger.setLevel(e.toUpperCase())}if(n){this.notification.setBark(n)}}}get isRequest(){return typeof $request!=="undefined"&&typeof $response==="undefined"}get isResponse(){return typeof $response!=="undefined"}get isDebug(){return this.logger.level==="DEBUG"}get request(){return typeof $request!=="undefined"?$request:undefined}get response(){if(typeof $response!=="undefined"){if($response.hasOwnProperty("status"))$response["statusCode"]=$response["status"];if($response.hasOwnProperty("statusCode"))$response["status"]=$response["statusCode"];return $response}else{return undefined}}done=(e={})=>{this._endTime=Date.now();let t=(this._endTime-this._startTime)/1e3;this.logger.info(`SCRIPT COMPLETED: ${t} S.`);if(typeof $done!=="undefined"){$done(e)}}}(e,t)}function MagicHttp(u,f){const t="Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.5 Mobile/15E148 Safari/604.1";const n="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36 Edg/84.0.522.59";let c;if(u.isNode){const l=require("axios");c=l.create()}class e{constructor(e=true){this.handlers=[];this.isRequest=e}use(e,t,n){this.handlers.push({fulfilled:e,rejected:t,synchronous:n?n.synchronous:false,runWhen:n?n.runWhen:null});return this.handlers.length-1}eject(e){if(this.handlers[e]){this.handlers[e]=null}}forEach(t){this.handlers.forEach(e=>{if(e!==null){t(e)}})}}function r(e){let n={...e};if(!!n.params){if(!u.isNode){let e=Object.keys(n.params).map(e=>{const t=encodeURIComponent(e);n.url=n.url.replace(new RegExp(`${e}=[^&]*`,"ig"),"");n.url=n.url.replace(new RegExp(`${t}=[^&]*`,"ig"),"");return`${t}=${encodeURIComponent(n.params[e])}`}).join("&");if(n.url.indexOf("?")<0)n.url+="?";if(!/(&|\?)$/g.test(n.url)){n.url+="&"}n.url+=e;delete n.params;f.debug(`Params to QueryString: ${n.url}`)}}return n}const d=(e,t)=>{let n=typeof t==="object"?{headers:{},...t}:{url:t,headers:{}};if(!n.method){n["method"]=e}n=r(n);if(n["rewrite"]===true){if(u.isSurge){n.headers["X-Surge-Skip-Scripting"]=false;delete n["rewrite"]}else if(u.isQuanX){n["hints"]=false;delete n["rewrite"]}}if(u.isSurge){if(n["method"]!=="GET"&&n.headers["Content-Type"].indexOf("application/json")>=0&&n.body instanceof Array){n.body=JSON.stringify(n.body);f.debug(`Convert Array object to String: ${n.body}`)}}else if(u.isQuanX){if(n.hasOwnProperty("body")&&typeof n["body"]!=="string")n["body"]=JSON.stringify(n["body"]);n["method"]=e}else if(u.isNode){if(e==="POST"||e==="PUT"||e==="PATCH"||e==="DELETE"){n.data=n.data||n.body}else if(e==="GET"){n.params=n.params||n.body}delete n.body}return n};const p=(t,n=null)=>{if(t){let e={...t,config:t.config||n,status:t.statusCode||t.status,body:t.body||t.data,headers:t.headers||t.header};if(typeof e.body==="string"){try{e.body=JSON.parse(e.body)}catch{}}delete t.data;return e}else{return t}};const s=r=>{if(!!r){delete r["Content-Length"];let e=new Set(["Accept","Accept-CH","Accept-Charset","Accept-Features","Accept-Encoding","Accept-Language","Accept-Ranges","Access-Control-Allow-Credentials","Access-Control-Allow-Origin","Access-Control-Allow-Methods","Access-Control-Allow-Headers","Access-Control-Max-Age","Access-Control-Expose-Headers","Access-Control-Request-Method","Access-Control-Request-Headers","Age","Allow","Alternates","Authorization","Cache-Control","Connection","Content-Encoding","Content-Language","ontent-Length","Content-Location","Content-Range","Content-Security-Policy","Content-Type","Cookie","DNT","Date","ETag","Expect","Expires","From","Host","If-Match","If-Modified-Since","If-None-Match","If-Range","If-Unmodified-Since","Last-Event-ID","Last-Modified","Link","Location","Max-Forwards","Negotiate","Origin","Pragma","Proxy-Authenticate","Proxy-Authorization","Range","Referer","Retry-After","Sec-Websocket-Extensions","Sec-Websocket-Key","Sec-Websocket-Origin","Sec-Websocket-Protocol","Sec-Websocket-Version","Server","Set-Cookie","Set-Cookie2","Strict-Transport-Security","TCN","TE","Trailer","Transfer-Encoding","Upgrade","User-Agent","Variant-Vary","Vary","Via","Warning","WWW-Authenticate","X-Content-Duration","X-Content-Security-Policy","X-DNSPrefetch-Control","X-Frame-Options","X-Requested-With"]);for(let n of Object.keys(r)){if(!e.has(n)){for(let t of e){let e=n.replace(new RegExp(t,"ig"),t);if(n!==e){r[e]=r[n];delete r[n];break}}}}if(!r["User-Agent"]){if(u.isNode){r["User-Agent"]=n}else{r["User-Agent"]=t}}return r}return r};const g=(t,n=null)=>{if(!!t&&t.status>=400){f.debug(`Raise exception when status code is ${t.status}`);let e={name:"RequestException",message:`Request failed with status code ${t.status}`,config:n||t.config,response:t};return e}};const i={request:new e,response:new e(false)};let y=[];let h=[];let m=true;function $(e){if(typeof e==="object"&&e["modify"]!==false){e["headers"]=s(e["headers"])}e=r(e);return e}function S(e){try{e=!!e?p(e):e;f.sniffer(`HTTP ${e.config["method"].toUpperCase()}:\n${JSON.stringify(e.config)}\nSTATUS CODE:\n${e.status}\nRESPONSE:\n${typeof e.body==="object"?JSON.stringify(e.body):e.body}`);const t=g(e);if(!!t){return Promise.reject(t)}return e}catch(t){f.error(t);return e}}const b=t=>{try{y=[];h=[];i.request.forEach(e=>{if(typeof e.runWhen==="function"&&e.runWhen(t)===false){return}m=m&&e.synchronous;y.unshift(e.fulfilled,e.rejected)});i.response.forEach(e=>{h.push(e.fulfilled,e.rejected)})}catch(e){f.error(`failed to register interceptors: ${e}`)}};const o=(e,r)=>{let s;const t=e.toUpperCase();r=d(t,r);if(u.isNode){s=c}else{if(u.isSurgeLike){s=i=>{return new Promise((r,s)=>{$httpClient[e.toLowerCase()](i,(t,n,e)=>{if(t){let e={name:t.name||t,message:t.message||t,stack:t.stack||t,config:i,response:p(n)};s(e)}else{n.config=i;n.body=e;r(n)}})})}}else{s=s=>{return new Promise((n,r)=>{$task.fetch(s).then(e=>{e=p(e,s);const t=g(e,s);if(t){return Promise.reject(t)}n(e)}).catch(e=>{let t={name:e.message||e.error,message:e.message||e.error,stack:e.error,config:s,response:!!e.response?p(e.response):null};r(t)})})}}}let i;b(r);const o=[$,undefined];const l=[S,undefined];if(!m){f.debug("Interceptors are executed in asynchronous mode");let n=[s,undefined];Array.prototype.unshift.apply(n,o);Array.prototype.unshift.apply(n,y);Array.prototype.unshift.apply(n,o);n=n.concat(l);n=n.concat(h);i=Promise.resolve(r);while(n.length){try{let e=n.shift();let t=n.shift();if(!u.isNode&&r["timeout"]&&e===s){i=a(r)}else{i=i.then(e,t)}}catch(e){f.error(`request exception: ${e}`)}}return i}else{f.debug("Interceptors are executed in synchronous mode");Array.prototype.unshift.apply(y,o);y=y.concat([$,undefined]);while(y.length){let e=y.shift();let t=y.shift();try{r=e(r)}catch(e){t(e);break}}try{if(!u.isNode&&r["timeout"]){i=a(r)}else{i=s(r)}}catch(e){return Promise.reject(e)}Array.prototype.unshift.apply(h,l);while(h.length){i=i.then(h.shift(),h.shift())}return i}function a(n){try{const e=new Promise((e,t)=>{setTimeout(()=>{let e={message:`timeout of ${n["timeout"]}ms exceeded`,config:n};t(e)},n["timeout"])});return Promise.race([s(n),e])}catch(e){f.error(`Request Timeout exception: ${e}`)}}};return{request:o,interceptors:i,modifyHeaders:s,modifyResponse:p,get:e=>{return o("GET",e)},post:e=>{return o("POST",e)},put:e=>{return o("PUT",e)},patch:e=>{return o("PATCH",e)},delete:e=>{return o("DELETE",e)},head:e=>{return o("HEAD",e)},options:e=>{return o("OPTIONS",e)}}}function MagicNotification(i,o,l,a){let u=null;let f=null;const e=t=>{try{let e=t.replace(/\/+$/g,"");u=`${/^https?:\/\/([^/]*)/.exec(e)[0]}/push`;f=/\/([^\/]+)\/?$/.exec(e)[1]}catch(e){l.error(`Bark url error: ${e}.`)}};function t(e=i,t="",n="",r=""){const s=n=>{try{let t={};if(typeof n==="string"){if(o.isLoon)t={openUrl:n};else if(o.isQuanX)t={"open-url":n};else if(o.isSurge)t={url:n}}else if(typeof n==="object"){if(o.isLoon){t["openUrl"]=!!n["open-url"]?n["open-url"]:"";t["mediaUrl"]=!!n["media-url"]?n["media-url"]:""}else if(o.isQuanX){t=!!n["open-url"]||!!n["media-url"]?n:{}}else if(o.isSurge){let e=n["open-url"]||n["openUrl"];t=e?{url:e}:{}}}return t}catch(e){l.error(`Failed to convert notification option, ${e}`)}return n};r=s(r);if(arguments.length==1){e=i;t="",n=arguments[0]}l.notify(`title:${e}\nsubTitle:${t}\nbody:${n}\noptions:${typeof r==="object"?JSON.stringify(r):r}`);if(o.isSurge){$notification.post(e,t,n,r)}else if(o.isLoon){if(!!r)$notification.post(e,t,n,r);else $notification.post(e,t,n)}else if(o.isQuanX){$notify(e,t,n,r)}if(u&&f){c(e,t,n)}}function n(e=i,t="",n="",r=""){if(l.level==="DEBUG"){if(arguments.length==1){e=i;t="",n=arguments[0]}this.notify(e,t,n,r)}}function c(e=i,t="",n="",r=""){if(typeof a==="undefined"||typeof a.post==="undefined"){throw"Bark notification needs to import MagicHttp module."}let s={url:u,headers:{"Content-Type":"application/json; charset=utf-8"},body:{title:e,body:t?`${t}\n${n}`:n,device_key:f}};a.post(s).catch(e=>{l.error(`Bark notify error: ${e}`)})}return{post:t,debug:n,bark:c,setBark:e}}function MagicData(o,l){let a={fs:undefined,data:{}};if(o.isNode){a.fs=require("fs");try{a.fs.accessSync("./magic.json",a.fs.constants.R_OK|a.fs.constants.W_OK)}catch(e){a.fs.writeFileSync("./magic.json","{}",{encoding:"utf8"})}a.data=require("./magic.json")}const u=(e,t)=>{if(typeof t==="object"){return false}else{return e===t}};const f=e=>{if(e==="true"){return true}else if(e==="false"){return false}else if(typeof e==="undefined"){return null}else{return e}};const c=(e,t,n,r)=>{if(n){try{if(typeof e==="string")e=JSON.parse(e);if(e["magic_session"]===true){e=e[n]}else{e=null}}catch{e=null}}if(typeof e==="string"&&e!=="null"){try{e=JSON.parse(e)}catch{}}if(r===false&&!!e&&e["magic_session"]===true){e=null}if((e===null||typeof e==="undefined")&&t!==null&&typeof t!=="undefined"){e=t}e=f(e);return e};const i=t=>{if(typeof t==="string"){let e={};try{e=JSON.parse(t);const n=typeof e;if(n!=="object"||e instanceof Array||n==="bool"||e===null){e={}}}catch{}return e}else if(t instanceof Array||t===null||typeof t==="undefined"||t!==t||typeof t==="boolean"){return{}}else{return t}};const d=(e,t=null,n="",r=false,s=null)=>{let i=s||a.data;if(!!i&&typeof i[e]!=="undefined"&&i[e]!==null){val=i[e]}else{val=!!n?{}:null}val=c(val,t,n,r);return val};const p=(e,t=null,n="",r=false,s=null)=>{let i="";if(s||o.isNode){i=d(e,t,n,r,s)}else{if(o.isSurgeLike){i=$persistentStore.read(e)}else if(o.isQuanX){i=$prefs.valueForKey(e)}i=c(i,t,n,r)}l.debug(`READ DATA [${e}]${!!n?`[${n}]`:""} <${typeof i}>\n${JSON.stringify(i)}`);return i};const g=(t,n,r="",e=null)=>{let s=e||a.data;s=i(s);if(!!r){let e=i(s[t]);e["magic_session"]=true;e[r]=n;s[t]=e}else{s[t]=n}if(e!==null){e=s}return s};const y=(e,t,n="",r=null)=>{if(typeof t==="undefined"||t!==t){return false}if(!o.isNode&&(typeof t==="boolean"||typeof t==="number")){t=String(t)}let s="";if(r||o.isNode){s=g(e,t,n,r)}else{if(!n){s=t}else{if(o.isSurgeLike){s=!!$persistentStore.read(e)?$persistentStore.read(e):s}else if(o.isQuanX){s=!!$prefs.valueForKey(e)?$prefs.valueForKey(e):s}s=i(s);s["magic_session"]=true;s[n]=t}}if(!!s&&typeof s==="object"){s=JSON.stringify(s,"","\t")}l.debug(`WRITE DATA [${e}]${n?`[${n}]`:""} <${typeof t}>\n${JSON.stringify(t)}`);if(!r){if(o.isSurgeLike){return $persistentStore.write(s,e)}else if(o.isQuanX){return $prefs.setValueForKey(s,e)}else if(o.isNode){try{a.fs.writeFileSync("./magic.json",s);return true}catch(e){l.error(e);return false}}}return true};const e=(t,n,r,s=u,i=null)=>{n=f(n);const e=p(t,null,r,false,i);if(s(e,n)===true){return false}else{const o=y(t,n,r,i);let e=p(t,null,r,false,i);if(s===u&&typeof e==="object"){return o}return s(n,e)}};const h=(e,t,n)=>{let r=n||a.data;r=i(r);if(!!t){obj=i(r[e]);delete obj[t];r[e]=obj}else{delete r[e]}if(!!n){n=r}return r};const t=(e,t="",n=null)=>{let r={};if(n||o.isNode){r=h(e,t,n);if(!n){a.fs.writeFileSync("./magic.json",JSON.stringify(r))}else{n=r}}else{if(!t){if(o.isStorm){return $persistentStore.remove(e)}else if(o.isSurgeLike){return $persistentStore.write(null,e)}else if(o.isQuanX){return $prefs.removeValueForKey(e)}}else{if(o.isSurgeLike){r=$persistentStore.read(e)}else if(o.isQuanX){r=$prefs.valueForKey(e)}r=i(r);delete r[t];const s=JSON.stringify(r);y(e,s)}}l.debug(`DELETE KEY [${e}]${!!t?`[${t}]`:""}`)};const n=(e,t=null)=>{let n=[];let r=p(e,null,null,true,t);r=i(r);if(r["magic_session"]!==true){n=[]}else{n=Object.keys(r).filter(e=>e!=="magic_session")}l.debug(`READ ALL SESSIONS [${e}] <${typeof n}>\n${JSON.stringify(n)}`);return n};return{read:p,write:y,del:t,update:e,allSessions:n,defaultValueComparator:u,convertToObject:i}}function MagicUtils(r,u){const e=(i,o=5,l=0,a=null)=>{return(...e)=>{return new Promise((n,r)=>{function s(...t){Promise.resolve().then(()=>i.apply(this,t)).then(e=>{if(typeof a==="function"){Promise.resolve().then(()=>a(e)).then(()=>{n(e)}).catch(e=>{if(o>=1){if(l>0)setTimeout(()=>s.apply(this,t),l);else s.apply(this,t)}else{r(e)}o--})}else{n(e)}}).catch(e=>{u.error(e);if(o>=1&&l>0){setTimeout(()=>s.apply(this,t),l)}else if(o>=1){s.apply(this,t)}else{r(e)}o--})}s.apply(this,e)})}};const t=(e,t="yyyy-MM-dd hh:mm:ss")=>{let n={"M+":e.getMonth()+1,"d+":e.getDate(),"h+":e.getHours(),"m+":e.getMinutes(),"s+":e.getSeconds(),"q+":Math.floor((e.getMonth()+3)/3),S:e.getMilliseconds()};if(/(y+)/.test(t))t=t.replace(RegExp.$1,(e.getFullYear()+"").substr(4-RegExp.$1.length));for(let e in n)if(new RegExp("("+e+")").test(t))t=t.replace(RegExp.$1,RegExp.$1.length==1?n[e]:("00"+n[e]).substr((""+n[e]).length));return t};const n=()=>{return t(new Date,"yyyy-MM-dd hh:mm:ss")};const s=()=>{return t(new Date,"yyyy-MM-dd")};const i=t=>{return new Promise(e=>setTimeout(e,t))};const o=(e,t=null)=>{if(r.isNode){const n=require("assert");if(t)n(e,t);else n(e)}else{if(e!==true){let e=`AssertionError: ${t||"The expression evaluated to a falsy value"}`;u.error(e)}}};return{retry:e,formatTime:t,now:n,today:s,sleep:i,assert:o}}
\ No newline at end of file
diff --git a/script/applestore/applestore.lnplugin b/script/applestore/applestore.lnplugin
new file mode 100644
index 000000000..9be2a1699
--- /dev/null
+++ b/script/applestore/applestore.lnplugin
@@ -0,0 +1,10 @@
+#!name= AppleStore
+#!desc= AppleStore线下库存监控
+#!openUrl= https://github.com/blackmatrix7/ios_rule_script/tree/master/script/applestore
+#!author= blackmatrix7
+#!homepage= https://github.com/blackmatrix7/ios_rule_script
+#!icon= https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/script/applestore/icon/applestore.png
+
+[Script]
+cron "0/5 * 6-23 * * *" script-path=https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/script/applestore/applestore.js,timeout=5,tag=AppleStore_查询商品库存
+
diff --git a/script/applestore/applestore.lnscript b/script/applestore/applestore.lnscript
deleted file mode 100644
index 1e8b80280..000000000
--- a/script/applestore/applestore.lnscript
+++ /dev/null
@@ -1 +0,0 @@
-cron "0/5 * 6-23 * * *" script-path=https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/script/applestore/applestore.js,timeout=5,tag=AppleStore_查询商品库存
\ No newline at end of file
diff --git a/script/applestore/images/01.png b/script/applestore/images/01.png
new file mode 100644
index 0000000000000000000000000000000000000000..32654d4087df772ad7ecaf02b9859af761ac02e3
GIT binary patch
literal 21429
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