├── .editorconfig
├── .gitignore
├── .npmrc
├── .prettierrc
├── README.md
├── hook-rules
└── js-hook.js
├── package.json
├── src
├── CHERWING-CHERWIN_SCRIPTS.js
├── DeathNote.js
├── QLScriptPublic.js
├── ddgyToken.js
├── features
│ ├── index.js
│ └── m3u8-ts-cache.js
├── huluwa.js
├── imaotai.js
├── index.js
├── jd.js
├── lzwme.js
├── ohhh_QL-Script.js
├── t.js
├── vip
│ ├── alipanCrack.js
│ ├── baiduCloud.js
│ ├── bilibiliHD.js
│ ├── index.js
│ ├── todo
│ │ └── wps.js
│ ├── xiaohongshu.js
│ ├── ximalaya.js
│ ├── xunlei.js
│ └── zhihu.js
└── youzan-liteapp.js
└── whistle-rules
├── ad-block.txt
├── x.json
└── zhihu.txt
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | end_of_line = lf
7 | indent_size = 2
8 | indent_style = space
9 | insert_final_newline = true
10 | max_line_length = 140
11 | trim_trailing_whitespace = true
12 |
13 | [*.md]
14 | max_line_length = 0
15 | trim_trailing_whitespace = false
16 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 |
4 | # build dist
5 | .nyc_output
6 | *.log
7 | /dist/
8 | /cjs/
9 | /esm/
10 | /release/
11 | /debug/
12 | /coverage/
13 | /docs/
14 | /tmp
15 | /cache
16 | /logs
17 |
18 | # manager
19 | npm-debug.log
20 | package-lock.json
21 | yarn.lock
22 | yarn-error.log
23 | pnpm-lock.yaml
24 | .pnpm-debug.log
25 |
26 | # config
27 | # .flh.config.js
28 | /env-config.sh
29 | /w2.x-scripts.config.js
30 | /w2.x-scripts.cache.json
31 | /test-*
32 | /local-x-scripts-rules
33 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 |
2 | registry="https://registry.npmmirror.com"
3 |
4 | # for pnpm
5 | strict-peer-dependencies=false
6 | shamefully-hoist=true
7 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 140,
3 | "singleQuote": true,
4 | "trailingComma": "es5",
5 | "proseWrap": "preserve",
6 | "semi": true,
7 | "bracketSpacing": true,
8 | "arrowParens": "avoid",
9 | "overrides": [
10 | {
11 | "files": ".prettierrc",
12 | "options": {
13 | "parser": "json"
14 | }
15 | }
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | @lzwme/x-scripts-rules
2 | ========
3 |
4 | [![node version][node-badge]][node-url]
5 | [![GitHub issues][issues-badge]][issues-url]
6 | [![GitHub forks][forks-badge]][forks-url]
7 | [![GitHub stars][stars-badge]][stars-url]
8 |
9 |
10 |
11 | 基于 [@lzwme/whistle.x-scripts](https://github.com/lzwme/whistle.x-scripts) 插件规范开发的规则脚本库。
12 |
13 | ## 免责说明
14 |
15 | - 本项目提供的内容用于个人对 web 程序逆向的兴趣研究学习,仅供学习交流使用,不用于其他任何目的,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关。**请在学习研究完毕24小时内予以删除。**
16 | - 请自行评估使用本项目内容可能产生的安全风险。本人对使用本项目涉及的任何脚本引发的问题概不负责,包括但不限于由脚本错误引起的任何损失或损害。
17 |
18 | ## 快速开始
19 |
20 | ```bash
21 | npm i -g whistle @lzwme/whistle.x-scripts
22 | git clone https://mirror.ghporxy.com/github.com/lzwme/x-scripts-rules.git
23 | w2 ca
24 | w2 proxy
25 | w2 run
26 | ```
27 |
28 | ## 安装与使用
29 |
30 | 请先了解 [@lzwme/whistle.x-scripts](https://github.com/lzwme/whistle.x-scripts) 项目的功能,并进行基本安装与配置。
31 |
32 | 应先全局安装 `whistle` 和 `@lzwme/whistle.x-scripts`:
33 |
34 | ```bash
35 | npm i -g whistle @lzwme/whistle.x-scripts
36 | ```
37 |
38 | 然后拉取本仓库代码到本地路径(如:`/Users/lzwme/coding/x-scripts-rules`):
39 |
40 | ```bash
41 | git clone https://github.com/lzwme/x-scripts-rules.git
42 | ```
43 |
44 | 接着在配置文件 `~/w2.x-scripts.config.js` 中的 `ruleDirs` 字段添加该仓库所在路径即可。示例:
45 |
46 | ```js
47 | module.exports = {
48 | ruleDirs: [
49 | '/Users/lzwme/coding/x-scripts-rules/', // 按目录:加载全部规则
50 | '/Users/lzwme/coding/x-scripts-rules/src/jd.js', // 按文件:加载部分规则
51 | ],
52 | };
53 | ```
54 |
55 | 最后启动 `whistle`:
56 |
57 | ```bash
58 | # 安装根证书
59 | w2 ca
60 | # 开启全局代理模式(关闭: w2 proxy off)
61 | w2 proxy
62 | # 调试模式启动
63 | w2 run
64 | ```
65 |
66 | ## License
67 |
68 | `@lzwme/x-scripts-rules` is released under the MIT license.
69 |
70 | 该插件由[志文工作室](https://lzw.me)开发和维护。
71 |
72 |
73 | [stars-badge]: https://img.shields.io/github/stars/lzwme/x-scripts-rules.svg
74 | [stars-url]: https://github.com/lzwme/x-scripts-rules/stargazers
75 | [forks-badge]: https://img.shields.io/github/forks/lzwme/x-scripts-rules.svg
76 | [forks-url]: https://github.com/lzwme/x-scripts-rules/network
77 | [issues-badge]: https://img.shields.io/github/issues/lzwme/x-scripts-rules.svg
78 | [issues-url]: https://github.com/lzwme/x-scripts-rules/issues
79 | [npm-badge]: https://img.shields.io/npm/v/@lzwme/x-scripts-rules.svg?style=flat-square
80 | [npm-url]: https://npmjs.org/package/@lzwme/x-scripts-rules
81 | [node-badge]: https://img.shields.io/badge/node.js-%3E=_16.15.0-green.svg?style=flat-square
82 | [node-url]: https://nodejs.org/download/
83 | [download-badge]: https://img.shields.io/npm/dm/@lzwme/x-scripts-rules.svg?style=flat-square
84 | [download-url]: https://npmjs.org/package/@lzwme/x-scripts-rules
85 | [bundlephobia-url]: https://bundlephobia.com/result?p=@lzwme/x-scripts-rules@latest
86 | [bundlephobia-badge]: https://badgen.net/bundlephobia/minzip/@lzwme/x-scripts-rules@latest
87 |
--------------------------------------------------------------------------------
/hook-rules/js-hook.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: renxia
3 | * @Date: 2024-03-17 14:12:30
4 | * @LastEditors: renxia
5 | * @LastEditTime: 2024-03-17 15:17:13
6 | * @Description:
7 | */
8 |
9 | // process.env.JS_HOOK_URL = 'qhres2.com,aigc.360.com,www.sou.com,qhimg.com';
10 |
11 | /** @type {import('@lzwme/whistle.x-scripts').RuleItem[]} */
12 | module.exports = [
13 | {
14 | disabled: !process.env.JS_HOOK_URL,
15 | on: 'res-body',
16 | ruleId: 'js-hook',
17 | desc: 'js-hook',
18 | method: '*',
19 | // mitm: 'game.xiaojukeji.com',
20 | url: process.env.JS_HOOK_URL?.split(','),
21 | handler({ resBody, headers, resHeaders, X, url }) {
22 | if (!resBody) return;
23 |
24 | const type = headers['content-type'] || '';
25 | const rtype = resHeaders['content-type'] || '';
26 |
27 | const isHtml = type.includes('html') || rtype.includes('html');
28 | const isJs = type.includes('javascript') || rtype.includes('javascript') || url.includes('.js');
29 |
30 | if (isHtml || isJs) {
31 | if (Buffer.isBuffer(resBody)) resBody = resBody.toString('utf8');
32 | let hookCode = Object.values(jsHookList).join('\n');
33 | if (isHtml) hookCode = ``;
34 | console.log('hook injected', X.FeUtils.color.gray(url));
35 | if (resBody.includes('
')) resBody = resBody.replace('', `\n${hookCode}`);
36 | else resBody = `${resBody}\n${hookCode}`;
37 |
38 | return { body: resBody };
39 | }
40 | },
41 | },
42 | ];
43 |
44 | const jsHookList = {
45 | json: `(function () {
46 | var my_stringify = JSON.stringify;
47 | JSON.stringify = function (params) {
48 | console.log('HOOK stringify', params);
49 | debugger;
50 | return my_stringify(params);
51 | };
52 | var my_parse = JSON.parse;
53 | JSON.parse = function (params) {
54 | console.log('HOOK parse', params);
55 | debugger;
56 | return my_parse(params);
57 | };
58 | })();`,
59 | cookie: `(function () {
60 | 'use strict';
61 | let cookie_cache = '';
62 | Object.defineProperty(document, 'cookie', {
63 | get: function () {
64 | //debugger;
65 | return cookie_cache;
66 | },
67 | set: function (value) {
68 | console.log('Set cookie', value);
69 | debugger;
70 | cookie_cache = value;
71 | return value;
72 | },
73 | });
74 | })();`,
75 | searchDecode: `(function () {
76 | setTimeout(function () {
77 | for (var p in window) {
78 | var s = p.toLowerCase();
79 | if (s.indexOf('encode') != -1 || s.indexOf('encry') != -1) {
80 | console.log('encode function.', window[p]);
81 | debugger;
82 | }
83 | if (s.indexOf('decode') != -1 || s.indexOf('decry') != -1) {
84 | console.log('decode function.', window[p]);
85 | debugger;
86 | }
87 | }
88 | }, 3000);
89 | })();`,
90 | debuggerFunc: `(() => {
91 | Function.prototype.__constructor = Function.prototype.constructor;
92 | Function.prototype.constructor = function() {
93 | if(arguments && typeof arguments[0]==='string') {
94 | if ("debugger"===arguments[0]) {
95 | console.trace('[Function]debugger 拦截');
96 | return () => () => {};
97 | }
98 | return Function.prototype.__constructor.apply(this,arguments);
99 | }
100 | }
101 | })();`,
102 | debuggerSetInterval: `(function() {
103 | globalThis._setInterval_ = globalThis.setInterval;
104 | globalThis.setInterval = function(a,b) {
105 | if (a.includes("debugger")) {
106 | console.trace('[setInterval] debugger 拦截')
107 | } else {
108 | return globalThis._setInterval_(a,b);
109 | }
110 | }
111 | });`,
112 | eval: `(function () {
113 | if (window.__cr_eval) return;
114 | window.__cr_eval = window.eval;
115 | var myeval = function (src) {
116 | console.log('==== eval begin: length=' + src.length + ',caller=' + (myeval.caller && myeval.caller.name) + ' ====');
117 | console.log(src);
118 | console.log('==== eval end ====');
119 | return window.__cr_eval(src);
120 | };
121 | var _myeval = myeval.bind(null);
122 | _myeval.toString = window.__cr_eval.toString;
123 | Object.defineProperty(window, 'eval', { value: _myeval });
124 | console.log('>>>> eval injected: ' + document.location + ' <<<<');
125 | })();`
126 | };
127 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "x-scripts-rules",
3 | "version": "1.0.0",
4 | "description": "基于 @lzwme/whistle.x-scripts 插件规范开发的规则脚本库",
5 | "main": "src/index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "devDependencies": {
13 | "@lzwme/whistle.x-scripts": "^0.0.5"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/CHERWING-CHERWIN_SCRIPTS.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 用于临时测试的一些例子
3 | * @type {import('@lzwme/whistle.x-scripts').RuleItem[]}
4 | */
5 | module.exports = [
6 | {
7 | on: 'req-header',
8 | ruleId: 'LSXDS',
9 | desc: '乐事心动社-小程序',
10 | url: 'https://campuscrm.pepsico.com.cn/web/**/*memberId=*',
11 | method: 'get',
12 | getCacheUid: ({ headers, X, url }) => {
13 | if (headers.authorization) {
14 | const q = X.FeUtils.getUrlParams(url);
15 | return { uid: q.memberId };
16 | }
17 | },
18 | handler: ({ cacheData: D }) => ({
19 | envConfig: { value: D.map(d => `${d.headers.authorization.replace(/bearer /i, '')}@UID_${d.uid}`).join('&'), sep: '&' },
20 | }),
21 | updateEnvValue: /@UID_(\d+)/,
22 | },
23 | {
24 | on: 'res-body',
25 | ruleId: 'TBHYZX',
26 | desc: '特步会员中心-小程序',
27 | url: 'https://wxa-tp.ezrpro.com/myvip/Base/User/WxAppOnLoginNew',
28 | getCacheUid: ({ resBody: B }) => {
29 | if (B?.Result?.Fields) {
30 | const uid = B.Result.VipId;
31 | return { uid, data: `${B.Result.Fields}@UID_${uid}` };
32 | }
33 | },
34 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => d.data).join('&'), sep: '&' } }),
35 | updateEnvValue: /@UID_(\d+)/,
36 | },
37 | {
38 | on: 'res-body',
39 | ruleId: 'AMX',
40 | desc: '安慕希-小程序',
41 | url: 'https://wx-amxshop.msxapi.digitalyili.com/api/user/getUser',
42 | method: 'get',
43 | getCacheUid: ({ headers, resBody: B }) => {
44 | if (headers.accesstoken) {
45 | const uid = B?.data?.user?.id;
46 | return { uid, data: `${headers.accesstoken}@UID_${uid}` };
47 | }
48 | },
49 | handler: ({ cacheData: D }) => ({
50 | envConfig: { value: D.map(v => v.data).join('&'), sep: '&' },
51 | }),
52 | updateEnvValue: /@UID_(\d+)/,
53 | },
54 | ];
55 |
--------------------------------------------------------------------------------
/src/DeathNote.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: renxia
3 | * @Date: 2024-02-19 19:23:02
4 | * @LastEditors: renxia
5 | * @LastEditTime: 2024-07-25 22:36:03
6 | * @Description: https://github.com/leafTheFish/DeathNote
7 | */
8 |
9 | /** @type {import('@lzwme/whistle.x-scripts').RuleItem[]} */
10 | module.exports = [
11 | {
12 | on: 'req-header',
13 | ruleId: 'meituanCookie',
14 | desc: '美团V3',
15 | method: 'POST',
16 | url: 'https://*.meituan.com*',
17 | // url: 'https://msp.meituan.com/api/**',
18 | getCacheUid: ({ cookieObj }) => ({ uid: cookieObj.userId || '_', data: `${cookieObj.token}#${cookieObj.uuid}` }),
19 | handler: ({ cacheData }) => ({ envConfig: { value: cacheData.map(d => d.data).join('\n') } }),
20 | },
21 | {
22 | on: 'req-header',
23 | ruleId: 'TxStockCookie',
24 | desc: '腾讯自选股-单账号',
25 | tip: '先打开微信公众号,进福利中心,再打开APP,进个人中心',
26 | url: 'https://*.tenpay.com/cgi-bin/**',
27 | method: '*',
28 | data: {},
29 | handler({ url, cookieObj, X }) {
30 | const obj = Object.assign(X.FeUtils.getUrlParams(url), cookieObj);
31 | const keys = ['openid', 'fskey', 'wzq_qlskey', 'wzq_qluin'];
32 | keys.forEach(key => {
33 | if (obj[key]) {
34 | if (!this.data[key]) console.log(`【腾讯自选股】已获取${key}: ${obj[key]}`);
35 | this.data[key] = obj[key];
36 | }
37 | });
38 | // console.log(obj, this.data);
39 | if (keys.every(key => this.data[key])) return { envConfig: { value: keys.map(key => `${key}=${this.data[key]}`).join('&') } };
40 | },
41 | },
42 | {
43 | on: 'req-header',
44 | ruleId: 'elmCookie',
45 | desc: '饿了么',
46 | url: 'https://*.ele.me/h5/**',
47 | getCacheUid: ({ cookieObj: ck }) => ({ uid: ck.user_id, data: `SID=${ck.SID};cookie2=${ck.cookie2};grabCoupon=1` }),
48 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => d.data).join('\n') } }),
49 | },
50 | {
51 | on: 'req-header',
52 | ruleId: 'sfsyUrl',
53 | desc: '顺丰速运',
54 | method: 'get',
55 | url: 'https://mcs-mimp-web.sf-express.com/mcs-mimp/share/weChat/shareGiftReceiveRedirect?**',
56 | getCacheUid({ url, X }) {
57 | const p = X.FeUtils.getUrlParams(url);
58 | return { uid: p.mobile, data: url };
59 | },
60 |
61 | handler: ({ cacheData: D }) => {
62 | const value = D.map(d => d.data).join('\n');
63 | return {
64 | envConfig: [
65 | { value, ruleId: 'SFSY' },
66 | { value, ruleId: 'sfsyUrl' },
67 | ],
68 | };
69 | },
70 | },
71 | {
72 | on: 'req-header',
73 | ruleId: 'xclxCookie',
74 | desc: '携程旅行',
75 | url: 'https://*m.ctrip.com/restapi/**',
76 | getCacheUid({ cookieObj: C }) {
77 | if (C.cticket) return { uid: C.login_uid, data: C.cticket };
78 | },
79 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => d.data).join('\n') } }),
80 | },
81 | {
82 | on: 'res-body',
83 | ruleId: 'tyqhCookie',
84 | desc: '统一茄皇三期', // 微信小程序: 统一快乐星球 -> 活动 -> 统一茄皇三期,点进页面即可
85 | url: 'https://qiehuang-apig.xiaoyisz.com/qiehuangsecond/ga/**',
86 | method: '*',
87 | cache: {
88 | tmp: {}, // 临时缓存,获取到 userId 后合并
89 | },
90 | getCacheUid({ reqBody, resBody }) {
91 | if (reqBody?.thirdId && reqBody.wid) this.cache = reqBody;
92 |
93 | if (resBody?.data?.userId && this.cache.thirdId) {
94 | const D = this.cache;
95 | this.cache = {};
96 | return { uid: resBody.data.userId, data: `${D.thirdId}#${D.wid}#${resBody.data.userId}` };
97 | }
98 | },
99 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => d.data).join('\n') } }),
100 | updateEnvValue: /#(\d+)$/,
101 | },
102 | {
103 | on: 'res-body',
104 | ruleId: 'bwcjCookie',
105 | desc: '霸王茶姬小程序签到',
106 | url: 'https://webapi*.qmai.cn/web/seller/oauth/flash-sale-login',
107 | method: 'post',
108 | getCacheUid: ({ resBody }) => {
109 | const uid = resBody?.data?.user?.id;
110 | if (uid) return { uid, data: `${resBody.data.token}` }; // #${uid}
111 | },
112 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => d.data).join('\n') } }),
113 | },
114 | {
115 | on: 'res-body',
116 | ruleId: 'blackJSON',
117 | desc: '全球购骑士特权签到',
118 | url: 'https://{vip-member,pyp-api}.chuxingyouhui.com/{api,vip-member}/**',
119 | method: 'get',
120 | getCacheUid: ({ resBody, headers: H }) => {
121 | const uid = resBody?.data?.userId || resBody?.data?.userPointsResp?.userId;
122 | if (uid && H['black-token']) {
123 | const data = { 'black-token': H['black-token'], token: H.token, 'User-Agent': H['user-agent'], userId: uid };
124 | return { uid, data: JSON.stringify(data) };
125 | }
126 | },
127 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => d.data).join('\n') } }),
128 | updateEnvValue: /"userId":(\d+)/,
129 | },
130 | {
131 | on: 'res-body',
132 | ruleId: 'jlzx',
133 | desc: '江铃智行小程序签到',
134 | url: 'https://superapp.jmc.com.cn/jmc-zx-app-owner/v1/user/userCenter',
135 | method: 'get',
136 | getCacheUid: ({ resBody: B, headers: H }) => ({ uid: B?.data.nickName, data: H['access-token'] }),
137 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => d.data).join('\n') } }),
138 | },
139 | {
140 | on: 'req-header',
141 | ruleId: 'paopaomate',
142 | desc: '微信小程序泡泡玛特',
143 | method: 'get',
144 | url: 'https://popvip.paquapp.com/miniapp/v2/wechat/getUserInfo/?user_id=*',
145 | getCacheUid({ url, X, headers }) {
146 | const p = X.FeUtils.getUrlParams(url);
147 | const uid = p.user_id;
148 | const openid = headers.identity_code || p.openid;
149 | if (uid && openid) return { uid, data: `${uid}#${openid}` };
150 | },
151 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => d.data).join('\n') } }),
152 | },
153 | {
154 | on: 'req-header',
155 | ruleId: 'hqcsh',
156 | desc: '好奇车生活-微信小程序',
157 | method: '*',
158 | url: 'https://channel.cheryfs.cn/archer/activity-api/**',
159 | getCacheUid: ({ headers }) => headers.accountid,
160 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => d.uid).join('\n') } }),
161 | },
162 | {
163 | on: 'req-header',
164 | ruleId: 'fenxiang',
165 | desc: '粉象生活App',
166 | url: 'https://*api.fenxianglife.com/**',
167 | getCacheUid: ({ headers: H }) => ({ uid: H.finger, data: `${H.did}#${H.finger}#${H.token}#${H.oaid || ''}` }),
168 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => d.data).join('\n') } }),
169 | },
170 | {
171 | on: 'req-header',
172 | ruleId: 'lenovoAccessToken',
173 | desc: '联想App',
174 | url: 'https://mmembership.lenovo.com.cn/member*/**',
175 | getCacheUid: ({ headers: H, url }) => {
176 | // console.log(H.lenovoid, url, H.accesstoken);
177 | return { uid: H.lenovoid, data: `${H.accesstoken}#${H.lenovoid}` };
178 | },
179 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => d.data).join('\n') } }),
180 | updateEnvValue: /#(\d+)$/i,
181 | },
182 | ];
183 |
--------------------------------------------------------------------------------
/src/QLScriptPublic.js:
--------------------------------------------------------------------------------
1 | /** @type {import('@lzwme/whistle.x-scripts').RuleItem[]} */
2 | module.exports = [
3 | {
4 | on: 'req-header',
5 | ruleId: 'hdl_data',
6 | method: '**',
7 | url: 'https://superapp-public.kiwa-tech.com/activity/wxapp/**',
8 | desc: '海底捞小程序签到 token',
9 | // getCacheUid: () => 'hdl',
10 | handler({ headers }) {
11 | // console.log('hdl', headers);
12 | if (headers['_haidilao_app_token']) {
13 | return { envConfig: { name: this.ruleId, value: headers['_haidilao_app_token'] } };
14 | }
15 | },
16 | },
17 | {
18 | on: 'res-body',
19 | ruleId: 'mxbc_data',
20 | desc: '蜜雪冰城小程序 Access-Token',
21 | method: 'get',
22 | url: 'https://mxsa.mxbc.net/api/v1/customer/info*',
23 | getCacheUid: ({ resBody }) => resBody?.data?.customerId,
24 | handler({ allCacheData }) {
25 | const value = allCacheData.map(d => d.headers['access-token']).join('@');
26 | if (value) return { envConfig: { name: this.ruleId, value } };
27 | },
28 | },
29 | {
30 | on: 'req-header',
31 | ruleId: 'zbsxcx',
32 | desc: '植白说小程序 x-dts-token',
33 | method: 'get',
34 | url: 'https://www.kozbs.com/demo/wx/**/*?userId=**',
35 | getCacheUid: ({ url }) => /userId=(\d{5,})/.exec(url)?.[1],
36 | handler({ allCacheData }) {
37 | const value = allCacheData.map(d => d.headers['x-dts-token']).join('&');
38 | if (value) return { envConfig: { name: this.ruleId, value } };
39 | },
40 | },
41 | {
42 | on: 'res-body',
43 | ruleId: 'ylnn',
44 | desc: '伊利牛奶小程序',
45 | method: '*',
46 | url: 'https://msmarket.msx.digitalyili.com/gateway/api/auth/account/**',
47 | getCacheUid: ({ resBody, headers: H }) => {
48 | const uid = resBody?.data?.userId || resBody?.data?.userInfo?.userId;
49 | if (uid && H['access-token']) return uid;
50 | },
51 | handler({ cacheData: C }) {
52 | const value = C.map(d => d.headers['access-token']).join('\n');
53 | if (value)
54 | return {
55 | envConfig: [
56 | { name: this.ruleId, value },
57 | { name: 'YLXL', value: C.map(d => d.headers['access-token']).join('&'), sep: '&' }, // 伊利系列小程序
58 | ],
59 | };
60 | },
61 | },
62 | {
63 | on: 'res-body',
64 | ruleId: 'lbvip',
65 | desc: '立白小白白会员俱乐部',
66 | method: 'get',
67 | url: 'https://clubwx.hm.liby.com.cn/b2cMiniApi/me/getUserData.htm',
68 | getCacheUid: ({ resBody }) => resBody?.data?.userName,
69 | handler({ allCacheData }) {
70 | const value = allCacheData.map(d => `${d.headers['unionid']}#${d.headers['x-wxde54fd27cb59db51-token']}`).join('\n');
71 | if (value) return { envConfig: { name: this.ruleId, value } };
72 | },
73 | },
74 | {
75 | on: 'req-header',
76 | ruleId: 'ddsy_songyao',
77 | desc: '叮当快药APP',
78 | method: 'get',
79 | url: 'https://xapi.ddky.com/mcp/weixin/rest.htm?sign=*',
80 | getCacheUid: ({ url, X }) => {
81 | const query = X.FeUtils.getUrlParams(url);
82 | return query.loginToken && query.userId ? { uid: query.userId, data: `${query.loginToken}&${query.userId}&${query.uDate}` } : '';
83 | },
84 | handler({ allCacheData }) {
85 | const value = allCacheData.map(d => d.data).join('@');
86 | if (value) return { envConfig: { name: this.ruleId, value } };
87 | },
88 | },
89 | {
90 | on: 'res-body',
91 | ruleId: 'jsbaxfls',
92 | desc: '杰士邦安心福利社',
93 | method: 'get',
94 | url: 'https://xh-vip-api.a-touchin.com/mp/user/info',
95 | getCacheUid: ({ resBody, headers }) => {
96 | const uid = resBody?.data?.userInfo?.user_id;
97 | if (uid) return { uid, data: `${headers['access-token']}##${uid}` };
98 | },
99 | handler({ allCacheData: D }) {
100 | return { envConfig: { value: D.map(d => d.data).join('\n') } };
101 | },
102 | },
103 | {
104 | on: 'res-body',
105 | ruleId: 'hrjmwshg',
106 | desc: '好人家美味生活馆',
107 | method: 'post',
108 | url: 'https://xapi.weimob.com/api3/onecrm/user/center/usercenter/queryUserHeadElement',
109 | getCacheUid: ({ resBody }) => resBody?.data?.nickname,
110 | handler({ allCacheData }) {
111 | const value = allCacheData.map(d => d.headers['x-wx-token']).join('&');
112 | if (value) return { envConfig: { name: this.ruleId, value } };
113 | },
114 | },
115 | {
116 | on: 'req-body',
117 | ruleId: 'hxek',
118 | desc: '鸿星尔克签到',
119 | url: 'https://bury.demogic.com/api-bury-point/bury-point',
120 | getCacheUid: ({ reqBody, headers, req }) => {
121 | if (typeof reqBody?.userInfo === 'string') {
122 | const userInfo = JSON.parse(reqBody.userInfo);
123 | return { uid: userInfo.phoneNumber, data: userInfo.memberId };
124 | }
125 | },
126 | handler({ allCacheData }) {
127 | const value = allCacheData.map(d => d.data).join('@');
128 | if (value) return { envConfig: { name: this.ruleId, value } };
129 | },
130 | },
131 | {
132 | disabled: false,
133 | on: 'req-header',
134 | ruleId: 'wx_xlxyh',
135 | desc: '微信小程序_骁龙骁友会',
136 | url: 'https://qualcomm.growthideadata.com/qualcomm-app/**',
137 | getCacheUid: ({ headers }) => {
138 | return { uid: headers.userid, data: `${headers.sessionkey}#${headers.userid}` };
139 | },
140 | handler({ allCacheData }) {
141 | const value = allCacheData.map(d => d.data).join('&');
142 | if (value) return { envConfig: { name: this.ruleId, value } };
143 | },
144 | },
145 | {
146 | on: 'res-body',
147 | ruleId: 'ljfsjlbCookie',
148 | desc: '微信小程序_罗技粉丝俱乐部',
149 | url: 'https://api.wincheers.net/api/services/app/crmAccount/GetLGFanBuyerCenter',
150 | getCacheUid: ({ resBody, headers }) => {
151 | return { uid: resBody?.result?.buyerId, data: headers['authorization']?.replace('Bearer ', '') };
152 | },
153 | handler({ allCacheData }) {
154 | const value = allCacheData.map(d => d.data).join('&');
155 | if (value) return { envConfig: { name: this.ruleId, value } };
156 | },
157 | },
158 | {
159 | on: 'req-body',
160 | ruleId: 'ksd',
161 | desc: '卡萨帝-小程序',
162 | method: 'post',
163 | url: 'https://yx.jsh.com/customer/api/activityCenter/recordLog',
164 | getCacheUid: ({ reqBody, headers }) => ({ uid: reqBody?.userId, data: `${headers.authorization}#${reqBody.openId}` }),
165 | handler({ allCacheData }) {
166 | return { envConfig: { name: this.ruleId, value: allCacheData.map(d => d.data).join('&') } };
167 | },
168 | },
169 | {
170 | on: 'req-header',
171 | ruleId: 'smart_car_plus',
172 | desc: 'smart汽车+-小程序,签到抽盲盒',
173 | url: 'https://app-api.smart.cn/**',
174 | getCacheUid: ({ headers }) => ({ uid: headers['x-user-id'], data: headers['id-token'] }),
175 | handler: ({ allCacheData }) => ({ envConfig: { value: allCacheData.map(d => d.data).join('&') } }),
176 | },
177 | {
178 | on: 'req-header',
179 | ruleId: 'wx_gjjkpro_data',
180 | desc: '高济健康pro小程序签到',
181 | method: 'get',
182 | url: 'https://api.gaojihealth.cn/fund/api/**/*userId=*',
183 | getCacheUid: ({ headers, url }) => {
184 | const userId = /userId=(\d{10,})/.exec(url)?.[1];
185 | if (userId) return { uid: userId, data: `${userId}&${headers['authorization']}` };
186 | },
187 | handler: ({ allCacheData }) => ({ envConfig: { value: allCacheData.map(d => d.data).join('\n') } }),
188 | },
189 | {
190 | on: 'req-header',
191 | ruleId: 'gacmotorToken',
192 | desc: '广汽传祺 - 单账号',
193 | method: 'get',
194 | url: 'https://next.gacmotor.com/mall/**',
195 | getCacheUid: () => 'gacmotorToken',
196 | handler({ headers }) {
197 | if (headers.token) return { envConfig: { value: headers.token } };
198 | },
199 | },
200 | {
201 | on: 'res-body',
202 | ruleId: 'nzqc',
203 | desc: '哪吒汽车_微信小程序_refresh_token',
204 | url: 'https://www.hozonauto.com/{user/miniProgramLoginNew,api_lottery/user_login}',
205 | getCacheUid: ({ resBody }) => {
206 | if (!resBody) return;
207 | const info = resBody.data?.info || resBody.data;
208 | if (info) return { uid: info.uuid, data: info.refresh_token };
209 | },
210 | handler: ({ allCacheData }) => ({ envConfig: { value: allCacheData.map(d => d.data).join('\n') } }),
211 | },
212 | {
213 | on: 'res-body',
214 | ruleId: 'ruilanCar',
215 | desc: '睿蓝汽车_小程序_aid#rid',
216 | method: 'get',
217 | url: 'https://api-gateway.livanauto.com/app/v1.0/clientapi//common/user/info',
218 | getCacheUid: ({ resBody, headers }) => ({ uid: resBody?.data?.userId, data: `${headers.aid}#${headers.rid}` }),
219 | handler: ({ allCacheData }) => ({ envConfig: { value: allCacheData.map(d => d.data).join('\n') } }),
220 | },
221 | {
222 | on: 'res-body',
223 | ruleId: 'leidaCarCookie',
224 | desc: '雷达汽车_小程序_aid#rid',
225 | method: 'get',
226 | url: 'https://mp.radar-ev.com/clientapi/{common/user/info,radaruser/api/user/home}',
227 | getCacheUid: ({ resBody, headers }) => ({ uid: resBody?.data?.userId, data: `${headers.rid}#${headers.rid}#${resBody?.data?.userId}` }),
228 | handler: ({ allCacheData }) => ({ envConfig: { value: allCacheData.map(d => d.data).join('\n') } }),
229 | },
230 | {
231 | on: 'res-body',
232 | ruleId: 'kyqc',
233 | desc: '凯翼汽车_小程序',
234 | method: 'get',
235 | url: 'https://fdt-gateway-prod.dm.newcowin.com/customer/community-vip-user/exterior/user/getMe',
236 | getCacheUid: ({ resBody, headers }) => ({ uid: resBody?.data?.id, data: `${headers.devicesn}@@@${headers.cookie}` }),
237 | handler: ({ allCacheData }) => ({ envConfig: { value: allCacheData.map(d => d.data).join('\n') } }),
238 | },
239 | {
240 | on: 'res-body',
241 | ruleId: 'xinxi',
242 | desc: '心喜_小程序',
243 | method: 'get',
244 | url: 'https://api.xinc818.com/mini/user',
245 | getCacheUid: ({ resBody, headers }) => ({ uid: resBody?.data?.id, data: `${headers.sso}##${resBody?.data?.id}` }),
246 | handler: ({ allCacheData: D }) => ({ envConfig: { value: D.map(d => d.data).join('\n') } }),
247 | },
248 | {
249 | on: 'req-body',
250 | ruleId: 'didi',
251 | desc: '滴滴领券&果园 - 单账号',
252 | method: 'POST',
253 | url: 'https://api.didi.cn/**',
254 | getCacheUid: () => 'lzwme',
255 | handler({ reqBody }) {
256 | if (reqBody?.token) return { envConfig: { value: reqBody.token + '#3' } };
257 | },
258 | },
259 | {
260 | on: 'req-header',
261 | ruleId: 'heyeHealth',
262 | desc: '荷叶健康小程序-果园[免费领水果]',
263 | url: 'https://tuan.api.ybm100.com/miniapp/my/accountInfo',
264 | getCacheUid: ({ headers }) => ({ uid: headers.userid, data: `${headers.token}##${headers.userid}` }),
265 | handler: ({ allCacheData }) => ({ envConfig: { value: allCacheData.map(d => d.data).join('\n') } }),
266 | },
267 | {
268 | on: 'req-header',
269 | ruleId: 'yyq_new',
270 | desc: '悦野圈-小程序',
271 | url: 'https://customer.yueyequan.cn/**',
272 | method: 'GET',
273 | getCacheUid: ({ cookieObj: C }) => ({ uid: C.userid, data: `${C.usersig}#${C.userid}` }),
274 | handler: ({ allCacheData }) => ({ envConfig: { value: allCacheData.map(d => d.data).join('\n') } }),
275 | updateEnvValue: /#(\d+)/,
276 | },
277 | {
278 | on: 'res-body',
279 | ruleId: 'yuepaiToken',
280 | desc: '悦拜APP_小程序/app',
281 | method: 'POST',
282 | url: 'https://app.yuebuy.cn/api/user/{UserCenter,getUserInfo}',
283 | getCacheUid: ({ headers, resBody, url }) => {
284 | const uid = resBody?.data?.id || resBody?.data?.user?.id;
285 | if (uid) return { uid, data: `${resBody.data.token || resBody.data.user?.token || headers['x-auth-token']}##${uid}` };
286 | },
287 | handler: ({ allCacheData: D }) => ({ envConfig: { value: D.map(d => d.data).join('\n') } }),
288 | },
289 | {
290 | on: 'res-body',
291 | ruleId: 'hlToken',
292 | desc: '哈啰签到',
293 | method: 'POST',
294 | url: 'https://*.hellobike.com/api?*',
295 | getCacheUid: ({ resBody, reqBody, url }) => {
296 | try {
297 | const uid = findKeyValue(resBody, 'userNewId');
298 | if (uid) {
299 | console.log('uid', uid, url);
300 | return { uid, data: `${reqBody.token}##${uid}` };
301 | }
302 | } catch (e) {
303 | console.log(e);
304 | }
305 | },
306 | handler: ({ allCacheData: D }) => ({ envConfig: { value: D.map(v => v.data).join('\n') } }),
307 | },
308 | {
309 | on: 'req-header',
310 | ruleId: 'dewuSK',
311 | desc: '得物-心愿森林-单用户',
312 | method: 'POST',
313 | url: 'https://app.dewu.com/**',
314 | getCacheUid: ({ headers: H, cookieObj: C }) => {
315 | const dutoken = C.duToken || H.dutoken || H.cookietoken;
316 | if (dutoken) {
317 | // && H.sk
318 | const uid = dutoken.split('|')[1];
319 | if (uid) {
320 | return { uid, data: `${H['x-auth-token'].replace(/Bearer /, '')}#${dutoken}` };
321 | }
322 | }
323 | },
324 | handler: ({ url, headers: H, allCacheData: D }) => {
325 | const ua = H['user-agent'];
326 | if (ua?.includes('Mozilla'))
327 | return {
328 | envConfig: [
329 | { name: 'dewuCK', value: D.map(d => d.data).join('\n') },
330 | { name: 'dewuSK', value: H.sk },
331 | { name: 'dewuUA', value: ua },
332 | ],
333 | };
334 | },
335 | },
336 | {
337 | on: 'req-header',
338 | ruleId: 'tpyzkj',
339 | desc: '太平洋科技app签到',
340 | url: 'https://pccoin.pconline.com.cn/*/*',
341 | method: '*',
342 | getCacheUid: ({ headers: H, cookieObj: C }) => {
343 | if (!H.uid || !C.common_session_id) return;
344 | return {
345 | uid: H.uid,
346 | data: `${H.uid}#${H.appsession}#${H.cookie}#${H.version}#${H['pc-agent']}#${H.channel}#${H['user-agent']}`,
347 | };
348 | },
349 | handler: ({ allCacheData: D }) => ({ envConfig: { value: D.map(d => d.data).join('\n') } }),
350 | },
351 | {
352 | on: 'req-header',
353 | ruleId: 'bnmdhg',
354 | desc: '巴奴毛肚火锅小程序签到',
355 | url: 'https://cloud.banu.cn/api/member/*?member_id=*',
356 | method: 'GET',
357 | getCacheUid: ({ url, X }) => {
358 | const query = X.FeUtils.getUrlParams('?' + url.split('?')[1]);
359 | return {
360 | uid: query.member_id,
361 | data: query.member_id,
362 | };
363 | },
364 | handler: ({ allCacheData: D }) => ({ envConfig: { value: D.map(d => d.data).join('\n') } }),
365 | },
366 | {
367 | on: 'res-body',
368 | ruleId: 'qfxhd', // 请求头的x-ds-key&返回报文体中的id
369 | desc: '起飞线生活小程序',
370 | url: 'https://cluster.qifeixian.com/api/user/v1/center/info',
371 | getCacheUid: ({ resBody, headers }) => ({ uid: resBody?.data?.id, data: `${headers['x-ds-key']}&${resBody?.data?.id}` }),
372 | handler: ({ allCacheData: D }) => ({ envConfig: { value: D.map(d => d.data).join('\n') } }),
373 | },
374 | {
375 | on: 'req-header',
376 | ruleId: 'wx_midea',
377 | desc: '美的会员',
378 | url: 'https://mvip.midea.cn/next/*/*',
379 | method: 'GET',
380 | getCacheUid: ({ cookieObj }) => cookieObj.uid,
381 | handler: ({ allCacheData: D }) => ({ envConfig: { value: D.map(d => d.headers.cookie).join('\n') } }),
382 | },
383 | ];
384 |
385 | function findKeyValue(obj, key) {
386 | let val;
387 |
388 | try {
389 | if (!obj || !key || typeof obj !== 'object') return;
390 |
391 | if (Buffer.isBuffer(obj)) obj = JSON.parse(obj.toString());
392 |
393 | if (Array.isArray(obj)) {
394 | for (const o of obj) {
395 | val = findKeyValue(o, key);
396 | if (val != null) break;
397 | }
398 |
399 | return val;
400 | }
401 |
402 | if (key in obj) return obj[key];
403 |
404 | for (let k in obj) {
405 | val = findKeyValue(obj[k], key);
406 | if (val != null) return val;
407 | }
408 | } catch (e) {
409 | console.log('[findKeyValue][error]', e);
410 | }
411 |
412 | return val;
413 | }
414 |
--------------------------------------------------------------------------------
/src/ddgyToken.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: renxia
3 | * @Date: 2024-02-06 11:25:49
4 | * @LastEditors: renxia
5 | * @LastEditTime: 2024-02-23 11:52:29
6 | * @Description:
7 | */
8 | /** @type {import('@lzwme/whistle.x-scripts').RuleItem[]} */
9 | module.exports = [
10 | // https://raw.githubusercontent.com/leafTheFish/DeathNote/main/ddgy.js
11 | {
12 | on: 'res-body',
13 | ruleId: 'ddgyToken',
14 | desc: '滴滴果园',
15 | method: 'POST',
16 | mitm: 'game.xiaojukeji.com',
17 | url: 'https://game.xiaojukeji.com/api/game/plant/enter?*',
18 | getCacheUid: ({ reqBody, resBody }) => ({ uid: resBody?.data?.uid, data: { reqBody, uid: resBody?.data?.uid } }),
19 | handler({ allCacheData }) {
20 | const value = allCacheData.map(({ data: d }) => `${d.uid}&${d.reqBody.token}`).join('@');
21 | if (value)
22 | return {
23 | envConfig: [
24 | { name: this.ruleId, value },
25 | { name: 'ddgyck', value: allCacheData.map(({ data: d }) => JSON.stringify(d.reqBody)).join('\n') },
26 | ],
27 | };
28 | },
29 | },
30 | ];
31 |
--------------------------------------------------------------------------------
/src/features/index.js:
--------------------------------------------------------------------------------
1 | module.exports = [
2 | ...require('./m3u8-ts-cache'),
3 | ];
4 |
--------------------------------------------------------------------------------
/src/features/m3u8-ts-cache.js:
--------------------------------------------------------------------------------
1 | const fs = require('node:fs');
2 | const { resolve } = require('node:path');
3 |
4 | const cache = {
5 | /** ts 文件缓存的路径 */
6 | cacheDir: process.env.M3U8_TS_CACHE_DIR || 'cache/ts',
7 | /** ts 文件最大缓存数量 */
8 | maxSize: Math.max(process.env.M3U8_TS_CACHE_MAX_SIZE || 5000, 1000),
9 | FeUtils: null,
10 | lru: null,
11 | /** 最近一次请求的 m3u8 文件 url */
12 | currentM3u8Url: '',
13 | tsDownloading: new Map(),
14 | clear(clearAll = false) {
15 | if (clearAll) return fs.rmSync(cache.cacheDir, { recursive: true });
16 | },
17 | init() {
18 | if (!fs.existsSync(cache.cacheDir)) {
19 | fs.mkdirSync(cache.cacheDir, { recursive: true });
20 | } else {
21 | fs.readdirSync(cache.cacheDir)
22 | .filter(d => d.length >= 32)
23 | .map(filename => [filename, fs.statSync(resolve(this.cacheDir, filename)).atimeMs])
24 | .sort(([a, b]) => b[1] - a[1])
25 | .forEach(([filename], atimeMs) => cache.lru.set(filename, atimeMs));
26 | }
27 |
28 | console.log('cache inited. ', cache.lru.info());
29 | },
30 | };
31 |
32 | /**
33 | * 用法:设置环境变量:
34 | * process.env.M3U8_CACHE_ENABLE = '1'; // 开启 m3u8 文件解析缓存规则
35 | * process.env.M3U8_TS_CACHE_ENABLE = '1'; // 开启 ts 缓存下载规则
36 | * process.env.M3U8_TS_CACHE_DIR = 'cache/ts'; // 自定义缓存目录
37 | * process.env.M3U8_TS_CACHE_MAX_SIZE = 5000; // 自定义缓存文件最大数量
38 | *
39 | * @type {import('@lzwme/whistle.x-scripts').RuleItem[]}
40 | */
41 | module.exports = [
42 | {
43 | on: 'res-body',
44 | ruleId: 'm3u8-preload-cache',
45 | desc: '根据 m3u8 文件内容缓存TS',
46 | method: 'get',
47 | url: (process.env.M3U8_CACHE_URL || '**.m3u8').split(','),
48 | disabled: process.env.M3U8_CACHE_ENABLE != '1',
49 | handler: async ({ url, resBody, X: { FeUtils } }) => {
50 | if (!url.endsWith('.m3u8')) return;
51 |
52 | if (!cache.FeUtils) {
53 | cache.FeUtils = FeUtils;
54 | cache.logger = logger;
55 | }
56 |
57 | try {
58 | cache.currentM3u8Url = url;
59 |
60 | const color = FeUtils.color;
61 | const baseUrl = url.slice(0, url.lastIndexOf('/'));
62 | const tasks = resBody
63 | .toString('utf-8')
64 | .split('\n')
65 | .filter(line => line.includes('.ts'))
66 | .map(tsurl => {
67 | if (!tsurl.startsWith('http')) tsurl = new URL(tsurl, baseUrl).toString();
68 | return () => cache.currentM3u8Url === url && downloadTs(tsurl);
69 | });
70 |
71 | console.log(color.cyan(`> 获取 ts 文件 ${tasks.length} 个:`), color.gray(url));
72 | FeUtils.concurrency(tasks, 8).then(d => console.log(color.green('[TS缓存下载完毕]'), d.length, color.gray(url)));
73 | } catch (e) {
74 | console.log(e);
75 | }
76 | },
77 | },
78 | {
79 | on: 'req-header',
80 | ruleId: 'm3u8-ts-cache',
81 | desc: 'm3u8 媒体的 ts 文件缓存',
82 | method: 'get',
83 | url: (process.env.M3U8_TS_CACHE_URL || '**.ts').split(','),
84 | disabled: process.env.M3U8_TS_CACHE_ENABLE != '1' && process.env.M3U8_CACHE_ENABLE != '1',
85 | handler: async ({ url, X: { FeUtils, logger } }) => {
86 | if (!cache.FeUtils) {
87 | cache.FeUtils = FeUtils;
88 | cache.logger = logger;
89 | }
90 |
91 | const filepath = await downloadTs(url);
92 | if (filepath) return { body: fs.readFileSync(filepath) };
93 | },
94 | },
95 | ];
96 |
97 | async function downloadTs(url) {
98 | if (!url.includes('.ts')) return;
99 |
100 | const FeUtils = cache.FeUtils;
101 | const color = FeUtils.color;
102 | const filename = FeUtils.md5(url);
103 | const filepath = resolve(cache.cacheDir, filename);
104 |
105 | if (!cache.lru) {
106 | cache.lru = new FeUtils.LRUCache({
107 | max: cache.maxSize,
108 | updateAgeOnGet: true,
109 | dispose(_val, key, reason) {
110 | if (reason !== 'set') {
111 | FeUtils.rmrf(resolve(cache.cacheDir, key));
112 | }
113 | },
114 | });
115 |
116 | cache.init();
117 | }
118 |
119 | let barrier = cache.tsDownloading.get(filename);
120 | if (barrier) await barrier.wait();
121 |
122 | if (!fs.existsSync(filepath)) {
123 | try {
124 | const timeKey = color.gray(filename);
125 | console.time(timeKey);
126 | console.log(color.cyanBright('- 开始缓存文件'), color.magenta(url));
127 |
128 | barrier = new FeUtils.Barrier();
129 | cache.tsDownloading.set(filename, barrier);
130 | setTimeout(() => barrier.open(), 60_000); // 超时 60s
131 | const r = await FeUtils.download({ url, filepath });
132 | barrier.open();
133 | cache.tsDownloading.delete(filename);
134 |
135 | console.log(color.green('[TS 已缓存]'), r.size / 1024, color.gray(filepath));
136 | console.timeEnd(timeKey);
137 | } catch (error) {
138 | console.error('下载失败!', color.red(url), error);
139 | return;
140 | }
141 | } else {
142 | console.log(color.green('[取缓存]'), color.gray(url));
143 | }
144 |
145 | if (fs.existsSync(filepath)) {
146 | cache.lru.set(filename, Date.now());
147 | return filepath;
148 | }
149 | }
150 |
151 | // console.log(module.exports);
152 |
--------------------------------------------------------------------------------
/src/huluwa.js:
--------------------------------------------------------------------------------
1 | const apps = {
2 | wxded2e7e6d60ac09d: { key: 'XLHG', channelId: '8', desc: '偲源惠购' },
3 | wx61549642d715f361: { key: 'GLYP', channelId: '7', desc: '贵旅优品' },
4 | wx613ba8ea6a002aa8: { key: 'KGLG', channelId: '2', desc: '空港乐购' },
5 | wx936aa5357931e226: { key: 'HLQG', channelId: '6', desc: '航旅黔购' },
6 | wx624149b74233c99a: { key: 'ZXCS', channelId: '5', desc: '遵航出山' },
7 | wx5508e31ffe9366b8: { key: 'GYQP', channelId: '3', desc: '贵盐黔品' },
8 | wx821fb4d8604ed4d6: { key: 'LLSC', channelId: '1', desc: '乐旅商城' },
9 | wxee0ce83ab4b26f9c: { key: 'YLQX', channelId: '9', desc: '驿路黔寻' },
10 | };
11 |
12 | //
13 | const tokenCache = new Map();
14 |
15 | /**
16 | * 葫芦娃 token 自动提取保存或上传至青龙
17 | * @type {import('@lzwme/whistle.x-scripts').RuleItem}
18 | */
19 | module.exports = {
20 | on: 'res-body',
21 | ruleId: 'huluwa',
22 | desc: '葫芦娃 x-access-token 获取',
23 | url: 'https://gw.huiqunchina.com/front-manager/api/**',
24 | getCacheUid: ({ headers, reqBody, resBody }) => {
25 | const token = headers['x-access-token'];
26 | if (!token) return;
27 |
28 | const info = tokenCache.get(token) || { appid: '', uid: '', token };
29 | if (resBody?.data?.phone) info.uid = resBody?.data?.phone;
30 | if (!info.appid) info.appid = /miniProgram\/(wx\w+)/.exec(headers['user-agent'])?.[1] || reqBody?.appId;
31 | tokenCache.set(token, info);
32 |
33 | if (info.uid && info.appid) return { uid: `${info.appid}_${info.uid}`, data: { token, appid: info.appid, uid: info.uid } };
34 | },
35 | handler: ({ allCacheData, headers, reqBody }) => {
36 | const info = tokenCache.get(headers['x-access-token']);
37 | if (!info) return;
38 |
39 | const allUserData = allCacheData.filter(d => d.data.appid === info.appid);
40 |
41 | if (allUserData.length) {
42 | const value = allUserData.map(d => `${d.data.token}##${d.data.uid || d.uid}`).join('\n');
43 | const envConfig = { name: `${apps[info.appid].key}_COOKIE`, value, desc: apps[info.appid].desc + '-huluwa' };
44 | return { envConfig };
45 | }
46 | },
47 | };
48 |
--------------------------------------------------------------------------------
/src/imaotai.js:
--------------------------------------------------------------------------------
1 | const cache = {
2 | userId: '',
3 | token: '',
4 | tokenWap: '',
5 | lng: '',
6 | lat: '',
7 | deviceId: '',
8 | };
9 |
10 | /** @type {import('@lzwme/whistle.x-scripts').RuleItem} */
11 | module.exports = {
12 | on: 'res-body',
13 | ruleId: 'imaotai',
14 | desc: 'imaotai预约 token 获取',
15 | /** url 匹配规则 */
16 | url: 'https://{h5,app}.moutai519.com.cn/**',
17 | /** 方法匹配 */
18 | method: '**',
19 | /** 是否上传至 青龙 环境变量配置 */
20 | toQL: true,
21 | /** 是否写入到环境变量配置文件中 */
22 | toEnvFile: true,
23 | /** 是否合并不同请求的缓存数据。默认为覆盖 */
24 | mergeCache: true,
25 | /** 获取当前用户唯一性的 uuid */
26 | getCacheUid: ({ headers, cookieObj, resBody }) => {
27 | if (/^\d+$/.test(resBody?.data?.userId)) cache.userId = resBody.data.userId;
28 | if (!cache.userId) return;
29 |
30 | const deviceId = headers['mt-device-id'] || cookieObj['MT-Device-ID-Wap'];
31 | if (deviceId) cache.deviceId = deviceId;
32 | if (cookieObj['MT-Token-Wap']) cache.tokenWap = cookieObj['MT-Token-Wap'];
33 | if (headers['mt-lng']) cache.lng = headers['mt-lng'];
34 | if (headers['mt-lat']) cache.lat = headers['mt-lat'];
35 | if (headers['mt-token']) cache.token = headers['mt-token'];
36 |
37 | Object.entries(cache).forEach(([key, val]) => {
38 | if (val === 'undifined') cache[key] = '';
39 | });
40 |
41 | console.log('geuid:', cache)
42 | return {
43 | /** user 唯一性标记 */
44 | uid: cache.userId,
45 | /** 保存至缓存中的自定义数据。是可选的,主要用于需组合多个请求数据的复杂场景 */
46 | data: { ...cache },
47 | };
48 | },
49 | handler: ({ allCacheData }) => {
50 | const allUserData = allCacheData.map(d => d.data).filter(d => d.token);
51 | if (allCacheData.length === 0) return;
52 | console.log('imaotai allUserData:', JSON.stringify(allUserData, null, 2));
53 | // const value = allUserData.map(d => `deviceId=${d.deviceId};token=${d.token};tokenWap=${d.tokenWap};city=x市;province=x省`).join('&');
54 | const value = allUserData.map(d => `userId=${d.userId};deviceId=${d.deviceId};token=${d.token};tokenWap=${d.tokenWap}`).join('\n');
55 |
56 | return { envConfig: { name: 'QL_IMAOTAI', value, desc: 'imaotai cookie' } };
57 | },
58 | updateEnvValue: /userId=([^;]+)/,
59 | };
60 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: renxia
3 | * @Date: 2024-01-22 14:00:13
4 | * @LastEditors: renxia
5 | * @LastEditTime: 2024-02-28 11:56:25
6 | * @Description:
7 | */
8 | module.exports = [
9 | ...require('./features'),
10 | // ...require('./vip'),
11 | // ...require('./jd'),
12 | // ...require('./QLScriptPublic'),
13 | ];
14 |
--------------------------------------------------------------------------------
/src/jd.js:
--------------------------------------------------------------------------------
1 | // @ts-check
2 | const cache = {
3 | uid: '',
4 | wskey: '',
5 | };
6 |
7 | /**
8 | * 京东 cookie 自动获取上传至青龙面板
9 | * WAP登录: https://bean.m.jd.com/bean/signIndex.action
10 | * @type {import('@lzwme/whistle.x-scripts').RuleItem[]}
11 | */
12 | module.exports = [
13 | {
14 | disabled: false,
15 | /** 保存缓存数据ID,应唯一 */
16 | ruleId: 'JD_COOKIE',
17 | desc: '京东 cookie 自动抓取并同步至青龙环境变量',
18 | /** url 匹配规则 */
19 | url: 'https://*.jd.com/**',
20 | /** 请求方法匹配 */
21 | method: '*',
22 | toQL: true,
23 | toEnvFile: true,
24 | mergeCache: true,
25 | /** 获取当前用户唯一性的 uid */
26 | getCacheUid({ cookieObj, url }) {
27 | if (cookieObj.wskey) {
28 | cache.wskey = cookieObj.wskey;
29 | console.log('wskey', cache);
30 | }
31 |
32 | const uid = cookieObj.pt_pin || cookieObj.pin;
33 |
34 | if (uid && !uid.startsWith('netdiag') && !uid.startsWith('***')) {
35 | if (cache.uid && cache.uid !== uid) cache.wskey = '';
36 | cache.uid = uid;
37 | if (cache.wskey) cookieObj.wskey = cache.wskey;
38 |
39 | return { uid, data: cookieObj };
40 | }
41 | },
42 | /** 规则处理并返回环境变量配置。可以数组的形式返回多个 */
43 | handler({ cacheData, cookieObj, X }) {
44 | // console.log('handler-1', cookieObj.pt_pin, cookieObj.pin, this.mergeCache);
45 | // 生成环境变量配置
46 | const envConfig = [
47 | {
48 | name: 'JD_COOKIE',
49 | value: cacheData
50 | .filter(d => d.data.pt_pin)
51 | .map(d => X.cookieStringfiy(d.data, { onlyKeys: ['pt_pin', 'pt_key'] }) + ';')
52 | .join('\n'),
53 | desc: '京东 cookie',
54 | sep: '\n',
55 | },
56 | {
57 | name: 'JD_WSCK',
58 | value: cacheData
59 | .filter(d => d.data.wskey)
60 | .map(d => `pin=${encodeURIComponent(d.uid)};wskey=${d.data.wskey}`)
61 | .join('&'),
62 | desc: '京东 wskey',
63 | sep: '&',
64 | },
65 | ].filter(d => d.value);
66 |
67 | return { envConfig };
68 | },
69 | /** 更新处理已存在的环境变量,返回合并后的结果。若无需修改则可返回空 */
70 | updateEnvValue({ value, sep = '\n' }, oldValue = '', X) {
71 | if (!oldValue) console.trace('[JD][OLDVALUE为空!]', value, oldValue);
72 |
73 | oldValue.split(sep).forEach(cookie => {
74 | if (!cookie) return;
75 | const pin = cookie.match(/pin=[^;]+/)?.[0];
76 | if (!pin || !value.includes(pin)) value += `${sep}${cookie}`;
77 | });
78 | return value;
79 | },
80 | },
81 | {
82 | desc: '签到有礼超级无线-七天签到LZKJ_SEVENDAY',
83 | ruleId: 'LZKJ_SEVENDAY',
84 | method: 'get',
85 | url: 'https://lzkj-isv.isvjcloud.com/sign/sevenDay/signActivity?activityId=*',
86 | getCacheUid: ({ url }) => new URL(url).searchParams.get('activityId'),
87 | handler({ cacheData }) {
88 | return { envConfig: { value: cacheData.map(d => d.uid).join(','), name: 'LZKJ_SEVENDAY' } };
89 | },
90 | },
91 | {
92 | desc: '签到有礼超级无线-CJHY_SEVENDAY',
93 | ruleId: 'CJHY_SEVENDAY',
94 | method: 'get',
95 | url: 'https://cjhy-isv.isvjcloud.com/sign/sevenDay/signActivity?activityId=*',
96 | getCacheUid: ({ url }) => new URL(url).searchParams.get('activityId'),
97 | handler: ({ cacheData: A }) => ({ value: A.map(d => d.uid).join(','), name: 'CJHY_SEVENDAY' }), // 可以直接返回 envConfig
98 | },
99 | {
100 | desc: 'lzkj签到有礼-activityId',
101 | ruleId: 'jd_lzkj_signActivity2_ids',
102 | url: 'https://lzkj-isv.isvjcloud.com/sign/signActivity2?activityId=*',
103 | getCacheUid: ({ url }) => new URL(url).searchParams.get('activityId'),
104 | handler({ cacheData }) {
105 | return [
106 | { value: cacheData.map(d => d.uid).join('&'), name: 'jd_lzkj_signActivity2_ids', desc: 'lzkj签到有礼' },
107 | { value: cacheData.map(d => d.uid).join(','), name: 'LZKJ_SIGN', desc: '签到有礼超级无线-LZKJ_SIGN' },
108 | ];
109 | },
110 | },
111 | {
112 | desc: 'cjhy签到有礼-activityId',
113 | ruleId: 'jd_cjhy_signActivity_ids',
114 | url: 'https://cjhy-isv.isvjcloud.com/wxActionCommon/getUserInfo',
115 | method: 'post',
116 | getCacheUid: ({ headers }) => {
117 | if (headers.referer) return new URL(headers.referer).searchParams.get('activityId');
118 | },
119 | handler({ cacheData }) {
120 | return [
121 | { value: cacheData.map(d => d.uid).join('&'), name: 'jd_cjhy_signActivity_ids', desc: 'cjhy签到有礼' },
122 | { value: cacheData.map(d => d.uid).join(','), name: 'CJHY_SIGN', desc: '签到有礼超级无线-CJHY_SIGN' },
123 | ];
124 | },
125 | },
126 | ];
127 |
--------------------------------------------------------------------------------
/src/lzwme.js:
--------------------------------------------------------------------------------
1 | /** @type {import('@lzwme/whistle.x-scripts').RuleItem[]} */
2 | module.exports = [
3 | // https://raw.githubusercontent.com/leafTheFish/DeathNote/main/ddgy.js
4 | {
5 | on: 'res-body',
6 | ruleId: 'ylhyencryptsessionid',
7 | desc: '伊利会员福利社',
8 | method: '*',
9 | url: 'https://wx-fulishe.msx.digitalyili.com/brandwxa/api/vip/getinfo*',
10 | getCacheUid: ({ reqBody, resBody }) => {
11 | // console.log('reqBody', reqBody);
12 | const uid = resBody?.data?.uid || (reqBody?.encryptsessionid ? resBody?.result?.vipcode : '');
13 | if (uid) return { uid, data: `${reqBody.encryptsessionid}##${uid}` };
14 | },
15 | handler: ({ cacheData }) => ({
16 | envConfig: {
17 | value: cacheData
18 | .filter(d => typeof d.data === 'string')
19 | .map(d => `${d.data}`)
20 | .join('\n'),
21 | },
22 | }),
23 | },
24 | {
25 | on: 'res-body',
26 | ruleId: 'sysxc',
27 | desc: '书亦烧仙草',
28 | method: '*',
29 | url: 'https://scrm-prod.shuyi.org.cn/saas-gateway/api/mini-app/v1/{member/mine,account/login}**',
30 | getCacheUid: ({ resBody, headers, url }) => {
31 | const data = {
32 | uid: resBody?.data?.user?.uid || resBody?.data?.member?.uid,
33 | data: headers.auth || resBody?.data?.auth,
34 | };
35 | return data;
36 | },
37 | handler({ cacheData }) {
38 | const value = cacheData.filter(d => d.data).map(d => `${d.data}##${d.uid}`);
39 | return { envConfig: { value: value.join('\n') } };
40 | },
41 | },
42 | {
43 | on: 'res-body',
44 | ruleId: 'alyp',
45 | desc: '阿里云盘',
46 | url: 'https://auth.alipan.com/v2/account/token',
47 | getCacheUid: ({ resBody }) => ({ uid: resBody?.user_id, data: resBody?.refresh_token }),
48 | handler: ({ cacheData }) => ({ envConfig: { value: cacheData.map(d => `${d.data}##${d.uid}`).join('\n') } }),
49 | },
50 | {
51 | on: 'req-header',
52 | ruleId: 'IQIYI_COOKIE',
53 | desc: '爱奇艺签到',
54 | url: 'https://*.iqiyi.com/*/api/**',
55 | method: '*',
56 | getCacheUid: ({ cookieObj: ck }) => ({ uid: ck.P00003, data: `P00003=${ck.P00003};P00001=${ck.P00001}` }),
57 | handler: ({ cacheData }) => ({ envConfig: { value: cacheData.map(d => `${d.data}`).join('\n') } }),
58 | updateEnvValue: /P00003=[^;]+/,
59 | },
60 | {
61 | on: 'res-body',
62 | ruleId: 'xmly_cookie',
63 | desc: '喜马拉雅签到 cookie 获取',
64 | url: ['https://m.ximalaya.com/starwar/task/listen/serverTime', 'https://pc.ximalaya.com/pc-application-server/user/isNew', 'http://xmc.ximalaya.com/xmlymain-login-web/**'],
65 | method: '*',
66 | getCacheUid: ({ headers, resBody = {} }) => {
67 | const uid = resBody.context?.currentUser.id || resBody.data?.uid || resBody.data?.userId;
68 | if (uid && headers.cookie?.includes('token')) return { uid, data: `${headers.cookie.replace(/ XD=[^;]+;/, '')}##${uid}` };
69 | },
70 | handler: ({ cacheData: d }) => ({ envConfig: { value: d.map(d => `${d.data}`).join('\n'), sep: '\n' } }),
71 | updateEnvValue: /##(\d+)/,
72 | },
73 | {
74 | disabled: true, // 脚本已废弃
75 | on: 'req-header',
76 | ruleId: 'dkl_token',
77 | desc: '迪卡侬签到-单账号',
78 | url: 'https://api-cn.decathlon.com.cn/**',
79 | method: '*',
80 | getCacheUid: () => 'default',
81 | handler: ({ headers }) => headers.authorization && { envConfig: { value: headers.authorization } },
82 | },
83 | {
84 | // 开代理时云闪付签到页面进不去;可以先关闭代理进入签到页面,再开代理后,随意点击签到页面的任意链接
85 | on: 'req-header',
86 | ruleId: 'ysfqd_data',
87 | desc: '云闪付签到-单账号',
88 | url: 'https://youhui.95516.com/newsign/**',
89 | method: '*',
90 | getCacheUid: () => 'default',
91 | handler: ({ headers }) => headers.authorization && { envConfig: { value: headers.authorization } },
92 | },
93 | {
94 | on: 'req-header',
95 | ruleId: 'ths_cookie',
96 | desc: '同花顺签到',
97 | url: 'https://eq.10jqka.com.cn/**',
98 | method: 'get',
99 | // getCacheUid: ({ cookieObj: C }) => C.userid,
100 | getCacheUid: ({ cookieObj: C }) => ({ uid: C.userid, data: `ticket=${C.ticket}; userid=${C.userid}; user=${C.user}` }),
101 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => `${d.data || d.headers.cookie}`).join('\n') } }),
102 | },
103 | {
104 | on: 'res-body',
105 | ruleId: 'JJCookie',
106 | desc: '掘金签到',
107 | url: 'https://api.juejin.cn/user_api/v1/user/get**',
108 | method: 'get',
109 | getCacheUid({ headers, resBody: B }) {
110 | const uid = B?.data?.user_id || B?.data?.user_basic?.user_id;
111 | if (uid && headers.cookie) return { uid };
112 | },
113 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => `${d.headers.cookie}##${d.uid}`).join('\n') } }),
114 | },
115 | {
116 | ruleId: 'gujing',
117 | desc: '古井贡酒会员中心小程序',
118 | method: 'post',
119 | url: 'https://scrm.gujing.com/gujing_scrm/wxclient/login/info',
120 | on: 'req-body',
121 | getCacheUid: ({ reqBody: R }) => R?.memberId,
122 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => `${d.headers['access-token']}##${d.uid}`).join('\n') } }),
123 | },
124 | {
125 | on: 'res-body',
126 | ruleId: 'aima',
127 | desc: '爱玛会员俱乐部-小程序',
128 | url: 'https://scrm.aimatech.com/aima/wxclient/member/IndexInfo',
129 | method: 'get',
130 | getCacheUid: ({ resBody: R, headers }) => (headers['access-token'] ? { uid: R?.content?.id } : nulll),
131 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => `${d.headers['access-token']}##${d.uid}`).join('\n') } }),
132 | // updateEnvValue: /&([\d\*]+)/,
133 | },
134 | {
135 | on: 'res-body',
136 | ruleId: 'mypd',
137 | desc: '漫游胖达-小程序',
138 | url: 'https://pw.gzych.vip/ykb_huiyuan/api/v2/MemberMine/BasicInfo',
139 | method: 'get',
140 | getCacheUid: ({ resBody: R, headers }) => (headers['authorization'] ? { uid: R?.Data?.CardNo } : nulll),
141 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => `${d.headers['authorization']}##${d.uid}`).join('\n') } }),
142 | // updateEnvValue: /&([\d\*]+)/,
143 | },
144 | {
145 | on: 'res-body',
146 | ruleId: 'aicnn_token',
147 | desc: 'AICNN签到 token 提取',
148 | source: 'https://github.com/lzwme/ql-scripts/blob/main/ql_aicnn.ts',
149 | url: 'https://api.aicnn.cn/app-api/system/auth/refresh-token*',
150 | method: 'post',
151 | getCacheUid: ({ resBody: R, headers }) => (R?.data?.userId ? { uid: R.data.userId, data: R.data.refreshToken } : nulll),
152 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => `${d.data}##${d.uid}`).join('\n') } }),
153 | },
154 | ];
155 |
--------------------------------------------------------------------------------
/src/ohhh_QL-Script.js:
--------------------------------------------------------------------------------
1 | /**
2 | * yang7758258/ohhh_QL-Script
3 | * @type {import('@lzwme/whistle.x-scripts').RuleItem[]}
4 | */
5 | module.exports = [
6 | {
7 | on: 'req-body',
8 | ruleId: 'chmlck',
9 | desc: '长虹美菱小程序签到',
10 | url: 'https://hongke.changhong.com/gw/burying/burying/report*',
11 | method: 'post',
12 | getCacheUid: ({ reqBody: R }) => R?.props?.wx_user?.phone_number,
13 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => `${d.headers.token}##${d.uid}`).join('\n') } }),
14 | },
15 | {
16 | on: 'res-body',
17 | ruleId: 'qchyjlb',
18 | desc: '雀巢会员俱乐部-小程序签到',
19 | url: 'https://crm.nestlechinese.com/openapi/member/api/User/GetUserInfo',
20 | method: 'get',
21 | getCacheUid: ({ resBody: R }) => ({ uid: R?.data?.mobile }),
22 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => `${d.headers.authorization}&${d.uid}`).join('\n') } }),
23 | updateEnvValue: /&([\d\*]+)/,
24 | },
25 | {
26 | on: 'res-body',
27 | ruleId: 'fsdlb',
28 | desc: '逢三得利吧-小程序签到',
29 | url: 'https://xiaodian.miyatech.com/api/user/member/info',
30 | method: 'post',
31 | getCacheUid: ({ resBody: R }) => ({ uid: R?.data?.memberId }),
32 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => `${d.headers.authorization}&${d.uid}`).join('\n'), sep: '\n' } }),
33 | updateEnvValue: /&([\d\*]+)/,
34 | },
35 | {
36 | on: 'res-body',
37 | ruleId: 'ywxspc',
38 | desc: '义乌小商品城会员-小程序签到',
39 | url: 'https://apiserver.chinagoods.com/ums/authentication/v1/userauthinfo',
40 | method: 'get',
41 | getCacheUid: ({ resBody: R, headers }) => headers.authorization && { uid: R?.data?.userinfo?.userId },
42 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => `${d.headers.authorization}&${d.uid}`).join('\n'), sep: '\n' } }),
43 | updateEnvValue: /&([\d\*]+)/,
44 | },
45 | {
46 | on: 'res-body',
47 | ruleId: 'zippo',
48 | desc: 'zippo会员中心-小程序签到',
49 | url: 'https://wx-center.zippo.com.cn/api/users/profile',
50 | method: 'get',
51 | getCacheUid: ({ resBody: R, headers }) => headers.authorization && { uid: R?.phone },
52 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => `${d.headers.authorization}&${d.uid}`).join('\n'), sep: '\n' } }),
53 | updateEnvValue: /&([\d\*]+)/,
54 | },
55 | {
56 | on: 'res-body',
57 | ruleId: 'ydxq',
58 | desc: '雅迪星球-小程序',
59 | url: 'https://planet-api.op.yadea.com.cn/user-api/app/user/getUsertoken',
60 | method: 'post',
61 | getCacheUid: ({ resBody: R, headers }) => headers.authorization && { uid: R?.object?.userinfo?.userid },
62 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => `${d.headers.authorization}&${d.uid}`).join('\n'), sep: '\n' } }),
63 | updateEnvValue: /&([\d\*]+)/,
64 | },
65 | {
66 | on: 'res-body',
67 | ruleId: 'xpnc',
68 | desc: '兴攀农场-小程序',
69 | url: 'https://p.xpfarm.cn/treemp/user.PersonalCenter/getInfo',
70 | method: 'post',
71 | getCacheUid: ({ resBody: R, headers }) => headers.authorization && ({ uid: R?.data?.id }),
72 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => `${d.headers.authorization}&${d.uid}`).join('\n'), sep: '\n' } }),
73 | updateEnvValue: /&.+/,
74 | },
75 | {
76 | on: 'res-body',
77 | ruleId: 'dfjsck',
78 | desc: '东方棘市-小程序',
79 | url: 'https://ys.shajixueyuan.com/api/user/info',
80 | method: 'GET',
81 | getCacheUid: ({ resBody: R, headers }) => headers.token && ({ uid: R?.data?.id }),
82 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => `${d.headers.token}#${d.uid}`).join('\n') } }),
83 | updateEnvValue: /#([\d\*]+)/,
84 | },
85 | {
86 | on: 'res-body',
87 | ruleId: 'rqtyg',
88 | desc: '日清体验馆-小程序',
89 | url: 'https://prod-api.nissinfoodium.com.cn/gw-shop/app/v1/user-center/detail?type=1',
90 | method: 'GET',
91 | getCacheUid: ({ resBody: R, headers }) => headers.token && ({ uid: R?.data?.user_id }),
92 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => `${d.headers.token}&${d.uid}`).join('\n'), sep: '\n' } }),
93 | updateEnvValue: /&([\d\*]+)/,
94 | },
95 | {
96 | on: 'res-body',
97 | ruleId: 'emsyhzx',
98 | desc: 'EMS邮惠中心-小程序签到得优惠券',
99 | url: 'https://ump.ems.com.cn/memberCenterApiV2/member/findByOpenIdAppId',
100 | method: 'post',
101 | getCacheUid: ({ reqBody: Q, resBody: R }) => Q.openId && ({ uid: R?.data?.user_id, data: `${Q.openId}&${R.data?.user_id}` }),
102 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => d.data).join('\n'), sep: '\n' } }),
103 | updateEnvValue: /&([\da-z]+)/,
104 | },
105 | {
106 | on: 'res-body',
107 | ruleId: 'tkzxbxCookie',
108 | desc: '泰康在线保险-小程序签到-单账号',
109 | url: 'https://m.tk.cn/member_api*',
110 | method: 'post',
111 | getCacheUid: ({ reqBody: Q, resBody: R, url }) => {
112 | if (typeof Q.params === 'string') Q = JSON.parse(Q.params);
113 | return { uid: Q.bindid, data: `${Q.bindid}` }; // &${R.data?.tkmid}
114 | },
115 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => d.data).join('\n'), sep: '\n' } }),
116 | updateEnvValue: /&([\da-z]+)/,
117 | },
118 | {
119 | on: 'res-body',
120 | ruleId: 'yshyjlb',
121 | desc: '仰韶会员俱乐部-小程序',
122 | url: 'https://hy.51pt.top/app/ys/mine/getMemberInfo',
123 | method: 'get',
124 | getCacheUid: ({ resBody: R }) => ({ uid: R?.data?.userId }),
125 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => `${d.headers.authorization}&${d.uid}`).join('\n'), sep: '\n' } }),
126 | updateEnvValue: /&([\d\*]+)/,
127 | },
128 | {
129 | on: 'res-body',
130 | ruleId: 'mswefls',
131 | desc: '麦斯威尔福利社-小程序',
132 | url: 'https://jde.mtbcpt.com/api/JDEMaxwellApi/QueryHomeInfo',
133 | method: 'post',
134 | getCacheUid: ({ resBody: R, reqBody: Q }) => {
135 | const uid = R?.data?.user?.Id;
136 | if (uid) return { uid, data: `${Q.openId}&${uid}` };
137 | },
138 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => d.data).join('\n'), sep: '\n' } }),
139 | updateEnvValue: /&([\d\*]+)/,
140 | },
141 | {
142 | on: 'res-body',
143 | ruleId: 'hqcsh',
144 | desc: '好奇车生活-小程序',
145 | url: 'https://channel.cheryfs.cn',
146 | method: '*',
147 | getCacheUid: ({ resBody: R, reqBody: Q, headers }) => {
148 | if (headers.accountid) {
149 | console.log(url, R, Q);
150 | }
151 | // const uid = R?.data?.user?.Id;
152 | // if (uid) return { uid, data: `${Q.openId}&${uid}` };
153 | },
154 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => `${d.headers.accountid}&${d.uid}`).join('\n'), sep: '\n' } }),
155 | updateEnvValue: /&([\d\*]+)/,
156 | },
157 | {
158 | on: 'res-body',
159 | ruleId: 'gljj',
160 | desc: '国乐酱酒-小程序签到得酒',
161 | url: 'https://member.guoyuejiu.com/api/user/info',
162 | method: 'get',
163 | getCacheUid: ({ resBody: R , headers }) => headers.authorization && ({ uid: R?.data?.id }),
164 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => `${d.headers.authorization}&${d.uid}`).join('\n'), sep: '\n' } }),
165 | updateEnvValue: /&([\d\*]+)/,
166 | },
167 | {
168 | on: 'res-body',
169 | ruleId: 'babaycare',
170 | desc: 'Babaycare-小程序签到',
171 | url: 'https://api.bckid.com.cn/lightpay/front/user/balance/info',
172 | method: 'post',
173 | getCacheUid: ({ resBody: R , headers }) => headers.authorization && ({ uid: R?.body?.userId }),
174 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => `${d.headers.authorization}&${d.uid}`).join('\n'), sep: '\n' } }),
175 | updateEnvValue: /&([\d\*]+)/,
176 | },
177 | {
178 | on: 'res-body',
179 | ruleId: 'mpcbh',
180 | desc: '毛铺草本荟-小程序签到',
181 | url: 'https://mpb.jingjiu.com/proxy-he/api/BlzAppletIndex/levelPowerList',
182 | method: 'post',
183 | getCacheUid: ({ resBody: R, headers }) => headers.authorization && ({ uid: R?.data?.user?.user_id }),
184 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => `${d.headers.authorization}&${d.uid}`).join('\n'), sep: '\n' } }),
185 | updateEnvValue: /&([\d\*]+)/,
186 | },
187 | {
188 | on: 'res-body',
189 | ruleId: 'jdfls',
190 | desc: '健达福利社-小程序签到',
191 | url: 'https://mole.ferrero.com.cn/boss/boss/scrm/home/info/get',
192 | method: 'post',
193 | getCacheUid: ({ resBody: R }) => ({ uid: R?.data?.memberDetail?.memberId }),
194 | handler: ({ cacheData: D }) => ({
195 | envConfig: { value: D.map(d => `${d.headers['kumi-token']}&${d.headers['project-id']}&${d.uid}`).join('\n'), sep: '\n' },
196 | }),
197 | updateEnvValue: /&([a-z\d]+)$/,
198 | },
199 | {
200 | on: 'res-body',
201 | ruleId: 'htmwg',
202 | desc: '海天美味馆-小程序签到',
203 | url: 'https://cmallapi.haday.cn/buyer-api/members',
204 | method: 'get',
205 | getCacheUid: ({ resBody: R, headers }) => headers.authorization && ({ uid: R?.member_id }),
206 | handler: ({ cacheData: D }) => ({
207 | envConfig: { value: D.map(d => `${d.headers.authorization}&${d.headers.uuid}&${d.uid}`).join('\n'), sep: '\n' },
208 | }),
209 | updateEnvValue: /&(\d+)$/,
210 | },
211 | {
212 | on: 'res-body',
213 | ruleId: 'glg',
214 | desc: '格力高-小程序签到',
215 | url: 'https://crm.glico.cn/miniapp/member/profile',
216 | method: 'get',
217 | getCacheUid: ({ resBody: R, headers }) => headers['x-auth-token'] && ({ uid: R?.data?.id }),
218 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => `${d.headers['x-auth-token']}&${d.uid}`).join('\n'), sep: '\n' } }),
219 | updateEnvValue: /&(\d+)$/,
220 | },
221 | {
222 | on: 'res-body',
223 | ruleId: 'fsinstax',
224 | desc: '富士instax玩拍由我俱乐部-小程序签到',
225 | url: 'https://instax.app.xcxd.net.cn/api/me',
226 | method: 'get',
227 | getCacheUid: ({ resBody: R, headers }) => headers.authorization && ({ uid: R?.data?.user_id || R?.data?.user?.id }),
228 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => `${d.uid}&${d.headers.authorization}`).join('\n'), sep: '\n' } }),
229 | updateEnvValue: /(\d+)&/,
230 | },
231 | {
232 | on: 'req-header',
233 | ruleId: 'lslyg',
234 | desc: '冷酸灵牙膏小程序签到',
235 | url: 'https://consumer-api.quncrm.com/**',
236 | method: 'post',
237 | getCacheUid: ({ headers: H, url }) => ({ uid: H['x-account-id'] }),
238 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => `${d.uid}&${d.headers['x-access-token']}`).join('\n'), sep: '\n' } }),
239 | }
240 | ];
241 |
--------------------------------------------------------------------------------
/src/t.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 用于临时测试的一些例子
3 | * @type {import('@lzwme/whistle.x-scripts').RuleItem[]}
4 | */
5 | module.exports = [
6 | {
7 | on: 'req-header',
8 | ruleId: 'CITIC_COOKIE',
9 | disabled: true,
10 | desc: '中信银行签到',
11 | url: 'https://thbank.tianhongjijin.com.cn/api/hy/signArea/*',
12 | method: '*',
13 | getCacheUid: ({ cookieObj: C }) => C.current_user,
14 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => `${d.headers.cookie}##${d.uid}`).join('\n') } }),
15 | },
16 | {
17 | on: 'res-body',
18 | ruleId: 'huangzuan_WX',
19 | desc: '媓钻_小程序签到',
20 | url: 'https://api.hzyxhfp.com/api/userRight/getUserRightDetail',
21 | method: 'post',
22 | getCacheUid: ({ resBody: R }) => ({ uid: R?.data?.phone }),
23 | handler: ({ cacheData: D }) => ({
24 | envConfig: {
25 | value: D.filter(d => d.headers.authorization)
26 | .map(d => `${d.headers.authorization.replace('Bearer ', '')}`)
27 | .join('\n'),
28 | },
29 | }),
30 | // updateEnvValue: /&([\d\*]+)/,
31 | },
32 | {
33 | on: 'res-body',
34 | ruleId: 'gmjkck',
35 | desc: '敢迈健康+_小程序签到',
36 | url: 'https://api.digital4danone.com.cn/healthyaging/danone/wx/ha/haUser/info',
37 | method: 'get',
38 | getCacheUid: ({ resBody: R }) => ({ uid: R?.result?.userId }),
39 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => `${d.headers['x-access-token']}`).join('\n') } }),
40 | // updateEnvValue: /&([\d\*]+)/,
41 | },
42 | {
43 | on: 'res-body',
44 | ruleId: 'this',
45 | desc: 'this官方商城-小程序签到',
46 | url: 'https://xcx.this.cn/api/user',
47 | method: 'get',
48 | getCacheUid: ({ resBody: R, headers }) => headers['authori-zation'] && { uid: R?.data?.uid },
49 | handler: ({ cacheData: D }) => ({
50 | envConfig: { value: D.map(d => `${d.headers['authori-zation'].replace('Bearer ', '')}`).join('\n'), sep: '\n' },
51 | }),
52 | },
53 | {
54 | on: 'req-body',
55 | ruleId: 'JDD',
56 | desc: '金杜丹-小程序签到-单账号',
57 | url: 'https://tianxin.jmd724.com/**',
58 | method: 'get',
59 | getCacheUid: ({ url, X }) => {
60 | const query = X.FeUtils.getUrlParams(url);
61 | if (query.access_token) return { uid: '_', data: query.access_token };
62 | },
63 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => d.data).join('@'), sep: '@' } }),
64 | },
65 | {
66 | on: 'res-body',
67 | ruleId: 'dqdd',
68 | desc: 'DQ点单-小程序签到-单账号',
69 | url: 'https://wechat.dairyqueen.com.cn/**',
70 | method: 'post',
71 | getCacheUid: ({ resBody: R }) => '_', // ({ uid: R?.data?.uid }),
72 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => d.headers.cookie).join('\n'), sep: '\n' } }),
73 | },
74 | {
75 | on: 'res-body',
76 | ruleId: 'LBDQ',
77 | desc: '老板电器服务微商城-小程序签到',
78 | url: 'https://vip.foxech.com/index.php/api/member/get_member_info',
79 | method: 'post',
80 | getCacheUid: ({ reqBody: Q, resBody: R }) =>
81 | Q.openid && { uid: R?.data?.info?.nickname, data: `${Q.openid}@UID_${R?.data?.info?.nickname}` },
82 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => d.data).join('\n') } }),
83 | updateEnvValue: /@([\da-z]+)/i,
84 | },
85 | {
86 | on: 'res-body',
87 | ruleId: 'mshy',
88 | desc: '慕思会员中心-小程序签到',
89 | url: 'https://atom.musiyoujia.com/member/wechatlogin/selectuserinfo',
90 | method: 'post',
91 | getCacheUid: ({ reqBody: Q, resBody: B, headers: H }) => {
92 | const uid = B?.data?.resMemberInfo?.userId;
93 | const openId = B?.data?.resMemberInfo?.openId || Q?.openId;
94 | if (uid && H.api_token && openId) {
95 | return { uid, data: `${H.api_token}#${openId}##${uid}` };
96 | }
97 | },
98 | handler: ({ cacheData: D }) => ({ envConfig: { value: D.map(d => d.data).join('\n') } }),
99 | updateEnvValue: /##(\d+)/i,
100 | },
101 | {
102 | on: 'res-body',
103 | ruleId: 'wawo',
104 | desc: '所有女生会员中心-小程序',
105 | url: 'https://7.wawo.cc/api/account/wx/member/base',
106 | method: 'get',
107 | getCacheUid: ({ resBody: R, headers }) => (headers.authorization ? { uid: R?.data?.cardNo } : nulll),
108 | handler: ({ cacheData: D }) => ({
109 | envConfig: { value: D.map(d => `${d.headers.authorization.replace(/bearer /i, '')}`).join('\n'), sep: '\n' },
110 | }),
111 | // updateEnvValue: /&([\d\*]+)/,
112 | },
113 | {
114 | on: 'res-body',
115 | desc: '广东/福建体彩服务号',
116 | ruleId: 'gdtc',
117 | url: 'https://pnup-hd.tcssyw.com/api/act/get_sign_use',
118 | getCacheUid({ url, reqBody: R,resBody: B = {}, headers: H, req, X }) {
119 | if (!R && req._readableState?.buffer) {
120 | R = X.FeUtils.getUrlParams(req._readableState.buffer.toString());
121 | }
122 |
123 | if (R.uuid && R.accessToken && B.data?.memberId) {
124 | const uid = B.data.memberId;
125 | return { uid, data: `${R.uuid}&${R.accessToken}&${uid}` };
126 | }
127 | },
128 | handler: ({ cacheData: D }) => ({ envConfig: { sep: '\n', value: D.map(v => v.data).join('\n') } }),
129 | updateEnvValue: /^&(\d+)$/,
130 | },
131 | ];
132 |
--------------------------------------------------------------------------------
/src/vip/alipanCrack.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: renxia
3 | * @Date: 2024-02-22 19:46:56
4 | * @LastEditors: renxia
5 | * @LastEditTime: 2024-05-20 10:18:29
6 | * @Description:
7 | */
8 |
9 | /** @type {import('@lzwme/whistle.x-scripts').RuleItem[]} */
10 | module.exports = [
11 | // https://github.com/zqzess/rule_for_quantumultX/raw/master/js/debug/aDriveCrack/aDriveCrack_test.js
12 | {
13 | on: 'res-body',
14 | ruleId: 'alipanVip',
15 | desc: '阿里云盘解锁vip',
16 | method: '*',
17 | mitm: '(api|member).alipan.com',
18 | url: /^https:\/\/(api|member)\.(alipan|aliyundrive)\.com\/(adrive|v1|v2|business|databox)\/.+\/(me|vip|feature|info|get_personal_info|driveCapacityDetails|getUserCapacityInfo)/,
19 | handler({ resBody, url, X }) {
20 | if (typeof resBody === 'object') {
21 | const color = X.FeUtils.color;
22 | let modified = resBody;
23 | url = color.gray(url);
24 |
25 | if (modified.rightButtonText) {
26 | // body2
27 | console.log('修改会员有效期', url);
28 | modified = {
29 | ...resBody,
30 | rightButtonText: '立即续费',
31 | identity: 'svip',
32 | level: '8t',
33 | titleNotice: null,
34 | titleImage: 'https://gw.alicdn.com/imgextra/i1/O1CN01Z2Yv4u1jrJ5S5TYpo_!!6000000004601-2-tps-216-60.png',
35 | description: '有效期至2034-01-30',
36 | };
37 | } else if (modified.dayDiscPrice) {
38 | // body6
39 | console.log('修改会员功能', url);
40 | modified.identity = 'svip';
41 | let features = modified.features;
42 | features.forEach(function (i) {
43 | i.name === '限免' ? (i.name = 'VIP') : i.name;
44 | if (i.intercept) i.intercept = false;
45 | i.name === '会员' ? (i.name = 'VIP') : i.name;
46 | if (i.backgroundImage)
47 | i.backgroundImage = 'https://gw.alicdn.com/imgextra/i3/O1CN01E7Gm7E1ZHRsDrNlLa_!!6000000003169-2-tps-84-42.png';
48 | if (i.features) {
49 | i.features.forEach(function (m) {
50 | m.intercept = false;
51 | });
52 | }
53 | });
54 | } else if (modified.personal_rights_info) {
55 | // body4
56 | console.log('修改用户账户信息和限制权限', url);
57 | modified.personal_rights_info.spu_id = 'svip';
58 | modified.personal_rights_info.name = 'SVIP';
59 | modified.personal_space_info.total_size = 43980465111040; // 40Tb
60 | } else if (modified.drive_capacity_details) {
61 | console.log('修改容量管理详情', url);
62 |
63 | modified.capacity_level_info = {
64 | capacity_type: 'svip',
65 | };
66 | modified.drive_capacity_details.drive_total_size = 43980465111040; // 40Tb
67 | } else if (modified.drive_total_size && modified.default_drive_used_size) {
68 | // body5
69 | console.log('修改容量管理总容量', url);
70 | modified.drive_total_size = 43980465111040; // 40Tb
71 | } else if (modified.membershipIdentity && modified.userId) {
72 | // body7
73 | console.log('修改用户基础信息', url);
74 | modified.membershipIdentity = 'svip';
75 | modified.membershipIcon = 'https://gw.alicdn.com/imgextra//i3//O1CN01iPKCuZ1urjDgiry5c_!!6000000006091-2-tps-60-60.png';
76 | } else {
77 | // body1
78 | if (modified.vipList) {
79 | console.log('修改会员状态', url);
80 | modified = {
81 | ...modified,
82 | identity: 'svip',
83 | level: '8t',
84 | icon: 'https://gw.alicdn.com/imgextra/i3/O1CN01iPKCuZ1urjDgiry5c_!!6000000006091-2-tps-60-60.png',
85 | mediumIcon: 'https://gw.alicdn.com/imgextra/i4/O1CN01Mk916Y1c99aVBrgxM_!!6000000003557-2-tps-222-60.png',
86 | status: 'normal',
87 | vipCode: 'svip.8t',
88 | };
89 | modified.vipList[0] = {
90 | name: '8TB超级会员',
91 | code: 'svip.8t',
92 | promotedAt: 1675599847,
93 | expire: 1906600189,
94 | };
95 | }
96 | }
97 |
98 | return { body: modified };
99 | }
100 | },
101 | },
102 | ];
103 |
--------------------------------------------------------------------------------
/src/vip/baiduCloud.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: renxia
3 | * @Date: 2024-02-28 10:08:29
4 | * @LastEditors: renxia
5 | * @LastEditTime: 2024-03-06 13:16:12
6 | * @Description: 待验证
7 | * @see https://github.com/Yu9191/Rewrite/blob/b96c7975b2afee78cb3e1e69888dfc988c20ba6f/yikexiangce.js
8 | * @see https://raw.githubusercontent.com/ddgksf2013/Rewrite/master/Function/BaiduCloud.conf
9 | */
10 |
11 | /** @type {import('@lzwme/whistle.x-scripts').RuleItem[]} */
12 | module.exports = [
13 | {
14 | on: 'res-body',
15 | ruleId: 'baiduCloudVip',
16 | desc: '百度网盘_解锁在线视频倍率/清晰度',
17 | method: '*',
18 | mitm: 'pan.zhihu.com',
19 | url: /^https?:\/\/pan\.baidu\.com\/(youai\/(user\/.+\/getminfo|membership\/.+\/adswitch)|(rest\/.+\/membership\/user|act\/.+\/(bchannel|welfare)\/list)|api\/usercfg|api\/getsyscfg)/,
20 | // url: 'https://pan.baidu.com/rest/*/membership/user',
21 | handler({ resBody: body, url, X }) {
22 | if (typeof body !== 'object') return;
23 | const color = X.FeUtils.color;
24 |
25 | const yike = '/youai/user/v1/getminfo';
26 | const ad = '/youai/membership/v1/adswitch';
27 | const list = '/bchannel/list';
28 | const hf = '/welfare/list';
29 | const usercfg = '/api/usercfg';
30 | let hit = 1;
31 |
32 | // 开屏广告过滤
33 | if (url.includes('api/getsyscfg')) {
34 | const propertiesToDelete = [
35 | 'switch_config_area',
36 | 'splash_advertise_fetch_config_area',
37 | 'bdnc_commerce_video_ad_area_pad',
38 | 'thrid_ad_funads_service',
39 | 'my_person_service',
40 | 'thrid_ad_buads_service',
41 | 'splash_advertise_type_area',
42 | 'business_ad_config_area',
43 | 'new_user_card',
44 | ];
45 | for (const prop of propertiesToDelete) {
46 | if (body[prop]) body[prop].cfg_list = [];
47 | }
48 | }
49 | // 会员权益
50 | else if (url.includes('membership/user')) {
51 | if (body.product_infos) {
52 | X.FeUtils.assign(body, {
53 | // request_id: 269895149694452300,
54 | product_infos: [
55 | // {
56 | // product_id: '5310897792128633390',
57 | // start_time: 1617260485,
58 | // end_time: 2147483648,
59 | // buy_time: '1417260485',
60 | // cluster: 'offlinedl',
61 | // detail_cluster: 'offlinedl',
62 | // product_name: 'gz_telecom_exp',
63 | // },
64 | {
65 | product_id: '5210897752128663390', // 5310897792128633390
66 | end_time: 4102415999,
67 | buy_time: '1384234467',
68 | cluster: 'offlinedl',
69 | status: '0',
70 | start_time: 1384234467,
71 | function_num: 2,
72 | buy_description: '离线下载套餐(永久)',
73 | product_description: '离线下载套餐(永久)',
74 | detail_cluster: 'offlinedl',
75 | product_name: 'offlinedl_permanent',
76 | },
77 | {
78 | cur_svip_type: 'month',
79 | product_name: 'svip2_nd',
80 | product_description: '超级会员',
81 | function_num: 0, // 510004015
82 | start_time: 1688356160,
83 | buy_description: '',
84 | buy_time: 0,
85 | product_id: '',
86 | auto_upgrade_to_svip: 0,
87 | end_time: 4102415999,
88 | cluster: 'vip',
89 | detail_cluster: 'svip',
90 | status: 0,
91 | },
92 | {
93 | product_name: 'contentvip_nd',
94 | product_description: '',
95 | function_num: 0,
96 | start_time: 1688356160,
97 | buy_description: '',
98 | buy_time: 0,
99 | product_id: '',
100 | auto_upgrade_to_svip: 0,
101 | end_time: 4102415999,
102 | cluster: 'contentvip',
103 | detail_cluster: 'contentvip',
104 | status: 0,
105 | },
106 | ],
107 | center_skip_config: {
108 | action_type: 0,
109 | action_url: 'https://pan.baidu.com/buy/center?tag=8',
110 | },
111 | last_privilege_card_v2: {},
112 | current_privilege_card: [],
113 | current_product_v2: {
114 | product_id: '12187135090581539740',
115 | detail_cluster: 'svip',
116 | cluster: 'vip',
117 | product_type: 'vip2_1y_auto',
118 | },
119 | current_privilege_card_v2: {},
120 | up_product_infos: [],
121 | last_privilege_card: [],
122 | level_info: {
123 | history_value: 3470,
124 | current_level: 10,
125 | last_manual_collection_time: 0,
126 | current_value: 970,
127 | history_level: 3,
128 | v10_id: '',
129 | },
130 | user_tag:
131 | '{\\"has_buy_record\\":1,\\"has_buy_vip_svip_record\\":1,\\"last_buy_record_creat_time\\":1688356106,\\"is_vip\\":0,\\"is_svip\\":1,\\"last_vip_type\\":1,\\"last_vip_svip_end_time\\":4102415999,\\"is_svip_sign\\":0,\\"notice_user_type\\":2,\\"notice_user_status\\":3,\\"is_first_act\\":0,\\"is_first_charge\\":0}',
132 | // currenttime: 1690687707,
133 | previous_product: [],
134 | current_mvip_v2: {},
135 | current_product: {
136 | product_id: '12187135090581539740',
137 | detail_cluster: 'svip',
138 | cluster: 'vip',
139 | product_type: 'vip2_1y_auto',
140 | },
141 | reminder: {
142 | reminderWithContent: {
143 | title: '已拥有超级会员',
144 | notice: '5T大空间、极速下载等特权已拥有~',
145 | },
146 | advertiseContent: {
147 | url: 'https://yun.baidu.com/buy/center?tag=8&from=reminderpush1',
148 | title: '您的超级会员将于2099-12-31到期',
149 | notice: '5T大空间、极速下载等特权已拥有~',
150 | },
151 | svip: {
152 | leftseconds: 390692,
153 | nextState: 'normal',
154 | },
155 | },
156 | current_mvip: [],
157 | previous_product_v2: {},
158 | guide_data: {
159 | title: '超级会员 SVIP-Baby',
160 | content: '已拥有极速下载+视频倍速特权',
161 | button: {
162 | text: '会员中心',
163 | action_url: 'https://pan.baidu.com/wap/vip/user?from=myvip2#svip',
164 | },
165 | },
166 | });
167 | }
168 |
169 | if (body.identity_icon) {
170 | X.FeUtils.assign(body, {
171 | vip: {
172 | emotional_tips_back: {
173 | first: '',
174 | daily: ['一起走过的每一天,我给了陪伴,而你给了我成长。'],
175 | },
176 | emotional_tip_front: '陪你走过的每一天',
177 | guide_tip: ['墨鱼提醒:已享会员权限!'],
178 | expired_tip: '不再享有视频备份、在线解压等特权',
179 | expire_remind_tip: '将不再享有视频备份、在线解压等特权',
180 | status: 0,
181 | },
182 | vipv2: {
183 | status: 1,
184 | },
185 | identity_icon: {
186 | vip: 'https://internal-amis-res.cdn.bcebos.com/images/2019-8/1566452237582/78b88bf113b7.png',
187 | common: 'https://internal-amis-res.cdn.bcebos.com/images/2019-8/1566452539056/bf72cf66fae1.png',
188 | svip: 'https://internal-amis-res.cdn.bcebos.com/images/2019-8/1566452115696/38c1d743bfe9.png',
189 | contentvip: '',
190 | },
191 | // request_id: 270055727479044860,
192 | svip: {
193 | emotional_tips_back: {
194 | first: '很高兴你在x年x月x日成为超级会员,愿美好时光与你相伴。',
195 | daily: ['据说超级会员,法力无边'],
196 | },
197 | expire_remind_tip: '将不再享有极速下载、5T空间等特权',
198 | emotional_tip_front: '陪你走过的每一天',
199 | identity_icon_list: ['https://internal-amis-res.cdn.bcebos.com/images/2019-8/1566452115696/38c1d743bfe9.png', ''],
200 | status: 2,
201 | expired_tip: '不再享有极速下载、5T空间等特权',
202 | guide_tip: ['超级会员尊享5T空间和极速下载特权'],
203 | is_sign_user: false,
204 | },
205 | error_code: 0,
206 | });
207 | }
208 |
209 | if (body.tips_data_list) {
210 | X.FeUtils.assign(body, {
211 | tips_data_list: [],
212 | status_data: '超级会员至:2099-12-31',
213 | guide_data: {
214 | action_url: '',
215 | title: '超级会员SVIP',
216 | title_action_url: '',
217 | content: '已拥有极速下载+视频倍速等54项特权',
218 | button: {
219 | text: '等级提升',
220 | action_url: 'https://github.com/lzwme/x-scripts-rules/',
221 | },
222 | },
223 | user_status: 2,
224 | tips_data: {},
225 | user_type: 'svip',
226 | request_id: 270614190566302800,
227 | level_info: {
228 | last_manual_collection_time: 0,
229 | current_max_points: 500,
230 | current_value: 1490,
231 | history_level: 3,
232 | accumulated_uncollected_points: 0,
233 | v10_id: '',
234 | daily_value: 0,
235 | accumulated_day: 0,
236 | history_value: 3470,
237 | current_level: 2,
238 | accumulated_lost_points: 0,
239 | default_daily_value: 5,
240 | },
241 | v10_guide: {
242 | get_next_value_gap: true,
243 | tips: '升级还需要1510成长值,可享更多权益',
244 | button: {
245 | text: '立即加速',
246 | action_url: 'https://github.com/lzwme/x-scripts-rules/',
247 | },
248 | ab_test: false,
249 | },
250 | status_data_arr: ['超级会员至:2099-12-31'],
251 | new_guide_data: {
252 | action_url: '',
253 | title: 'SVIP V2',
254 | title_action_url: '',
255 | button: {
256 | text: '等级提升',
257 | action_url: 'https://github.com/lzwme/x-scripts-rules/',
258 | },
259 | sub_card_list: [
260 | {
261 | content: '已解锁倍速超清权益',
262 | icon_url: 'https://staticsns.cdn.bcebos.com/amis/2022-3/1646383463592/%E5%8A%A0%E9%80%9F%E5%8D%87%E7%BA%A7.png',
263 | action_url: 'https://github.com/lzwme/x-scripts-rules/',
264 | },
265 | ],
266 | },
267 | });
268 | }
269 |
270 | hit = 1;
271 | }
272 |
273 | // 一刻相册
274 | else if (url.includes(yike)) {
275 | Object.assign(body, {
276 | // request_id: 342581654394297772,
277 | errno: 0,
278 | has_purchased: 1,
279 | has_buy_1m_auto_first: 0,
280 | can_buy_1m_auto_first: 0,
281 | can_buy_1m_auto_first_6: 0,
282 | has_received_7dfree: 1,
283 | product_tag: 3,
284 | sign_status: 1,
285 | sign_infos: [
286 | {
287 | product_id: '12745849497343294855',
288 | order_no: '2203060931530010416',
289 | ctime: 1646537208,
290 | mtime: '2022-05-06 11:26:48',
291 | status: 1,
292 | sign_price: 1000,
293 | sign_channel: 0,
294 | },
295 | ],
296 | vip_tags: ['album_vip'],
297 | product_infos: [
298 | {
299 | product_id: '12745849497343294855',
300 | start_time: 1646534568,
301 | end_time: 4092599349,
302 | buy_time: 1649994533,
303 | tag: 'album_vip',
304 | order_no: '2203060931530010416',
305 | },
306 | ],
307 | vip_infos: [
308 | {
309 | tag: 'album_vip',
310 | start_time: 1646537208,
311 | end_time: 4092599349,
312 | },
313 | ],
314 | expire_time: 0,
315 | });
316 | hit = 1;
317 | } else if (url.includes(ad)) {
318 | body.switch = 'open';
319 | hit = 1;
320 | } else if (url.indexOf(list) != -1) {
321 | body.data = [
322 | {
323 | sub_title: '',
324 | id: 856,
325 | bg_icon: '',
326 | button_text: '',
327 | web_url: '',
328 | type: 3,
329 | name: '已解锁SVIP,未完整解锁',
330 | },
331 | {
332 | sub_title: '',
333 | id: 460,
334 | bg_icon: '',
335 | button_text: '',
336 | web_url: '',
337 | type: 3,
338 | name: '已拥有极速下载+视频倍速特权',
339 | },
340 | ];
341 |
342 | hit = 1;
343 | } else if (url.indexOf(hf) != -1) {
344 | delete body.data;
345 |
346 | hit = 1;
347 | } else if (url.indexOf(usercfg) != -1) {
348 | body.user_new_define_cards = [
349 | {
350 | card_id: '1',
351 | card_type: '4',
352 | card_area_name: '首页笔记-卡片',
353 | },
354 | {
355 | is_manager: 1,
356 | card_area_name: '最近',
357 | card_id: '1',
358 | card_type: '7',
359 | },
360 | {
361 | card_id: '1',
362 | card_type: '13',
363 | card_area_name: '卡片管理-卡片',
364 | },
365 | ];
366 |
367 | hit = 1;
368 | }
369 |
370 | if (hit) {
371 | console.log(`[${this.desc}]`, color.gray(url));
372 | return { body };
373 | } else {
374 | console.warn(`[${this.desc}][missed]`, color.gray(url));
375 | }
376 | },
377 | },
378 | {
379 | on: 'req-header',
380 | ruleId: 'baiduCloudReject200',
381 | desc: '百度网盘广告过滤',
382 | method: '*',
383 | url: url => {
384 | const list = [
385 | // # > 百度网盘_设置信息流
386 | /^https?:\/\/pan\.baidu\.com\/act\/v\d\/(bchannel|welfare)\/list/,
387 | // # > 百度网盘_通用广告
388 | /^https?:\/\/pan.baidu.com\/rest\/.*\/pcs\/ad/,
389 | // # > 百度网盘_活动推广
390 | /^https?:\/\/pan\.baidu\.com\/act\/api\/activityentry/,
391 | ];
392 |
393 | for (const re of list) if (re.test(url)) return true;
394 | },
395 | handler: () => ({ body: '' }),
396 | },
397 | ];
398 |
--------------------------------------------------------------------------------
/src/vip/bilibiliHD.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: renxia
3 | * @Date: 2024-02-28 10:08:29
4 | * @LastEditors: renxia
5 | * @LastEditTime: 2024-02-28 14:18:08
6 | * @Description: 待验证
7 | */
8 |
9 | /** @type {import('@lzwme/whistle.x-scripts').RuleItem[]} */
10 | module.exports = [
11 | {
12 | // 参考: https://raw.githubusercontent.com/itcast-l/shadowrocket-module/main/js/BiliBiliHD.js
13 | on: 'res-body',
14 | ruleId: 'bilibiliHD',
15 | desc: 'B站高清解锁去广告',
16 | method: '*',
17 | mitm: '*.bilibili.com',
18 | url: 'https://*.bilibili.com/x/v2/**',
19 | cache: {
20 | bilibili_story_aid: '',
21 | bilibili_feed_black: '',
22 | },
23 | handler({ resBody: body, headers, url, X }) {
24 | if (!X.isText(headers) || Buffer.isBuffer(body) || typeof body !== 'object') return;
25 |
26 | // 更新时间:2023-01-29
27 | //Customize blacklist
28 | let blacklist = this.cache.bilibili_feed_black || [];
29 | let obj = body;
30 | let hit = 0;
31 |
32 | switch (true) {
33 | // 推荐去广告,最后问号不能去掉,以免匹配到story模式
34 | case /^https:\/\/app\.bilibili\.com\/x\/v2\/feed\/index\?/.test(url):
35 | try {
36 | let items = [];
37 | for (let item of obj['data']['items']) {
38 | if (item.hasOwnProperty('banner_item')) {
39 | let bannerItems = [];
40 | for (let banner of item['banner_item']) {
41 | if (banner['type'] === 'ad') {
42 | continue;
43 | } else if (banner['static_banner'] && banner['static_banner']['is_ad_loc'] != true) {
44 | bannerItems.push(banner);
45 | }
46 | }
47 | // 去除广告后,如果banner大于等于1个才添加到响应体
48 | if (bannerItems.length >= 1) {
49 | item['banner_item'] = bannerItems;
50 | items.push(item);
51 | }
52 | } else if (
53 | !item.hasOwnProperty('ad_info') &&
54 | !blacklist.includes(item['args']['up_name']) &&
55 | item.card_goto.indexOf('ad') === -1 &&
56 | (item['card_type'] === 'small_cover_v2' ||
57 | item['card_type'] === 'large_cover_v1' ||
58 | item['card_type'] === 'large_cover_single_v9')
59 | ) {
60 | items.push(item);
61 | }
62 | }
63 | obj['data']['items'] = items;
64 | hit = 1;
65 | } catch (err) {
66 | console.error(`[${this.desc}]推荐去广告出现异常:`, err);
67 | }
68 | break;
69 | // 匹配story模式,用于记录Story的aid
70 | case /^https:\/\/app\.bilibili\.com\/x\/v2\/feed\/index\/story\?/.test(url):
71 | try {
72 | let items = [];
73 | for (let item of obj['data']['items']) {
74 | if (!item.hasOwnProperty('ad_info') && item.card_goto.indexOf('ad') === -1) {
75 | items.push(item);
76 | }
77 | }
78 | obj['data']['items'] = items;
79 | hit = 1;
80 | } catch (err) {
81 | console.error(`[${this.desc}]记录Story的aid出现异常:`, err);
82 | }
83 | break;
84 |
85 | // 标签页处理,如去除会员购等等
86 | case /^https?:\/\/app\.bilibili\.com\/x\/resource\/show\/tab/.test(url):
87 | try {
88 | const tabList = new Set([39, 40, 41, 774, 857, 545, 151, 442, 99, 100, 101, 554, 556]);
89 |
90 | const topList = new Set([176, 107]);
91 |
92 | const bottomList = new Set([177, 178, 179, 181, 102, 104, 106, 486, 488, 489]);
93 |
94 | if (obj['data']['tab']) {
95 | let tab = obj['data']['tab'].filter(e => {
96 | return tabList.has(e.id);
97 | });
98 | obj['data']['tab'] = tab;
99 | }
100 | // 将 id(222 & 107)调整为Story功能按钮
101 | let storyAid = this.cache.bilibili_story_aid || '246834163';
102 |
103 | if (obj['data']['top']) {
104 | let top = obj['data']['top'].filter(e => {
105 | if (e.id === 222 || e.id === 107) {
106 | e.uri = `bilibili://story/${storyAid}`;
107 | e.icon = 'https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/script/bilibili/bilibili_icon.png';
108 | e.tab_id = 'Story_Top';
109 | e.name = 'Story';
110 | }
111 | return topList.has(e.id);
112 | });
113 | obj['data']['top'] = top;
114 | }
115 | if (obj['data']['bottom']) {
116 | let bottom = obj['data']['bottom'].filter(e => {
117 | return bottomList.has(e.id);
118 | });
119 | obj['data']['bottom'] = bottom;
120 | }
121 | hit = 1;
122 | } catch (err) {
123 | console.error(`[${this.desc}]标签页处理出现异常:`, err);
124 | }
125 | break;
126 | // 我的页面处理,去除一些推广按钮
127 | case /^https?:\/\/app\.bilibili\.com\/x\/v2\/account\/mine/.test(url):
128 | try {
129 | const itemList = new Set([
130 | 396, 397, 398, 399, 402, 404, 407, 410, 425, 426, 427, 428, 430, 432, 433, 434, 494, 495, 496, 497, 500, 501,
131 | ]);
132 | obj['data']['sections_v2'].forEach((element, index) => {
133 | element['items'].forEach(e => {
134 | if (e['id'] === 622) {
135 | e['title'] = '会员购';
136 | e['uri'] = 'bilibili://mall/home';
137 | }
138 | });
139 | let items = element['items'].filter(e => {
140 | return itemList.has(e.id);
141 | });
142 | obj['data']['sections_v2'][index].button = {};
143 | delete obj['data']['sections_v2'][index].be_up_title;
144 | delete obj['data']['sections_v2'][index].tip_icon;
145 | delete obj['data']['sections_v2'][index].tip_title;
146 | //2022-02-16 add by ddgksf2013
147 | for (let ii = 0; ii < obj['data']['sections_v2'].length; ii++) {
148 | if (obj.data.sections_v2[ii].title == '推荐服务' || obj.data.sections_v2[ii].title == '推薦服務') {
149 | //obj.data.sections_v2[ii].items[0].title='\u516C\u773E\u865F';
150 | //obj.data.sections_v2[ii].items[1].title='\u58A8\u9B5A\u624B\u8A18';
151 | }
152 | if (obj.data.sections_v2[ii].title == '更多服務' || obj.data.sections_v2[ii].title == '更多服务') {
153 | if (obj.data.sections_v2[ii].items[0].id == 500) {
154 | //obj.data.sections_v2[ii].items[0].title='\u516C\u773E\u865F';
155 | }
156 | if (obj.data.sections_v2[ii].items[1].id == 501) {
157 | //obj.data.sections_v2[ii].items[1].title='\u58A8\u9B5A\u624B\u8A18';
158 | }
159 | }
160 | if (obj.data.sections_v2[ii].title == '创作中心' || obj.data.sections_v2[ii].title == '創作中心') {
161 | delete obj.data.sections_v2[ii].title;
162 | delete obj.data.sections_v2[ii].type;
163 | }
164 | }
165 | delete obj.data.vip_section_v2;
166 | delete obj.data.vip_section;
167 | obj['data']['sections_v2'][index]['items'] = items;
168 | //2022-03-05 add by ddgksf2013
169 | if (obj.data.hasOwnProperty('live_tip')) {
170 | obj['data']['live_tip'] = {};
171 | }
172 | if (obj.data.hasOwnProperty('answer')) {
173 | obj['data']['answer'] = {};
174 | }
175 | obj['data']['vip_type'] = 2;
176 | obj['data']['vip']['type'] = 2;
177 | obj['data']['vip']['status'] = 1;
178 | obj['data']['vip']['vip_pay_type'] = 1;
179 | obj['data']['vip']['due_date'] = 4669824160;
180 | });
181 | hit = 1;
182 | } catch (err) {
183 | console.error(`[${this.desc}]我的页面处理出现异常:`, err);
184 | }
185 | break;
186 | // 直播去广告
187 | case /^https?:\/\/api\.live\.bilibili\.com\/xlive\/app-room\/v1\/index\/getInfoByRoom/.test(url):
188 | try {
189 | obj['data']['activity_banner_info'] = null;
190 | hit = 1;
191 | } catch (err) {
192 | console.error(`[${this.desc}]直播去广告出现异常:`, err);
193 | }
194 | break;
195 | //屏蔽热搜
196 | case /^https?:\/\/app\.bilibili\.com\/x\/v2\/search\/square/.test(url):
197 | try {
198 | obj.data = {
199 | type: 'history',
200 | title: '搜索历史',
201 | search_hotword_revision: 2,
202 | };
203 | hit = 1;
204 | } catch (err) {
205 | console.error(`[${this.desc}]热搜去广告出现异常:`, err);
206 | }
207 | break;
208 | //2022-03-05 add by ddgksf2013
209 | case /https?:\/\/app\.bilibili\.com\/x\/v2\/account\/myinfo\?/.test(url):
210 | try {
211 | //magicJS.logInfo(`公众号墨鱼手记`);
212 | obj['data']['vip']['type'] = 2;
213 | obj['data']['vip']['status'] = 1;
214 | obj['data']['vip']['vip_pay_type'] = 1;
215 | obj['data']['vip']['due_date'] = 4669824160;
216 | hit = 1;
217 | } catch (err) {
218 | console.error(`[${this.desc}]1080P出现异常:`, err);
219 | }
220 | break;
221 | // 追番去广告
222 | case /pgc\/page\/bangumi/.test(url):
223 | try {
224 | obj.result.modules.forEach(module => {
225 | // 头部banner
226 | if (module.style.startsWith('banner')) {
227 | //i.source_content && i.source_content.ad_content
228 | module.items = module.items.filter(i => !(i.link.indexOf('play') == -1));
229 | }
230 | if (module.style.startsWith('function')) {
231 | module.items = module.items.filter(i => i.blink.indexOf('www.bilibili.com') == -1);
232 | }
233 | if (module.style.startsWith('tip')) {
234 | module.items = null;
235 | }
236 | });
237 | hit = 1;
238 | } catch (err) {
239 | console.error(`[${this.desc}]追番去广告出现异常:`, err);
240 | }
241 | break;
242 | // 观影页去广告
243 | case /pgc\/page\/cinema\/tab\?/.test(url):
244 | try {
245 | obj.result.modules.forEach(module => {
246 | // 头部banner
247 | if (module.style.startsWith('banner')) {
248 | module.items = module.items.filter(i => !(i.link.indexOf('play') == -1));
249 | }
250 | if (module.style.startsWith('function')) {
251 | module.items = module.items.filter(i => i.blink.indexOf('www.bilibili.com') == -1);
252 | }
253 | if (module.style.startsWith('tip')) {
254 | module.items = null;
255 | }
256 | });
257 | hit = 1;
258 | } catch (err) {
259 | console.error(`[${this.desc}]观影页去广告出现异常:`, err);
260 | }
261 | break;
262 | // 动态去广告
263 | case /^https?:\/\/api\.vc\.bilibili\.com\/dynamic_svr\/v1\/dynamic_svr\/dynamic_(history|new)\?/.test(url):
264 | try {
265 | let cards = [];
266 | obj.data.cards.forEach(element => {
267 | if (element.hasOwnProperty('display') && element.card.indexOf('ad_ctx') <= 0) {
268 | // 解决number类型精度问题导致B站动态中图片无法打开的问题
269 | element['desc']['dynamic_id'] = element['desc']['dynamic_id_str'];
270 | element['desc']['pre_dy_id'] = element['desc']['pre_dy_id_str'];
271 | element['desc']['orig_dy_id'] = element['desc']['orig_dy_id_str'];
272 | element['desc']['rid'] = element['desc']['rid_str'];
273 | cards.push(element);
274 | }
275 | });
276 | obj.data.cards = cards;
277 | hit = 1;
278 | } catch (err) {
279 | console.error(`[${this.desc}]动态去广告出现异常:`, err);
280 | }
281 | break;
282 | // 去除统一设置的皮肤
283 | case /^https?:\/\/app\.bilibili\.com\/x\/resource\/show\/skin\?/.test(url):
284 | if (obj?.data?.common_equip?.package_url) {
285 | //obj["data"]["common_equip"]["package_url"] = "";
286 | // hit = 1;
287 | }
288 | break;
289 | // 开屏广告(预加载)如果粗暴地关掉,那么就使用预加载的数据,就会导致关不掉
290 | case /^https:\/\/app\.bilibili\.com\/x\/v2\/splash\/list/.test(url):
291 | try {
292 | if (obj.data) {
293 | for (let item of obj['data']['list']) {
294 | item['duration'] = 0; // 显示时间
295 | // 2040 年
296 | item['begin_time'] = 2240150400;
297 | item['end_time'] = 2240150400;
298 | }
299 | }
300 | hit = 1;
301 | } catch (err) {
302 | console.error(`[${this.desc}]开屏广告(预加载)出现异常:`, err);
303 | }
304 | break;
305 | default:
306 | // console.warn('触发意外的请求处理,请确认脚本或复写配置正常。', url);
307 | return;
308 | }
309 |
310 | if (hit) {
311 | const color = X.FeUtils.color;
312 | console.log(`[${color.cyan(this.desc)}]`, color.gray(url));
313 | return { body: obj };
314 | }
315 | },
316 | },
317 | ];
318 |
--------------------------------------------------------------------------------
/src/vip/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: renxia
3 | * @Date: 2024-02-28 10:07:54
4 | * @LastEditors: renxia
5 | * @LastEditTime: 2024-02-28 11:42:24
6 | * @Description:
7 | */
8 | module.exports = [
9 | ...require('./baiduCloud.js'),
10 | // ...require('./wps.js'),
11 | ...require('./xiaohongshu.js'),
12 | ...require('./xunlei.js'),
13 | ...require('./zhihu.js'),
14 | ];
15 |
--------------------------------------------------------------------------------
/src/vip/todo/wps.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: renxia
3 | * @Date: 2024-02-28 10:08:29
4 | * @LastEditors: renxia
5 | * @LastEditTime: 2024-02-28 10:28:18
6 | * @Description: 待验证
7 | */
8 |
9 | /** @type {import('@lzwme/whistle.x-scripts').RuleItem[]} */
10 | module.exports = [
11 | {
12 | on: 'res-body',
13 | ruleId: 'wpsVipCrack',
14 | desc: 'WPS VIP',
15 | method: '*',
16 | mitm: /^https?:\/\/[a-z-]*account\.wps\.c(n|om)/,
17 | url: /^https?:\/\/[a-z-]*account\.wps\.c(n|om)(:\d+|)\/api\/users/,
18 | handler({ resBody : body, url, X }) {
19 | if (typeof body === 'object') {
20 | const color = X.FeUtils.color;
21 | console.log(`[${this.desc}]`, color.gray(url));
22 |
23 | const privilege = [
24 | { spid: "data_recover", times: 0, expire_time: 4133059437 },
25 | { spid: "ocr", times: 0, expire_time: 4133059437 },
26 | { spid: "pdf2doc", times: 0, expire_time: 4133059437 },
27 | { spid: "pdf_merge", times: 0, expire_time: 4133059437 },
28 | { spid: "pdf_sign", times: 0, expire_time: 4133059437 },
29 | { spid: "pdf_split", times: 0, expire_time: 4133059437 }
30 | ];
31 | const vip = {
32 | name: "超级会员",
33 | has_ad: 0,
34 | memberid: 40,
35 | expire_time: 4133059437,
36 | enabled: [
37 | { memberid: 40, name: "超级会员", expire_time: 4133059437 },
38 | { memberid: 20, name: "WPS会员", expire_time: 4133059437 },
39 | { memberid: 12, name: "稻壳会员", expire_time: 4133059437 }
40 | ]
41 | };
42 |
43 | Object.assign(body, {
44 | level: 5,
45 | exp: 999,
46 | privilege,
47 | vip,
48 | expire_time: 4133059437,
49 | total_cost: -30,
50 | });
51 |
52 | if (body.data) {
53 | Object.assign(body.data, {
54 | level: 5,
55 | exp: 999,
56 | privilege,
57 | vip,
58 | expire_time: 4133059437,
59 | total_cost: -30,
60 | spaces_info: {
61 | "used": "0.10",
62 | "total": "1000.21",
63 | "unit": "T"
64 | }
65 | });
66 | }
67 |
68 | return { body };
69 | }
70 | },
71 | },
72 | ];
73 |
--------------------------------------------------------------------------------
/src/vip/xiaohongshu.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: renxia
3 | * @Date: 2024-02-28 10:08:29
4 | * @LastEditors: renxia
5 | * @LastEditTime: 2024-03-04 16:26:10
6 | * @Description: 待验证
7 | */
8 |
9 | /** @type {import('@lzwme/whistle.x-scripts').RuleItem[]} */
10 | module.exports = [
11 | {
12 | on: 'res-body',
13 | ruleId: 'xiaohongshuVip',
14 | desc: '小红书去广告、解除下载限制、画质增强等',
15 | method: '*',
16 | mitm: '*.xiaohongshu.com',
17 | url: 'https://*.xiaohongshu.com/v{1,2,3,4,6,10}/**',
18 | handler({ resBody: body, url, X }) {
19 | if (!body || typeof body !== 'object') return;
20 | const color = X.FeUtils.color;
21 | console.log(`[${this.desc}]`, color.gray(url));
22 |
23 | if (url.includes('/v1/search/banner_list')) {
24 | if (body.data) {
25 | body.data = {};
26 | }
27 | } else if (url.includes('/v1/search/hot_list')) {
28 | // 热搜列表
29 | if (body.data?.items?.length > 0) {
30 | body.data.items = [];
31 | }
32 | } else if (url.includes('/v1/system_service/config')) {
33 | // 整体配置
34 | const item = ['app_theme', 'loading_img', 'splash', 'store'];
35 | if (body.data) {
36 | for (let i of item) {
37 | delete body.data[i];
38 | }
39 | }
40 | } else if (url.includes('/v2/note/widgets')) {
41 | const item = ['generic'];
42 | if (body.data) {
43 | for (let i of item) {
44 | delete body.data[i];
45 | }
46 | }
47 | } else if (url.includes('/v2/note/feed')) {
48 | // 信息流 图片
49 | if (body.data?.length > 0) {
50 | let data0 = body.data[0];
51 | if (data0?.note_list?.length > 0) {
52 | for (let item of data0.note_list) {
53 | if (item?.media_save_config) {
54 | // 水印
55 | item.media_save_config.disable_save = false;
56 | item.media_save_config.disable_watermark = true;
57 | item.media_save_config.disable_weibo_cover = true;
58 | }
59 | if (item?.share_info?.function_entries?.length > 0) {
60 | // 下载限制
61 | const additem = { type: 'video_download' };
62 | let func = item.share_info.function_entries[0];
63 | if (func?.type !== 'video_download') {
64 | // 向数组开头添加对象
65 | item.share_info.function_entries.unshift(additem);
66 | }
67 | }
68 | }
69 | }
70 | }
71 | const images_list = body.data[0].note_list[0].images_list;
72 | body.data[0].note_list[0].images_list = imageEnhance(JSON.stringify(images_list));
73 |
74 | // 保存无水印信息
75 | this['fmz200.xiaohongshu.feed.rsp'] = images_list;
76 | console.log('已存储无水印信息♻️');
77 | } else if (url.includes('/v3/note/videofeed')) {
78 | // 信息流 视频
79 | if (body.data?.length > 0) {
80 | for (let item of body.data) {
81 | if (item?.media_save_config) {
82 | // 水印
83 | item.media_save_config.disable_save = false;
84 | item.media_save_config.disable_watermark = true;
85 | item.media_save_config.disable_weibo_cover = true;
86 | }
87 | if (item?.share_info?.function_entries?.length > 0) {
88 | // 下载限制
89 | const additem = { type: 'video_download' };
90 | let func = item.share_info.function_entries[0];
91 | if (func?.type !== 'video_download') {
92 | // 向数组开头添加对象
93 | item.share_info.function_entries.unshift(additem);
94 | }
95 | }
96 | }
97 | }
98 | } else if (url.includes('/v2/system_service/splash_config')) {
99 | // 开屏广告
100 | if (body.data?.ads_groups?.length > 0) {
101 | for (let i of body.data.ads_groups) {
102 | i.start_time = 2208960000; // Unix 时间戳 2040-01-01 00:00:00
103 | i.end_time = 2209046399; // Unix 时间戳 2040-01-01 23:59:59
104 | if (i?.ads?.length > 0) {
105 | for (let ii of i.ads) {
106 | ii.start_time = 2208960000; // Unix 时间戳 2040-01-01 00:00:00
107 | ii.end_time = 2209046399; // Unix 时间戳 2040-01-01 23:59:59
108 | }
109 | }
110 | }
111 | }
112 | } else if (url.includes('/v4/followfeed')) {
113 | // 关注列表
114 | if (body.data?.items?.length > 0) {
115 | // recommend_user 可能感兴趣的人
116 | body.data.items = body.data.items.filter(i => !['recommend_user'].includes(i.recommend_reason));
117 | }
118 | } else if (url.includes('/v4/search/trending')) {
119 | // 搜索栏
120 | if (body.data?.queries?.length > 0) {
121 | body.data.queries = [];
122 | }
123 | if (body.data?.hint_word) {
124 | body.data.hint_word = {};
125 | }
126 | } else if (url.includes('/v4/search/hint')) {
127 | // 搜索栏填充词
128 | if (body.data?.hint_words?.length > 0) {
129 | body.data.hint_words = [];
130 | }
131 | } else if (url.includes('/v6/homefeed')) {
132 | if (body.data?.length > 0) {
133 | // 信息流广告
134 | let newItems = [];
135 | for (let item of body.data) {
136 | if (item?.model_type === 'live_v2') {
137 | // 信息流-直播
138 | } else if (item?.hasOwnProperty('ads_info')) {
139 | // 信息流-赞助
140 | } else if (item?.hasOwnProperty('card_icon')) {
141 | // 信息流-带货
142 | } else if (item?.note_attributes?.includes('goods')) {
143 | // 信息流-商品
144 | } else {
145 | if (item?.related_ques) {
146 | delete item.related_ques;
147 | }
148 | newItems.push(item);
149 | }
150 | }
151 | body.data = newItems;
152 | }
153 | } else if (url.includes('/v10/search/notes')) {
154 | // 搜索结果
155 | if (body.data?.items?.length > 0) {
156 | body.data.items = body.data.items.filter(i => i.model_type === 'note');
157 | }
158 | } else if (url.includes('/v1/note/live_photo/save')) {
159 | console.log('原body:' + rsp_body);
160 | const rsp = this['fmz200.xiaohongshu.feed.rsp'];
161 | console.log('读取缓存key:fmz200.xiaohongshu.feed.rsp');
162 | // console.log("读取缓存val:" + rsp);
163 | if (rsp == null) {
164 | console.log('缓存无内容,返回原body');
165 | return;
166 | }
167 |
168 | const cache_body = rsp;
169 | let new_data = [];
170 | for (const images of cache_body) {
171 | if (images.live_photo_file_id) {
172 | const item = {
173 | file_id: images.live_photo_file_id,
174 | video_id: images.live_photo.media.video_id,
175 | url: images.live_photo.media.stream.h265[0].master_url,
176 | };
177 | new_data.push(item);
178 | }
179 | }
180 | if (body.data.datas) {
181 | replaceUrlContent(body.data.datas, new_data);
182 | } else {
183 | body = { code: 0, success: true, msg: '成功', data: { datas: new_data } };
184 | }
185 | }
186 |
187 | return { body };
188 | },
189 | },
190 | {
191 | on: 'res-body',
192 | ruleId: 'xiaohongshuVip',
193 | desc: '小红书去广告、解除下载限制、画质增强等',
194 | method: '*',
195 | mitm: '*.xiaohongshu.com',
196 | url: 'https://edith.xiaohongshu.com/api/sns/v*/{note,homefeed,system_service,search}**',
197 | handler({ resBody: body, url, X }) {
198 | // @see https://raw.githubusercontent.com/ddgksf2013/Scripts/master/redbook_json.js
199 | if (body) {
200 | switch (!0) {
201 | case /api\/sns\/v\d\/note\/widgets/.test(url):
202 | try {
203 | let e = body,
204 | t = ['goods_card_v2', 'note_next_step'];
205 | for (let a of t) e.data?.[a] && delete e.data[a];
206 | } catch (s) {
207 | console.log('widgets: ' + s);
208 | }
209 | break;
210 | case /api\/sns\/v\d\/note\/redtube/.test(url):
211 | try {
212 | let o = body;
213 | for (let d of o.data.items)
214 | d.related_goods_num && (d.related_goods_num = 0),
215 | d.has_related_goods && (d.has_related_goods = !1),
216 | d.media_save_config && (d.media_save_config = { disable_save: !1, disable_watermark: !0, disable_weibo_cover: !0 }),
217 | d.share_info &&
218 | (d.share_info.function_entries = [
219 | { type: 'video_download' },
220 | { type: 'generate_image' },
221 | { type: 'copy_link' },
222 | { type: 'native_voice' },
223 | { type: 'video_speed' },
224 | { type: 'dislike' },
225 | { type: 'report' },
226 | { type: 'video_feedback' },
227 | ]);
228 | } catch (r) {
229 | console.log('redtube: ' + r);
230 | }
231 | break;
232 | case /api\/sns\/v\d\/note\/videofeed/.test(url):
233 | try {
234 | let i = body;
235 | for (let l of i.data)
236 | l.related_goods_num && (l.related_goods_num = 0),
237 | l.has_related_goods && (l.has_related_goods = !1),
238 | l.media_save_config && (l.media_save_config = { disable_save: !1, disable_watermark: !0, disable_weibo_cover: !0 }),
239 | l.share_info &&
240 | (l.share_info.function_entries = [
241 | { type: 'video_download' },
242 | { type: 'generate_image' },
243 | { type: 'copy_link' },
244 | { type: 'native_voice' },
245 | { type: 'video_speed' },
246 | { type: 'dislike' },
247 | { type: 'report' },
248 | { type: 'video_feedback' },
249 | ]);
250 | } catch (n) {
251 | console.log('videofeed: ' + n);
252 | }
253 | break;
254 | case /api\/sns\/v\d\/note\/feed/.test(url):
255 | try {
256 | let c = body;
257 | for (let y of c.data)
258 | if ((y.related_goods_num && (y.related_goods_num = 0), y.has_related_goods && (y.has_related_goods = !1), y.note_list))
259 | for (let g of y.note_list) g.media_save_config = { disable_save: !1, disable_watermark: !0, disable_weibo_cover: !0 };
260 | } catch (f) {
261 | console.log('feed: ' + f);
262 | }
263 | break;
264 | case /api\/sns\/v\d\/homefeed\/categories\?/.test(url):
265 | try {
266 | let b = body;
267 | b.data.categories = b.data.categories.filter(e => !('homefeed.shop' == e.oid || 'homefeed.live' == e.oid));
268 | } catch (p) {
269 | console.log('categories: ' + p);
270 | }
271 | break;
272 | case /api\/sns\/v\d\/search\/hint/.test(url):
273 | try {
274 | let h = body;
275 | h.data?.hint_words &&
276 | (h.data.hint_words = [{ title: '搜索笔记', type: 'firstEnterOther#itemCfRecWord#搜索笔记#1', search_word: '搜索笔记' }]);
277 | } catch (v) {
278 | console.log('hint: ' + v);
279 | }
280 | break;
281 | case /api\/sns\/v\d\/search\/hot_list/.test(url):
282 | try {
283 | let m = body;
284 | m.data = { scene: '', title: '', items: [], host: '', background_color: {}, word_request_id: '' };
285 | } catch (u) {
286 | console.log('hot_list: ' + u);
287 | }
288 | break;
289 | case /api\/sns\/v\d\/search\/trending/.test(url):
290 | try {
291 | let k = body;
292 | k.data = { title: '', queries: [], type: '', word_request_id: '' };
293 | } catch (e) {
294 | console.log('trending: ', e);
295 | }
296 | break;
297 | case /api\/sns\/v\d\/system_service\/splash_config/.test(url):
298 | try {
299 | let w = body;
300 | w.data.ads_groups.forEach(e => {
301 | (e.start_time = '2208963661'),
302 | (e.end_time = '2209050061'),
303 | e.ads &&
304 | e.ads.forEach(e => {
305 | (e.start_time = '2208963661'), (e.end_time = '2209050061');
306 | });
307 | });
308 | } catch (_) {
309 | console.log('splash_config: ' + _);
310 | }
311 | break;
312 | case /api\/sns\/v\d\/homefeed\?/.test(url):
313 | try {
314 | let q = body;
315 | q.data = q.data.filter(e => !e.is_ads);
316 | } catch (E) {
317 | console.log('homefeed: ' + E);
318 | }
319 | break;
320 | case /api\/sns\/v\d\/system_service\/config\?/.test(url):
321 | try {
322 | let x = body,
323 | C = ['store', 'splash', 'loading_img', 'app_theme', 'cmt_words', 'highlight_tab'];
324 | for (let O of C) x.data?.[O] && delete x.data[O];
325 | } catch (R) {
326 | console.log('system_service: ' + R);
327 | }
328 | break;
329 | default:
330 | return;
331 | }
332 | return { body };
333 | }
334 | },
335 | },
336 | ];
337 |
338 | // 小红书画质增强:加载2K分辨率的图片
339 | function imageEnhance(jsonStr) {
340 | const regex1 = /imageView2\/2\/w\/\d+\/format/g;
341 | jsonStr = jsonStr.replace(regex1, `imageView2/2/w/2160/format`);
342 |
343 | const regex2 = /imageView2\/2\/h\/\d+\/format/g;
344 | jsonStr = jsonStr.replace(regex2, `imageView2/2/h/2160/format`);
345 | console.log('图片画质增强完成✅');
346 | return JSON.parse(jsonStr);
347 | }
348 |
349 | function replaceUrlContent(collectionA, collectionB) {
350 | console.log('替换无水印的URL');
351 | collectionA.forEach(itemA => {
352 | const matchingItemB = collectionB.find(itemB => itemB.file_id === itemA.file_id);
353 | if (matchingItemB) {
354 | itemA.url = itemA.url.replace(/(.*)\.mp4/, `${matchingItemB.url.match(/(.*)\.mp4/)[1]}.mp4`);
355 | itemA.author = '@renxia';
356 | }
357 | });
358 | }
359 |
--------------------------------------------------------------------------------
/src/vip/ximalaya.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: renxia
3 | * @Date: 2024-02-28 10:08:29
4 | * @LastEditors: renxia
5 | * @LastEditTime: 2024-09-30 11:27:14
6 | * @Description: 待验证
7 | */
8 |
9 | /** @type {import('@lzwme/whistle.x-scripts').RuleItem[]} */
10 | module.exports = [
11 | {
12 | // @see https://github.com/ddgksf2013/Scripts/raw/master/ximalaya_json.js
13 | on: 'res-body',
14 | ruleId: 'ximalayaADBlock',
15 | desc: '喜马拉雅去广告',
16 | method: '*',
17 | url: 'https://*.ximalaya.com/{focus-mobile,discovery-feed,discovery-category,mobile-user,mobile-playpage,starwar,mobile,product}/**',
18 | handler({ resBody: body, url, X }) {
19 | if (!body || Buffer.isBuffer(body)) return;
20 | if (typeof body === 'string') return;
21 |
22 | const color = X.FeUtils.color;
23 | console.log(`[${this.desc}]`, color.gray(url));
24 | let hit = commModify(body);
25 |
26 | switch (!0) {
27 | case /discovery-category\/customCategories/.test(url):
28 | try {
29 | let e = body;
30 | if (e.customCategoryList) {
31 | e.customCategoryList = e.customCategoryList.filter(
32 | e =>
33 | ('recommend' == e.itemType || 'template_category' == e.itemType || 'single_category' == e.itemType) &&
34 | 1005 !== e.categoryId
35 | );
36 | hit++;
37 | }
38 | if (e.defaultTabList) {
39 | e.defaultTabList = e.defaultTabList.filter(
40 | e =>
41 | ('recommend' == e.itemType || 'template_category' == e.itemType || 'single_category' == e.itemType) &&
42 | 1005 !== e.categoryId
43 | );
44 | hit++;
45 | }
46 | } catch (t) {
47 | console.log('customCategories: ' + t);
48 | }
49 | break;
50 | case /discovery-category\/v\d\/category/.test(url):
51 | try {
52 | let a = body;
53 | if (a.focusImages && a.focusImages.data) {
54 | a.focusImages.data = a.focusImages.data.filter(e => -1 != e.realLink.indexOf('open') && !e.isAd);
55 | hit++;
56 | }
57 | } catch (r) {
58 | console.log('categories: ' + r);
59 | }
60 | break;
61 | case /focus-mobile\/focusPic/.test(url):
62 | try {
63 | let s = body;
64 | if (s.header && s.header.length <= 1) {
65 | s.header[0].item.list[0].data = s.header[0].item.list[0].data.filter(e => -1 != e.realLink.indexOf('open') && !e.isAd);
66 | hit++;
67 | }
68 | } catch (i) {
69 | console.log('discovery-feed' + i);
70 | }
71 | break;
72 | case /discovery-feed\/v\d\/mix/.test(url):
73 | try {
74 | if (body.header?.length == 2) {
75 | delete body.header[0];
76 | body.body = body.body.filter(e => !(e.item?.adInfo || e.item?.moduleType == 'mix_ad' || 'bigCard' == e.displayClass));
77 | hit++;
78 | }
79 | } catch (d) {
80 | console.log('discovery-feed:' + d);
81 | }
82 | break;
83 | case /mobile-user\/v\d\/homePage/.test(url):
84 | try {
85 | let c = new Set([210, 213, 215]),
86 | y = body;
87 | if (y.data.serviceModule.entrances) {
88 | let l = y.data.serviceModule.entrances.filter(e => c.has(e.id));
89 | y.data.serviceModule.entrances = l;
90 | hit = 1;
91 | }
92 | } catch (g) {
93 | console.log('mobile-user:' + g);
94 | }
95 | break;
96 | default:
97 | break;
98 | }
99 |
100 | if (hit) {
101 | console.log(` - [updated][${color.green(this.desc)}]`, color.gray(url));
102 | return { body };
103 | }
104 | },
105 | },
106 | ];
107 |
108 | function commModify(body) {
109 | let hit = 0;
110 |
111 | if (Array.isArray(body)) {
112 | body.forEach(item => commModify(item) && (hit = 1));
113 | return hit;
114 | }
115 |
116 | if (!body || typeof body !== 'object') return hit;
117 |
118 | for (const [key, val] of Object.entries(body)) {
119 | switch (key) {
120 | case 'trackInfo':
121 | if (val && val.trackId) {
122 | Object.assign(val, {
123 | authorizedType: 0,
124 | permissionSource: '108',
125 | permissionExpireTime: 253402271999000,
126 | isVip: false,
127 | isVipFree: true,
128 | });
129 | hit = 1;
130 | continue;
131 | }
132 | case 'picbook':
133 | continue;
134 | case 'expireTime':
135 | body[key] = 4073558400000;
136 | hit = 1;
137 | continue;
138 | case 'isFree':
139 | case 'isVip':
140 | case 'isEnglishVip':
141 | case 'isXiaoyaUser':
142 | case 'isVipFree':
143 | case 'isAuthorized':
144 | case 'isXimiUhqAuthorized':
145 | case 'hasShqAuthorized':
146 | case 'inThreeMonth':
147 | case 'canFreeListen':
148 | case 'havePurchased':
149 | case 'isShowEntrance':
150 | case 'isVerified':
151 | case 'isXimiUhqTrack':
152 | case 'currentUserIsCopyright':
153 | case 'hasCart':
154 | body[key] = true;
155 | hit = 1;
156 | continue;
157 | case 'hqNeedVip':
158 | body[key] = false;
159 | hit = 1;
160 | continue;
161 | case 'ximiFirstStatus':
162 | case 'vipFirstStatus':
163 | case 'paidType':
164 | case 'tailSkip':
165 | case 'childAlbumInWhiteList':
166 | case 'freeListenStatus':
167 | body[key] = 1;
168 | hit = 1;
169 | continue;
170 | case 'sampleDuration':
171 | body[key] = 1000000;
172 | hit = 1;
173 | default:
174 | if (commModify(val)) hit = 1;
175 | }
176 | }
177 |
178 | return hit;
179 | }
180 |
--------------------------------------------------------------------------------
/src/vip/xunlei.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: renxia
3 | * @Date: 2024-02-28 10:08:29
4 | * @LastEditors: renxia
5 | * @LastEditTime: 2024-03-04 16:37:08
6 | * @Description: 待验证
7 | */
8 |
9 | /** @type {import('@lzwme/whistle.x-scripts').RuleItem[]} */
10 | module.exports = [
11 | {
12 | on: 'res-body',
13 | ruleId: 'xunleiVipCrack',
14 | desc: '迅雷 VIP',
15 | method: '*',
16 | mitm: 'xluser-ssl.zhihu.com',
17 | url: "https://xluser-ssl.xunlei.com/xluser.core.login/v3/getuserinfo",
18 | handler({ resBody: body, url, X }) {
19 | if (typeof body === 'object') {
20 | const color = X.FeUtils.color;
21 | console.log(`[${this.desc}]`, color.gray(url));
22 |
23 | body.vipList = [
24 | {
25 | expireDate: '20290609',
26 | isAutoDeduct: '0',
27 | isVip: '1',
28 | isYear: '1',
29 | payId: '0',
30 | payName: '---',
31 | register: '0',
32 | vasid: '2',
33 | vasType: '5',
34 | vipDayGrow: '20',
35 | vipGrow: '840',
36 | vipLevel: '7',
37 | },
38 | ];
39 |
40 | return { body };
41 | }
42 | },
43 | },
44 | ];
45 |
--------------------------------------------------------------------------------
/src/vip/zhihu.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: renxia
3 | * @Date: 2024-02-28 10:08:29
4 | * @LastEditors: renxia
5 | * @LastEditTime: 2024-03-01 14:02:43
6 | * @Description: 待验证
7 | */
8 |
9 | /** @type {import('@lzwme/whistle.x-scripts').RuleItem[]} */
10 | module.exports = [
11 | {
12 | on: 'res-body',
13 | ruleId: 'zhihuFilter',
14 | desc: '知乎去广告',
15 | method: '*',
16 | url: 'https://{api,www,m-cloud,appcloud2}.zhihu.com/**',
17 | handler({ resBody: body, headers, url, X }) {
18 | if (!X.isText(headers) || Buffer.isBuffer(body) || typeof body !== 'object') return;
19 |
20 | let hit = 0;
21 | if ('svip_privileges' in body) {
22 | hit = 1;
23 | body.svip_privileges = true;
24 | }
25 |
26 | if (body.right?.ownership === false) {
27 | hit = 1;
28 | Object.assign(body, {
29 | ownership: true,
30 | purchased: true,
31 | anonymous: true,
32 | });
33 | }
34 |
35 | if (!hit) {
36 | const regList = [
37 | /^https:\/\/api\.zhihu\.com\/commercial_api\/app_float_layer/,
38 | /^https:\/\/api\.zhihu\.com\/feed\/render\/tab\/config/,
39 | /^https:\/\/api\.zhihu\.com\/(moments_v3|topstory\/hot-lists\/total|topstory\/recommend)/,
40 | /^https:\/\/api\.zhihu\.com\/v2\/topstory\/hot-lists\/everyone-seeing/,
41 | /^https:\/\/api\.zhihu\.com\/next-(bff|data|render)/,
42 | /^https:\/\/api\.zhihu\.com\/questions\/\d+(\/answers|\/feeds|\?include=)/,
43 | /^https:\/\/www\.zhihu\.com\/api\/v4\/(articles|answers)\/\d+\/recommendations?/,
44 | /^https:\/\/appcloud2\.zhihu\.com\/v3\/config/,
45 | /^https:\/\/m-cloud\.zhihu\.com\/api\/cloud\/config\/all/,
46 | /sku\/reversion_sku_ext/,
47 | /people\/self/,
48 | /unlimited\/go\/my_card/,
49 | /\/books\/\d+/,
50 | ];
51 | if (!regList.some(reg => reg.test(url))) return;
52 | }
53 |
54 | const color = X.FeUtils.color;
55 | console.log(`[${this.desc}]`, color.gray(url));
56 |
57 | // 参考: https://raw.githubusercontent.com/RuCu6/QuanX/main/Scripts/zhihu.js
58 | // 2023-11-17 11:30
59 |
60 | let obj = body;
61 | let bodyStr = JSON.stringify(body);
62 |
63 | if (body.vip_info && url.indexOf('people/self') != -1) {
64 | X.FeUtils.assign(body, {
65 | vip_info: {
66 | is_vip: true,
67 | vip_type: 1,
68 | },
69 | });
70 | hit = 1;
71 |
72 | return { body };
73 | }
74 |
75 | if (url.indexOf('unlimited/go/my_card') != -1) {
76 | X.FeUtils.assign(body, {
77 | button_text: '点击反馈',
78 | jump_url: 'https://github.com/lzwme/x-scripts-rules/issues',
79 | title: '2999-09-09到期',
80 | songNeedPay: 0,
81 | });
82 |
83 | return { body };
84 | }
85 |
86 | if (url.indexOf('sku/reversion_sku_ext') != -1) {
87 | body.data.center.buttons[1].sub_text = '无法观看?点击此处反馈!';
88 | body.data.center.buttons[1].link_url = 'https://github.com/lzwme/x-scripts-rules/issues';
89 | body.data.center.buttons[1].button_text = '已解锁该内容';
90 | body.data.bottom.buttons[1].button_text = '立即阅读';
91 | body.data.center.buttons[0].sub_text = '已解锁';
92 | return { body };
93 | }
94 |
95 | if (url.includes('/api/cloud/config/all')) {
96 | if (obj?.data?.configs) {
97 | obj.data.configs.forEach(i => {
98 | if (i.configKey === 'feed_gray_theme') {
99 | if (i.configValue) {
100 | i.configValue.start_time = '3818332800'; // Unix 时间戳 2090-12-31 00:00:00
101 | i.configValue.end_time = '3818419199'; // Unix 时间戳 2090-12-31 23:59:59
102 | i.status = false;
103 | }
104 | } else if (i.configKey === 'feed_top_res') {
105 | if (i.configValue) {
106 | i.configValue.start_time = '3818332800'; // Unix 时间戳 2090-12-31 00:00:00
107 | i.configValue.end_time = '3818419199'; // Unix 时间戳 2090-12-31 23:59:59
108 | i.status = false;
109 | }
110 | }
111 | });
112 | }
113 | } else if (url.includes('/api/v4/answers')) {
114 | if (obj?.data) {
115 | delete obj.data;
116 | }
117 | if (obj?.paging) {
118 | delete obj.paging;
119 | }
120 | } else if (url.includes('/api/v4/articles')) {
121 | const item = ['ad_info', 'paging', 'recommend_info'];
122 | item.forEach(i => {
123 | delete obj[i];
124 | });
125 | } else if (url.includes('.zhihu.com/v3/config')) {
126 | if (obj?.config) {
127 | if (obj.config?.homepage_feed_tab) {
128 | obj.config.homepage_feed_tab.tab_infos = obj.config.homepage_feed_tab.tab_infos.filter(i => {
129 | if (i.tab_type === 'activity_tab') {
130 | i.start_time = '3818332800'; // Unix 时间戳 2090-12-31 00:00:00
131 | i.end_time = '3818419199'; // Unix 时间戳 2090-12-31 23:59:59
132 | return true;
133 | } else {
134 | return false;
135 | }
136 | });
137 | }
138 | if (obj.config?.hp_channel_tab) {
139 | delete obj.config.hp_channel_tab;
140 | }
141 | if (obj.config?.zombie_conf) {
142 | obj.config.zombie_conf.zombieEnable = false;
143 | }
144 | if (obj.config?.gray_mode) {
145 | obj.config.gray_modeenable = false;
146 | obj.config.gray_mode.start_time = '3818332800'; // Unix 时间戳 2090-12-31 00:00:00
147 | obj.config.gray_mode.end_time = '3818419199'; // Unix 时间戳 2090-12-31 23:59:59
148 | }
149 | if (obj.config?.zhcnh_thread_sync) {
150 | obj.config.zhcnh_thread_sync.LocalDNSSetHostWhiteList = [];
151 | obj.config.zhcnh_thread_sync.isOpenLocalDNS = '0';
152 | obj.config.zhcnh_thread_sync.ZHBackUpIP_Switch_Open = '0';
153 | obj.config.zhcnh_thread_sync.dns_ip_detector_operation_lock = '1';
154 | obj.config.zhcnh_thread_sync.ZHHTTPSessionManager_setupZHHTTPHeaderField = '1';
155 | }
156 | obj.config.zvideo_max_number = 1;
157 | obj.config.is_show_followguide_alert = false;
158 | }
159 | } else if (url.includes('/commercial_api/app_float_layer')) {
160 | // 悬浮图标
161 | if ('feed_egg' in obj) {
162 | delete obj.feed_egg;
163 | }
164 | } else if (url.includes('/feed/render/tab/config')) {
165 | if (obj?.selected_sections?.length > 0) {
166 | // 首页顶部tab
167 | obj.selected_sections = obj.selected_sections.filter(i => !['activity', 'live']?.includes(i?.tab_type));
168 | }
169 | } else if (url.includes('/moments_v3')) {
170 | if (obj?.data?.length > 0) {
171 | obj.data = obj.data.filter(i => !i?.title?.includes('为您推荐'));
172 | }
173 | } else if (url.includes('/next-bff')) {
174 | if (obj?.data?.length > 0) {
175 | obj.data = obj.data.filter(
176 | i =>
177 | !(
178 | i?.origin_data?.type?.includes('ad') ||
179 | i?.origin_data?.resource_type?.includes('ad') ||
180 | i?.origin_data?.next_guide?.title?.includes('推荐')
181 | )
182 | );
183 | }
184 | } else if (url.includes('/next-data')) {
185 | if (obj?.data?.data?.length > 0) {
186 | obj.data.data = obj.data.data.filter(i => !(i?.type?.includes('ad') || i?.data?.answer_type?.includes('PAID')));
187 | }
188 | } else if (url.includes('/next-render')) {
189 | if (obj?.data?.length > 0) {
190 | obj.data = obj.data.filter(
191 | i =>
192 | !(
193 | i?.adjson ||
194 | i?.biz_type_list?.includes('article') ||
195 | i?.biz_type_list?.includes('content') ||
196 | i?.business_type?.includes('paid') ||
197 | i?.section_info ||
198 | i?.tips ||
199 | i?.type?.includes('ad')
200 | )
201 | );
202 | }
203 | } else if (url.includes('/questions/')) {
204 | // 问题回答列表
205 | if (obj?.data?.length > 0) {
206 | obj.data = obj.data.filter(i => !i?.target?.answer_type?.includes('paid'));
207 | }
208 | if (obj?.data?.ad_info) {
209 | delete obj.data.ad_info;
210 | }
211 | if (obj?.ad_info) {
212 | delete obj.ad_info;
213 | }
214 | if (obj?.query_info) {
215 | delete obj.query_info;
216 | }
217 | } else if (url.includes('/topstory/hot-lists/everyone-seeing')) {
218 | // 热榜信息流
219 | if (obj?.data?.data?.length > 0) {
220 | // 合作推广
221 | obj.data.data = obj.data.data.filter(i => !i.target?.metrics_area?.text?.includes('合作推广'));
222 | }
223 | } else if (url.includes('/topstory/hot-lists/total')) {
224 | // 热榜排行榜
225 | if (obj?.data?.length > 0) {
226 | // 品牌甄选
227 | obj.data = obj.data.filter(i => !i?.hasOwnProperty('ad'));
228 | }
229 | } else if (url.includes('/topstory/recommend')) {
230 | // 推荐信息流
231 | if (obj.data?.length > 0) {
232 | obj.data = obj.data.filter(i => {
233 | if (i.type === 'market_card' && i.fields?.header?.url && i.fields.body?.video?.id) {
234 | let videoID = getUrlParamValue(item.fields.header.url, 'videoID');
235 | if (videoID) {
236 | i.fields.body.video.id = videoID;
237 | }
238 | } else if (i.type === 'common_card') {
239 | if (i.extra?.type === 'drama') {
240 | // 直播内容
241 | return false;
242 | } else if (i.extra?.type === 'zvideo') {
243 | // 推广视频
244 | let videoUrl = i.common_card.feed_content.video.customized_page_url;
245 | let videoID = getUrlParamValue(videoUrl, 'videoID');
246 | if (videoID) {
247 | i.common_card.feed_content.video.id = videoID;
248 | }
249 | } else if (i.common_card?.feed_content?.video?.id) {
250 | let search = '"feed_content":{"video":{"id":';
251 | let str = bodyStr.substring(bodyStr.indexOf(search) + search.length);
252 | let videoID = str.substring(0, str.indexOf(','));
253 | i.common_card.feed_content.video.id = videoID;
254 | } else if (i.common_card?.footline?.elements?.[0]?.text?.panel_text?.includes('广告')) {
255 | return false;
256 | } else if (i.common_card?.feed_content?.source_line?.elements?.[1]?.text?.panel_text?.includes('盐选')) {
257 | return false;
258 | } else if (i?.promotion_extra) {
259 | // 营销信息
260 | return false;
261 | }
262 | return true;
263 | } else if (i.type.includes('aggregation_card')) {
264 | // 横排卡片 知乎热榜
265 | return false;
266 | } else if (i.type === 'feed_advert') {
267 | // 伪装成正常内容的卡片
268 | return false;
269 | }
270 | return true;
271 | });
272 | fixPos(obj.data);
273 | }
274 | }
275 |
276 | return { body: obj };
277 | },
278 | },
279 | ];
280 |
281 | // 修复offset
282 | function fixPos(arr) {
283 | for (let i = 0; i < arr.length; i++) {
284 | arr[i].offset = i + 1;
285 | }
286 | }
287 |
288 | function getUrlParamValue(url, queryName) {
289 | return Object.fromEntries(
290 | url
291 | .substring(url.indexOf('?') + 1)
292 | .split('&')
293 | .map(pair => pair.split('='))
294 | )[queryName];
295 | }
296 |
--------------------------------------------------------------------------------
/src/youzan-liteapp.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: renxia
3 | * @Date: 2024-02-06 11:25:49
4 | * @LastEditors: renxia
5 | * @LastEditTime: 2024-04-09 09:16:31
6 | * @Description:
7 | */
8 |
9 | const pd_map = {
10 | 8: '韩都严选',
11 | 17: '极客农场与胡子叔的餐盘',
12 | 47: '植观微信旗舰店',
13 | 102: '榴芒一刻',
14 | 347: '乒乓生活商城',
15 | 379: '燕之坊五谷为养官方商城',
16 | 816: '名后官方旗舰店',
17 | 1220: '良品铺子官方商城', // 连续签到领优惠券
18 | 1380: '幸福西饼',
19 | 1579: '等蜂来天然蜂蜜旗舰店',
20 | 1612: '新疆万科广场店',
21 | 1631: '云南白药',
22 | 1700: '中粮-健康生活甄选',
23 | 2042: '物道生活',
24 | 2426: '钟薛高旗舰店',
25 | 2527: '米卡米卡蛋糕旗舰店',
26 | 2728: '小香真精油旗舰店',
27 | 2729: '相逢幸福 生日蛋糕 下午茶',
28 | 3124: '东鹏特饮微店',
29 | 3262: 'TOIs朵茜情调生活馆',
30 | 3821: '乐汁商城-素食更健康',
31 | 4345: '悦上美妆',
32 | 4744: '环球嗨购精选',
33 | 5054: '自然兰官方旗舰店',
34 | 5998: '森马集团官方商城',
35 | 7302: '暖家好物',
36 | 8249: '贝因美贝家商城',
37 | 8353: '润百颜护肤品商城',
38 | 8449: '中国原产递优选',
39 | 8887: '印趣严选',
40 | 9332: '三只松鼠旗舰店',
41 | 12307: 'colorkey珂拉琪旗舰店',
42 | 13546: '广缘唐海曹妃甸店',
43 | 13891: '潘达微信旗舰店',
44 | 13904: '小茶婆婆旗舰店',
45 | 13968: '圣牧有机官方商城',
46 | 16453: 'PMPM',
47 | 17273: '香气优选',
48 | 17666: '爱依服商城-总店',
49 | 18415: '得宝Tempo',
50 | 22432: '一封情酥',
51 | 1465878: '隅田川旗舰店',
52 | 1479428: 'ffit8',
53 | 1595664: '参半口腔护理',
54 | 1597464: 'Xbox俱乐部',
55 | 1876007: 'FLORTTE花洛莉亚',
56 | 1903120: 'KIMTRUE且初',
57 | 1985507: '肤漾FORYON',
58 | 2050884: '伯喜线上商城',
59 | 2081204: '果壳市集',
60 | 2176467: 'chillmore且悠',
61 | 2187565: '蜜蜂惊喜社',
62 | 2299510: '燕京啤酒电商旗舰店',
63 | 2386563: 'HBN品牌店',
64 | 2646845: '海贽医疗科技',
65 | 2692852: '老爹果园',
66 | 2713880: '莱克旗舰店',
67 | 2905214: '百事可乐',
68 | 2910869: 'ficcecode菲诗蔻官方旗舰店',
69 | 2923467: '红之旗舰店',
70 | 3010256: '燕子约官方旗舰店',
71 | 3014060: 'LAN蘭',
72 | 3347128: '松鲜鲜官方旗舰店',
73 | 3805112: '广州日报电商',
74 | };
75 |
76 | /** @type {import('@lzwme/whistle.x-scripts').RuleItem[]} */
77 | module.exports = [
78 | {
79 | on: 'res-body',
80 | ruleId: 'youzan_le_data',
81 | desc: '有赞小程序签到',
82 | url: ['https://h5.youzan.com/wscump/checkin/*', 'https://h5.youzan.com/{wscuser,wscdeco}/**'],
83 | method: '*',
84 | cache: {}, // app_id: { checkinId, uid }
85 | getCacheUid({ url, X, headers, resBody }) {
86 | let { app_id, checkinId, buyerId } = X.FeUtils.getUrlParams('?' + url.split('?')[1]);
87 | if (!app_id) app_id = /\/(wx.+)\//.exec(headers['referer'])?.[1];
88 | if (!app_id) return;
89 |
90 | const shopName = resBody?.data?.shopName || pd_map[checkinId] || '';
91 | if (!this.cache[app_id]) this.cache[app_id] = {};
92 | if (checkinId) this.cache[app_id].checkinId = checkinId;
93 | if (+buyerId) this.cache[app_id].uid = buyerId;
94 | if (shopName) this.cache[app_id].shopName = shopName;
95 |
96 | if (headers['extra-data']?.startsWith('{')) {
97 | const { checkinId, uid, shopName = '' } = this.cache[app_id];
98 | if (checkinId && uid) {
99 | const edata = JSON.parse(headers['extra-data']);
100 | const sessionId = edata.sid;
101 | console.log(`'${checkinId}': '${shopName}',`, uid, sessionId);
102 |
103 | if (shopName && !pd_map[checkinId]) {
104 | pd_map[checkinId] = shopName;
105 | console.log(pd_map);
106 | }
107 |
108 | if (sessionId) {
109 | return { uid: `${checkinId}_${uid}`, data: `${checkinId}:${sessionId}##${uid}_${checkinId}${shopName ? `_${shopName}` : ''}` };
110 | }
111 | }
112 | }
113 | },
114 | handler: ({ allCacheData: d }) => ({ envConfig: { value: d.map(d => `${d.data}`).join('\n') } }),
115 | updateEnvValue: /##\d+_\d+/,
116 | },
117 | ];
118 |
--------------------------------------------------------------------------------
/whistle-rules/ad-block.txt:
--------------------------------------------------------------------------------
1 | # 避免迅雷版权问题
2 | hub5idx.v6.shub.sandai.net statusCode://200
3 | hub5emu.v6.shub.sandai.net statusCode://200
4 | hub5btmain.v6.shub.sandai.net statusCode://200
5 |
6 | # 绕过 IOS 企业证书过期
7 | ocsp.apple.com statusCode://200
8 |
9 | # 百度地图 @see https://gist.githubusercontent.com/ddgksf2013/beec132ca0c3570ffa0cf331bce8f82a/raw/baidumap.adblock.conf
10 | ^https?:\/\/ugc\.map\.baidu\.com\/govui\/rich_content statusCode://200
11 | ^https?:\/\/newclient\.map\.baidu\.com\/client\/phpui.*qt=hw statusCode://200
12 | ^https?:\/\/newclient\.map\.baidu\.com\/client\/phpui2\/\?qt=ads statusCode://200
13 | # 百度地图_DNS处理
14 | ^https?:\/\/httpdns\.baidubce\.com statusCode://200
15 | ^https?:\/\/newclient\.map\.baidu\.com\/client\/crossmarketing statusCode://200
16 | ^https?:\/\/newclient\.map\.baidu\.com\/client\/usersystem\/home\/dynamic statusCode://200
17 |
18 | # 小红书 @see https://raw.githubusercontent.com/ddgksf2013/Rewrite/master/AdBlock/XiaoHongShu.conf
19 | # > 小红书_通用广告请求
20 | ^https?:\/\/www\.xiaohongshu\.com\/api\/sns\/v\d\/(tag\/)?ads statusCode://200
21 | # > 小红书_隐私屏蔽
22 | ^https?:\/\/referee\.xiaohongshu\.com\/v\d\/stateReport statusCode://200
23 | # > 小红书_Switches
24 | ^https?:\/\/pages\.xiaohongshu\.com\/data\/native\/matrix_switches statusCode://200
25 | # > 小红书_青少年请求
26 | ^https?:\/\/edith\.xiaohongshu\.com\/api\/sns\/v\d\/user\/teenager\/status statusCode://200
27 | # > 小红书_启动引导
28 | ^https?:\/\/edith\.xiaohongshu\.com\/api\/sns\/v\d\/guide\/home_guide statusCode://200
29 |
30 | # 喜马拉雅
31 | # ~ XiMaLaYa_喜马拉雅_修复轮播Ad失效Bug
32 | ^https?:\/\/.*\.xima.*\.com\/discovery-feed\/focus\/queryF statusCode://200
33 | # ~ XiMaLaYa_喜马拉雅_播放页_Live
34 | ^https?:\/\/.*\.xima.*\.com\/mobile-playpage\/view\/ statusCode://200
35 | # ~ XiMaLaYa_喜马拉雅_MyInfo红点提醒
36 | ^https?:\/\/.*\.xima.*\.com\/chaos-notice-web\/v1\/message\/preview\/list statusCode://200
37 | # ~ XiMaLaYa_喜马拉雅_屏蔽大红包Tips
38 | ^https?:\/\/.*\.xima.*\.com\/social-web\/bottomTabs\/dynamicEntrance\/status statusCode://200
39 | # ~ XiMaLaYa_喜马拉雅_屏蔽gif弹窗Ad
40 | ^https?:\/\/.*\.xmcdn\.com\/\w{8}\/\w{4}-\w{16}\/.+gif$ statusCode://200
41 | # ~ XiMaLaYa_喜马拉雅_gslb
42 | ^https?:\/\/gslb.*\.xima.*\.com\/ statusCode://200
43 | # ~ XiMaLaYa_喜马拉雅_屏蔽Aged请求
44 | ^https?:\/\/.*\.xima.*\.com\/(dog-portal\/checkOld|(child-mobile\/child|aged-mobile\/aged)\/mode\/query) statusCode://200
45 | # ~ XiMaLaYa_喜马拉雅_部分Tab弹窗
46 | ^https?:\/\/.*\.xima.*\.com\/discovery-feed\/isShowUserGiftPendant statusCode://200
47 | # ~ XiMaLaYa_喜马拉雅_屏蔽红点提示
48 | ^https?:\/\/.*\.xima.*\.com\/mobile-user\/unread statusCode://200
49 | # ~ XiMaLaYa_喜马拉雅_屏蔽minor请求
50 | ^https?:\/\/.*\.xima.*\.com/mobile-user/minorProtection/pop statusCode://200
51 | # ~ XiMaLaYa_喜马拉雅_屏蔽隐私搜集
52 | ^https?:\/\/.*\.xima.*\.com\/collector\/xl\/v\d statusCode://200
53 | # ~ XiMaLaYa_喜马拉雅_屏蔽版本更新
54 | ^https?:\/\/.*\.xima.*\.com\/butler-portal\/versionCheck statusCode://200
55 | # ~ XiMaLaYa_喜马拉雅_屏蔽开屏广告
56 | ^https?:\/\/(adse\.wsa|adse|adbehavior|xdcs-collector)\.xima.*\.com\/.* statusCode://200
57 | # ~ XiMaLaYa_喜马拉雅_屏蔽位置请求
58 | ^https?:\/\/.*\.xima.*\.com\/mobile\/discovery\/v\d\/location statusCode://200
59 | # ~ XiMaLaYa_喜马拉雅_屏蔽热搜词
60 | ^https?:\/\/.*\.xima.*\.com\/hotWord statusCode://200
61 | # ~ XiMaLaYa_喜马拉雅_屏蔽搜索框定时_Ad
62 | ^https?:\/\/.*\.xima.*\.com\/(hub)?guideWord statusCode://200
63 | # ~ XiMaLaYa_喜马拉雅_屏蔽实时Ad请求
64 | ^https?:\/\/.*\.xima.*\.com\/api\/v\d\/adRealTime statusCode://200
65 | # ~ XiMaLaYa_喜马拉雅_屏蔽ting_Ad
66 | ^https?:\/\/.*\.xima.*\.com\/ting\/(loading|feed|home)? statusCode://200
67 |
--------------------------------------------------------------------------------
/whistle-rules/x.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": [
3 | "www.zhihu.com ua://{iphoneUA}",
4 | "^https?://www\\.bing\\.com/(search|new|web) ua://{edgUA}"
5 | ],
6 | "values": {
7 | "iphoneUA": "osee2unifiedRelease/17634_osee2unifiedReleaseVersion/9.38.1_Mozilla/5.0_(iPhone;CPU_iPhone_OS 17_0_2_like_Mac_OS_X)_AppleWebKit/605.1.15_Mobile/15E148",
8 | "edgUA": "AppleWebKit/537.36 Chrome/110.0 Safari/537.36 Edg/110.0"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/whistle-rules/zhihu.txt:
--------------------------------------------------------------------------------
1 | # test: 知乎过滤
2 | ^https://www.zhihu.com/api/v4/questions/*/related-readings statusCode://200
3 | ^https://www.zhihu.com/api/v4/answers/*/related-readings statusCode://200
4 | https://www.zhihu.com/api/v4/hot_recommendation statusCode://200
5 | https://www.zhihu.com/commercial_api/banners_v3/mobile_banner statusCode://200
6 | ^https://zhuanlan.zhihu.com/api/articles/*/recommendation statusCode://200
7 |
--------------------------------------------------------------------------------