├── .gitignore
├── AppPriceMonitor.js
├── Bilibili.js
├── BilibiliMonitor.js
├── Checkin.js
├── Config.js
├── Dler Cloud.js
├── DoubanMonitor.js
├── Env.js
├── Install Scripts.js
├── NASA.js
├── NASAwDetail.js
├── README.md
├── README_EN.md
├── RRShare.js
├── RRShareMonitor.js
├── RSS.js
├── RSSMonitor.js
├── Weibo.js
├── WeiboMonitor.js
├── Zhihu.js
├── ZhihuMonitor.js
├── checkin_example.json
├── crypto-js.js
├── picture
├── apppricemonitor.jpeg
├── config.gif
├── config.mp4
├── hotlistmonitor.jpeg
└── nasaandmonitor.jpeg
└── 北京尾号限行.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .Trash
2 | desktop.ini
3 | GideonSenku
4 | sbsdata
5 | 机场流量.js
6 | flow.js
7 | 10010.js
8 | 10086.js
9 | recordcheckintime.txt
10 | checkin.json
11 | Config.js
12 | gist.js
13 | Env/Env-sun
14 | weather.js
15 | weather-cal.js
16 | TrasnparentForcastWidget.js
17 | Env/Env-location
18 | 2YaInstall.js
19 | AppWatcher.js
20 | BiliBili(1).js
21 | ChinaUnicom.js
22 | ChinaTelecom.js
23 | ChinaMobile.js
24 | Calendar.js
25 | Birthday.js
26 | BiliBiliWatch.js
27 | BiliBiliUp.js
28 | Contact.js
29 | COVID-19.js
30 | HistoryToday.js
31 | DmYY.js
32 | Health.js
33 | JDDou.js
34 | JDDouK.js
35 | JDWuLiu.js
36 | PoisonCalendar.js
37 | Telegram.js
38 | TodayOilPrice.js
39 | VPNBoard.js
40 | VPNBoardPress.js
41 | VPNSubscription.js
42 | VPNV2Board.js
43 | weatherCache/lastread
44 | settings-json/covid-19.json
45 | widget.Install
46 | widget.Install.js
47 | YouTube.js
48 | ZXTrains.js
49 | CountDownCalendar.js
50 | crypto-js.js
51 | PoisonCalendarText.js
52 | *.json
53 | crypto-js.js
54 | Config.js
55 |
--------------------------------------------------------------------------------
/AppPriceMonitor.js:
--------------------------------------------------------------------------------
1 | // Variables used by Scriptable.
2 | // These must be at the very top of the file. Do not edit.
3 | // icon-color: deep-blue; icon-glyph: mobile-alt;
4 | /*
5 | * Author: evilbutcher 修改自t.me/QuanXApp群友分享
6 | * Github: https://github.com/evilbutcher
7 | * 本脚本使用了@Gideon_Senku的Env,Peng-YM的OpenAPI!感谢!
8 | * 感谢@MuTu88帮忙测试!
9 | */
10 | const goupdate = false; //自动更新,默认关闭。需要时打开。
11 | const $http = HTTP();
12 | const G = importModule("Env");
13 | let apps = [
14 | "1443988620|hk",
15 | "1312014438 cn",
16 | "499470113/vn",
17 | "1314212521-jp",
18 | "1282297037_au",
19 | "932747118:ie",
20 | "1116905928",
21 | "1373567447",
22 | ]; //app跟踪id
23 | let reg = "cn"; //默认区域:美国us 中国cn 香港hk
24 | let notifys = [];
25 | try {
26 | const con = importModule("Config");
27 | apps = con.apps();
28 | reg = con.reg();
29 | if (apps == [] || reg == "") {
30 | log("配置文件内签到信息不完整");
31 | throw new Error(err);
32 | }
33 | log("将使用配置文件内App监控信息");
34 | } catch (err) {
35 | log("将使用脚本内App监控信息");
36 | if (apps == "" || reg == "") {
37 | $.msg("请检查脚本内填入的App监控信息是否完整");
38 | }
39 | }
40 |
41 | const isDark = Device.isUsingDarkAppearance();
42 | const bgColor = new LinearGradient();
43 | bgColor.colors = isDark
44 | ? [new Color("#030079"), new Color("#000000")]
45 | : [new Color("#a18cd1"), new Color("#fbc2eb")];
46 | bgColor.locations = [0.0, 1.0];
47 | const scripts = [
48 | {
49 | moduleName: "AppPriceMonitor",
50 | url:
51 | "https://raw.githubusercontent.com/evilbutcher/Scriptables/master/AppPriceMonitor.js",
52 | },
53 | ];
54 |
55 | !(async () => {
56 | await format_apps(apps);
57 | log(notifys);
58 | let widget = createWidget(notifys);
59 | Script.setWidget(widget);
60 | Script.complete();
61 | })()
62 | .catch((err) => {
63 | G.msg("App价格版本监控 运行出现错误❌\n" + err);
64 | })
65 | .finally(update());
66 |
67 | function createWidget(notifys) {
68 | const w = new ListWidget();
69 | w.backgroundGradient = bgColor;
70 | w.addSpacer();
71 | w.spacing = 5;
72 |
73 | addTitleTextToListWidget("App价格版本监控", w);
74 | for (var i = 0; i < notifys.length; i++) {
75 | addTextToListWidget(notifys[i], w);
76 | }
77 |
78 | w.addSpacer();
79 | w.spacing = 5;
80 | w.presentLarge();
81 | return w;
82 | }
83 |
84 | function addTextToListWidget(text, listWidget) {
85 | let item = listWidget.addText(text);
86 | item.textColor = isDark ? Color.white() : Color.black();
87 | item.font = new Font('SF Mono', 12);
88 | }
89 |
90 | function addTitleTextToListWidget(text, listWidget) {
91 | let item = listWidget.addText(text);
92 | item.textColor = isDark ? Color.white() : Color.black();
93 | try {
94 | item.applyHeadlineTextStyling();
95 | } catch(e) {
96 | item.font = new Font('SF Mono', 18);
97 | }
98 | }
99 |
100 | async function format_apps(x) {
101 | let apps_f = {};
102 | x.forEach((n) => {
103 | if (/^[a-zA-Z0-9:/|\-_\s]{1,}$/.test(n)) {
104 | n = n.replace(/[/|\-_\s]/g, ":");
105 | let n_n = n.split(":");
106 | if (n_n.length === 1) {
107 | if (apps_f.hasOwnProperty(reg)) {
108 | apps_f[reg].push(n_n);
109 | } else {
110 | apps_f[reg] = [];
111 | apps_f[reg].push(n_n[0]);
112 | }
113 | } else if (n_n.length === 2) {
114 | if (apps_f.hasOwnProperty(n_n[1])) {
115 | apps_f[n_n[1]].push(n_n[0]);
116 | } else {
117 | apps_f[n_n[1]] = [];
118 | apps_f[n_n[1]].push(n_n[0]);
119 | }
120 | } else {
121 | notifys.push(`ID格式错误:【${n}】`);
122 | }
123 | } else {
124 | notifys.push(`ID格式错误:【${n}】`);
125 | }
126 | });
127 | if (Object.keys(apps_f).length > 0) {
128 | await post_data(apps_f);
129 | }
130 | }
131 |
132 | async function post_data(d) {
133 | try {
134 | var app_monitor = {};
135 | let infos = {};
136 | await Promise.all(
137 | Object.keys(d).map(async (k) => {
138 | let config = {
139 | url: "https://itunes.apple.com/lookup?id=" + d[k] + "&country=" + k,
140 | };
141 | await $http
142 | .get(config)
143 | .then((response) => {
144 | let results = JSON.parse(response.body).results;
145 | if (Array.isArray(results) && results.length > 0) {
146 | results.forEach((x) => {
147 | infos[x.trackId] = {
148 | n: x.trackName,
149 | v: x.version,
150 | p: x.formattedPrice,
151 | };
152 | if (app_monitor.hasOwnProperty(x.trackId)) {
153 | if (
154 | JSON.stringify(app_monitor[x.trackId]) !==
155 | JSON.stringify(infos[x.trackId])
156 | ) {
157 | if (x.version !== app_monitor[x.trackId].v) {
158 | notifys.push(
159 | `${flag(k)}🧩${x.trackName}:升级【${x.version}】`
160 | );
161 | }
162 | if (x.formattedPrice !== app_monitor[x.trackId].p) {
163 | notifys.push(
164 | `${flag(k)}💰${x.trackName}:价格【${x.formattedPrice}】`
165 | );
166 | }
167 | }
168 | } else {
169 | notifys.push(`${flag(k)} ${x.trackName}`);
170 | notifys.push(
171 | `🧩版本【${x.version}】/💰价格【${x.formattedPrice}】`
172 | );
173 | }
174 | });
175 | }
176 | return Promise.resolve();
177 | })
178 | .catch((e) => {
179 | console.log(e);
180 | });
181 | })
182 | );
183 | return notifys;
184 | } catch (e) {
185 | console.log(e);
186 | }
187 | }
188 |
189 | function flag(x) {
190 | var flags = new Map([
191 | ["AC", "🇦🇨"],
192 | ["AF", "🇦🇫"],
193 | ["AI", "🇦🇮"],
194 | ["AL", "🇦🇱"],
195 | ["AM", "🇦🇲"],
196 | ["AQ", "🇦🇶"],
197 | ["AR", "🇦🇷"],
198 | ["AS", "🇦🇸"],
199 | ["AT", "🇦🇹"],
200 | ["AU", "🇦🇺"],
201 | ["AW", "🇦🇼"],
202 | ["AX", "🇦🇽"],
203 | ["AZ", "🇦🇿"],
204 | ["BB", "🇧🇧"],
205 | ["BD", "🇧🇩"],
206 | ["BE", "🇧🇪"],
207 | ["BF", "🇧🇫"],
208 | ["BG", "🇧🇬"],
209 | ["BH", "🇧🇭"],
210 | ["BI", "🇧🇮"],
211 | ["BJ", "🇧🇯"],
212 | ["BM", "🇧🇲"],
213 | ["BN", "🇧🇳"],
214 | ["BO", "🇧🇴"],
215 | ["BR", "🇧🇷"],
216 | ["BS", "🇧🇸"],
217 | ["BT", "🇧🇹"],
218 | ["BV", "🇧🇻"],
219 | ["BW", "🇧🇼"],
220 | ["BY", "🇧🇾"],
221 | ["BZ", "🇧🇿"],
222 | ["CA", "🇨🇦"],
223 | ["CF", "🇨🇫"],
224 | ["CH", "🇨🇭"],
225 | ["CK", "🇨🇰"],
226 | ["CL", "🇨🇱"],
227 | ["CM", "🇨🇲"],
228 | ["CN", "🇨🇳"],
229 | ["CO", "🇨🇴"],
230 | ["CP", "🇨🇵"],
231 | ["CR", "🇨🇷"],
232 | ["CU", "🇨🇺"],
233 | ["CV", "🇨🇻"],
234 | ["CW", "🇨🇼"],
235 | ["CX", "🇨🇽"],
236 | ["CY", "🇨🇾"],
237 | ["CZ", "🇨🇿"],
238 | ["DE", "🇩🇪"],
239 | ["DG", "🇩🇬"],
240 | ["DJ", "🇩🇯"],
241 | ["DK", "🇩🇰"],
242 | ["DM", "🇩🇲"],
243 | ["DO", "🇩🇴"],
244 | ["DZ", "🇩🇿"],
245 | ["EA", "🇪🇦"],
246 | ["EC", "🇪🇨"],
247 | ["EE", "🇪🇪"],
248 | ["EG", "🇪🇬"],
249 | ["EH", "🇪🇭"],
250 | ["ER", "🇪🇷"],
251 | ["ES", "🇪🇸"],
252 | ["ET", "🇪🇹"],
253 | ["EU", "🇪🇺"],
254 | ["FI", "🇫🇮"],
255 | ["FJ", "🇫🇯"],
256 | ["FK", "🇫🇰"],
257 | ["FM", "🇫🇲"],
258 | ["FO", "🇫🇴"],
259 | ["FR", "🇫🇷"],
260 | ["GA", "🇬🇦"],
261 | ["GB", "🇬🇧"],
262 | ["HK", "🇭🇰"],
263 | ["ID", "🇮🇩"],
264 | ["IE", "🇮🇪"],
265 | ["IL", "🇮🇱"],
266 | ["IM", "🇮🇲"],
267 | ["IN", "🇮🇳"],
268 | ["IS", "🇮🇸"],
269 | ["IT", "🇮🇹"],
270 | ["JP", "🇯🇵"],
271 | ["KR", "🇰🇷"],
272 | ["MO", "🇲🇴"],
273 | ["MX", "🇲🇽"],
274 | ["MY", "🇲🇾"],
275 | ["NL", "🇳🇱"],
276 | ["PH", "🇵🇭"],
277 | ["RO", "🇷🇴"],
278 | ["RS", "🇷🇸"],
279 | ["RU", "🇷🇺"],
280 | ["RW", "🇷🇼"],
281 | ["SA", "🇸🇦"],
282 | ["SB", "🇸🇧"],
283 | ["SC", "🇸🇨"],
284 | ["SD", "🇸🇩"],
285 | ["SE", "🇸🇪"],
286 | ["SG", "🇸🇬"],
287 | ["TH", "🇹🇭"],
288 | ["TN", "🇹🇳"],
289 | ["TO", "🇹🇴"],
290 | ["TR", "🇹🇷"],
291 | ["TV", "🇹🇻"],
292 | ["TW", "🇨🇳"],
293 | ["UK", "🇬🇧"],
294 | ["UM", "🇺🇲"],
295 | ["US", "🇺🇸"],
296 | ["UY", "🇺🇾"],
297 | ["UZ", "🇺🇿"],
298 | ["VA", "🇻🇦"],
299 | ["VE", "🇻🇪"],
300 | ["VG", "🇻🇬"],
301 | ["VI", "🇻🇮"],
302 | ["VN", "🇻🇳"],
303 | ]);
304 | return flags.get(x.toUpperCase());
305 | }
306 |
307 | //From Peng-YM's OpenAPI.js
308 | function ENV() {
309 | const e = "undefined" != typeof $task,
310 | t = "undefined" != typeof $loon,
311 | s = "undefined" != typeof $httpClient && !this.isLoon,
312 | o = "function" == typeof require && "undefined" != typeof $jsbox;
313 | return {
314 | isQX: e,
315 | isLoon: t,
316 | isSurge: s,
317 | isNode: "function" == typeof require && !o,
318 | isJSBox: o,
319 | isRequest: "undefined" != typeof $request,
320 | isScriptable: "undefined" != typeof importModule,
321 | };
322 | }
323 | function HTTP(e, t = {}) {
324 | const { isQX: s, isLoon: o, isSurge: i, isScriptable: n, isNode: r } = ENV();
325 | const u = {};
326 | return (
327 | ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"].forEach(
328 | (h) =>
329 | (u[h.toLowerCase()] = (u) =>
330 | (function (u, h) {
331 | (h = "string" == typeof h ? { url: h } : h).url = e
332 | ? e + h.url
333 | : h.url;
334 | const c = (h = { ...t, ...h }).timeout,
335 | l = {
336 | onRequest: () => {},
337 | onResponse: (e) => e,
338 | onTimeout: () => {},
339 | ...h.events,
340 | };
341 | let d, a;
342 | if ((l.onRequest(u, h), s)) d = $task.fetch({ method: u, ...h });
343 | else if (o || i || r)
344 | d = new Promise((e, t) => {
345 | (r ? require("request") : $httpClient)[u.toLowerCase()](
346 | h,
347 | (s, o, i) => {
348 | s
349 | ? t(s)
350 | : e({
351 | statusCode: o.status || o.statusCode,
352 | headers: o.headers,
353 | body: i,
354 | });
355 | }
356 | );
357 | });
358 | else if (n) {
359 | const e = new Request(h.url);
360 | (e.method = u),
361 | (e.headers = h.headers),
362 | (e.body = h.body),
363 | (d = new Promise((t, s) => {
364 | e.loadString()
365 | .then((s) => {
366 | t({
367 | statusCode: e.response.statusCode,
368 | headers: e.response.headers,
369 | body: s,
370 | });
371 | })
372 | .catch((e) => s(e));
373 | }));
374 | }
375 | const f = c
376 | ? new Promise((e, t) => {
377 | a = setTimeout(
378 | () => (
379 | l.onTimeout(),
380 | t(`${u} URL: ${h.url} exceeds the timeout ${c} ms`)
381 | ),
382 | c
383 | );
384 | })
385 | : null;
386 | return (f
387 | ? Promise.race([f, d]).then((e) => (clearTimeout(a), e))
388 | : d
389 | ).then((e) => l.onResponse(e));
390 | })(h, u))
391 | ),
392 | u
393 | );
394 | }
395 |
396 | function update() {
397 | if (goupdate == true) {
398 | log("🔔更新脚本开始!");
399 | scripts.forEach(async (script) => {
400 | await G.getFile(script);
401 | });
402 | log("🔔更新脚本结束!");
403 | }
404 | }
405 |
--------------------------------------------------------------------------------
/Bilibili.js:
--------------------------------------------------------------------------------
1 | // Variables used by Scriptable.
2 | // These must be at the very top of the file. Do not edit.
3 | // icon-color: pink; icon-glyph: heartbeat;
4 | /*
5 | * Author: evilbutcher
6 | * Github: https://github.com/evilbutcher
7 | * 本脚本使用了@Gideon_Senku的Env.scriptable,感谢!
8 | */
9 | const goupdate = true;
10 | const $ = importModule("Env");
11 | var rid = 0; //rid对应不同的B站榜单:0全站,1动画,3音乐,4游戏,5娱乐,36科技,119鬼畜,129舞蹈。
12 | var num = 6; //自定义显示数量
13 | var rancolor = true; //true为开启随机颜色
14 |
15 | try {
16 | var { bilibili, blnum, blrancolor } = importModule("Config");
17 | rid = bilibili();
18 | num = blnum();
19 | rancolor = blrancolor();
20 | console.log("将使用配置文件内B站配置");
21 | } catch (e) {
22 | console.log("将使用脚本内B站配置");
23 | }
24 |
25 | const res = await getinfo();
26 |
27 | let widget = createWidget(res);
28 | Script.setWidget(widget);
29 | Script.complete();
30 |
31 | function createWidget(res) {
32 | var group = res.data;
33 | items = [];
34 | for (var i = 0; i < num; i++) {
35 | var item = group[i].title;
36 | items.push(item);
37 | }
38 | console.log(items);
39 |
40 | const w = new ListWidget();
41 | const bgColor = new LinearGradient();
42 | bgColor.colors = [new Color("#1c1c1c"), new Color("#29323c")];
43 | bgColor.locations = [0.0, 1.0];
44 | w.backgroundGradient = bgColor;
45 | w.addSpacer();
46 | w.spacing = 5;
47 |
48 | const firstLine = w.addText(`💗B站榜单`);
49 | firstLine.font = new Font('SF Mono', 15);
50 | firstLine.textColor = Color.white();
51 | firstLine.textOpacity = 0.7;
52 |
53 | for (var i = 0; i < items.length; i++) {
54 | addTextToListWidget(`• ${items[i]}`, w);
55 | }
56 |
57 | w.addSpacer();
58 | w.spacing = 5;
59 | w.presentSmall();
60 | return w;
61 | }
62 |
63 | async function getinfo() {
64 | const blRequest = {
65 | url: `https://app.bilibili.com/x/v2/rank/region?rid=${rid}`,
66 | };
67 | const res = await $.get(blRequest);
68 | log(res);
69 | return res;
70 | }
71 |
72 | function addTextToListWidget(text, listWidget) {
73 | let item = listWidget.addText(text);
74 | if (rancolor == true) {
75 | item.textColor = new Color(color16());
76 | } else {
77 | item.textColor = Color.white();
78 | }
79 | item.font = new Font('SF Mono', 12);
80 | }
81 |
82 | function color16() {
83 | var r = Math.floor(Math.random() * 256);
84 | if (r + 50 < 255) {
85 | r = r + 50;
86 | }
87 | if (r > 230 && r < 255) {
88 | r = r - 50;
89 | }
90 | var g = Math.floor(Math.random() * 256);
91 | if (g + 50 < 255) {
92 | g = g + 50;
93 | }
94 | if (g > 230 && g < 255) {
95 | g = g - 50;
96 | }
97 | var b = Math.floor(Math.random() * 256);
98 | if (b + 50 < 255) {
99 | b = b + 50;
100 | }
101 | if (b > 230 && b < 255) {
102 | b = b - 50;
103 | }
104 | var color = "#" + r.toString(16) + g.toString(16) + b.toString(16);
105 | return color;
106 | }
107 |
108 | //更新代码
109 | function update() {
110 | log("🔔更新脚本开始!");
111 | scripts.forEach(async (script) => {
112 | await $.getFile(script);
113 | });
114 | log("🔔更新脚本结束!");
115 | }
116 |
117 | const scripts = [
118 | {
119 | moduleName: "Bilibili",
120 | url:
121 | "https://raw.githubusercontent.com/evilbutcher/Scriptables/master/Bilibili.js",
122 | },
123 | ];
124 | if (goupdate == true) update();
--------------------------------------------------------------------------------
/BilibiliMonitor.js:
--------------------------------------------------------------------------------
1 | // Variables used by Scriptable.
2 | // These must be at the very top of the file. Do not edit.
3 | // icon-color: pink; icon-glyph: heartbeat;
4 | /*
5 | * Author: evilbutcher
6 | * Github: https://github.com/evilbutcher
7 | * 本脚本使用了@Gideon_Senku的Env.scriptable,感谢!
8 | */
9 | const goupdate = true;
10 | const $ = importModule("Env");
11 | var rid = 0; //rid对应不同的B站榜单:0全站,1动画,3音乐,4游戏,5娱乐,36科技,119鬼畜,129舞蹈。
12 | const title = `💗 B站榜单`;
13 | const preview = "medium";
14 | const goto = 'app'; // 可更改为 browser,跳转到浏览器,选择跳转 app 时若未安装 app,则会无响应
15 | const spacing = 5;
16 |
17 | try {
18 | var { bilibili } = importModule("Config");
19 | rid = bilibili();
20 | console.log("将使用配置文件内B站配置");
21 | } catch (e) {
22 | console.log("将使用脚本内B站配置");
23 | }
24 |
25 | const res = await getinfo();
26 |
27 | let widget = await createWidget(res);
28 | Script.setWidget(widget);
29 | Script.complete();
30 |
31 | function decideGoto(item) {
32 | switch(goto) {
33 | case 'app':
34 | return item.uri;
35 | case 'browser':
36 | return `https://bilibili.com/${item.goto}${item.param}`;
37 | default:
38 | return void 0;
39 | }
40 | }
41 |
42 | async function createWidget(res) {
43 | var group = res.data;
44 | items = [];
45 | for (var i = 0; i < 6; i++) {
46 | var item = group[i].title;
47 | items.push(item);
48 | }
49 | console.log(items);
50 |
51 | const opts = {
52 | title,
53 | texts: {
54 | text1: { text: `• ${group[0].title}`, url: decideGoto(group[0]) },
55 | text2: { text: `• ${group[1].title}`, url: decideGoto(group[1]) },
56 | text3: { text: `• ${group[2].title}`, url: decideGoto(group[2]) },
57 | text4: { text: `• ${group[3].title}`, url: decideGoto(group[3]) },
58 | text5: { text: `• ${group[4].title}`, url: decideGoto(group[4]) },
59 | text6: { text: `• ${group[5].title}`, url: decideGoto(group[5]) },
60 | battery: "true",
61 | },
62 | preview,
63 | spacing,
64 | };
65 |
66 | let widget = await $.createWidget(opts);
67 | return widget;
68 | }
69 |
70 | async function getinfo() {
71 | const blRequest = {
72 | url: `https://app.bilibili.com/x/v2/rank/region?rid=${rid}`,
73 | };
74 | const res = await $.get(blRequest);
75 | log(res);
76 | return res;
77 | }
78 |
79 | //更新代码
80 | function update() {
81 | log("🔔更新脚本开始!");
82 | scripts.forEach(async (script) => {
83 | await $.getFile(script);
84 | });
85 | log("🔔更新脚本结束!");
86 | }
87 |
88 | const scripts = [
89 | {
90 | moduleName: "BilibiliMonitor",
91 | url:
92 | "https://raw.githubusercontent.com/evilbutcher/Scriptables/master/BilibiliMonitor.js",
93 | },
94 | ];
95 | if (goupdate == true) update();
96 |
--------------------------------------------------------------------------------
/Checkin.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: plane-departure;
4 | /*
5 | * Author: evilbutcher Neurogram
6 | * Github: https://github.com/evilbutcher
7 | * 本脚本使用了@Gideon_Senku的Env.scriptable,感谢!
8 | * 感谢@MuTu88帮忙测试!
9 | * 自动更新打开后会运行覆盖脚本内已有修改,多种解决方案:
10 | * 一、配置Config文件,请参考https://github.com/evilbutcher/Scriptables/blob/master/Config.js,下载后导入Scriptable,脚本运行会❗️优先❗️调取Config文件中信息,此方法只能显示❗️一个❗️机场。
11 | * 二、【推荐】Scriptable的iCloud文件夹内,配置checkin.json文件(注意文件名),具体格式参考https://github.com/evilbutcher/Scriptables/blob/master/checkin_example.json,可以通过创建桌面小组件时填入不同参数如“c1”、“c2”等实现读取多个机场信息。
12 | * 三、脚本内配置,在下方注释写有填写签到标题的引号内,填写对应的签到信息,注意,此方法一旦更新脚本,所做的更改就会被远程文件覆盖。
13 | * 脚本运行后,会在iCloud/Scriptable文件夹内写入一个recordcheckintime.txt,用于记录签到时间,脚本逻辑每天签到一次。
14 | */
15 | const goupdate = false; //默认关闭,需要时打开,更新后会覆盖脚本已有的签到信息,建议使用Config或Scriptable的iCloud文件夹存入checkin.json文件的方式
16 | const $ = importModule("Env");
17 | $.autoLogout = false; //退出登录后再签到
18 | try {
19 | const para = args.widgetParameter || "c1";
20 | const fileName = "checkin.json";
21 | const res = JSON.parse($.read(fileName));
22 | var checkintitle = res[para].title || ""; //填写签到标题
23 | var checkinloginurl = res[para].url || ""; //填写签到登陆链接
24 | var checkinemail = res[para].email || ""; //填写签到邮箱
25 | var checkinpwd = res[para].password || ""; //填写签到密码
26 | } catch (e) {
27 | log("获取JSON文件失败");
28 | }
29 | const size = 12; //字体大小
30 | const isDark = Device.isUsingDarkAppearance();
31 | const bgColor = new LinearGradient();
32 | bgColor.colors = isDark
33 | ? [new Color("#030079"), new Color("#000000")]
34 | : [new Color("#a18cd1"), new Color("#fbc2eb")];
35 | bgColor.locations = [0.0, 1.0];
36 | function addTextToListWidget(text, listWidget) {
37 | let item = listWidget.addText(text);
38 | item.textColor = isDark ? Color.white() : Color.black();
39 | item.font = new Font('SF Mono', size);
40 | }
41 | function addTitleTextToListWidget(text, listWidget) {
42 | let item = listWidget.addText(text);
43 | item.textColor = isDark ? Color.white() : Color.black();
44 | try {
45 | item.font = Font.boldSystemFont(18);
46 | } catch(e) {
47 | item.font = new Font('SF Mono', 18);
48 | }
49 | }
50 |
51 | const scripts = [
52 | {
53 | moduleName: "Checkin",
54 | url:
55 | "https://raw.githubusercontent.com/evilbutcher/Scriptables/master/Checkin.js",
56 | },
57 | ];
58 |
59 | !(async () => {
60 | init();
61 | getinfo();
62 | await launch();
63 | log($.checkintitle);
64 | log($.checkinMsg);
65 | log($.todayUsed);
66 | log($.usedData);
67 | log($.restData);
68 | let widget = createWidget(
69 | $.checkintitle,
70 | $.checkinMsg,
71 | $.todayUsed,
72 | $.usedData,
73 | $.restData
74 | );
75 | Script.setWidget(widget);
76 | Script.complete();
77 | })()
78 | .catch((err) => {
79 | $.msg("Checkin运行出现错误❌\n" + err);
80 | })
81 | .finally(update());
82 |
83 | function getinfo() {
84 | try {
85 | const con = importModule("Config");
86 | $.checkintitle = con.checkintitle();
87 | $.checkinloginurl = con.checkinloginurl();
88 | $.checkinemail = con.checkinemail();
89 | $.checkinpwd = con.checkinpwd();
90 | if (
91 | $.checkintitle == "" ||
92 | $.checkinloginurl == "" ||
93 | $.checkinemail == "" ||
94 | $.checkinpwd == ""
95 | ) {
96 | log("配置文件内签到信息不完整");
97 | throw new Error(err);
98 | }
99 | log("将使用配置文件内签到信息");
100 | } catch (err) {
101 | $.checkintitle = checkintitle;
102 | $.checkinloginurl = checkinloginurl;
103 | $.checkinemail = checkinemail;
104 | $.checkinpwd = checkinpwd;
105 | log("将使用脚本内签到信息");
106 | if (
107 | $.checkintitle == "" ||
108 | $.checkinloginurl == "" ||
109 | $.checkinemail == "" ||
110 | $.checkinpwd == ""
111 | ) {
112 | $.msg("请检查填入的签到信息是否完整");
113 | }
114 | }
115 | }
116 |
117 | function init() {
118 | $.nowtime = new Date().getTime();
119 | log($.nowtime);
120 | if ($.isFileExists("recordcheckintime.txt") == true) {
121 | var recordtime = $.read("recordcheckintime.txt");
122 | log(recordtime);
123 | if ($.nowtime - recordtime > 86400000) {
124 | $.cancheckin = true;
125 | $.write("recordcheckintime.txt", JSON.stringify($.nowtime));
126 | } else {
127 | $.cancheckin = false;
128 | }
129 | } else {
130 | $.write("recordcheckintime.txt", JSON.stringify($.nowtime));
131 | log("初始时间已写入");
132 | $.cancheckin = true;
133 | }
134 | }
135 |
136 | async function launch() {
137 | let title = $.checkintitle;
138 | let url = $.checkinloginurl;
139 | let email = $.checkinemail;
140 | let password = $.checkinpwd;
141 | if ($.autoLogout == true) {
142 | let logoutPath =
143 | url.indexOf("auth/login") != -1 ? "user/logout" : "user/logout.php";
144 | var logouturl = {
145 | url: url.replace(/(auth|user)\/login(.php)*/g, "") + logoutPath,
146 | };
147 | log(logouturl);
148 | await $.getStr(logouturl);
149 | await login(url, email, password, title);
150 | if ($.loginok == true) {
151 | if ($.cancheckin == true) {
152 | await checkin(url, email, password, title);
153 | if ($.checkinok == true) {
154 | await dataResults(url, $.checkindatamsg, title);
155 | }
156 | } else {
157 | await dataResults(url, "签到完成🎉", title);
158 | }
159 | }
160 | } else {
161 | if ($.cancheckin == true) {
162 | await checkin(url, email, password, title);
163 | if ($.checkinok == true) {
164 | await dataResults(url, $.checkindatamsg, title);
165 | } else {
166 | await login(url, email, password, title);
167 | if ($.loginok == true) {
168 | await checkin(url, email, password, title);
169 | await dataResults(url, "签到完成🎉", title);
170 | }
171 | }
172 | } else {
173 | await dataResults(url, "签到完成🎉", title);
174 | if ($.getdata == false) {
175 | await login(url, email, password, title);
176 | if ($.loginok == true) {
177 | await dataResults(url, "签到完成🎉", title);
178 | }
179 | }
180 | }
181 | }
182 | }
183 |
184 | async function login(url, email, password, title) {
185 | let loginPath =
186 | url.indexOf("auth/login") != -1 ? "auth/login" : "user/_login.php";
187 | let table = {
188 | url:
189 | url.replace(/(auth|user)\/login(.php)*/g, "") +
190 | loginPath +
191 | `?email=${email}&passwd=${password}&rumber-me=week`,
192 | };
193 | log(table);
194 | await $.post(table, async (response, data) => {
195 | if (
196 | JSON.parse(data).msg.match(
197 | /邮箱不存在|邮箱或者密码错误|Mail or password is incorrect/
198 | )
199 | ) {
200 | $.msg(title + "邮箱或者密码错误");
201 | $.loginok = false;
202 | log("登陆失败");
203 | } else {
204 | $.loginok = true;
205 | log("登陆成功");
206 | }
207 | });
208 | }
209 |
210 | async function checkin(url, email, password, title) {
211 | let checkinPath =
212 | url.indexOf("auth/login") != -1 ? "user/checkin" : "user/_checkin.php";
213 | var checkinreqest = {
214 | url: url.replace(/(auth|user)\/login(.php)*/g, "") + checkinPath,
215 | };
216 | log(checkinreqest);
217 | await $.post(checkinreqest, async (response, data) => {
218 | if (data.match(/\"msg\"\:/)) {
219 | $.checkinok = true;
220 | $.checkindatamsg = JSON.parse(data).msg;
221 | log("签到成功");
222 | } else {
223 | $.checkinok = false;
224 | log("签到失败");
225 | }
226 | });
227 | }
228 |
229 | async function dataResults(url, checkinMsg, title) {
230 | let userPath = url.indexOf("auth/login") != -1 ? "user" : "user/index.php";
231 | var datarequest = {
232 | url: url.replace(/(auth|user)\/login(.php)*/g, "") + userPath,
233 | };
234 | log(datarequest);
235 | await $.getStr(datarequest, async (response, data) => {
236 | if (data.match(/login|请填写邮箱|登陆/)) {
237 | $.getdata = false;
238 | } else {
239 | let resultData = "";
240 | let result = [];
241 | if (data.match(/theme\/malio/)) {
242 | let flowInfo = data.match(/trafficDountChat\s*\(([^\)]+)/);
243 | if (flowInfo) {
244 | let flowData = flowInfo[1].match(/\d[^\']+/g);
245 | let usedData = flowData[0];
246 | let todatUsed = flowData[1];
247 | let restData = flowData[2];
248 | $.todayUsed = `今日已用:${flowData[1]}`;
249 | $.usedData = `累计使用:${flowData[0]}`;
250 | $.restData = `剩余流量:${flowData[2]}`;
251 | result.push(
252 | `今日:${todatUsed}\n已用:${usedData}\n剩余:${restData}`
253 | );
254 | }
255 | let userInfo = data.match(/ChatraIntegration\s*=\s*({[^}]+)/);
256 | if (userInfo) {
257 | let user_name = userInfo[1].match(/name.+'(.+)'/)[1];
258 | let user_class = userInfo[1].match(/Class.+'(.+)'/)[1];
259 | let class_expire = userInfo[1].match(/Class_Expire.+'(.+)'/)[1];
260 | let money = userInfo[1].match(/Money.+'(.+)'/)[1];
261 | result.push(
262 | `用户名:${user_name}\n用户等级:lv${user_class}\n余额:${money}\n到期时间:${class_expire}`
263 | );
264 | }
265 | if (result.length != 0) {
266 | resultData = result.join("\n\n");
267 | }
268 | } else {
269 | let todayUsed = data.match(/>*\s*今日(已用|使用)*[^B]+/);
270 | if (todayUsed) {
271 | todayUsed = flowFormat(todayUsed[0]);
272 | result.push(`今日:${todayUsed}`);
273 | $.todayUsed = `今日已用:${todayUsed}`;
274 | } else {
275 | $.todayUsed = `今日已用获取失败`;
276 | result.push(`今日已用获取失败`);
277 | }
278 | let usedData = data.match(
279 | /(Used Transfer|>过去已用|>已用|>总已用|\"已用)[^B]+/
280 | );
281 | if (usedData) {
282 | usedData = flowFormat(usedData[0]);
283 | result.push(`已用:${usedData}`);
284 | $.usedData = `累计使用:${usedData}`;
285 | } else {
286 | $.usedData = `累计使用获取失败`;
287 | result.push(`累计使用获取失败`);
288 | }
289 | let restData = data.match(
290 | /(Remaining Transfer|>剩余流量|>流量剩余|>可用|\"剩余)[^B]+/
291 | );
292 | if (restData) {
293 | restData = flowFormat(restData[0]);
294 | result.push(`剩余:${restData}`);
295 | $.restData = `剩余流量:${restData}`;
296 | } else {
297 | $.restData = `剩余流量获取失败`;
298 | result.push(`剩余流量获取失败`);
299 | }
300 | resultData = result.join("\n");
301 | }
302 | $.checkinMsg = checkinMsg;
303 | log(title + "\n" + checkinMsg + "\n" + resultData);
304 | }
305 | });
306 | }
307 |
308 | function flowFormat(data) {
309 | data = data.replace(/\d+(\.\d+)*%/, "");
310 | let flow = data.match(/\d+(\.\d+)*\w*/);
311 | return flow[0] + "B";
312 | }
313 |
314 | function createWidget(checkintitle, checkinMsg, todayUsed, usedData, restData) {
315 | const w = new ListWidget();
316 | w.backgroundGradient = bgColor;
317 | w.addSpacer();
318 | w.spacing = 5;
319 |
320 | const emoji = w.addText(`🪐`);
321 | emoji.font = new Font('SF Mono', 30);
322 |
323 | addTitleTextToListWidget(checkintitle, w);
324 | addTextToListWidget(checkinMsg, w);
325 | addTextToListWidget(todayUsed, w);
326 | addTextToListWidget(usedData, w);
327 | addTextToListWidget(restData, w);
328 |
329 | w.addSpacer();
330 | w.spacing = 5;
331 | w.presentSmall();
332 | return w;
333 | }
334 |
335 | //更新代码
336 | function update() {
337 | if (goupdate == true) {
338 | log("🔔更新脚本开始!");
339 | scripts.forEach(async (script) => {
340 | await $.getFile(script);
341 | });
342 | log("🔔更新脚本结束!");
343 | }
344 | }
345 |
--------------------------------------------------------------------------------
/Config.js:
--------------------------------------------------------------------------------
1 | // Variables used by Scriptable.
2 | // These must be at the very top of the file. Do not edit.
3 | // icon-color: deep-blue; icon-glyph: plus;
4 | /*
5 | * Author: evilbutcher
6 | * Github: https://github.com/evilbutcher
7 | */
8 |
9 | module.exports = {
10 | bilibili: () => 0, //👈就改这个数字。B站榜单对应关系:0全站,1动画,3音乐,4游戏,5娱乐,36科技,119鬼畜,129舞蹈。
11 | blnum: () => 6, //自定义B站显示数量
12 | blrancolor: () => true, //是否开启B站随机颜色
13 | dbnum: () => 6, //自定义豆瓣显示数量
14 | dbrancolor: () => true, //是否开启豆瓣随机颜色
15 | rrnum: () => 6, //自定义人人影视显示数量
16 | rrrancolor: () => true, //是否开启人人影视随机颜色
17 | rsslink: () =>
18 | "https://github.com/GideonSenku/Scriptable/commits/master.atom", //👈就改引号里的链接。
19 | rssnum: () => 6, //自定义RSS显示数量
20 | rssrancolor: () => true, //是否开启RSS随机颜色
21 | wbnum: () => 6, //自定义微博显示数量
22 | wbrancolor: () => true, //是否开启微博随机颜色
23 | zhnum: () => 6, //自定义知乎显示数量
24 | zhrancolor: () => true, //是否开启知乎随机颜色
25 | nasaapi: () => "686BJ2YbpYYmyxvbk312vmj5EuMcOp8gaVTeVs0t", //填写NASA API Key
26 | imglink: () => "http://api.dujin.org/bing/1366.php", //NASA备用图片地址,可自定义
27 | imglink2: () => "https://source.unsplash.com/random", //NASA备用图片地址,可自定义
28 | checkintitle: () => "", //填写签到标题
29 | checkinloginurl: () => "", //填写签到登陆链接
30 | checkinemail: () => "", //填写签到邮箱
31 | checkinpwd: () => "", //填写签到密码
32 | apps: () => [
33 | "1443988620|hk",
34 | "1312014438 cn",
35 | "499470113/vn",
36 | "1314212521-jp",
37 | "1282297037_au",
38 | "932747118:ie",
39 | "1116905928",
40 | "1373567447",
41 | ], //app跟踪id
42 | reg: () => "cn", //默认区域:美国us 中国cn 香港hk
43 | lastnumberofcar: () => "3" //北京尾号限行脚本填写汽车尾号
44 | };
45 |
--------------------------------------------------------------------------------
/Dler Cloud.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: plane-departure;
4 | /*
5 | * Author: evilbutcher Neurogram
6 | * Github: https://github.com/evilbutcher
7 | * 本脚本使用了@Gideon_Senku的Env.scriptable,感谢!
8 | * 感谢@MuTu88帮忙测试!
9 | * 自动更新打开后会运行覆盖脚本内已有修改,多种解决方案:
10 | * 一、配置Config文件,请参考https://github.com/evilbutcher/Scriptables/blob/master/Config.js,下载后导入Scriptable,脚本运行会❗️优先❗️调取Config文件中信息,此方法只能显示❗️一个❗️机场。
11 | * 二、【推荐】Scriptable的iCloud文件夹内,配置checkin.json文件(注意文件名),具体格式参考https://github.com/evilbutcher/Scriptables/blob/master/checkin_example.json,可以通过创建桌面小组件时填入不同参数如“c1”、“c2”等实现读取多个机场信息。
12 | * 三、脚本内配置,在下方注释写有填写签到标题的引号内,填写对应的签到信息,注意,此方法一旦更新脚本,所做的更改就会被远程文件覆盖。
13 | * 脚本运行后,会在iCloud/Scriptable文件夹内写入一个recordcheckintime.txt,用于记录签到时间,脚本逻辑每天签到一次。
14 | */
15 | const goupdate = false; //默认关闭,需要时打开,更新后会覆盖脚本已有的签到信息,建议使用Config或Scriptable的iCloud文件夹存入checkin.json文件的方式
16 | const $ = importModule("Env");
17 | $.autoLogout = false; //退出登录后再签到
18 | try {
19 | const para = args.widgetParameter || "c1";
20 | const fileName = "checkin.json";
21 | const res = JSON.parse($.read(fileName));
22 | var checkintitle = res[para].title || ""; //填写签到标题
23 | var checkinloginurl = res[para].url || ""; //填写签到登陆链接
24 | var checkinemail = res[para].email || ""; //填写签到邮箱
25 | var checkinpwd = res[para].password || ""; //填写签到密码
26 | } catch (e) {
27 | log("获取JSON文件失败");
28 | }
29 | const size = 12; //字体大小
30 | const isDark = Device.isUsingDarkAppearance();
31 | const bgColor = new LinearGradient();
32 | bgColor.colors = isDark
33 | ? [new Color("#030079"), new Color("#000000")]
34 | : [new Color("#a18cd1"), new Color("#fbc2eb")];
35 | bgColor.locations = [0.0, 1.0];
36 | function addTextToListWidget(text, listWidget) {
37 | let item = listWidget.addText(text);
38 | item.textColor = isDark ? Color.white() : Color.black();
39 | item.font = new Font('SF Mono', size);
40 | }
41 | function addTitleTextToListWidget(text, listWidget) {
42 | let item = listWidget.addText(text);
43 | item.textColor = isDark ? Color.white() : Color.black();
44 | try {
45 | item.font = Font.boldSystemFont(18);
46 | } catch(e) {
47 | item.font = new Font('SF Mono', 18);
48 | }
49 | }
50 |
51 | const scripts = [
52 | {
53 | moduleName: "Checkin",
54 | url:
55 | "https://raw.githubusercontent.com/evilbutcher/Scriptables/master/Dler%20Cloud.js",
56 | },
57 | ];
58 |
59 | !(async () => {
60 | init();
61 | getinfo();
62 | await launch();
63 | log($.checkintitle);
64 | log($.checkinMsg);
65 | log($.todayUsed);
66 | log($.usedData);
67 | log($.restData);
68 | let widget = createWidget(
69 | $.checkintitle,
70 | $.checkinMsg,
71 | $.todayUsed,
72 | $.usedData,
73 | $.restData
74 | );
75 | Script.setWidget(widget);
76 | Script.complete();
77 | })()
78 | .catch((err) => {
79 | $.msg("Checkin运行出现错误❌\n" + err);
80 | })
81 | .finally(update());
82 |
83 | function getinfo() {
84 | try {
85 | const con = importModule("Config");
86 | $.checkintitle = con.checkintitle();
87 | $.checkinloginurl = con.checkinloginurl();
88 | $.checkinemail = con.checkinemail();
89 | $.checkinpwd = con.checkinpwd();
90 | if (
91 | $.checkintitle == "" ||
92 | $.checkinloginurl == "" ||
93 | $.checkinemail == "" ||
94 | $.checkinpwd == ""
95 | ) {
96 | log("配置文件内签到信息不完整");
97 | throw new Error(err);
98 | }
99 | log("将使用配置文件内签到信息");
100 | } catch (err) {
101 | $.checkintitle = checkintitle;
102 | $.checkinloginurl = checkinloginurl;
103 | $.checkinemail = checkinemail;
104 | $.checkinpwd = checkinpwd;
105 | log("将使用脚本内签到信息");
106 | if (
107 | $.checkintitle == "" ||
108 | $.checkinloginurl == "" ||
109 | $.checkinemail == "" ||
110 | $.checkinpwd == ""
111 | ) {
112 | $.msg("请检查填入的签到信息是否完整");
113 | }
114 | }
115 | }
116 |
117 | function init() {
118 | $.nowtime = new Date().getTime();
119 | log($.nowtime);
120 | if ($.isFileExists("recordcheckintime.txt") == true) {
121 | var recordtime = $.read("recordcheckintime.txt");
122 | log(recordtime);
123 | if ($.nowtime - recordtime > 86400000) {
124 | $.cancheckin = true;
125 | $.write("recordcheckintime.txt", JSON.stringify($.nowtime));
126 | } else {
127 | $.cancheckin = false;
128 | }
129 | } else {
130 | $.write("recordcheckintime.txt", JSON.stringify($.nowtime));
131 | log("初始时间已写入");
132 | $.cancheckin = true;
133 | }
134 | }
135 |
136 | async function launch() {
137 | let title = $.checkintitle;
138 | let url = $.checkinloginurl;
139 | let email = $.checkinemail;
140 | let password = $.checkinpwd;
141 | if ($.autoLogout == true) {
142 | let logoutPath =
143 | url.indexOf("auth/login") != -1 ? "user/logout" : "user/logout.php";
144 | var logouturl = {
145 | url: url.replace(/(auth|user)\/login(.php)*/g, "") + logoutPath,
146 | };
147 | log(logouturl);
148 | await $.getStr(logouturl);
149 | await login(url, email, password, title);
150 | if ($.loginok == true) {
151 | if ($.cancheckin == true) {
152 | await checkin(url, email, password, title);
153 | if ($.checkinok == true) {
154 | await dataResults(url, $.checkindatamsg, title);
155 | }
156 | } else {
157 | await dataResults(url, "签到完成🎉", title);
158 | }
159 | }
160 | } else {
161 | if ($.cancheckin == true) {
162 | await checkin(url, email, password, title);
163 | if ($.checkinok == true) {
164 | await dataResults(url, $.checkindatamsg, title);
165 | } else {
166 | await login(url, email, password, title);
167 | if ($.loginok == true) {
168 | await checkin(url, email, password, title);
169 | await dataResults(url, "签到完成🎉", title);
170 | }
171 | }
172 | } else {
173 | await dataResults(url, "签到完成🎉", title);
174 | if ($.getdata == false) {
175 | await login(url, email, password, title);
176 | if ($.loginok == true) {
177 | await dataResults(url, "签到完成🎉", title);
178 | }
179 | }
180 | }
181 | }
182 | }
183 |
184 | async function login(url, email, password, title) {
185 | let loginPath =
186 | url.indexOf("auth/login") != -1 ? "auth/login" : "user/_login.php";
187 | let table = {
188 | url:
189 | url.replace(/(auth|user)\/login(.php)*/g, "") +
190 | loginPath +
191 | `?email=${email}&passwd=${password}&rumber-me=week`,
192 | };
193 | log(table);
194 | await $.post(table, async (response, data) => {
195 | if (
196 | JSON.parse(data).msg.match(
197 | /邮箱不存在|邮箱或者密码错误|Mail or password is incorrect/
198 | )
199 | ) {
200 | $.msg(title + "邮箱或者密码错误");
201 | $.loginok = false;
202 | log("登陆失败");
203 | } else {
204 | $.loginok = true;
205 | log("登陆成功");
206 | }
207 | });
208 | }
209 |
210 | async function checkin(url, email, password, title) {
211 | let checkinPath =
212 | url.indexOf("auth/login") != -1 ? "user/checkin" : "user/_checkin.php";
213 | var checkinreqest = {
214 | url: url.replace(/(auth|user)\/login(.php)*/g, "") + checkinPath,
215 | };
216 | log(checkinreqest);
217 | await $.post(checkinreqest, async (response, data) => {
218 | if (data.match(/\"msg\"\:/)) {
219 | $.checkinok = true;
220 | $.checkindatamsg = JSON.parse(data).msg;
221 | log("签到成功");
222 | } else {
223 | $.checkinok = false;
224 | log("签到失败");
225 | }
226 | });
227 | }
228 |
229 | async function dataResults(url, checkinMsg, title) {
230 | let userPath = url.indexOf("auth/login") != -1 ? "user" : "user/index.php";
231 | var datarequest = {
232 | url: url.replace(/(auth|user)\/login(.php)*/g, "") + userPath,
233 | };
234 | log(datarequest);
235 | await $.getStr(datarequest, async (response, data) => {
236 | if (data.match(/login|请填写邮箱|登陆/)) {
237 | $.getdata = false;
238 | } else {
239 | let resultData = "";
240 | let result = [];
241 | if (data.match(/theme\/malio/)) {
242 | let flowInfo = data.match(/trafficDountChat\s*\(([^\)]+)/);
243 | if (flowInfo) {
244 | let flowData = flowInfo[1].match(/\d[^\']+/g);
245 | let usedData = flowData[0];
246 | let todatUsed = flowData[1];
247 | let restData = flowData[2];
248 | $.todayUsed = `今日已用:${flowData[1]}`;
249 | $.usedData = `本月已用:${flowData[0]}`;
250 | $.restData = `剩余流量:${flowData[2]}`;
251 | result.push(
252 | `今日:${todatUsed}\n已用:${usedData}\n剩余:${restData}`
253 | );
254 | }
255 | let userInfo = data.match(/ChatraIntegration\s*=\s*({[^}]+)/);
256 | if (userInfo) {
257 | let user_name = userInfo[1].match(/name.+'(.+)'/)[1];
258 | let user_class = userInfo[1].match(/Class.+'(.+)'/)[1];
259 | let class_expire = userInfo[1].match(/Class_Expire.+'(.+)'/)[1];
260 | let money = userInfo[1].match(/Money.+'(.+)'/)[1];
261 | result.push(
262 | `用户名:${user_name}\n用户等级:lv${user_class}\n余额:${money}\n到期时间:${class_expire}`
263 | );
264 | }
265 | if (result.length != 0) {
266 | resultData = result.join("\n\n");
267 | }
268 | } else {
269 | let todayUsed = data.match(/expire\"\,\s\".*?\"/);
270 | if (todayUsed) {
271 | var day = JSON.stringify(todayUsed).slice(14, -4);
272 | var time = day.replace(/-/g, "/");
273 | var expire = new Date(time).getTime();
274 | var left = ((expire - $.nowtime) / 86400000).toFixed(0);
275 | result.push(`剩余天数:${left}天`);
276 | $.todayUsed = `剩余天数:${left}天`;
277 | } else {
278 | $.todayUsed = `剩余天数获取失败`;
279 | result.push(`剩余天数获取失败`);
280 | }
281 | let usedData = data.match(
282 | /(Used Transfer|>过去已用|>已用|>总已用|\"已用)[^B]+/
283 | );
284 | if (usedData) {
285 | usedData = flowFormat(usedData[0]);
286 | result.push(`已用:${usedData}`);
287 | $.usedData = `本月已用:${usedData}`;
288 | } else {
289 | $.usedData = `本月已用获取失败`;
290 | result.push(`本月已用获取失败`);
291 | }
292 | let restData = data.match(
293 | /(Remaining Transfer|>剩余流量|>流量剩余|>可用|\"剩余)[^B]+/
294 | );
295 | if (restData) {
296 | restData = flowFormat(restData[0]);
297 | result.push(`剩余:${restData}`);
298 | $.restData = `剩余流量:${restData}`;
299 | } else {
300 | $.restData = `剩余流量获取失败`;
301 | result.push(`剩余流量获取失败`);
302 | }
303 | resultData = result.join("\n");
304 | }
305 | $.checkinMsg = checkinMsg;
306 | log(title + "\n" + checkinMsg + "\n" + resultData);
307 | }
308 | });
309 | }
310 |
311 | function flowFormat(data) {
312 | data = data.replace(/\d+(\.\d+)*%/, "");
313 | let flow = data.match(/\d+(\.\d+)*\w*/);
314 | return flow[0] + "B";
315 | }
316 |
317 | function createWidget(checkintitle, checkinMsg, todayUsed, usedData, restData) {
318 | const w = new ListWidget();
319 | w.backgroundGradient = bgColor;
320 | w.addSpacer();
321 | w.spacing = 5;
322 |
323 | const emoji = w.addText(`🪐`);
324 | emoji.font = new Font('SF Mono', 30);
325 |
326 | addTitleTextToListWidget(checkintitle, w);
327 | addTextToListWidget(checkinMsg, w);
328 | addTextToListWidget(todayUsed, w);
329 | addTextToListWidget(usedData, w);
330 | addTextToListWidget(restData, w);
331 |
332 | w.addSpacer();
333 | w.spacing = 5;
334 | w.presentSmall();
335 | return w;
336 | }
337 |
338 | //更新代码
339 | function update() {
340 | if (goupdate == true) {
341 | log("🔔更新脚本开始!");
342 | scripts.forEach(async (script) => {
343 | await $.getFile(script);
344 | });
345 | log("🔔更新脚本结束!");
346 | }
347 | }
348 |
--------------------------------------------------------------------------------
/DoubanMonitor.js:
--------------------------------------------------------------------------------
1 | // Variables used by Scriptable.
2 | // These must be at the very top of the file. Do not edit.
3 | // icon-color: green; icon-glyph: film;
4 | /*
5 | * Author: evilbutcher
6 | * Github: https://github.com/evilbutcher
7 | * 本脚本使用了@Gideon_Senku的Env.scriptable,感谢!
8 | */
9 | const goupdate = true;
10 | const $ = importModule("Env");
11 | const title = `🎞 豆瓣电影`;
12 | const preview = "medium";
13 | const spacing = 5;
14 | const goto = 'app'; // 可更改为 browser,跳转到浏览器,选择跳转 app 时若未安装 app,则会无响应
15 |
16 | const res = await getinfo();
17 |
18 | let widget = await createWidget(res);
19 | Script.setWidget(widget);
20 | Script.complete();
21 |
22 | function decideGoto(item) {
23 | switch(goto) {
24 | case 'app':
25 | return item.uri;
26 | case 'browser':
27 | return item.url;
28 | default:
29 | return void 0;
30 | }
31 | }
32 |
33 | async function createWidget(res) {
34 | var group = res["subject_collection_items"];
35 | items = [];
36 | for (var i = 0; i < 6; i++) {
37 | var gTitle = group[i].title;
38 | var rating = group[i].rating;
39 | if (rating == null) {
40 | var star = "暂无";
41 | } else {
42 | star = rating["star_count"];
43 | }
44 | var item = gTitle + " " + star + "✨";
45 | items.push(item);
46 | }
47 | console.log(items);
48 |
49 | const opts = {
50 | title,
51 | texts: {
52 | text1: { text: `• ${items[0]}`, url: decideGoto(group[0]) },
53 | text2: { text: `• ${items[1]}`, url: decideGoto(group[1]) },
54 | text3: { text: `• ${items[2]}`, url: decideGoto(group[2]) },
55 | text4: { text: `• ${items[3]}`, url: decideGoto(group[3]) },
56 | text5: { text: `• ${items[4]}`, url: decideGoto(group[4]) },
57 | text6: { text: `• ${items[5]}`, url: decideGoto(group[5]) },
58 | battery: "true",
59 | },
60 | preview,
61 | spacing,
62 | };
63 |
64 | let widget = await $.createWidget(opts);
65 | return widget;
66 | }
67 |
68 | async function getinfo() {
69 | const dbheader = {
70 | Referer: `https://m.douban.com/pwa/cache_worker`,
71 | };
72 | const dbRequest = {
73 | url:
74 | "https://m.douban.com/rexxar/api/v2/subject_collection/movie_real_time_hotest/items?start=0&count=50&items_only=1&for_mobile=1",
75 | headers: dbheader,
76 | };
77 | const res = await $.get(dbRequest);
78 | log(res);
79 | return res;
80 | }
81 |
82 | //更新代码
83 | function update() {
84 | log("🔔更新脚本开始!");
85 | scripts.forEach(async (script) => {
86 | await $.getFile(script);
87 | });
88 | log("🔔更新脚本结束!");
89 | }
90 |
91 | const scripts = [
92 | {
93 | moduleName: "DoubanMonitor",
94 | url:
95 | "https://raw.githubusercontent.com/evilbutcher/Scriptables/master/DoubanMonitor.js",
96 | },
97 | ];
98 | if (goupdate == true) update();
99 |
--------------------------------------------------------------------------------
/Env.js:
--------------------------------------------------------------------------------
1 | // Variables used by Scriptable.
2 | // These must be at the very top of the file. Do not edit.
3 | // icon-color: brown; icon-glyph: terminal;
4 | /**
5 | * Author: GideonSenku
6 | * Github: https://github.com/GideonSenku
7 | */
8 |
9 | var locationData, sunData
10 | const currentDate = new Date()
11 | const request = new Request('')
12 | const files = FileManager.iCloud()
13 | const dict = files.documentsDirectory()
14 | files.isDirectory(`${dict}/Env`) ? `` : files.createDirectory(`${dict}/Env`)
15 | const defaultHeaders = {
16 | "Accept": "*/*",
17 | "Content-Type": "application/json"
18 | }
19 | const textFormat = {
20 | defaultText: { size: 14, color: "ffffff", font: "regular" },
21 | battery: { size: 10, color: "", font: "bold" },
22 | title: { size: 16, color: "", font: "semibold" },
23 | SFMono: { size: 12, color: "ffffff", font: "SF Mono" }
24 | }
25 | /**
26 | * @description GET,返回String数据
27 | * @param {*} param0 request信息
28 | * @param {*} callback 回调返回response和JSON对象
29 | */
30 | const get = async ({ url, headers = {} }, callback = () => {} ) => {
31 | request.url = url
32 | request.method = 'GET'
33 | request.headers = {
34 | ...headers,
35 | ...defaultHeaders
36 | }
37 | const data = await request.loadJSON()
38 | callback(request.response, data)
39 | return data
40 | }
41 |
42 | /**
43 | * @description GET,返回String数据
44 | * @param {*} param0 request信息
45 | * @param {*} callback 回调返回response和String对象
46 | */
47 | const getStr = async ({ url, headers = {} }, callback = () => {} ) => {
48 | request.url = url
49 | request.method = 'GET'
50 | request.headers = {
51 | ...headers,
52 | ...defaultHeaders
53 | }
54 | const data = await request.loadString()
55 | callback(request.response, data)
56 | return data
57 | }
58 |
59 | /**
60 | * @description POST,返回String数据
61 | * @param {*} param0 request信息
62 | * @param {*} callback 回调返回response和String
63 | */
64 | const post = async ({ url, body, headers = {} }, callback = () => {} ) => {
65 | request.url = url
66 | request.body = body
67 | request.method = 'POST'
68 | request.headers = {
69 | ...defaultHeaders,
70 | ...headers
71 | }
72 | const data = await request.loadString()
73 | callback(request.response, data)
74 | return data
75 | }
76 |
77 | /**
78 | * @description POST,返回JSON数据
79 | * @param {*} param0 request信息
80 | * @param {*} callback 回调返回response和JSON
81 | */
82 | const _post = async ({ url, body, headers = {} }, callback = () => {} ) => {
83 | request.url = url
84 | request.body = body
85 | request.method = 'POST'
86 | request.headers = {
87 | ...defaultHeaders,
88 | ...headers
89 | }
90 | const data = await request.loadJSON()
91 | callback(request.response, data)
92 | return data
93 | }
94 |
95 | /**
96 | * @description 下载文件
97 | * @param {*} param0
98 | */
99 | const getFile = async ({moduleName, url}) => {
100 | log(`开始下载文件: 🌝 ${moduleName}`)
101 | const header = `// Variables used by Scriptable.
102 | // These must be at the very top of the file. Do not edit.
103 | // icon-color: deep-gray; icon-glyph: file-code;\n`;
104 | const content = await getStr({url})
105 | const fileHeader = content.includes('icon-color') ? `` : header
106 | write(`${moduleName}`, `${fileHeader}${content}`)
107 | log(`文件下载完成: 🌚 ${moduleName}`)
108 | }
109 |
110 | /**
111 | *
112 | * @description 导入模块,不存在即下载模块,也可传入forceDownload: true 强制更新模块
113 | * @param {*} param0
114 | */
115 | const require = ({
116 | moduleName,
117 | url = '',
118 | forceDownload = false
119 | }) => {
120 | if (isFileExists(moduleName) && !forceDownload) {
121 | log(`导入模块: 🪐${moduleName}`)
122 | return importModule(moduleName)
123 | } else {
124 | getFile({ moduleName, url })
125 | log(`导入模块: 🪐${moduleName}`)
126 | return importModule(moduleName)
127 | }
128 | }
129 | /**
130 | *
131 | * @description 将数据写入文件
132 | * @param {*} fileName 要写入的文件名,默认JS文件,可选其他,加上文件名后缀即可
133 | * @param {*} content 要写入的文件内容
134 | */
135 | const write = (fileName, content) => {
136 | let file = initFile(fileName)
137 | const filePath = `${dict}/${file}`
138 | FileManager.iCloud().writeString(filePath, content)
139 | return true
140 | }
141 |
142 | /**
143 | *
144 | * @description 判断文件是否存在
145 | * @param {*} fileName
146 | */
147 | const isFileExists = (fileName) => {
148 | let file = initFile(fileName)
149 | return FileManager.iCloud().fileExists(`${dict}/${file}`)
150 | }
151 |
152 | const initFile = (fileName) => {
153 | const hasSuffix = fileName.lastIndexOf('.') + 1
154 | return !hasSuffix ? `${fileName}.js` : fileName
155 | }
156 |
157 | /**
158 | *
159 | * @description 读取文件内容
160 | * @param {*} fileName 要读取的文件名,默认JS文件,可选其他,加上文件名后缀即可
161 | * @return 返回文件内容,字符串形式
162 | */
163 | const read = (fileName) => {
164 | const file = initFile(fileName)
165 | return FileManager.iCloud().readString(`${dict}/${file}`)
166 | }
167 |
168 | /**
169 | *
170 | * @description 提示框
171 | * @param {*} title 提示框标题
172 | * @param {*} message 提示框内容
173 | * @param {*} btnMes 提示框按钮标题,默认Cancel
174 | */
175 | const msg = (title, message, btnMes = 'Cancel') => {
176 | if (!config.runsInWidget) {
177 | const alert = new Alert()
178 | alert.title = title
179 | alert.message = message
180 | alert.addAction(btnMes)
181 | alert.present()
182 | }
183 | }
184 |
185 | const setdata = (Val, Key) => {
186 | Keychain.set(Val, Key)
187 | return true
188 | }
189 |
190 | const getdata = (Key) => {
191 | return Keychain.get(Key)
192 | }
193 |
194 | const hasdata = (Key) => {
195 | return Keychain.contains(Key)
196 | }
197 |
198 | const rmdata = (Key) => {
199 | Keychain.remove(Key)
200 | return true
201 | }
202 |
203 | // Presents an alert where the user can enter a value in a text field.
204 | // Returns the entered value.
205 | const input = async(title, message, placeholder, value = null) => {
206 | if (!config.runsInWidget) {
207 | let alert = new Alert()
208 | alert.title = title
209 | alert.message = message
210 | alert.addTextField(placeholder, value)
211 | alert.addAction("OK")
212 | alert.addCancelAction("Cancel")
213 | let idx = await alert.present()
214 | if (idx != -1) {
215 | return alert.textFieldValue(0)
216 | } else {
217 | throw new Error("Cancelled entering value")
218 | }
219 | }
220 | }
221 |
222 | /**
223 | *
224 | * 示例:$.time('yyyy-MM-dd qq HH:mm:ss.S')
225 | * :$.time('yyyyMMddHHmmssS')
226 | * y:年 M:月 d:日 q:季 H:时 m:分 s:秒 S:毫秒
227 | * 其中y可选0-4位占位符、S可选0-1位占位符,其余可选0-2位占位符
228 | * @param {*} fmt 格式化参数
229 | * @param {*} ts 时间戳 13位
230 | */
231 | const time = (fmt, ts = null) => {
232 | const date = ts ? new Date(ts) : new Date()
233 | let o = {
234 | 'M+': date.getMonth() + 1,
235 | 'd+': date.getDate(),
236 | 'H+': date.getHours(),
237 | 'm+': date.getMinutes(),
238 | 's+': date.getSeconds(),
239 | 'q+': Math.floor((date.getMonth() + 3) / 3),
240 | 'S': date.getMilliseconds()
241 | }
242 | if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
243 | for (let k in o)
244 | if (new RegExp('(' + k + ')').test(fmt))
245 | fmt = fmt.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length))
246 | return fmt
247 | }
248 |
249 | /**
250 | * @description create wiget
251 | * @param {*} title required
252 | * @param {*} texts required
253 | * @param {*} preview option
254 | */
255 | const createWidget = async({ title, texts = { },spacing = 5, preview = '' }) => {
256 | let w = new ListWidget()
257 | w.spacing = spacing
258 |
259 | let gradient = new LinearGradient()
260 | let gradientSettings = await setupGradient()
261 |
262 | gradient.colors = gradientSettings.color()
263 | gradient.locations = gradientSettings.position()
264 |
265 | w.backgroundGradient = gradient
266 | texts['battery'] ? battery(w, title) : provideText(title, w, textFormat.title)
267 | for (const text in texts) {
268 | if (text != 'battery' && text != 'updateTime' && texts.hasOwnProperty(text) && texts[text]) {
269 | const element = texts[text]
270 | provideText(element, w, textFormat.SFMono)
271 | }
272 | }
273 | texts['updateTime'] ? provideText(`[更新] ${time('MM-dd HH:mm')}`, w, textFormat.SFMono) : ``
274 |
275 | widgetPreview = preview ? preview: 'small'
276 |
277 | if(widgetPreview == "small") { w.presentSmall() }
278 | else if (widgetPreview == "medium") { w.presentMedium() }
279 | else if (widgetPreview == "large") { w.presentLarge() }
280 | return w
281 | }
282 |
283 |
284 | /**
285 | * @description Provide a font based on the input.
286 | * @param {*} fontName
287 | * @param {*} fontSize
288 | */
289 | const provideFont = (fontName, fontSize) => {
290 | const fontGenerator = {
291 | "ultralight": function() { return Font.ultraLightSystemFont(fontSize) },
292 | "light": function() { return Font.lightSystemFont(fontSize) },
293 | "regular": function() { return Font.regularSystemFont(fontSize) },
294 | "medium": function() { return Font.mediumSystemFont(fontSize) },
295 | "semibold": function() { return Font.semiboldSystemFont(fontSize) },
296 | "bold": function() { return Font.boldSystemFont(fontSize) },
297 | "heavy": function() { return Font.heavySystemFont(fontSize) },
298 | "black": function() { return Font.blackSystemFont(fontSize) },
299 | "italic": function() { return Font.italicSystemFont(fontSize) }
300 | }
301 |
302 | const systemFont = fontGenerator[fontName]
303 | if (systemFont) { return systemFont() }
304 | return new Font(fontName, fontSize)
305 | }
306 |
307 |
308 | /**
309 | * @description Add formatted text to a container.
310 | * @param {*} string
311 | * @param {*} container widget container
312 | * @param {*} format Object: size, color, font
313 | */
314 |
315 | const provideText = (string, container, format) => {
316 | let url
317 | if (typeof string !== 'string') {
318 | url = string.url
319 | string = string.text
320 | }
321 | const stackItem = container.addStack()
322 |
323 | if (url) {
324 | stackItem.url = url
325 | }
326 |
327 | const textItem = stackItem.addText(string)
328 | const textFont = format.font || textFormat.defaultText.font
329 | const textSize = format.size || textFormat.defaultText.size
330 | const textColor = format.color || textFormat.defaultText.color
331 |
332 | textItem.font = provideFont(textFont, textSize)
333 | textItem.textColor = new Color(textColor)
334 | return stackItem
335 | }
336 |
337 | // Set up the gradient for the widget background.
338 | const setupGradient = async() => {
339 |
340 | // Requirements: sunrise
341 | if (!sunData) { await setupSunrise() }
342 |
343 | let gradient = {
344 | dawn: {
345 | color() { return [new Color("142C52"), new Color("1B416F"), new Color("62668B")] },
346 | position() { return [0, 0.5, 1] },
347 | },
348 |
349 | sunrise: {
350 | color() { return [new Color("274875"), new Color("766f8d"), new Color("f0b35e")] },
351 | position() { return [0, 0.8, 1.5] },
352 | },
353 |
354 | midday: {
355 | color() { return [new Color("3a8cc1"), new Color("90c0df")] },
356 | position() { return [0, 1] },
357 | },
358 |
359 | noon: {
360 | color() { return [new Color("b2d0e1"), new Color("80B5DB"), new Color("3a8cc1")] },
361 | position() { return [-0.2, 0.2, 1.5] },
362 | },
363 |
364 | sunset: {
365 | color() { return [new Color("32327A"), new Color("662E55"), new Color("7C2F43")] },
366 | position() { return [0.1, 0.9, 1.2] },
367 | },
368 |
369 | twilight: {
370 | color() { return [new Color("021033"), new Color("16296b"), new Color("414791")] },
371 | position() { return [0, 0.5, 1] },
372 | },
373 |
374 | night: {
375 | color() { return [new Color("16296b"), new Color("021033"), new Color("021033"), new Color("113245")] },
376 | position() { return [-0.5, 0.2, 0.5, 1] },
377 | },
378 | }
379 |
380 | const sunrise = sunData.sunrise
381 | const sunset = sunData.sunset
382 | const utcTime = currentDate.getTime()
383 |
384 | function closeTo(time,mins) {
385 | return Math.abs(utcTime - time) < (mins * 60000)
386 | }
387 |
388 | // Use sunrise or sunset if we're within 30min of it.
389 | if (closeTo(sunrise,15)) { return gradient.sunrise }
390 | if (closeTo(sunset,15)) { return gradient.sunset }
391 |
392 | // In the 30min before/after, use dawn/twilight.
393 | if (closeTo(sunrise,45) && utcTime < sunrise) { return gradient.dawn }
394 | if (closeTo(sunset,45) && utcTime > sunset) { return gradient.twilight }
395 |
396 | // Otherwise, if it's night, return night.
397 | if (isNight(currentDate)) { return gradient.night }
398 |
399 | // If it's around noon, the sun is high in the sky.
400 | if (currentDate.getHours() == 12) { return gradient.noon }
401 | // Otherwise, return the "typical" theme.
402 | return gradient.midday
403 | }
404 |
405 | // Set up the sunData object.
406 | const setupSunrise = async () => {
407 |
408 | // Requirements: location
409 | if (!locationData) { await setupLocation() }
410 |
411 | // Set up the sunrise/sunset cache.
412 | const sunCachePath = files.joinPath(dict, "Env/Env-sun")
413 | const sunCacheExists = files.fileExists(sunCachePath)
414 | const sunCacheDate = sunCacheExists ? files.modificationDate(sunCachePath) : 0
415 | var sunDataRaw
416 |
417 | // If cache exists and it was created today, use cached data.
418 | if (sunCacheExists && sameDay(currentDate, sunCacheDate)) {
419 | const sunCache = files.readString(sunCachePath)
420 | sunDataRaw = JSON.parse(sunCache)
421 |
422 | // Otherwise, use the API to get sunrise and sunset times.
423 | } else {
424 | const sunReq = "https://api.sunrise-sunset.org/json?lat=" + locationData.latitude + "&lng=" + locationData.longitude + "&formatted=0&date=" + currentDate.getFullYear() + "-" + (currentDate.getMonth()+1) + "-" + currentDate.getDate()
425 | sunDataRaw = await new Request(sunReq).loadJSON()
426 | files.writeString(sunCachePath, JSON.stringify(sunDataRaw))
427 | }
428 |
429 | // Store the timing values.
430 | sunData = {}
431 | sunData.sunrise = new Date(sunDataRaw.results.sunrise).getTime()
432 | sunData.sunset = new Date(sunDataRaw.results.sunset).getTime()
433 | }
434 |
435 | const setupLocation = async (lockLocation = true) => {
436 |
437 | locationData = {}
438 | const locationPath = files.joinPath(dict, "Env/Env-location")
439 |
440 | // If our location is unlocked or cache doesn't exist, ask iOS for location.
441 | var readLocationFromFile = false
442 | if (!lockLocation || !files.fileExists(locationPath)) {
443 | try {
444 | const location = await Location.current()
445 | locationData.latitude = location.latitude
446 | locationData.longitude = location.longitude
447 | files.writeString(locationPath, location.latitude + "," + location.longitude)
448 |
449 | } catch(e) {
450 | // If we fail in unlocked mode, read it from the cache.
451 | if (!lockLocation) { readLocationFromFile = true }
452 |
453 | // We can't recover if we fail on first run in locked mode.
454 | else { return }
455 | }
456 | }
457 |
458 | // If our location is locked or we need to read from file, do it.
459 | if (lockLocation || readLocationFromFile) {
460 | const locationStr = files.readString(locationPath).split(",")
461 | locationData.latitude = locationStr[0]
462 | locationData.longitude = locationStr[1]
463 | }
464 | return locationData
465 | }
466 |
467 | // Determines if the provided date is at night.
468 | const isNight = (dateInput) => {
469 | const timeValue = dateInput.getTime()
470 | return (timeValue < sunData.sunrise) || (timeValue > sunData.sunset)
471 | }
472 | // Determines if two dates occur on the same day
473 | const sameDay = (d1, d2) => {
474 | return d1.getFullYear() === d2.getFullYear() &&
475 | d1.getMonth() === d2.getMonth() &&
476 | d1.getDate() === d2.getDate()
477 | }
478 | /**
479 | * @description 返回电池百分比
480 | */
481 | const renderBattery = () => {
482 | const batteryLevel = Device.batteryLevel()
483 | const batteryAscii = `${Math.round(batteryLevel * 100)}%`
484 | return batteryAscii
485 | }
486 |
487 |
488 | // Add a battery element to the widget; consisting of a battery icon and percentage.
489 | function battery(column,title) {
490 | const batteryLevel = Device.batteryLevel()
491 | // Set up the battery level item
492 | let batteryStack = column.addStack()
493 | provideText(title, batteryStack, textFormat.title)
494 |
495 | batteryStack.centerAlignContent()
496 |
497 | batteryStack.addSpacer()
498 |
499 | let batteryIcon = batteryStack.addImage(provideBatteryIcon())
500 | batteryIcon.imageSize = new Size(20,20)
501 |
502 |
503 | // Change the battery icon to red if battery level is <= 20 to match system behavior
504 | if ( Math.round(batteryLevel * 100) > 20 || Device.isCharging() ) {
505 |
506 | batteryIcon.tintColor = Color.white()
507 |
508 | } else {
509 |
510 | batteryIcon.tintColor = Color.red()
511 |
512 | }
513 |
514 | // Display the battery status
515 | let batteryInfo = provideText(' '+renderBattery(), batteryStack, textFormat.battery)
516 |
517 |
518 | }
519 |
520 |
521 | // Provide a battery SFSymbol with accurate level drawn on top of it.
522 | function provideBatteryIcon() {
523 |
524 | if (Device.isCharging()) { return SFSymbol.named("battery.100.bolt").image }
525 |
526 | // Set the size of the battery icon.
527 | const batteryWidth = 87
528 | const batteryHeight = 41
529 |
530 | // Start our draw context.
531 | let draw = new DrawContext()
532 | draw.opaque = false
533 | draw.respectScreenScale = true
534 | draw.size = new Size(batteryWidth, batteryHeight)
535 |
536 | // Draw the battery.
537 | draw.drawImageInRect(SFSymbol.named("battery.0").image, new Rect(0, 0, batteryWidth, batteryHeight))
538 |
539 | // Match the battery level values to the SFSymbol.
540 | const x = batteryWidth*0.1525
541 | const y = batteryHeight*0.247
542 | const width = batteryWidth*0.602
543 | const height = batteryHeight*0.505
544 |
545 | // Prevent unreadable icons.
546 | let level = Device.batteryLevel()
547 | if (level < 0.05) { level = 0.05 }
548 |
549 | // Determine the width and radius of the battery level.
550 | const current = width * level
551 | let radius = height/6.5
552 |
553 | // When it gets low, adjust the radius to match.
554 | if (current < (radius * 2)) { radius = current / 2 }
555 |
556 | // Make the path for the battery level.
557 | let barPath = new Path()
558 | barPath.addRoundedRect(new Rect(x, y, current, height), radius, radius)
559 | draw.addPath(barPath)
560 | draw.setFillColor(Color.black())
561 | draw.fillPath()
562 | return draw.getImage()
563 | }
564 |
565 | const logErr = (e, messsage) => {
566 | console.error(e)
567 | }
568 |
569 |
570 | module.exports = {
571 | dict,
572 | get,
573 | getStr,
574 | post,
575 | _post,
576 | getFile,
577 | require,
578 | write,
579 | isFileExists,
580 | initFile,
581 | read,
582 | setdata,
583 | getdata,
584 | hasdata,
585 | rmdata,
586 | msg,
587 | input,
588 | time,
589 | createWidget,
590 | provideText,
591 | setupLocation,
592 | renderBattery,
593 | logErr
594 | }
595 |
--------------------------------------------------------------------------------
/Install Scripts.js:
--------------------------------------------------------------------------------
1 | // Variables used by Scriptable.
2 | // These must be at the very top of the file. Do not edit.
3 | // icon-color: brown; icon-glyph: download;
4 | /**
5 | * Author: GideonSenku
6 | * Github: https://github.com/GideonSenku
7 | */
8 | const scripts = [
9 | {
10 | moduleName: "10010",
11 | url:
12 | "https://raw.githubusercontent.com/GideonSenku/Scriptable/master/10010/10010.js",
13 | },
14 | {
15 | moduleName: "10086",
16 | url:
17 | "https://raw.githubusercontent.com/GideonSenku/Scriptable/master/10086/10086.js",
18 | },
19 | {
20 | moduleName: "BilibiliMonitor",
21 | url:
22 | "https://raw.githubusercontent.com/evilbutcher/Scriptables/master/BilibiliMonitor.js",
23 | },
24 | {
25 | moduleName: "RRShareMonitor",
26 | url:
27 | "https://raw.githubusercontent.com/evilbutcher/Scriptables/master/RRShareMonitor.js",
28 | },
29 | {
30 | moduleName: "RSSMonitor",
31 | url:
32 | "https://raw.githubusercontent.com/evilbutcher/Scriptables/master/RSSMonitor.js",
33 | },
34 | {
35 | moduleName: "WeiboMonitor",
36 | url:
37 | "https://raw.githubusercontent.com/evilbutcher/Scriptables/master/WeiboMonitor.js",
38 | },
39 | {
40 | moduleName: "ZhihuMonitor",
41 | url:
42 | "https://raw.githubusercontent.com/evilbutcher/Scriptables/master/ZhihuMonitor.js",
43 | },
44 | {
45 | moduleName: "DoubanMonitor",
46 | url:
47 | "https://raw.githubusercontent.com/evilbutcher/Scriptables/master/DoubanMonitor.js",
48 | },
49 | {
50 | moduleName: "Env",
51 | url:
52 | "https://raw.githubusercontent.com/GideonSenku/Scriptable/master/Env.js",
53 | },
54 | {
55 | moduleName: "Install Scripts",
56 | url:
57 | "https://raw.githubusercontent.com/GideonSenku/Scriptable/master/Install%20Scripts.js",
58 | },
59 | {
60 | moduleName: "Checkin",
61 | url:
62 | "https://raw.githubusercontent.com/evilbutcher/Scriptables/master/Checkin.js",
63 | },
64 | {
65 | moduleName: "Dler Cloud",
66 | url:
67 | "https://raw.githubusercontent.com/evilbutcher/Scriptables/master/Dler%20Cloud.js",
68 | },
69 | {
70 | moduleName: "AppPriceMonitor",
71 | url:
72 | "https://raw.githubusercontent.com/evilbutcher/Scriptables/master/AppPriceMonitor.js",
73 | },
74 | {
75 | moduleName: "北京尾号限行",
76 | url:
77 | "https://raw.githubusercontent.com/evilbutcher/Scriptables/master/%E5%8C%97%E4%BA%AC%E5%B0%BE%E5%8F%B7%E9%99%90%E8%A1%8C.js",
78 | },
79 | ];
80 | // Install Scripts.js
81 | const $ = importModule("Env");
82 | function update() {
83 | log("🔔更新脚本开始!");
84 | scripts.forEach((script) => {
85 | $.getFile(script);
86 | });
87 | log("🔔更新脚本结束!");
88 | }
89 | update();
90 |
--------------------------------------------------------------------------------
/NASA.js:
--------------------------------------------------------------------------------
1 | // Variables used by Scriptable.
2 | // These must be at the very top of the file. Do not edit.
3 | // icon-color: deep-blue; icon-glyph: star-and-crescent;
4 | /**
5 | * Author: evilbutcher
6 | * Github: https://github.com/evilbutcher
7 | * 本脚本使用了@Gideon_Senku的Env.scriptable,感谢!
8 | * 感谢@MuTu88帮忙测试!
9 | */
10 | const goupdate = true;
11 | const $ = new importModule("Env");
12 | const ERR = MYERR();
13 | const scripts = [
14 | {
15 | moduleName: "NASA",
16 | url:
17 | "https://raw.githubusercontent.com/evilbutcher/Scriptables/master/NASA.js",
18 | },
19 | ];
20 |
21 | !(async () => {
22 | if (checkkey() == true) {
23 | await getinfo();
24 | var flag = Math.floor(Math.random() * 10);
25 | if ($.headers.statusCode == 200) {
26 | if (flag >= 0 && flag < 2) {
27 | log(`${flag} 展示备用图片1`);
28 | cover = $.imglink;
29 | } else if (flag >= 2 && flag < 4) {
30 | log(`${flag} 展示备用图片2`);
31 | cover = $.imglink2;
32 | } else {
33 | log(`${flag} 展示NASA图片`);
34 | cover = $.data.url;
35 | }
36 | } else {
37 | if (flag >= 0 && flag < 5) {
38 | log(`${flag} 展示备用图片1`);
39 | cover = $.imglink;
40 | } else {
41 | log(`${flag} 展示备用图片2`);
42 | cover = $.imglink2;
43 | }
44 | }
45 | var img = await new Request(cover).loadImage();
46 | let widget = createWidget(img);
47 | Script.setWidget(widget);
48 | Script.complete();
49 | }
50 | })()
51 | .catch((err) => {
52 | if (err instanceof ERR.TokenError) {
53 | $.msg("NASA - Config配置错误❌\n" + err.message);
54 | } else {
55 | $.msg("NASA - 出现错误❌\n" + JSON.stringify(err));
56 | }
57 | })
58 | .finally(update());
59 |
60 | function checkkey() {
61 | try {
62 | const { nasaapi, imglink, imglink2 } = importModule("Config");
63 | $.apikey = nasaapi();
64 | $.imglink = imglink();
65 | $.imglink2 = imglink2();
66 | return true;
67 | } catch (err) {
68 | throw new ERR.TokenError("❌ 配置文件中未找到NASA API或备用图片地址");
69 | }
70 | }
71 |
72 | function createWidget(img) {
73 | const w = new ListWidget();
74 | const bgColor = new LinearGradient();
75 | bgColor.colors = [new Color("#1c1c1c"), new Color("#29323c")];
76 | bgColor.locations = [0.0, 1.0];
77 | w.backgroundGradient = bgColor;
78 | w.backgroundImage = img;
79 | w.addSpacer();
80 | w.spacing = 5;
81 |
82 | const imgLine = w.addImage(img);
83 | imgLine.imageSize = new Size(400, 400);
84 |
85 | w.addSpacer();
86 | w.spacing = 5;
87 | w.presentLarge();
88 | return w;
89 | }
90 |
91 | function MYERR() {
92 | class TokenError extends Error {
93 | constructor(message) {
94 | super(message);
95 | this.name = "TokenError";
96 | }
97 | }
98 | class TimeError extends Error {
99 | constructor(message) {
100 | super(message);
101 | this.name = "TimeError";
102 | }
103 | }
104 | class ImageError extends Error {
105 | constructor(message) {
106 | super(message);
107 | this.name = "ImageError";
108 | }
109 | }
110 | return {
111 | TokenError,
112 | TimeError,
113 | ImageError,
114 | };
115 | }
116 |
117 | function getinfo() {
118 | const url = `https://api.nasa.gov/planetary/apod?api_key=${$.apikey}`;
119 | return new Promise((resolve) => {
120 | const res = $.get({ url }, (resp, data) => {
121 | $.data = data;
122 | $.headers = resp;
123 | if (resp.statusCode == 404) {
124 | log("NASA - 暂无图片" + err.message);
125 | }
126 | resolve();
127 | });
128 | });
129 | }
130 |
131 | //更新代码
132 | function update() {
133 | if (goupdate == true) {
134 | log("🔔更新脚本开始!");
135 | scripts.forEach(async (script) => {
136 | await $.getFile(script);
137 | });
138 | log("🔔更新脚本结束!");
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/NASAwDetail.js:
--------------------------------------------------------------------------------
1 | // Variables used by Scriptable.
2 | // These must be at the very top of the file. Do not edit.
3 | // icon-color: deep-blue; icon-glyph: star-and-crescent;
4 | /**
5 | * Author: evilbutcher
6 | * Github: https://github.com/evilbutcher
7 | * 本脚本使用了@Gideon_Senku的Env.scriptable,感谢!
8 | * 感谢@MuTu88帮忙测试!
9 | */
10 | const goupdate = true;
11 | const $ = new importModule("Env");
12 | const ERR = MYERR();
13 | const scripts = [
14 | {
15 | moduleName: "NASAwDetail",
16 | url:
17 | "https://raw.githubusercontent.com/evilbutcher/Scriptables/master/NASAwDetail.js",
18 | },
19 | ];
20 |
21 | !(async () => {
22 | if (checkkey() == true) {
23 | await getinfo();
24 | if ($.headers.statusCode == 200) {
25 | var title = $.data.title;
26 | var copyright = $.data.copyright;
27 | var time = $.data.date;
28 | var exp = $.data.explanation;
29 | var detail = `🌃 ${title}\n©️Copyright:${copyright}\n⌚️Date:${time}\n${exp}`;
30 | var cover = $.data.url;
31 | } else {
32 | title = "随机图片展示";
33 | cover = $.imglink;
34 | detail = `🌃 ${title}`;
35 | }
36 | try {
37 | var img = await new Request(cover).loadImage();
38 | } catch (err) {
39 | throw new ERR.ImageError("NASA提供的是视频/备用图片地址不支持");
40 | }
41 | //QuickLook.present(img);
42 | let widget = createWidget(img, detail);
43 | Script.setWidget(widget);
44 | Script.complete();
45 | }
46 | })()
47 | .catch((err) => {
48 | if (err instanceof ERR.TokenError) {
49 | $.msg("NASA - Config配置错误❌\n" + err.message);
50 | } else if (err instanceof ERR.ImageError) {
51 | $.msg("NASA - 图片错误❌\n" + err.message);
52 | } else {
53 | $.msg("NASA - 出现错误❌\n" + JSON.stringify(err));
54 | }
55 | })
56 | .finally(update());
57 |
58 | function checkkey() {
59 | try {
60 | const { nasaapi, imglink } = importModule("Config");
61 | $.apikey = nasaapi();
62 | $.imglink = imglink();
63 | return true;
64 | } catch (err) {
65 | throw new ERR.TokenError("❌ 配置文件中未找到NASA API或备用图片地址");
66 | }
67 | }
68 |
69 | function createWidget(img, detail) {
70 | const w = new ListWidget();
71 | const bgColor = new LinearGradient();
72 | bgColor.colors = [new Color("#1c1c1c"), new Color("#29323c")];
73 | bgColor.locations = [0.0, 1.0];
74 | w.backgroundGradient = bgColor;
75 | w.addSpacer();
76 | w.spacing = 5;
77 |
78 | const imgLine = w.addImage(img);
79 | imgLine.containerRelativeShape = true;
80 |
81 | const top1Line = w.addText(detail);
82 | top1Line.font = new Font('SF Mono', 12);
83 | top1Line.textColor = new Color("#7dbbae");
84 |
85 | w.addSpacer();
86 | w.spacing = 5;
87 | w.presentLarge();
88 | return w;
89 | }
90 |
91 | function MYERR() {
92 | class TokenError extends Error {
93 | constructor(message) {
94 | super(message);
95 | this.name = "TokenError";
96 | }
97 | }
98 | class TimeError extends Error {
99 | constructor(message) {
100 | super(message);
101 | this.name = "TimeError";
102 | }
103 | }
104 | class ImageError extends Error {
105 | constructor(message) {
106 | super(message);
107 | this.name = "ImageError";
108 | }
109 | }
110 | return {
111 | TokenError,
112 | TimeError,
113 | ImageError,
114 | };
115 | }
116 |
117 | function getinfo() {
118 | const url = `https://api.nasa.gov/planetary/apod?api_key=${$.apikey}`;
119 | return new Promise((resolve) => {
120 | const res = $.get({ url }, (resp, data) => {
121 | try {
122 | $.data = data;
123 | $.headers = resp;
124 | if (resp.statusCode == 404) {
125 | throw new ERR.TimeError("❌ 暂无图片,内容在更新,请稍等呦~");
126 | }
127 | } catch (err) {
128 | if (err instanceof ERR.TimeError) {
129 | $.msg("NASA - 暂无图片" + err.message);
130 | }
131 | return;
132 | }
133 | resolve();
134 | });
135 | });
136 | }
137 |
138 | //更新代码
139 | function update() {
140 | if (goupdate == true) {
141 | log("🔔更新脚本开始!");
142 | scripts.forEach(async (script) => {
143 | await $.getFile(script);
144 | });
145 | log("🔔更新脚本结束!");
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://github.com/anuraghazra/github-readme-stats)
2 |
3 | # Scriptable 脚本整理
4 |
5 | #### [English Version](https://github.com/evilbutcher/Scriptables/blob/master/README_EN.md)
6 |
7 | 文档和脚本使用方法请前往@GideonSenku 仓库【[Scriptable](https://github.com/GideonSenku/Scriptable)】的 README.md。欢迎使用反馈。
8 |
9 | ## 致谢
10 |
11 | 感谢@GideonSenku 的 Env 感谢@MuTu88 帮忙测试
12 |
13 | 如果能请杯奶茶,就很感谢啦!
14 |
15 |
16 | ### 更新
17 |
18 | 2020.11.24 恢复了 Config.js 支持的脚本文件。
19 |
20 | 2020.11.13 注意,因为模板采用 Env 生成,热门监控类脚本的 Config 会失效,其他脚本的 Config 配置正常。
21 |
22 | ### 如何安装?(重要)
23 |
24 | 全部脚本都需要 Env,点击[这里](https://github.com/evilbutcher/Scriptables/blob/master/Env.js)下载安装 Env.js。
25 |
26 | 下载想要使用的.js 文件后,直接导入 Scriptable 即可。也可使用 Install Scripts 一键安装所有脚本,点击[这里](https://github.com/evilbutcher/Scriptables/blob/master/Install%20Scripts.js)下载安装 Install Scripts.js。
27 |
28 | ~~如果想要保持自动更新,又想要自定义脚本内设置,需要使用 Config,点击[这里](https://github.com/evilbutcher/Scriptables/blob/master/Config.js)下载安装 Config.js。~~
29 |
30 | ### 脚本安装
31 |
32 | B 站榜单 [下载地址](https://github.com/evilbutcher/Scriptables/blob/master/BilibiliMonitor.js)
33 |
34 | 豆瓣电影监控 [下载地址](https://github.com/evilbutcher/Scriptables/blob/master/DoubanMonitor.js)
35 |
36 | ~~人人影视资源 [下载地址](https://github.com/evilbutcher/Scriptables/blob/master/RRShareMonitor.js)~~
37 |
38 | RSS 监控 [下载地址](https://github.com/evilbutcher/Scriptables/blob/master/RSSMonitor.js)
39 |
40 | 微博热搜 [下载地址](https://github.com/evilbutcher/Scriptables/blob/master/WeiboMonitor.js)
41 |
42 | 知乎热榜 [下载地址](https://github.com/evilbutcher/Scriptables/blob/master/ZhihuMonitor.js)
43 |
44 | NASA 精简 [下载地址](https://github.com/evilbutcher/Scriptables/blob/master/NASA.js) NASA 丰富 [下载地址](https://github.com/evilbutcher/Scriptables/blob/master/NASAwDetail.js)
45 |
46 | 通用签到 [下载地址](https://github.com/evilbutcher/Scriptables/blob/master/Checkin.js) 洞签到 [下载地址](https://github.com/evilbutcher/Scriptables/blob/master/Dler%20Cloud.js)
47 |
48 | App 价格及版本监控 [下载地址](https://github.com/evilbutcher/Scriptables/blob/master/AppPriceMonitor.js)
49 |
50 | 北京尾号限行 [下载地址](https://raw.githubusercontent.com/evilbutcher/Scriptables/master/%E5%8C%97%E4%BA%AC%E5%B0%BE%E5%8F%B7%E9%99%90%E8%A1%8C.js)
51 |
52 | ### 脚本效果演示
53 |
54 | ##### App 价格及版本监控演示图片
55 |
56 |
57 |
58 | ##### 热门监控演示图片
59 |
60 |
61 |
62 | ##### NASA 每日一图和 RSS 监控演示图片
63 |
64 |
65 |
66 | #### 自定义配置效果演示
67 |
68 | 配置 Config 文件后,脚本运行优先使用 Config 文件内的设置,这样可以保证每次更新不会影响自定义设置。
69 |
70 |
71 |
72 | ### 免责声明
73 |
74 | 1. 此脚本仅用于学习研究,不保证其合法性、准确性、有效性,请根据情况自行判断,本人对此不承担任何保证责任。
75 | 2. 由于此脚本仅用于学习研究,您必须在下载后 24 小时内将所有内容从您的计算机或手机或任何存储设备中完全删除,若违反规定引起任何事件本人对此均不负责。
76 | 3. 请勿将此脚本用于任何商业或非法目的,若违反规定请自行对此负责。
77 | 4. 此脚本涉及应用与本人无关,本人对因此引起的任何隐私泄漏或其他后果不承担任何责任。
78 | 5. 本人对任何脚本引发的问题概不负责,包括但不限于由脚本错误引起的任何损失和损害。
79 | 6. 如果任何单位或个人认为此脚本可能涉嫌侵犯其权利,应及时通知并提供身份证明,所有权证明,我们将在收到认证文件确认后删除此脚本。
80 | 7. 所有直接或间接使用、查看此脚本的人均应该仔细阅读此声明。本人保留随时更改或补充此声明的权利。一旦您使用或复制了此脚本,即视为您已接受此免责声明。
81 |
82 | ### 访问量
83 |
84 | 
85 |
--------------------------------------------------------------------------------
/README_EN.md:
--------------------------------------------------------------------------------
1 | [](https://github.com/anuraghazra/github-readme-stats)
2 |
3 | # Scriptable Scripts Collations
4 |
5 | Documentation and scripts instructions can be found in @GideonSenku [Scriptable](https://github.com/GideonSenku/Scriptable) README.md. Feedback is welcome!
6 |
7 | ## Acknowledgements
8 |
9 | Thanks to @GideonSenku for the Env! Thanks to @MuTu88 for helping with testing!
10 |
11 | ### How to install?(Important)
12 |
13 | Env is required for all scripts, click [here](https://github.com/evilbutcher/Scriptables/blob/master/Env.js) to download and install Env.js.
14 |
15 | After downloading the .js file you want to use, you can just import to Scriptable directly. You can also use Install Scripts to install all the scripts in one click, click [here](https://github.com/evilbutcher/Scriptables/blob/master/Install%20Scripts.js) to download and install Install Scripts.js.
16 |
17 | ~~If you want to keep it updated automatically and want to customize the settings within the script, you need to use Config. Click [here](https://github.com/evilbutcher/Scriptables/blob/master/Config.js) to download and install Config.js.~~
18 |
19 | ### Script Installation
20 |
21 | Bilibili Monitor [Download](https://github.com/evilbutcher/Scriptables/blob/master/BilibiliMonitor.js)
22 |
23 | Douban Movie Monitor [Download](https://github.com/evilbutcher/Scriptables/blob/master/DoubanMonitor.js)
24 |
25 | ~~RRShare Monitor [Download](https://github.com/evilbutcher/Scriptables/blob/master/RRShareMonitor.js)~~
26 |
27 | RSS Monitor [Download](https://github.com/evilbutcher/Scriptables/blob/master/RSSMonitor.js)
28 |
29 | Weibo Monitor [Download](https://github.com/evilbutcher/Scriptables/blob/master/WeiboMonitor.js)
30 |
31 | Zhihu Monitor [Download](https://github.com/evilbutcher/Scriptables/blob/master/ZhihuMonitor.js)
32 |
33 | NASA Streamlined [Download](https://github.com/evilbutcher/Scriptables/blob/master/NASA.js) NASA Enriched [Download](https://github.com/evilbutcher/Scriptables/blob/master/NASAwDetail.js)
34 |
35 | Checkin [Download](https://github.com/evilbutcher/Scriptables/blob/master/Checkin.js) Dler [Download](https://github.com/evilbutcher/Scriptables/blob/master/Dler%20Cloud.js)
36 |
37 | App Price and Version Monitor [Download](https://github.com/evilbutcher/Scriptables/blob/master/AppPriceMonitor.js)
38 |
39 | Beijing's Tail Number Limit [Download](https://raw.githubusercontent.com/evilbutcher/Scriptables/master/%E5%8C%97%E4%BA%AC%E5%B0%BE%E5%8F%B7%E9%99%90%E8%A1%8C.js)
40 |
41 | ### Scripts Demo
42 |
43 | ##### App Price and Version Monitor Demo
44 |
45 |
46 |
47 | ##### Hot Monitor Demo
48 |
49 |
50 |
51 | ##### NASA's Picture of the Day and RSS Monitor Demo
52 |
53 |
54 |
55 | #### Using Custom Configuration Demo
56 |
57 | Once the Config file is configured, the script runs prioritizing the settings within the Config file, so that each update does not affect the custom settings.
58 |
59 |
60 |
61 | ### Disclaimer
62 |
63 | 1. This script is only used for study and research, and does not guarantee its legitimacy, accuracy, and validity. Please make your own judgment based on the situation. I do not assume any guarantee responsibility for this.
64 | 2. Since this script is only used for learning and research, you must completely delete all content from your computer or mobile phone or any storage device within 24 hours after downloading. I am not responsible for any incidents caused by violation of the regulations.
65 | 3. Please do not use this script for any commercial or illegal purposes. If you violate the regulations, please be responsible for it.
66 | 4. The application involved in this script has nothing to do with me, and I am not responsible for any privacy leakage or other consequences caused by this.
67 | 5. I am not responsible for any problems caused by scripts, including but not limited to any loss and damage caused by script errors.
68 | 6. If any unit or individual believes that this script may be suspected of infringing on their rights, they should promptly notify and provide proof of identity and ownership. We will delete this script after receiving the confirmation of the certification document.
69 | 7. All people who directly or indirectly use or view this script should read this statement carefully. I reserve the right to change or supplement this statement at any time. Once you use or copy this script, you are deemed to have accepted this disclaimer.
70 |
71 | ### Visitors
72 |
73 | 
74 |
--------------------------------------------------------------------------------
/RRShare.js:
--------------------------------------------------------------------------------
1 | // Variables used by Scriptable.
2 | // These must be at the very top of the file. Do not edit.
3 | // icon-color: blue; icon-glyph: film;
4 | /*
5 | * Author: evilbutcher
6 | * Github: https://github.com/evilbutcher
7 | * 本脚本使用了@Gideon_Senku的Env.scriptable,感谢!
8 | */
9 | const goupdate = true;
10 | const $ = importModule("Env");
11 | var num = 6; //自定义显示数量
12 | var rancolor = true; //true为开启随机颜色
13 |
14 | try {
15 | var { rrnum, rrrancolor } = importModule("Config");
16 | num = rrnum();
17 | rancolor = rrrancolor();
18 | console.log("将使用配置文件内人人影视配置");
19 | } catch (e) {
20 | console.log("将使用脚本内人人影视配置");
21 | }
22 |
23 | const res = await getinfo();
24 |
25 | let widget = createWidget(res);
26 | Script.setWidget(widget);
27 | Script.complete();
28 |
29 | function createWidget(res) {
30 | items = [];
31 | for (var i = 0; i < num; i++) {
32 | var item = res[i]["file_name"];
33 | items.push(item);
34 | }
35 | console.log(items);
36 |
37 | const w = new ListWidget();
38 | const bgColor = new LinearGradient();
39 | bgColor.colors = [new Color("#1c1c1c"), new Color("#29323c")];
40 | bgColor.locations = [0.0, 1.0];
41 | w.backgroundGradient = bgColor;
42 | w.addSpacer();
43 | w.spacing = 5;
44 |
45 | const firstLine = w.addText(`🎬人人影视`);
46 | firstLine.font = new Font('SF Mono', 15);
47 | firstLine.textColor = Color.white();
48 | firstLine.textOpacity = 0.7;
49 |
50 | for (var i = 0; i < items.length; i++) {
51 | addTextToListWidget(`• ${items[i]}`, w);
52 | }
53 |
54 | w.addSpacer();
55 | w.spacing = 5;
56 | w.presentSmall();
57 | return w;
58 | }
59 |
60 | async function getinfo() {
61 | const zmzRequest = {
62 | url: `http://file.apicvn.com/file/list?page=1&order=create_time&sort=desc`,
63 | headers: {
64 | Host: "file.apicvn.com",
65 | "Content-Type": "application/x-www-form-urlencoded",
66 | "User-Agent": "Mozilla/5.0",
67 | },
68 | };
69 | const res = await $.get(zmzRequest);
70 | log(res);
71 | return res;
72 | }
73 |
74 | function addTextToListWidget(text, listWidget) {
75 | let item = listWidget.addText(text);
76 | if (rancolor == true) {
77 | item.textColor = new Color(color16());
78 | } else {
79 | item.textColor = Color.white();
80 | }
81 | item.font = new Font('SF Mono', 12);
82 | }
83 |
84 | function color16() {
85 | var r = Math.floor(Math.random() * 256);
86 | if (r + 50 < 255) {
87 | r = r + 50;
88 | }
89 | if (r > 230 && r < 255) {
90 | r = r - 50;
91 | }
92 | var g = Math.floor(Math.random() * 256);
93 | if (g + 50 < 255) {
94 | g = g + 50;
95 | }
96 | if (g > 230 && g < 255) {
97 | g = g - 50;
98 | }
99 | var b = Math.floor(Math.random() * 256);
100 | if (b + 50 < 255) {
101 | b = b + 50;
102 | }
103 | if (b > 230 && b < 255) {
104 | b = b - 50;
105 | }
106 | var color = "#" + r.toString(16) + g.toString(16) + b.toString(16);
107 | return color;
108 | }
109 |
110 | //更新代码
111 | function update() {
112 | log("🔔更新脚本开始!");
113 | scripts.forEach(async (script) => {
114 | await $.getFile(script);
115 | });
116 | log("🔔更新脚本结束!");
117 | }
118 |
119 | const scripts = [
120 | {
121 | moduleName: "RRShare",
122 | url:
123 | "https://raw.githubusercontent.com/evilbutcher/Scriptables/master/RRShare.js",
124 | },
125 | ];
126 | if (goupdate == true) update();
--------------------------------------------------------------------------------
/RRShareMonitor.js:
--------------------------------------------------------------------------------
1 | // Variables used by Scriptable.
2 | // These must be at the very top of the file. Do not edit.
3 | // icon-color: blue; icon-glyph: film;
4 | /*
5 | * Author: evilbutcher
6 | * Github: https://github.com/evilbutcher
7 | * 本脚本使用了@Gideon_Senku的Env.scriptable,感谢!
8 | */
9 | const goupdate = true;
10 | const $ = importModule("Env");
11 | const title = `🎬 人人影视`;
12 | const preview = "medium";
13 | const spacing = 5;
14 |
15 | const res = await getinfo();
16 |
17 | let widget = await createWidget(res);
18 | Script.setWidget(widget);
19 | Script.complete();
20 |
21 | async function createWidget(res) {
22 | items = [];
23 | for (var i = 0; i < 6; i++) {
24 | var item = res[i]["file_name"];
25 | items.push(item);
26 | }
27 | console.log(items);
28 |
29 | const opts = {
30 | title,
31 | texts: {
32 | text1: `• ${items[0]}`,
33 | text2: `• ${items[1]}`,
34 | text3: `• ${items[2]}`,
35 | text4: `• ${items[3]}`,
36 | text5: `• ${items[4]}`,
37 | text6: `• ${items[5]}`,
38 | battery: "true",
39 | },
40 | preview,
41 | spacing,
42 | };
43 |
44 | let widget = await $.createWidget(opts);
45 | return widget;
46 | }
47 |
48 | async function getinfo() {
49 | const zmzRequest = {
50 | url: `http://file.apicvn.com/file/list?page=1&order=create_time&sort=desc`,
51 | headers: {
52 | Host: "file.apicvn.com",
53 | "Content-Type": "application/x-www-form-urlencoded",
54 | "User-Agent": "Mozilla/5.0",
55 | },
56 | };
57 | const res = await $.get(zmzRequest);
58 | log(res);
59 | return res;
60 | }
61 |
62 | //更新代码
63 | function update() {
64 | log("🔔更新脚本开始!");
65 | scripts.forEach(async (script) => {
66 | await $.getFile(script);
67 | });
68 | log("🔔更新脚本结束!");
69 | }
70 |
71 | const scripts = [
72 | {
73 | moduleName: "RRShareMonitor",
74 | url:
75 | "https://raw.githubusercontent.com/evilbutcher/Scriptables/master/RRShareMonitor.js",
76 | },
77 | ];
78 | if (goupdate == true) update();
79 |
--------------------------------------------------------------------------------
/RSS.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: rss;
4 | /*
5 | * Author: evilbutcher
6 | * Github: https://github.com/evilbutcher
7 | * 本脚本使用了@Gideon_Senku的Env.scriptable,感谢!
8 | */
9 | const goupdate = true; //默认关闭,需要更新时请手动打开
10 | const $ = importModule("Env");
11 | var num = 6; //自定义显示数量
12 | var rancolor = true; //true为开启随机颜色
13 | // 填写RSS订阅链接,默认为仓库的最近Commit
14 | // Fill in the RSS subscription link, the default is the latest Commit of the Repo
15 | var rsslink = "https://github.com/GideonSenku/Scriptable/commits/master.atom";
16 | try {
17 | const con = importModule("Config");
18 | num = con.rssnum();
19 | rancolor = con.rssrancolor();
20 | rsslink = con.rsslink();
21 | console.log("将使用配置文件内RSS配置");
22 | } catch (e) {
23 | console.log("将使用脚本内RSS配置");
24 | }
25 |
26 | const res = await getinfo();
27 |
28 | let widget = createWidget(res);
29 | Script.setWidget(widget);
30 | Script.complete();
31 |
32 | function createWidget(res) {
33 | if (res.status == "ok") {
34 | var titlerss = res.feed.title;
35 | var group = res.items;
36 | items = [];
37 | for (var i = 0; i < num; i++) {
38 | var item = group[i].title;
39 | items.push(item);
40 | }
41 | console.log(items);
42 |
43 | const w = new ListWidget();
44 | const bgColor = new LinearGradient();
45 | bgColor.colors = [new Color("#1c1c1c"), new Color("#29323c")];
46 | bgColor.locations = [0.0, 1.0];
47 | w.backgroundGradient = bgColor;
48 | w.addSpacer();
49 | w.spacing = 5;
50 |
51 | const firstLine = w.addText(`📻${titlerss}`);
52 | firstLine.font = new Font('SF Mono', 15);
53 | firstLine.textColor = Color.white();
54 | firstLine.textOpacity = 0.7;
55 |
56 | for (var i = 0; i < items.length; i++) {
57 | addTextToListWidget(`• ${items[i]}`, w);
58 | }
59 |
60 | w.addSpacer();
61 | w.spacing = 5;
62 | w.presentMedium();
63 | return w;
64 | }
65 | }
66 |
67 | async function getinfo() {
68 | const rssRequest = {
69 | url:
70 | "https://api.rss2json.com/v1/api.json?rss_url=" +
71 | encodeURIComponent(rsslink),
72 | };
73 | const res = await $.get(rssRequest);
74 | log(res);
75 | return res;
76 | }
77 |
78 | function addTextToListWidget(text, listWidget) {
79 | let item = listWidget.addText(text);
80 | if (rancolor == true) {
81 | item.textColor = new Color(color16());
82 | } else {
83 | item.textColor = Color.white();
84 | }
85 | item.font = new Font('SF Mono', 12);
86 | }
87 |
88 | function color16() {
89 | var r = Math.floor(Math.random() * 256);
90 | if (r + 50 < 255) {
91 | r = r + 50;
92 | }
93 | if (r > 230 && r < 255) {
94 | r = r - 50;
95 | }
96 | var g = Math.floor(Math.random() * 256);
97 | if (g + 50 < 255) {
98 | g = g + 50;
99 | }
100 | if (g > 230 && g < 255) {
101 | g = g - 50;
102 | }
103 | var b = Math.floor(Math.random() * 256);
104 | if (b + 50 < 255) {
105 | b = b + 50;
106 | }
107 | if (b > 230 && b < 255) {
108 | b = b - 50;
109 | }
110 | var color = "#" + r.toString(16) + g.toString(16) + b.toString(16);
111 | return color;
112 | }
113 |
114 | //更新代码
115 | function update() {
116 | log("🔔更新脚本开始!");
117 | scripts.forEach(async (script) => {
118 | await $.getFile(script);
119 | });
120 | log("🔔更新脚本结束!");
121 | }
122 |
123 | const scripts = [
124 | {
125 | moduleName: "RSS",
126 | url:
127 | "https://raw.githubusercontent.com/evilbutcher/Scriptables/master/RSS.js",
128 | },
129 | ];
130 | if (goupdate == true) update();
--------------------------------------------------------------------------------
/RSSMonitor.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: rss;
4 | /*
5 | * Author: evilbutcher
6 | * Github: https://github.com/evilbutcher
7 | * 本脚本使用了@Gideon_Senku的Env.scriptable,感谢!
8 | */
9 | const goupdate = true; //默认关闭,需要更新时请手动打开
10 | const $ = importModule("Env");
11 | const preview = "medium";
12 | const spacing = 5;
13 | // 填写RSS订阅链接,默认为仓库的最近Commit
14 | // Fill in the RSS subscription link, the default is the latest Commit of the Repo
15 | var rsslink = "https://github.com/GideonSenku/Scriptable/commits/master.atom";
16 | try {
17 | const con = importModule("Config");
18 | rsslink = con.rsslink();
19 | console.log("将使用配置文件内RSS配置");
20 | } catch (e) {
21 | console.log("将使用脚本内RSS配置");
22 | }
23 |
24 | const res = await getinfo();
25 |
26 | let widget = await createWidget(res);
27 | Script.setWidget(widget);
28 | Script.complete();
29 |
30 | async function createWidget(res) {
31 | if (res.status == "ok") {
32 | var titlerss = res.feed.title;
33 | var group = res.items;
34 | items = [];
35 | for (var i = 0; i < 6; i++) {
36 | var item = group[i].title;
37 | items.push(item);
38 | }
39 | console.log(items);
40 |
41 | const title = `📻 ${titlerss}`;
42 | const opts = {
43 | title,
44 | texts: {
45 | text1: `• ${items[0]}`,
46 | text2: `• ${items[1]}`,
47 | text3: `• ${items[2]}`,
48 | text4: `• ${items[3]}`,
49 | text5: `• ${items[4]}`,
50 | text6: `• ${items[5]}`,
51 | battery: "true",
52 | },
53 | preview,
54 | spacing,
55 | };
56 |
57 | let widget = await $.createWidget(opts);
58 | return widget;
59 | }
60 | }
61 |
62 | async function getinfo() {
63 | const rssRequest = {
64 | url:
65 | "https://api.rss2json.com/v1/api.json?rss_url=" +
66 | encodeURIComponent(rsslink),
67 | };
68 | const res = await $.get(rssRequest);
69 | log(res);
70 | return res;
71 | }
72 |
73 | function addTextToListWidget(text, listWidget) {
74 | let item = listWidget.addText(text);
75 | if (rancolor == true) {
76 | item.textColor = new Color(color16());
77 | } else {
78 | item.textColor = Color.white();
79 | }
80 | item.font = new Font("SF Mono", 12);
81 | }
82 |
83 | function color16() {
84 | var r = Math.floor(Math.random() * 256);
85 | if (r + 50 < 255) {
86 | r = r + 50;
87 | }
88 | if (r > 230 && r < 255) {
89 | r = r - 50;
90 | }
91 | var g = Math.floor(Math.random() * 256);
92 | if (g + 50 < 255) {
93 | g = g + 50;
94 | }
95 | if (g > 230 && g < 255) {
96 | g = g - 50;
97 | }
98 | var b = Math.floor(Math.random() * 256);
99 | if (b + 50 < 255) {
100 | b = b + 50;
101 | }
102 | if (b > 230 && b < 255) {
103 | b = b - 50;
104 | }
105 | var color = "#" + r.toString(16) + g.toString(16) + b.toString(16);
106 | return color;
107 | }
108 |
109 | //更新代码
110 | function update() {
111 | log("🔔更新脚本开始!");
112 | scripts.forEach(async (script) => {
113 | await $.getFile(script);
114 | });
115 | log("🔔更新脚本结束!");
116 | }
117 |
118 | const scripts = [
119 | {
120 | moduleName: "RSSMonitor",
121 | url:
122 | "https://raw.githubusercontent.com/evilbutcher/Scriptables/master/RSSMonitor.js",
123 | },
124 | ];
125 | if (goupdate == true) update();
126 |
--------------------------------------------------------------------------------
/Weibo.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: fire;
4 | /*
5 | * Author: evilbutcher
6 | * Github: https://github.com/evilbutcher
7 | * 本脚本使用了@Gideon_Senku的Env.scriptable,感谢!
8 | */
9 | const goupdate = true;
10 | const $ = importModule("Env");
11 | var num = 6; //自定义显示数量
12 | var rancolor = true; //true为开启随机颜色
13 |
14 | try {
15 | var { wbnum, wbrancolor } = importModule("Config");
16 | num = wbnum();
17 | rancolor = wbrancolor();
18 | console.log("将使用配置文件内微博配置");
19 | } catch (e) {
20 | console.log("将使用脚本内微博配置");
21 | }
22 |
23 | const res = await getinfo();
24 |
25 | let widget = createWidget(res);
26 | Script.setWidget(widget);
27 | Script.complete();
28 |
29 | function createWidget(res) {
30 | if (res.data.cards[0].title == "实时热点,每分钟更新一次") {
31 | var group = res.data.cards[0]["card_group"];
32 | items = [];
33 | for (var i = 0; i < num; i++) {
34 | var item = group[i].desc;
35 | items.push(item);
36 | }
37 | console.log(items);
38 |
39 | const w = new ListWidget();
40 | const bgColor = new LinearGradient();
41 | bgColor.colors = [new Color("#1c1c1c"), new Color("#29323c")];
42 | bgColor.locations = [0.0, 1.0];
43 | w.backgroundGradient = bgColor;
44 | w.addSpacer();
45 | w.spacing = 5;
46 |
47 | const firstLine = w.addText(`🔥微博热搜`);
48 | firstLine.font = new Font('SF Mono', 15);
49 | firstLine.textColor = Color.white();
50 | firstLine.textOpacity = 0.7;
51 |
52 | const top1Line = w.addText(`📌 ${items[0]}`);
53 | top1Line.font = new Font('SF Mono', 12);
54 | top1Line.textColor = Color.white();
55 |
56 | for (var i = 1; i < items.length; i++) {
57 | addTextToListWidget(`• ${items[i]}`, w);
58 | }
59 |
60 | w.addSpacer();
61 | w.spacing = 5;
62 | w.presentSmall();
63 | return w;
64 | }
65 | }
66 |
67 | async function getinfo() {
68 | const url = {
69 | url:
70 | "https://m.weibo.cn/api/container/getIndex?containerid=106003%26filter_type%3Drealtimehot",
71 | };
72 | const res = await $.get(url);
73 | log(res);
74 | return res;
75 | }
76 |
77 | function addTextToListWidget(text, listWidget) {
78 | let item = listWidget.addText(text);
79 | if (rancolor == true) {
80 | item.textColor = new Color(color16());
81 | } else {
82 | item.textColor = Color.white();
83 | }
84 | item.font = new Font('SF Mono', 12);
85 | }
86 |
87 | function color16() {
88 | var r = Math.floor(Math.random() * 256);
89 | if (r + 50 < 255) {
90 | r = r + 50;
91 | }
92 | if (r > 230 && r < 255) {
93 | r = r - 50;
94 | }
95 | var g = Math.floor(Math.random() * 256);
96 | if (g + 50 < 255) {
97 | g = g + 50;
98 | }
99 | if (g > 230 && g < 255) {
100 | g = g - 50;
101 | }
102 | var b = Math.floor(Math.random() * 256);
103 | if (b + 50 < 255) {
104 | b = b + 50;
105 | }
106 | if (b > 230 && b < 255) {
107 | b = b - 50;
108 | }
109 | var color = "#" + r.toString(16) + g.toString(16) + b.toString(16);
110 | return color;
111 | }
112 |
113 | //更新代码
114 | function update() {
115 | log("🔔更新脚本开始!");
116 | scripts.forEach(async (script) => {
117 | await $.getFile(script);
118 | });
119 | log("🔔更新脚本结束!");
120 | }
121 |
122 | const scripts = [
123 | {
124 | moduleName: "Weibo",
125 | url:
126 | "https://raw.githubusercontent.com/evilbutcher/Scriptables/master/Weibo.js",
127 | },
128 | ];
129 | if (goupdate == true) update();
--------------------------------------------------------------------------------
/WeiboMonitor.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: fire;
4 | /*
5 | * Author: evilbutcher
6 | * Github: https://github.com/evilbutcher
7 | * 本脚本使用了@Gideon_Senku的Env.scriptable,感谢!
8 | */
9 | const goupdate = true;
10 | const $ = importModule("Env");
11 | const title = `🔥 微博热搜`;
12 | const preview = "medium";
13 | const spacing = 5;
14 |
15 | const res = await getinfo();
16 |
17 | let widget = await createWidget(res);
18 | Script.setWidget(widget);
19 | Script.complete();
20 |
21 | async function createWidget(res) {
22 | if (res.data.cards[0].title == "实时热点,每分钟更新一次") {
23 | var group = res.data.cards[0]["card_group"];
24 | items = [];
25 | for (var i = 0; i < 6; i++) {
26 | var item = group[i].desc;
27 | items.push(item);
28 | }
29 | console.log(items);
30 |
31 | const opts = {
32 | title,
33 | texts: {
34 | text1: { text: `📌 ${items[0]}`, url: group[0].scheme },
35 | text2: { text: `• ${items[1]}`, url: group[1].scheme },
36 | text3: { text: `• ${items[2]}`, url: group[2].scheme },
37 | text4: { text: `• ${items[3]}`, url: group[3].scheme },
38 | text5: { text: `• ${items[4]}`, url: group[4].scheme },
39 | text6: { text: `• ${items[5]}`, url: group[5].scheme },
40 | battery: "true",
41 | },
42 | preview,
43 | spacing,
44 | };
45 |
46 | let widget = await $.createWidget(opts);
47 | return widget;
48 | }
49 | }
50 |
51 | async function getinfo() {
52 | const url = {
53 | url:
54 | "https://m.weibo.cn/api/container/getIndex?containerid=106003%26filter_type%3Drealtimehot",
55 | };
56 | const res = await $.get(url);
57 | //log(res);
58 | return res;
59 | }
60 |
61 | //更新代码
62 | function update() {
63 | log("🔔更新脚本开始!");
64 | scripts.forEach(async (script) => {
65 | await $.getFile(script);
66 | });
67 | log("🔔更新脚本结束!");
68 | }
69 |
70 | const scripts = [
71 | {
72 | moduleName: "WeiboMonitor",
73 | url:
74 | "https://raw.githubusercontent.com/evilbutcher/Scriptables/master/WeiboMonitor.js",
75 | },
76 | ];
77 | if (goupdate == true) update();
78 |
--------------------------------------------------------------------------------
/Zhihu.js:
--------------------------------------------------------------------------------
1 | // Variables used by Scriptable.
2 | // These must be at the very top of the file. Do not edit.
3 | // icon-color: deep-blue; icon-glyph: book-open;
4 | /*
5 | * Author: evilbutcher
6 | * Github: https://github.com/evilbutcher
7 | * 本脚本使用了@Gideon_Senku的Env.scriptable,感谢!
8 | */
9 | const goupdate = true;
10 | const $ = importModule("Env");
11 | var num = 6; //自定义显示数量
12 | var rancolor = true; //true为开启随机颜色
13 |
14 | try {
15 | var { zhnum, zhrancolor } = importModule("Config");
16 | num = zhnum();
17 | rancolor = zhrancolor();
18 | console.log("将使用配置文件内知乎配置");
19 | } catch (e) {
20 | console.log("将使用脚本内知乎配置");
21 | }
22 |
23 | const res = await getinfo();
24 |
25 | let widget = createWidget(res);
26 | Script.setWidget(widget);
27 | Script.complete();
28 |
29 | function createWidget(res) {
30 | if (res.fresh_text == "热榜已更新") {
31 | var group = res.data;
32 | items = [];
33 | for (var i = 0; i < num; i++) {
34 | var item = group[i].target.title;
35 | items.push(item);
36 | }
37 | console.log(items);
38 |
39 | const w = new ListWidget();
40 | const bgColor = new LinearGradient();
41 | bgColor.colors = [new Color("#1c1c1c"), new Color("#29323c")];
42 | bgColor.locations = [0.0, 1.0];
43 | w.backgroundGradient = bgColor;
44 | w.addSpacer();
45 | w.spacing = 5;
46 |
47 | const firstLine = w.addText(`📖知乎热榜`);
48 | firstLine.font = new Font('SF Mono', 15);
49 | firstLine.textColor = Color.white();
50 | firstLine.textOpacity = 0.7;
51 |
52 | for (var i = 0; i < items.length; i++) {
53 | addTextToListWidget(`• ${items[i]}`, w);
54 | }
55 |
56 | w.addSpacer();
57 | w.spacing = 5;
58 | w.presentSmall();
59 | return w;
60 | }
61 | }
62 |
63 | async function getinfo() {
64 | const url = {
65 | url: `https://api.zhihu.com/topstory/hot-lists/total?limit=10&reverse_order=0`,
66 | };
67 | const res = await $.get(url);
68 | log(res);
69 | return res;
70 | }
71 |
72 | function addTextToListWidget(text, listWidget) {
73 | let item = listWidget.addText(text);
74 | if (rancolor == true) {
75 | item.textColor = new Color(color16());
76 | } else {
77 | item.textColor = Color.white();
78 | }
79 | item.font = new Font('SF Mono', 12);
80 | }
81 |
82 | function color16() {
83 | var r = Math.floor(Math.random() * 256);
84 | if (r + 50 < 255) {
85 | r = r + 50;
86 | }
87 | if (r > 230 && r < 255) {
88 | r = r - 50;
89 | }
90 | var g = Math.floor(Math.random() * 256);
91 | if (g + 50 < 255) {
92 | g = g + 50;
93 | }
94 | if (g > 230 && g < 255) {
95 | g = g - 50;
96 | }
97 | var b = Math.floor(Math.random() * 256);
98 | if (b + 50 < 255) {
99 | b = b + 50;
100 | }
101 | if (b > 230 && b < 255) {
102 | b = b - 50;
103 | }
104 | var color = "#" + r.toString(16) + g.toString(16) + b.toString(16);
105 | return color;
106 | }
107 |
108 | //更新代码
109 | function update() {
110 | log("🔔更新脚本开始!");
111 | scripts.forEach(async (script) => {
112 | await $.getFile(script);
113 | });
114 | log("🔔更新脚本结束!");
115 | }
116 |
117 | const scripts = [
118 | {
119 | moduleName: "Zhihu",
120 | url:
121 | "https://raw.githubusercontent.com/evilbutcher/Scriptables/master/Zhihu.js",
122 | },
123 | ];
124 | if (goupdate == true) update();
--------------------------------------------------------------------------------
/ZhihuMonitor.js:
--------------------------------------------------------------------------------
1 | // Variables used by Scriptable.
2 | // These must be at the very top of the file. Do not edit.
3 | // icon-color: deep-blue; icon-glyph: book-open;
4 | /*
5 | * Author: evilbutcher
6 | * Github: https://github.com/evilbutcher
7 | * 本脚本使用了@Gideon_Senku的Env.scriptable,感谢!
8 | */
9 | const goupdate = false;
10 | const $ = importModule("Env");
11 | const title = `📖 知乎热榜`;
12 | const preview = "medium";
13 | const spacing = 5;
14 | const goto = 'app'; // 可更改为 browser,跳转到浏览器,选择跳转 app 时若未安装 app,则会无响应
15 |
16 | const res = await getinfo();
17 |
18 | let widget = await createWidget(res);
19 | Script.setWidget(widget);
20 | Script.complete();
21 |
22 | function decideGoto(item) {
23 | switch(goto) {
24 | case 'app':
25 | return `zhihu://question/${item.target.id}`;
26 | case 'browser':
27 | return `https://m.zhihu.com/question/${item.target.id}`;
28 | default:
29 | return void 0;
30 | }
31 | }
32 |
33 | async function createWidget(res) {
34 | if (res.fresh_text == "热榜已更新") {
35 | var group = res.data;
36 | items = [];
37 | for (var i = 0; i < 6; i++) {
38 | var item = group[i].target.title;
39 | items.push(item);
40 | }
41 | console.log(items);
42 |
43 | const opts = {
44 | title,
45 | texts: {
46 | text1: { text: `• ${items[0]}`, url: decideGoto(group[0]) },
47 | text2: { text: `• ${items[1]}`, url: decideGoto(group[1]) },
48 | text3: { text: `• ${items[2]}`, url: decideGoto(group[2]) },
49 | text4: { text: `• ${items[3]}`, url: decideGoto(group[3]) },
50 | text5: { text: `• ${items[4]}`, url: decideGoto(group[4]) },
51 | text6: { text: `• ${items[5]}`, url: decideGoto(group[5]) },
52 | battery: "true",
53 | },
54 | preview,
55 | spacing,
56 | };
57 |
58 | let widget = await $.createWidget(opts);
59 | return widget;
60 | }
61 | }
62 |
63 | async function getinfo() {
64 | const url = {
65 | url: `https://api.zhihu.com/topstory/hot-lists/total?limit=10&reverse_order=0`,
66 | };
67 | const res = await $.get(url);
68 | log(res);
69 | return res;
70 | }
71 |
72 | //更新代码
73 | function update() {
74 | log("🔔更新脚本开始!");
75 | scripts.forEach(async (script) => {
76 | await $.getFile(script);
77 | });
78 | log("🔔更新脚本结束!");
79 | }
80 |
81 | const scripts = [
82 | {
83 | moduleName: "ZhihuMonitor",
84 | url:
85 | "https://raw.githubusercontent.com/evilbutcher/Scriptables/master/ZhihuMonitor.js",
86 | },
87 | ];
88 | if (goupdate == true) update();
89 |
--------------------------------------------------------------------------------
/checkin_example.json:
--------------------------------------------------------------------------------
1 | {
2 | "c1": {
3 | "title": "name",
4 | "url": "https://your.loginurl.com/auth/login",
5 | "email": "example@email.com",
6 | "password": "password"
7 | },
8 | "c2": {
9 | "title": "name",
10 | "url": "https://your.loginurl.com/auth/login",
11 | "email": "example@email.com",
12 | "password": "password"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/crypto-js.js:
--------------------------------------------------------------------------------
1 | // Variables used by Scriptable.
2 | // These must be at the very top of the file. Do not edit.
3 | // icon-color: teal; icon-glyph: cogs;
4 |
5 | (function(t,e){"object"==typeof exports?module.exports=exports=e():"function"==typeof define&&define.amd?define([],e):t.CryptoJS=e()})(this,function(){var t,e,r,i,n,o,s,c,a,h,l=l||function(t,e){var r;if("undefined"!=typeof window&&window.crypto&&(r=window.crypto),!r&&"undefined"!=typeof window&&window.msCrypto&&(r=window.msCrypto),!r&&"undefined"!=typeof global&&global.crypto&&(r=global.crypto),!r&&"function"==typeof require)try{r=require("crypto")}catch(t){}var i=function(){if(r){if("function"==typeof r.getRandomValues)try{return r.getRandomValues(new Uint32Array(1))[0]}catch(t){}if("function"==typeof r.randomBytes)try{return r.randomBytes(4).readInt32LE()}catch(t){}}throw new Error("Native crypto module could not be used to get secure random number.")},n=Object.create||function(){function t(){}return function(e){var r;return t.prototype=e,r=new t,t.prototype=null,r}}(),o={},s=o.lib={},c=s.Base={extend:function(t){var e=n(this);return t&&e.mixIn(t),e.hasOwnProperty("init")&&this.init!==e.init||(e.init=function(){e.$super.init.apply(this,arguments)}),e.init.prototype=e,e.$super=this,e},create:function(){var t=this.extend();return t.init.apply(t,arguments),t},init:function(){},mixIn:function(t){for(var e in t)t.hasOwnProperty(e)&&(this[e]=t[e]);t.hasOwnProperty("toString")&&(this.toString=t.toString)},clone:function(){return this.init.prototype.extend(this)}},a=s.WordArray=c.extend({init:function(t,r){t=this.words=t||[],this.sigBytes=r!=e?r:4*t.length},toString:function(t){return(t||l).stringify(this)},concat:function(t){var e=this.words,r=t.words,i=this.sigBytes,n=t.sigBytes;if(this.clamp(),i%4)for(var o=0;o>>2]>>>24-o%4*8&255;e[i+o>>>2]|=s<<24-(i+o)%4*8}else for(o=0;o>>2]=r[o>>>2];return this.sigBytes+=n,this},clamp:function(){var e=this.words,r=this.sigBytes;e[r>>>2]&=4294967295<<32-r%4*8,e.length=t.ceil(r/4)},clone:function(){var t=c.clone.call(this);return t.words=this.words.slice(0),t},random:function(t){for(var e=[],r=0;r>>2]>>>24-n%4*8&255;i.push((o>>>4).toString(16)),i.push((15&o).toString(16))}return i.join("")},parse:function(t){for(var e=t.length,r=[],i=0;i>>3]|=parseInt(t.substr(i,2),16)<<24-i%8*4;return new a.init(r,e/2)}},f=h.Latin1={stringify:function(t){for(var e=t.words,r=t.sigBytes,i=[],n=0;n>>2]>>>24-n%4*8&255;i.push(String.fromCharCode(o))}return i.join("")},parse:function(t){for(var e=t.length,r=[],i=0;i>>2]|=(255&t.charCodeAt(i))<<24-i%4*8;return new a.init(r,e)}},u=h.Utf8={stringify:function(t){try{return decodeURIComponent(escape(f.stringify(t)))}catch(t){throw new Error("Malformed UTF-8 data")}},parse:function(t){return f.parse(unescape(encodeURIComponent(t)))}},d=s.BufferedBlockAlgorithm=c.extend({reset:function(){this._data=new a.init,this._nDataBytes=0},_append:function(t){"string"==typeof t&&(t=u.parse(t)),this._data.concat(t),this._nDataBytes+=t.sigBytes},_process:function(e){var r,i=this._data,n=i.words,o=i.sigBytes,s=this.blockSize,c=4*s,h=o/c;h=e?t.ceil(h):t.max((0|h)-this._minBufferSize,0);var l=h*s,f=t.min(4*l,o);if(l){for(var u=0;u>>6-s%4*2,h=c|a;n[o>>>2]|=h<<24-o%4*8,o++}return i.create(n,o)}var e=l,r=e.lib,i=r.WordArray,n=e.enc;n.Base64={stringify:function(t){var e=t.words,r=t.sigBytes,i=this._map;t.clamp();for(var n=[],o=0;o>>2]>>>24-o%4*8&255,c=e[o+1>>>2]>>>24-(o+1)%4*8&255,a=e[o+2>>>2]>>>24-(o+2)%4*8&255,h=s<<16|c<<8|a,l=0;l<4&&o+.75*l>>6*(3-l)&63));var f=i.charAt(64);if(f)for(;n.length%4;)n.push(f);return n.join("")},parse:function(e){var r=e.length,i=this._map,n=this._reverseMap;if(!n){n=this._reverseMap=[];for(var o=0;o>>32-o)+e}function r(t,e,r,i,n,o,s){var c=t+(e&i|r&~i)+n+s;return(c<>>32-o)+e}function i(t,e,r,i,n,o,s){var c=t+(e^r^i)+n+s;return(c<>>32-o)+e}function n(t,e,r,i,n,o,s){var c=t+(r^(e|~i))+n+s;return(c<>>32-o)+e}var o=l,s=o.lib,c=s.WordArray,a=s.Hasher,h=o.algo,f=[];(function(){for(var e=0;e<64;e++)f[e]=4294967296*t.abs(t.sin(e+1))|0})();var u=h.MD5=a.extend({_doReset:function(){this._hash=new c.init([1732584193,4023233417,2562383102,271733878])},_doProcessBlock:function(t,o){for(var s=0;s<16;s++){var c=o+s,a=t[c];t[c]=16711935&(a<<8|a>>>24)|4278255360&(a<<24|a>>>8)}var h=this._hash.words,l=t[o+0],u=t[o+1],d=t[o+2],p=t[o+3],_=t[o+4],v=t[o+5],y=t[o+6],g=t[o+7],B=t[o+8],w=t[o+9],k=t[o+10],S=t[o+11],m=t[o+12],x=t[o+13],b=t[o+14],H=t[o+15],z=h[0],A=h[1],C=h[2],D=h[3];z=e(z,A,C,D,l,7,f[0]),D=e(D,z,A,C,u,12,f[1]),C=e(C,D,z,A,d,17,f[2]),A=e(A,C,D,z,p,22,f[3]),z=e(z,A,C,D,_,7,f[4]),D=e(D,z,A,C,v,12,f[5]),C=e(C,D,z,A,y,17,f[6]),A=e(A,C,D,z,g,22,f[7]),z=e(z,A,C,D,B,7,f[8]),D=e(D,z,A,C,w,12,f[9]),C=e(C,D,z,A,k,17,f[10]),A=e(A,C,D,z,S,22,f[11]),z=e(z,A,C,D,m,7,f[12]),D=e(D,z,A,C,x,12,f[13]),C=e(C,D,z,A,b,17,f[14]),A=e(A,C,D,z,H,22,f[15]),z=r(z,A,C,D,u,5,f[16]),D=r(D,z,A,C,y,9,f[17]),C=r(C,D,z,A,S,14,f[18]),A=r(A,C,D,z,l,20,f[19]),z=r(z,A,C,D,v,5,f[20]),D=r(D,z,A,C,k,9,f[21]),C=r(C,D,z,A,H,14,f[22]),A=r(A,C,D,z,_,20,f[23]),z=r(z,A,C,D,w,5,f[24]),D=r(D,z,A,C,b,9,f[25]),C=r(C,D,z,A,p,14,f[26]),A=r(A,C,D,z,B,20,f[27]),z=r(z,A,C,D,x,5,f[28]),D=r(D,z,A,C,d,9,f[29]),C=r(C,D,z,A,g,14,f[30]),A=r(A,C,D,z,m,20,f[31]),z=i(z,A,C,D,v,4,f[32]),D=i(D,z,A,C,B,11,f[33]),C=i(C,D,z,A,S,16,f[34]),A=i(A,C,D,z,b,23,f[35]),z=i(z,A,C,D,u,4,f[36]),D=i(D,z,A,C,_,11,f[37]),C=i(C,D,z,A,g,16,f[38]),A=i(A,C,D,z,k,23,f[39]),z=i(z,A,C,D,x,4,f[40]),D=i(D,z,A,C,l,11,f[41]),C=i(C,D,z,A,p,16,f[42]),A=i(A,C,D,z,y,23,f[43]),z=i(z,A,C,D,w,4,f[44]),D=i(D,z,A,C,m,11,f[45]),C=i(C,D,z,A,H,16,f[46]),A=i(A,C,D,z,d,23,f[47]),z=n(z,A,C,D,l,6,f[48]),D=n(D,z,A,C,g,10,f[49]),C=n(C,D,z,A,b,15,f[50]),A=n(A,C,D,z,v,21,f[51]),z=n(z,A,C,D,m,6,f[52]),D=n(D,z,A,C,p,10,f[53]),C=n(C,D,z,A,k,15,f[54]),A=n(A,C,D,z,u,21,f[55]),z=n(z,A,C,D,B,6,f[56]),D=n(D,z,A,C,H,10,f[57]),C=n(C,D,z,A,y,15,f[58]),A=n(A,C,D,z,x,21,f[59]),z=n(z,A,C,D,_,6,f[60]),D=n(D,z,A,C,S,10,f[61]),C=n(C,D,z,A,d,15,f[62]),A=n(A,C,D,z,w,21,f[63]),h[0]=h[0]+z|0,h[1]=h[1]+A|0,h[2]=h[2]+C|0,h[3]=h[3]+D|0},_doFinalize:function(){var e=this._data,r=e.words,i=8*this._nDataBytes,n=8*e.sigBytes;r[n>>>5]|=128<<24-n%32;var o=t.floor(i/4294967296),s=i;r[15+(n+64>>>9<<4)]=16711935&(o<<8|o>>>24)|4278255360&(o<<24|o>>>8),r[14+(n+64>>>9<<4)]=16711935&(s<<8|s>>>24)|4278255360&(s<<24|s>>>8),e.sigBytes=4*(r.length+1),this._process();for(var c=this._hash,a=c.words,h=0;h<4;h++){var l=a[h];a[h]=16711935&(l<<8|l>>>24)|4278255360&(l<<24|l>>>8)}return c},clone:function(){var t=a.clone.call(this);return t._hash=this._hash.clone(),t}});o.MD5=a._createHelper(u),o.HmacMD5=a._createHmacHelper(u)}(Math),t=l,e=t.lib,r=e.WordArray,i=e.Hasher,n=t.algo,o=[],s=n.SHA1=i.extend({_doReset:function(){this._hash=new r.init([1732584193,4023233417,2562383102,271733878,3285377520])},_doProcessBlock:function(t,e){for(var r=this._hash.words,i=r[0],n=r[1],s=r[2],c=r[3],a=r[4],h=0;h<80;h++){if(h<16)o[h]=0|t[e+h];else{var l=o[h-3]^o[h-8]^o[h-14]^o[h-16];o[h]=l<<1|l>>>31}var f=(i<<5|i>>>27)+a+o[h];f+=h<20?1518500249+(n&s|~n&c):h<40?1859775393+(n^s^c):h<60?(n&s|n&c|s&c)-1894007588:(n^s^c)-899497514,a=c,c=s,s=n<<30|n>>>2,n=i,i=f}r[0]=r[0]+i|0,r[1]=r[1]+n|0,r[2]=r[2]+s|0,r[3]=r[3]+c|0,r[4]=r[4]+a|0},_doFinalize:function(){var t=this._data,e=t.words,r=8*this._nDataBytes,i=8*t.sigBytes;return e[i>>>5]|=128<<24-i%32,e[14+(i+64>>>9<<4)]=Math.floor(r/4294967296),e[15+(i+64>>>9<<4)]=r,t.sigBytes=4*e.length,this._process(),this._hash},clone:function(){var t=i.clone.call(this);return t._hash=this._hash.clone(),t}}),t.SHA1=i._createHelper(s),t.HmacSHA1=i._createHmacHelper(s),function(t){var e=l,r=e.lib,i=r.WordArray,n=r.Hasher,o=e.algo,s=[],c=[];(function(){function e(e){for(var r=t.sqrt(e),i=2;i<=r;i++)if(!(e%i))return!1;return!0}function r(t){return 4294967296*(t-(0|t))|0}for(var i=2,n=0;n<64;)e(i)&&(n<8&&(s[n]=r(t.pow(i,.5))),c[n]=r(t.pow(i,1/3)),n++),i++})();var a=[],h=o.SHA256=n.extend({_doReset:function(){this._hash=new i.init(s.slice(0))},_doProcessBlock:function(t,e){for(var r=this._hash.words,i=r[0],n=r[1],o=r[2],s=r[3],h=r[4],l=r[5],f=r[6],u=r[7],d=0;d<64;d++){if(d<16)a[d]=0|t[e+d];else{var p=a[d-15],_=(p<<25|p>>>7)^(p<<14|p>>>18)^p>>>3,v=a[d-2],y=(v<<15|v>>>17)^(v<<13|v>>>19)^v>>>10;a[d]=_+a[d-7]+y+a[d-16]}var g=h&l^~h&f,B=i&n^i&o^n&o,w=(i<<30|i>>>2)^(i<<19|i>>>13)^(i<<10|i>>>22),k=(h<<26|h>>>6)^(h<<21|h>>>11)^(h<<7|h>>>25),S=u+k+g+c[d]+a[d],m=w+B;u=f,f=l,l=h,h=s+S|0,s=o,o=n,n=i,i=S+m|0}r[0]=r[0]+i|0,r[1]=r[1]+n|0,r[2]=r[2]+o|0,r[3]=r[3]+s|0,r[4]=r[4]+h|0,r[5]=r[5]+l|0,r[6]=r[6]+f|0,r[7]=r[7]+u|0},_doFinalize:function(){var e=this._data,r=e.words,i=8*this._nDataBytes,n=8*e.sigBytes;return r[n>>>5]|=128<<24-n%32,r[14+(n+64>>>9<<4)]=t.floor(i/4294967296),r[15+(n+64>>>9<<4)]=i,e.sigBytes=4*r.length,this._process(),this._hash},clone:function(){var t=n.clone.call(this);return t._hash=this._hash.clone(),t}});e.SHA256=n._createHelper(h),e.HmacSHA256=n._createHmacHelper(h)}(Math),function(){function t(t){return t<<8&4278255360|t>>>8&16711935}var e=l,r=e.lib,i=r.WordArray,n=e.enc;n.Utf16=n.Utf16BE={stringify:function(t){for(var e=t.words,r=t.sigBytes,i=[],n=0;n>>2]>>>16-n%4*8&65535;i.push(String.fromCharCode(o))}return i.join("")},parse:function(t){for(var e=t.length,r=[],n=0;n>>1]|=t.charCodeAt(n)<<16-n%2*16;return i.create(r,2*e)}};n.Utf16LE={stringify:function(e){for(var r=e.words,i=e.sigBytes,n=[],o=0;o>>2]>>>16-o%4*8&65535);n.push(String.fromCharCode(s))}return n.join("")},parse:function(e){for(var r=e.length,n=[],o=0;o>>1]|=t(e.charCodeAt(o)<<16-o%2*16);return i.create(n,2*r)}}}(),function(){if("function"==typeof ArrayBuffer){var t=l,e=t.lib,r=e.WordArray,i=r.init,n=r.init=function(t){if(t instanceof ArrayBuffer&&(t=new Uint8Array(t)),(t instanceof Int8Array||"undefined"!=typeof Uint8ClampedArray&&t instanceof Uint8ClampedArray||t instanceof Int16Array||t instanceof Uint16Array||t instanceof Int32Array||t instanceof Uint32Array||t instanceof Float32Array||t instanceof Float64Array)&&(t=new Uint8Array(t.buffer,t.byteOffset,t.byteLength)),t instanceof Uint8Array){for(var e=t.byteLength,r=[],n=0;n>>2]|=t[n]<<24-n%4*8;i.call(this,r,e)}else i.apply(this,arguments)};n.prototype=r}}(),function(t){function e(t,e,r){return t^e^r}function r(t,e,r){return t&e|~t&r}function i(t,e,r){return(t|~e)^r}function n(t,e,r){return t&r|e&~r}function o(t,e,r){return t^(e|~r)}function s(t,e){return t<>>32-e}var c=l,a=c.lib,h=a.WordArray,f=a.Hasher,u=c.algo,d=h.create([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,7,4,13,1,10,6,15,3,12,0,9,5,2,14,11,8,3,10,14,4,9,15,8,1,2,7,0,6,13,11,5,12,1,9,11,10,0,8,12,4,13,3,7,15,14,5,6,2,4,0,5,9,7,12,2,10,14,1,3,8,11,6,15,13]),p=h.create([5,14,7,0,9,2,11,4,13,6,15,8,1,10,3,12,6,11,3,7,0,13,5,10,14,15,8,12,4,9,1,2,15,5,1,3,7,14,6,9,11,8,12,2,10,0,4,13,8,6,4,1,3,11,15,0,5,12,2,13,9,7,10,14,12,15,10,4,1,5,8,7,6,2,13,14,0,3,9,11]),_=h.create([11,14,15,12,5,8,7,9,11,13,14,15,6,7,9,8,7,6,8,13,11,9,7,15,7,12,15,9,11,7,13,12,11,13,6,7,14,9,13,15,14,8,13,6,5,12,7,5,11,12,14,15,14,15,9,8,9,14,5,6,8,6,5,12,9,15,5,11,6,8,13,12,5,12,13,14,11,8,5,6]),v=h.create([8,9,9,11,13,15,15,5,7,7,8,11,14,14,12,6,9,13,15,7,12,8,9,11,7,7,12,7,6,15,13,11,9,7,15,11,8,6,6,14,12,13,5,14,13,13,7,5,15,5,8,11,14,14,6,14,6,9,12,9,12,5,15,8,8,5,12,9,12,5,14,6,8,13,6,5,15,13,11,11]),y=h.create([0,1518500249,1859775393,2400959708,2840853838]),g=h.create([1352829926,1548603684,1836072691,2053994217,0]),B=u.RIPEMD160=f.extend({_doReset:function(){this._hash=h.create([1732584193,4023233417,2562383102,271733878,3285377520])},_doProcessBlock:function(t,c){for(var a=0;a<16;a++){var h=c+a,l=t[h];t[h]=16711935&(l<<8|l>>>24)|4278255360&(l<<24|l>>>8)}var f,u,B,w,k,S,m,x,b,H,z,A=this._hash.words,C=y.words,D=g.words,E=d.words,R=p.words,M=_.words,F=v.words;S=f=A[0],m=u=A[1],x=B=A[2],b=w=A[3],H=k=A[4];for(a=0;a<80;a+=1)z=f+t[c+E[a]]|0,z+=a<16?e(u,B,w)+C[0]:a<32?r(u,B,w)+C[1]:a<48?i(u,B,w)+C[2]:a<64?n(u,B,w)+C[3]:o(u,B,w)+C[4],z|=0,z=s(z,M[a]),z=z+k|0,f=k,k=w,w=s(B,10),B=u,u=z,z=S+t[c+R[a]]|0,z+=a<16?o(m,x,b)+D[0]:a<32?n(m,x,b)+D[1]:a<48?i(m,x,b)+D[2]:a<64?r(m,x,b)+D[3]:e(m,x,b)+D[4],z|=0,z=s(z,F[a]),z=z+H|0,S=H,H=b,b=s(x,10),x=m,m=z;z=A[1]+B+b|0,A[1]=A[2]+w+H|0,A[2]=A[3]+k+S|0,A[3]=A[4]+f+m|0,A[4]=A[0]+u+x|0,A[0]=z},_doFinalize:function(){var t=this._data,e=t.words,r=8*this._nDataBytes,i=8*t.sigBytes;e[i>>>5]|=128<<24-i%32,e[14+(i+64>>>9<<4)]=16711935&(r<<8|r>>>24)|4278255360&(r<<24|r>>>8),t.sigBytes=4*(e.length+1),this._process();for(var n=this._hash,o=n.words,s=0;s<5;s++){var c=o[s];o[s]=16711935&(c<<8|c>>>24)|4278255360&(c<<24|c>>>8)}return n},clone:function(){var t=f.clone.call(this);return t._hash=this._hash.clone(),t}});c.RIPEMD160=f._createHelper(B),c.HmacRIPEMD160=f._createHmacHelper(B)}(Math),function(){var t=l,e=t.lib,r=e.Base,i=t.enc,n=i.Utf8,o=t.algo;o.HMAC=r.extend({init:function(t,e){t=this._hasher=new t.init,"string"==typeof e&&(e=n.parse(e));var r=t.blockSize,i=4*r;e.sigBytes>i&&(e=t.finalize(e)),e.clamp();for(var o=this._oKey=e.clone(),s=this._iKey=e.clone(),c=o.words,a=s.words,h=0;h>>24)|4278255360&(o<<24|o>>>8),s=16711935&(s<<8|s>>>24)|4278255360&(s<<24|s>>>8);var c=r[n];c.high^=s,c.low^=o}for(var l=0;l<24;l++){for(var d=0;d<5;d++){for(var p=0,_=0,v=0;v<5;v++){c=r[d+5*v];p^=c.high,_^=c.low}var y=u[d];y.high=p,y.low=_}for(d=0;d<5;d++){var g=u[(d+4)%5],B=u[(d+1)%5],w=B.high,k=B.low;for(p=g.high^(w<<1|k>>>31),_=g.low^(k<<1|w>>>31),v=0;v<5;v++){c=r[d+5*v];c.high^=p,c.low^=_}}for(var S=1;S<25;S++){c=r[S];var m=c.high,x=c.low,b=a[S];b<32?(p=m<>>32-b,_=x<>>32-b):(p=x<>>64-b,_=m<>>64-b);var H=u[h[S]];H.high=p,H.low=_}var z=u[0],A=r[0];z.high=A.high,z.low=A.low;for(d=0;d<5;d++)for(v=0;v<5;v++){S=d+5*v,c=r[S];var C=u[S],D=u[(d+1)%5+5*v],E=u[(d+2)%5+5*v];c.high=C.high^~D.high&E.high,c.low=C.low^~D.low&E.low}c=r[0];var R=f[l];c.high^=R.high,c.low^=R.low}},_doFinalize:function(){var e=this._data,r=e.words,n=(this._nDataBytes,8*e.sigBytes),o=32*this.blockSize;r[n>>>5]|=1<<24-n%32,r[(t.ceil((n+1)/o)*o>>>5)-1]|=128,e.sigBytes=4*r.length,this._process();for(var s=this._state,c=this.cfg.outputLength/8,a=c/8,h=[],l=0;l>>24)|4278255360&(u<<24|u>>>8),d=16711935&(d<<8|d>>>24)|4278255360&(d<<24|d>>>8),h.push(d),h.push(u)}return new i.init(h,c)},clone:function(){for(var t=n.clone.call(this),e=t._state=this._state.slice(0),r=0;r<25;r++)e[r]=e[r].clone();return t}});e.SHA3=n._createHelper(d),e.HmacSHA3=n._createHmacHelper(d)}(Math),function(){function t(){return o.create.apply(o,arguments)}var e=l,r=e.lib,i=r.Hasher,n=e.x64,o=n.Word,s=n.WordArray,c=e.algo,a=[t(1116352408,3609767458),t(1899447441,602891725),t(3049323471,3964484399),t(3921009573,2173295548),t(961987163,4081628472),t(1508970993,3053834265),t(2453635748,2937671579),t(2870763221,3664609560),t(3624381080,2734883394),t(310598401,1164996542),t(607225278,1323610764),t(1426881987,3590304994),t(1925078388,4068182383),t(2162078206,991336113),t(2614888103,633803317),t(3248222580,3479774868),t(3835390401,2666613458),t(4022224774,944711139),t(264347078,2341262773),t(604807628,2007800933),t(770255983,1495990901),t(1249150122,1856431235),t(1555081692,3175218132),t(1996064986,2198950837),t(2554220882,3999719339),t(2821834349,766784016),t(2952996808,2566594879),t(3210313671,3203337956),t(3336571891,1034457026),t(3584528711,2466948901),t(113926993,3758326383),t(338241895,168717936),t(666307205,1188179964),t(773529912,1546045734),t(1294757372,1522805485),t(1396182291,2643833823),t(1695183700,2343527390),t(1986661051,1014477480),t(2177026350,1206759142),t(2456956037,344077627),t(2730485921,1290863460),t(2820302411,3158454273),t(3259730800,3505952657),t(3345764771,106217008),t(3516065817,3606008344),t(3600352804,1432725776),t(4094571909,1467031594),t(275423344,851169720),t(430227734,3100823752),t(506948616,1363258195),t(659060556,3750685593),t(883997877,3785050280),t(958139571,3318307427),t(1322822218,3812723403),t(1537002063,2003034995),t(1747873779,3602036899),t(1955562222,1575990012),t(2024104815,1125592928),t(2227730452,2716904306),t(2361852424,442776044),t(2428436474,593698344),t(2756734187,3733110249),t(3204031479,2999351573),t(3329325298,3815920427),t(3391569614,3928383900),t(3515267271,566280711),t(3940187606,3454069534),t(4118630271,4000239992),t(116418474,1914138554),t(174292421,2731055270),t(289380356,3203993006),t(460393269,320620315),t(685471733,587496836),t(852142971,1086792851),t(1017036298,365543100),t(1126000580,2618297676),t(1288033470,3409855158),t(1501505948,4234509866),t(1607167915,987167468),t(1816402316,1246189591)],h=[];(function(){for(var e=0;e<80;e++)h[e]=t()})();var f=c.SHA512=i.extend({_doReset:function(){this._hash=new s.init([new o.init(1779033703,4089235720),new o.init(3144134277,2227873595),new o.init(1013904242,4271175723),new o.init(2773480762,1595750129),new o.init(1359893119,2917565137),new o.init(2600822924,725511199),new o.init(528734635,4215389547),new o.init(1541459225,327033209)])},_doProcessBlock:function(t,e){for(var r=this._hash.words,i=r[0],n=r[1],o=r[2],s=r[3],c=r[4],l=r[5],f=r[6],u=r[7],d=i.high,p=i.low,_=n.high,v=n.low,y=o.high,g=o.low,B=s.high,w=s.low,k=c.high,S=c.low,m=l.high,x=l.low,b=f.high,H=f.low,z=u.high,A=u.low,C=d,D=p,E=_,R=v,M=y,F=g,P=B,W=w,O=k,I=S,U=m,K=x,X=b,L=H,j=z,N=A,T=0;T<80;T++){var q,Z,V=h[T];if(T<16)Z=V.high=0|t[e+2*T],q=V.low=0|t[e+2*T+1];else{var G=h[T-15],J=G.high,$=G.low,Q=(J>>>1|$<<31)^(J>>>8|$<<24)^J>>>7,Y=($>>>1|J<<31)^($>>>8|J<<24)^($>>>7|J<<25),tt=h[T-2],et=tt.high,rt=tt.low,it=(et>>>19|rt<<13)^(et<<3|rt>>>29)^et>>>6,nt=(rt>>>19|et<<13)^(rt<<3|et>>>29)^(rt>>>6|et<<26),ot=h[T-7],st=ot.high,ct=ot.low,at=h[T-16],ht=at.high,lt=at.low;q=Y+ct,Z=Q+st+(q>>>0>>0?1:0),q+=nt,Z=Z+it+(q>>>0>>0?1:0),q+=lt,Z=Z+ht+(q>>>0>>0?1:0),V.high=Z,V.low=q}var ft=O&U^~O&X,ut=I&K^~I&L,dt=C&E^C&M^E&M,pt=D&R^D&F^R&F,_t=(C>>>28|D<<4)^(C<<30|D>>>2)^(C<<25|D>>>7),vt=(D>>>28|C<<4)^(D<<30|C>>>2)^(D<<25|C>>>7),yt=(O>>>14|I<<18)^(O>>>18|I<<14)^(O<<23|I>>>9),gt=(I>>>14|O<<18)^(I>>>18|O<<14)^(I<<23|O>>>9),Bt=a[T],wt=Bt.high,kt=Bt.low,St=N+gt,mt=j+yt+(St>>>0>>0?1:0),xt=(St=St+ut,mt=mt+ft+(St>>>0>>0?1:0),St=St+kt,mt=mt+wt+(St>>>0>>0?1:0),St=St+q,mt=mt+Z+(St>>>0>>0?1:0),vt+pt),bt=_t+dt+(xt>>>0>>0?1:0);j=X,N=L,X=U,L=K,U=O,K=I,I=W+St|0,O=P+mt+(I>>>0>>0?1:0)|0,P=M,W=F,M=E,F=R,E=C,R=D,D=St+xt|0,C=mt+bt+(D>>>0>>0?1:0)|0}p=i.low=p+D,i.high=d+C+(p>>>0>>0?1:0),v=n.low=v+R,n.high=_+E+(v>>>0>>0?1:0),g=o.low=g+F,o.high=y+M+(g>>>0>>0?1:0),w=s.low=w+W,s.high=B+P+(w>>>0>>0?1:0),S=c.low=S+I,c.high=k+O+(S>>>0>>0?1:0),x=l.low=x+K,l.high=m+U+(x>>>0>>0?1:0),H=f.low=H+L,f.high=b+X+(H>>>0>>0?1:0),A=u.low=A+N,u.high=z+j+(A>>>0>>0?1:0)},_doFinalize:function(){var t=this._data,e=t.words,r=8*this._nDataBytes,i=8*t.sigBytes;e[i>>>5]|=128<<24-i%32,e[30+(i+128>>>10<<5)]=Math.floor(r/4294967296),e[31+(i+128>>>10<<5)]=r,t.sigBytes=4*e.length,this._process();var n=this._hash.toX32();return n},clone:function(){var t=i.clone.call(this);return t._hash=this._hash.clone(),t},blockSize:32});e.SHA512=i._createHelper(f),e.HmacSHA512=i._createHmacHelper(f)}(),function(){var t=l,e=t.x64,r=e.Word,i=e.WordArray,n=t.algo,o=n.SHA512,s=n.SHA384=o.extend({_doReset:function(){this._hash=new i.init([new r.init(3418070365,3238371032),new r.init(1654270250,914150663),new r.init(2438529370,812702999),new r.init(355462360,4144912697),new r.init(1731405415,4290775857),new r.init(2394180231,1750603025),new r.init(3675008525,1694076839),new r.init(1203062813,3204075428)])},_doFinalize:function(){var t=o._doFinalize.call(this);return t.sigBytes-=16,t}});t.SHA384=o._createHelper(s),t.HmacSHA384=o._createHmacHelper(s)}(),l.lib.Cipher||function(t){var e=l,r=e.lib,i=r.Base,n=r.WordArray,o=r.BufferedBlockAlgorithm,s=e.enc,c=(s.Utf8,s.Base64),a=e.algo,h=a.EvpKDF,f=r.Cipher=o.extend({cfg:i.extend(),createEncryptor:function(t,e){return this.create(this._ENC_XFORM_MODE,t,e)},createDecryptor:function(t,e){return this.create(this._DEC_XFORM_MODE,t,e)},init:function(t,e,r){this.cfg=this.cfg.extend(r),this._xformMode=t,this._key=e,this.reset()},reset:function(){o.reset.call(this),this._doReset()},process:function(t){return this._append(t),this._process()},finalize:function(t){t&&this._append(t);var e=this._doFinalize();return e},keySize:4,ivSize:4,_ENC_XFORM_MODE:1,_DEC_XFORM_MODE:2,_createHelper:function(){function t(t){return"string"==typeof t?m:w}return function(e){return{encrypt:function(r,i,n){return t(i).encrypt(e,r,i,n)},decrypt:function(r,i,n){return t(i).decrypt(e,r,i,n)}}}}()}),u=(r.StreamCipher=f.extend({_doFinalize:function(){var t=this._process(!0);return t},blockSize:1}),e.mode={}),d=r.BlockCipherMode=i.extend({createEncryptor:function(t,e){return this.Encryptor.create(t,e)},createDecryptor:function(t,e){return this.Decryptor.create(t,e)},init:function(t,e){this._cipher=t,this._iv=e}}),p=u.CBC=function(){function e(e,r,i){var n,o=this._iv;o?(n=o,this._iv=t):n=this._prevBlock;for(var s=0;s>>2];t.sigBytes-=e}},y=(r.BlockCipher=f.extend({cfg:f.cfg.extend({mode:p,padding:v}),reset:function(){var t;f.reset.call(this);var e=this.cfg,r=e.iv,i=e.mode;this._xformMode==this._ENC_XFORM_MODE?t=i.createEncryptor:(t=i.createDecryptor,this._minBufferSize=1),this._mode&&this._mode.__creator==t?this._mode.init(this,r&&r.words):(this._mode=t.call(i,this,r&&r.words),this._mode.__creator=t)},_doProcessBlock:function(t,e){this._mode.processBlock(t,e)},_doFinalize:function(){var t,e=this.cfg.padding;return this._xformMode==this._ENC_XFORM_MODE?(e.pad(this._data,this.blockSize),t=this._process(!0)):(t=this._process(!0),e.unpad(t)),t},blockSize:4}),r.CipherParams=i.extend({init:function(t){this.mixIn(t)},toString:function(t){return(t||this.formatter).stringify(this)}})),g=e.format={},B=g.OpenSSL={stringify:function(t){var e,r=t.ciphertext,i=t.salt;return e=i?n.create([1398893684,1701076831]).concat(i).concat(r):r,e.toString(c)},parse:function(t){var e,r=c.parse(t),i=r.words;return 1398893684==i[0]&&1701076831==i[1]&&(e=n.create(i.slice(2,4)),i.splice(0,4),r.sigBytes-=16),y.create({ciphertext:r,salt:e})}},w=r.SerializableCipher=i.extend({cfg:i.extend({format:B}),encrypt:function(t,e,r,i){i=this.cfg.extend(i);var n=t.createEncryptor(r,i),o=n.finalize(e),s=n.cfg;return y.create({ciphertext:o,key:r,iv:s.iv,algorithm:t,mode:s.mode,padding:s.padding,blockSize:t.blockSize,formatter:i.format})},decrypt:function(t,e,r,i){i=this.cfg.extend(i),e=this._parse(e,i.format);var n=t.createDecryptor(r,i).finalize(e.ciphertext);return n},_parse:function(t,e){return"string"==typeof t?e.parse(t,this):t}}),k=e.kdf={},S=k.OpenSSL={execute:function(t,e,r,i){i||(i=n.random(8));var o=h.create({keySize:e+r}).compute(t,i),s=n.create(o.words.slice(e),4*r);return o.sigBytes=4*e,y.create({key:o,iv:s,salt:i})}},m=r.PasswordBasedCipher=w.extend({cfg:w.cfg.extend({kdf:S}),encrypt:function(t,e,r,i){i=this.cfg.extend(i);var n=i.kdf.execute(r,t.keySize,t.ivSize);i.iv=n.iv;var o=w.encrypt.call(this,t,e,n.key,i);return o.mixIn(n),o},decrypt:function(t,e,r,i){i=this.cfg.extend(i),e=this._parse(e,i.format);var n=i.kdf.execute(r,t.keySize,t.ivSize,e.salt);i.iv=n.iv;var o=w.decrypt.call(this,t,e,n.key,i);return o}})}(),l.mode.CFB=function(){function t(t,e,r,i){var n,o=this._iv;o?(n=o.slice(0),this._iv=void 0):n=this._prevBlock,i.encryptBlock(n,0);for(var s=0;s>>2]|=n<<24-o%4*8,t.sigBytes+=n},unpad:function(t){var e=255&t.words[t.sigBytes-1>>>2];t.sigBytes-=e}},l.pad.Iso10126={pad:function(t,e){var r=4*e,i=r-t.sigBytes%r;t.concat(l.lib.WordArray.random(i-1)).concat(l.lib.WordArray.create([i<<24],1))},unpad:function(t){var e=255&t.words[t.sigBytes-1>>>2];t.sigBytes-=e}},l.pad.Iso97971={pad:function(t,e){t.concat(l.lib.WordArray.create([2147483648],1)),l.pad.ZeroPadding.pad(t,e)},unpad:function(t){l.pad.ZeroPadding.unpad(t),t.sigBytes--}},l.mode.OFB=(a=l.lib.BlockCipherMode.extend(),h=a.Encryptor=a.extend({processBlock:function(t,e){var r=this._cipher,i=r.blockSize,n=this._iv,o=this._keystream;n&&(o=this._keystream=n.slice(0),this._iv=void 0),r.encryptBlock(o,0);for(var s=0;s>>8^255&l^99,n[r]=l,o[l]=r;var _=t[r],v=t[_],y=t[v],g=257*t[l]^16843008*l;s[r]=g<<24|g>>>8,c[r]=g<<16|g>>>16,a[r]=g<<8|g>>>24,h[r]=g;g=16843009*y^65537*v^257*_^16843008*r;f[l]=g<<24|g>>>8,u[l]=g<<16|g>>>16,d[l]=g<<8|g>>>24,p[l]=g,r?(r=_^t[t[t[y^_]]],i^=t[t[i]]):r=i=1}})();var _=[0,1,2,4,8,16,32,64,128,27,54],v=i.AES=r.extend({_doReset:function(){if(!this._nRounds||this._keyPriorReset!==this._key){for(var t=this._keyPriorReset=this._key,e=t.words,r=t.sigBytes/4,i=this._nRounds=r+6,o=4*(i+1),s=this._keySchedule=[],c=0;c6&&c%r==4&&(l=n[l>>>24]<<24|n[l>>>16&255]<<16|n[l>>>8&255]<<8|n[255&l]):(l=l<<8|l>>>24,l=n[l>>>24]<<24|n[l>>>16&255]<<16|n[l>>>8&255]<<8|n[255&l],l^=_[c/r|0]<<24),s[c]=s[c-r]^l);for(var a=this._invKeySchedule=[],h=0;h>>24]]^u[n[l>>>16&255]]^d[n[l>>>8&255]]^p[n[255&l]]}}},encryptBlock:function(t,e){this._doCryptBlock(t,e,this._keySchedule,s,c,a,h,n)},decryptBlock:function(t,e){var r=t[e+1];t[e+1]=t[e+3],t[e+3]=r,this._doCryptBlock(t,e,this._invKeySchedule,f,u,d,p,o);r=t[e+1];t[e+1]=t[e+3],t[e+3]=r},_doCryptBlock:function(t,e,r,i,n,o,s,c){for(var a=this._nRounds,h=t[e]^r[0],l=t[e+1]^r[1],f=t[e+2]^r[2],u=t[e+3]^r[3],d=4,p=1;p>>24]^n[l>>>16&255]^o[f>>>8&255]^s[255&u]^r[d++],v=i[l>>>24]^n[f>>>16&255]^o[u>>>8&255]^s[255&h]^r[d++],y=i[f>>>24]^n[u>>>16&255]^o[h>>>8&255]^s[255&l]^r[d++],g=i[u>>>24]^n[h>>>16&255]^o[l>>>8&255]^s[255&f]^r[d++];h=_,l=v,f=y,u=g}_=(c[h>>>24]<<24|c[l>>>16&255]<<16|c[f>>>8&255]<<8|c[255&u])^r[d++],v=(c[l>>>24]<<24|c[f>>>16&255]<<16|c[u>>>8&255]<<8|c[255&h])^r[d++],y=(c[f>>>24]<<24|c[u>>>16&255]<<16|c[h>>>8&255]<<8|c[255&l])^r[d++],g=(c[u>>>24]<<24|c[h>>>16&255]<<16|c[l>>>8&255]<<8|c[255&f])^r[d++];t[e]=_,t[e+1]=v,t[e+2]=y,t[e+3]=g},keySize:8});t.AES=r._createHelper(v)}(),function(){function t(t,e){var r=(this._lBlock>>>t^this._rBlock)&e;this._rBlock^=r,this._lBlock^=r<>>t^this._lBlock)&e;this._lBlock^=r,this._rBlock^=r<>>5]>>>31-n%32&1}for(var o=this._subKeys=[],s=0;s<16;s++){var l=o[s]=[],f=h[s];for(i=0;i<24;i++)l[i/6|0]|=r[(a[i]-1+f)%28]<<31-i%6,l[4+(i/6|0)]|=r[28+(a[i+24]-1+f)%28]<<31-i%6;l[0]=l[0]<<1|l[0]>>>31;for(i=1;i<7;i++)l[i]=l[i]>>>4*(i-1)+3;l[7]=l[7]<<5|l[7]>>>27}var u=this._invSubKeys=[];for(i=0;i<16;i++)u[i]=o[15-i]},encryptBlock:function(t,e){this._doCryptBlock(t,e,this._subKeys)},decryptBlock:function(t,e){this._doCryptBlock(t,e,this._invSubKeys)},_doCryptBlock:function(r,i,n){this._lBlock=r[i],this._rBlock=r[i+1],t.call(this,4,252645135),t.call(this,16,65535),e.call(this,2,858993459),e.call(this,8,16711935),t.call(this,1,1431655765);for(var o=0;o<16;o++){for(var s=n[o],c=this._lBlock,a=this._rBlock,h=0,l=0;l<8;l++)h|=f[l][((a^s[l])&u[l])>>>0];this._lBlock=a,this._rBlock=c^h}var d=this._lBlock;this._lBlock=this._rBlock,this._rBlock=d,t.call(this,1,1431655765),e.call(this,8,16711935),e.call(this,2,858993459),t.call(this,16,65535),t.call(this,4,252645135),r[i]=this._lBlock,r[i+1]=this._rBlock},keySize:2,ivSize:2,blockSize:2});r.DES=o._createHelper(d);var p=s.TripleDES=o.extend({_doReset:function(){var t=this._key,e=t.words;if(2!==e.length&&4!==e.length&&e.length<6)throw new Error("Invalid key length - 3DES requires the key length to be 64, 128, 192 or >192.");var r=e.slice(0,2),i=e.length<4?e.slice(0,2):e.slice(2,4),o=e.length<6?e.slice(0,2):e.slice(4,6);this._des1=d.createEncryptor(n.create(r)),this._des2=d.createEncryptor(n.create(i)),this._des3=d.createEncryptor(n.create(o))},encryptBlock:function(t,e){this._des1.encryptBlock(t,e),this._des2.decryptBlock(t,e),this._des3.encryptBlock(t,e)},decryptBlock:function(t,e){this._des3.decryptBlock(t,e),this._des2.encryptBlock(t,e),this._des1.decryptBlock(t,e)},keySize:6,ivSize:2,blockSize:2});r.TripleDES=o._createHelper(p)}(),function(){function t(){for(var t=this._S,e=this._i,r=this._j,i=0,n=0;n<4;n++){e=(e+1)%256,r=(r+t[e])%256;var o=t[e];t[e]=t[r],t[r]=o,i|=t[(t[e]+t[r])%256]<<24-8*n}return this._i=e,this._j=r,i}var e=l,r=e.lib,i=r.StreamCipher,n=e.algo,o=n.RC4=i.extend({_doReset:function(){for(var t=this._key,e=t.words,r=t.sigBytes,i=this._S=[],n=0;n<256;n++)i[n]=n;n=0;for(var o=0;n<256;n++){var s=n%r,c=e[s>>>2]>>>24-s%4*8&255;o=(o+i[n]+c)%256;var a=i[n];i[n]=i[o],i[o]=a}this._i=this._j=0},_doProcessBlock:function(e,r){e[r]^=t.call(this)},keySize:8,ivSize:0});e.RC4=i._createHelper(o);var s=n.RC4Drop=o.extend({cfg:o.cfg.extend({drop:192}),_doReset:function(){o._doReset.call(this);for(var e=this.cfg.drop;e>0;e--)t.call(this)}});e.RC4Drop=i._createHelper(s)}(),l.mode.CTRGladman=function(){function t(t){if(255==(t>>24&255)){var e=t>>16&255,r=t>>8&255,i=255&t;255===e?(e=0,255===r?(r=0,255===i?i=0:++i):++r):++e,t=0,t+=e<<16,t+=r<<8,t+=i}else t+=1<<24;return t}function e(e){return 0===(e[0]=t(e[0]))&&(e[1]=t(e[1])),e}var r=l.lib.BlockCipherMode.extend(),i=r.Encryptor=r.extend({processBlock:function(t,r){var i=this._cipher,n=i.blockSize,o=this._iv,s=this._counter;o&&(s=this._counter=o.slice(0),this._iv=void 0),e(s);var c=s.slice(0);i.encryptBlock(c,0);for(var a=0;a>>0>>0?1:0)|0,e[2]=e[2]+886263092+(e[1]>>>0>>0?1:0)|0,e[3]=e[3]+1295307597+(e[2]>>>0>>0?1:0)|0,e[4]=e[4]+3545052371+(e[3]>>>0>>0?1:0)|0,e[5]=e[5]+886263092+(e[4]>>>0>>0?1:0)|0,e[6]=e[6]+1295307597+(e[5]>>>0>>0?1:0)|0,e[7]=e[7]+3545052371+(e[6]>>>0>>0?1:0)|0,this._b=e[7]>>>0>>0?1:0;for(r=0;r<8;r++){var i=t[r]+e[r],n=65535&i,o=i>>>16,a=((n*n>>>17)+n*o>>>15)+o*o,h=((4294901760&i)*i|0)+((65535&i)*i|0);c[r]=a^h}t[0]=c[0]+(c[7]<<16|c[7]>>>16)+(c[6]<<16|c[6]>>>16)|0,t[1]=c[1]+(c[0]<<8|c[0]>>>24)+c[7]|0,t[2]=c[2]+(c[1]<<16|c[1]>>>16)+(c[0]<<16|c[0]>>>16)|0,t[3]=c[3]+(c[2]<<8|c[2]>>>24)+c[1]|0,t[4]=c[4]+(c[3]<<16|c[3]>>>16)+(c[2]<<16|c[2]>>>16)|0,t[5]=c[5]+(c[4]<<8|c[4]>>>24)+c[3]|0,t[6]=c[6]+(c[5]<<16|c[5]>>>16)+(c[4]<<16|c[4]>>>16)|0,t[7]=c[7]+(c[6]<<8|c[6]>>>24)+c[5]|0}var e=l,r=e.lib,i=r.StreamCipher,n=e.algo,o=[],s=[],c=[],a=n.Rabbit=i.extend({_doReset:function(){for(var e=this._key.words,r=this.cfg.iv,i=0;i<4;i++)e[i]=16711935&(e[i]<<8|e[i]>>>24)|4278255360&(e[i]<<24|e[i]>>>8);var n=this._X=[e[0],e[3]<<16|e[2]>>>16,e[1],e[0]<<16|e[3]>>>16,e[2],e[1]<<16|e[0]>>>16,e[3],e[2]<<16|e[1]>>>16],o=this._C=[e[2]<<16|e[2]>>>16,4294901760&e[0]|65535&e[1],e[3]<<16|e[3]>>>16,4294901760&e[1]|65535&e[2],e[0]<<16|e[0]>>>16,4294901760&e[2]|65535&e[3],e[1]<<16|e[1]>>>16,4294901760&e[3]|65535&e[0]];this._b=0;for(i=0;i<4;i++)t.call(this);for(i=0;i<8;i++)o[i]^=n[i+4&7];if(r){var s=r.words,c=s[0],a=s[1],h=16711935&(c<<8|c>>>24)|4278255360&(c<<24|c>>>8),l=16711935&(a<<8|a>>>24)|4278255360&(a<<24|a>>>8),f=h>>>16|4294901760&l,u=l<<16|65535&h;o[0]^=h,o[1]^=f,o[2]^=l,o[3]^=u,o[4]^=h,o[5]^=f,o[6]^=l,o[7]^=u;for(i=0;i<4;i++)t.call(this)}},_doProcessBlock:function(e,r){var i=this._X;t.call(this),o[0]=i[0]^i[5]>>>16^i[3]<<16,o[1]=i[2]^i[7]>>>16^i[5]<<16,o[2]=i[4]^i[1]>>>16^i[7]<<16,o[3]=i[6]^i[3]>>>16^i[1]<<16;for(var n=0;n<4;n++)o[n]=16711935&(o[n]<<8|o[n]>>>24)|4278255360&(o[n]<<24|o[n]>>>8),e[r+n]^=o[n]},blockSize:4,ivSize:2});e.Rabbit=i._createHelper(a)}(),l.mode.CTR=function(){var t=l.lib.BlockCipherMode.extend(),e=t.Encryptor=t.extend({processBlock:function(t,e){var r=this._cipher,i=r.blockSize,n=this._iv,o=this._counter;n&&(o=this._counter=n.slice(0),this._iv=void 0);var s=o.slice(0);r.encryptBlock(s,0),o[i-1]=o[i-1]+1|0;for(var c=0;c>>0>>0?1:0)|0,e[2]=e[2]+886263092+(e[1]>>>0>>0?1:0)|0,e[3]=e[3]+1295307597+(e[2]>>>0>>0?1:0)|0,e[4]=e[4]+3545052371+(e[3]>>>0>>0?1:0)|0,e[5]=e[5]+886263092+(e[4]>>>0>>0?1:0)|0,e[6]=e[6]+1295307597+(e[5]>>>0>>0?1:0)|0,e[7]=e[7]+3545052371+(e[6]>>>0>>0?1:0)|0,this._b=e[7]>>>0>>0?1:0;for(r=0;r<8;r++){var i=t[r]+e[r],n=65535&i,o=i>>>16,a=((n*n>>>17)+n*o>>>15)+o*o,h=((4294901760&i)*i|0)+((65535&i)*i|0);c[r]=a^h}t[0]=c[0]+(c[7]<<16|c[7]>>>16)+(c[6]<<16|c[6]>>>16)|0,t[1]=c[1]+(c[0]<<8|c[0]>>>24)+c[7]|0,t[2]=c[2]+(c[1]<<16|c[1]>>>16)+(c[0]<<16|c[0]>>>16)|0,t[3]=c[3]+(c[2]<<8|c[2]>>>24)+c[1]|0,t[4]=c[4]+(c[3]<<16|c[3]>>>16)+(c[2]<<16|c[2]>>>16)|0,t[5]=c[5]+(c[4]<<8|c[4]>>>24)+c[3]|0,t[6]=c[6]+(c[5]<<16|c[5]>>>16)+(c[4]<<16|c[4]>>>16)|0,t[7]=c[7]+(c[6]<<8|c[6]>>>24)+c[5]|0}var e=l,r=e.lib,i=r.StreamCipher,n=e.algo,o=[],s=[],c=[],a=n.RabbitLegacy=i.extend({_doReset:function(){var e=this._key.words,r=this.cfg.iv,i=this._X=[e[0],e[3]<<16|e[2]>>>16,e[1],e[0]<<16|e[3]>>>16,e[2],e[1]<<16|e[0]>>>16,e[3],e[2]<<16|e[1]>>>16],n=this._C=[e[2]<<16|e[2]>>>16,4294901760&e[0]|65535&e[1],e[3]<<16|e[3]>>>16,4294901760&e[1]|65535&e[2],e[0]<<16|e[0]>>>16,4294901760&e[2]|65535&e[3],e[1]<<16|e[1]>>>16,4294901760&e[3]|65535&e[0]];this._b=0;for(var o=0;o<4;o++)t.call(this);for(o=0;o<8;o++)n[o]^=i[o+4&7];if(r){var s=r.words,c=s[0],a=s[1],h=16711935&(c<<8|c>>>24)|4278255360&(c<<24|c>>>8),l=16711935&(a<<8|a>>>24)|4278255360&(a<<24|a>>>8),f=h>>>16|4294901760&l,u=l<<16|65535&h;n[0]^=h,n[1]^=f,n[2]^=l,n[3]^=u,n[4]^=h,n[5]^=f,n[6]^=l,n[7]^=u;for(o=0;o<4;o++)t.call(this)}},_doProcessBlock:function(e,r){var i=this._X;t.call(this),o[0]=i[0]^i[5]>>>16^i[3]<<16,o[1]=i[2]^i[7]>>>16^i[5]<<16,o[2]=i[4]^i[1]>>>16^i[7]<<16,o[3]=i[6]^i[3]>>>16^i[1]<<16;for(var n=0;n<4;n++)o[n]=16711935&(o[n]<<8|o[n]>>>24)|4278255360&(o[n]<<24|o[n]>>>8),e[r+n]^=o[n]},blockSize:4,ivSize:2});e.RabbitLegacy=i._createHelper(a)}(),l.pad.ZeroPadding={pad:function(t,e){var r=4*e;t.clamp(),t.sigBytes+=r-(t.sigBytes%r||r)},unpad:function(t){var e=t.words,r=t.sigBytes-1;for(r=t.sigBytes-1;r>=0;r--)if(e[r>>>2]>>>24-r%4*8&255){t.sigBytes=r+1;break}}},l});
--------------------------------------------------------------------------------
/picture/apppricemonitor.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evilbutcher/Scriptables/54ca437ed237dec2d1539ce7c2806ea32a95f665/picture/apppricemonitor.jpeg
--------------------------------------------------------------------------------
/picture/config.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evilbutcher/Scriptables/54ca437ed237dec2d1539ce7c2806ea32a95f665/picture/config.gif
--------------------------------------------------------------------------------
/picture/config.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evilbutcher/Scriptables/54ca437ed237dec2d1539ce7c2806ea32a95f665/picture/config.mp4
--------------------------------------------------------------------------------
/picture/hotlistmonitor.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evilbutcher/Scriptables/54ca437ed237dec2d1539ce7c2806ea32a95f665/picture/hotlistmonitor.jpeg
--------------------------------------------------------------------------------
/picture/nasaandmonitor.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evilbutcher/Scriptables/54ca437ed237dec2d1539ce7c2806ea32a95f665/picture/nasaandmonitor.jpeg
--------------------------------------------------------------------------------
/北京尾号限行.js:
--------------------------------------------------------------------------------
1 | // Variables used by Scriptable.
2 | // These must be at the very top of the file. Do not edit.
3 | // icon-color: red; icon-glyph: car-alt;
4 | /**
5 | * Author: evilbutcher
6 | * Github: https://github.com/evilbutcher
7 | * 本脚本使用了@Gideon_Senku的Env.scriptable,感谢!
8 | * ⚠️免责声明:本脚本数据从官网获取,不保证准确性,仅供学习交流,若由此脚本引发的任何责任,本人概不承担!详见仓库内免责声明!
9 | */
10 |
11 | const goupdate = true;
12 | const $ = importModule("Env");
13 | try {
14 | var { lastnumberofcar } = importModule("Config");
15 | lastnumberofcar = lastnumberofcar();
16 | console.log("将使用配置文件内尾号: " + lastnumberofcar);
17 | } catch (e) {
18 | console.log("未获取汽车尾号,需正确配置");
19 | }
20 |
21 | const isDark = Device.isUsingDarkAppearance();
22 | const bgColor = new LinearGradient();
23 | bgColor.colors = isDark
24 | ? [new Color("#030079"), new Color("#000000")]
25 | : [new Color("#a18cd1"), new Color("#fbc2eb")];
26 | bgColor.locations = [0.0, 1.0];
27 |
28 | const res = await getinfo();
29 |
30 | let widget = createWidget(res);
31 | Script.setWidget(widget);
32 | Script.complete();
33 |
34 | function createWidget(res) {
35 | if (res.state == "success") {
36 | var group = res.result;
37 | items = [];
38 | for (var i = 0; i < 6; i++) {
39 | var week = group[i].limitedWeek;
40 | var number = group[i].limitedNumber;
41 | var time = group[i].limitedTime;
42 | items.push(
43 | `• ${JSON.stringify(time).slice(1, -1)} ${JSON.stringify(week).slice(
44 | 1,
45 | -1
46 | )} ${JSON.stringify(number).slice(1, -1)}`
47 | );
48 | }
49 | const w = new ListWidget();
50 | w.backgroundGradient = bgColor;
51 | w.addSpacer();
52 | w.spacing = 5;
53 |
54 | if (lastnumberofcar == undefined || lastnumberofcar == "") {
55 | var firstLine = w.addText(`🚙 北京尾号限行`);
56 | } else {
57 | if (group[0].limitedNumber.indexOf(lastnumberofcar) != -1) {
58 | firstLine = w.addText(`🚙 今日限行‼️ 注意遵守交规哦`);
59 | } else {
60 | firstLine = w.addText(`🚙 今日不限行🎉 放心出门吧`);
61 | }
62 | }
63 | firstLine.textColor = isDark ? Color.white() : Color.black();
64 | try {
65 | firstLine.applyHeadlineTextStyling();
66 | } catch (e) {
67 | firstLine.font = new Font('SF Mono', 18);
68 | }
69 |
70 | for (var i = 0; i < items.length; i++) {
71 | addTextToListWidget(`${items[i]}`, w);
72 | }
73 |
74 | w.addSpacer();
75 | w.spacing = 5;
76 | w.presentMedium();
77 | return w;
78 | }
79 | }
80 |
81 | function addTextToListWidget(text, listWidget) {
82 | let item = listWidget.addText(text);
83 | item.textColor = isDark ? Color.white() : Color.black();
84 | item.font = new Font('SF Mono', 12);
85 | }
86 |
87 | async function getinfo() {
88 | const url = {
89 | url: `http://yw.jtgl.beijing.gov.cn/jgjxx/services/getRuleWithWeek`,
90 | };
91 | const res = await $.get(url);
92 | log(res);
93 | return res;
94 | }
95 |
96 | //更新代码
97 | function update() {
98 | log("🔔更新脚本开始!");
99 | scripts.forEach(async (script) => {
100 | await $.getFile(script);
101 | });
102 | log("🔔更新脚本结束!");
103 | }
104 |
105 | const scripts = [
106 | {
107 | moduleName: "北京尾号限行",
108 | url:
109 | "https://raw.githubusercontent.com/evilbutcher/Scriptables/master/%E5%8C%97%E4%BA%AC%E5%B0%BE%E5%8F%B7%E9%99%90%E8%A1%8C.js",
110 | },
111 | ];
112 | if (goupdate == true) update();
113 |
--------------------------------------------------------------------------------