Skip to content

Commit 86e34e2

Browse files
author
Taois
committed
feat: 兼容dr2模板源协议
1 parent 96cf833 commit 86e34e2

File tree

10 files changed

+685
-358
lines changed

10 files changed

+685
-358
lines changed

docs/updateRecord.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
# drpyS更新记录
22

3+
### 20250911
4+
5+
更新至V1.2.29
6+
7+
1. 支持模板继承匹配,包括自动模板
8+
2. 支持模板源搜索自动过验证
9+
3. 修复首页和首页推荐接口多次请求问题
10+
4. 删除已兼容为ds协议的dr2源
11+
312
### 20250910
413

514
更新至V1.2.28

libs/drpyS.js

Lines changed: 565 additions & 133 deletions
Large diffs are not rendered by default.

libs_drpy/drpyCustom.js

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ globalThis.decodeStr = function (input, encoding) {
227227

228228
globalThis.getCryptoJS = function () {
229229
// return request('https://ghproxy.net/https://raw.githubusercontent.com/hjdhnx/dr_py/main/libs/crypto-hiker.js');
230-
return 'console.log("CryptoJS已装载");'
230+
return 'log("CryptoJS已装载");'
231231
}
232232

233233
// 封装的RSA加解密类
@@ -327,7 +327,7 @@ globalThis.fixAdM3u8Ai = async function (m3u8_url, headers) {
327327
}
328328
if (last_url.includes(".m3u8") && last_url !== m3u8_url) {
329329
m3u8_url = urljoin(m3u8_url, last_url);
330-
log("嵌套的m3u8_url:" + m3u8_url);
330+
log("[fixAdM3u8Ai]嵌套的m3u8_url:" + m3u8_url);
331331
m3u8 = (await req(m3u8_url, option)).content;
332332
}
333333
let s = m3u8.trim().split("\n").filter(it => it.trim()).join("\n");
@@ -375,7 +375,7 @@ globalThis.fixAdM3u8Ai = async function (m3u8_url, headers) {
375375
return false
376376
}
377377
);
378-
log("最后一条切片:" + laststr);
378+
log("[fixAdM3u8Ai]最后一条切片:" + laststr);
379379
let ad_urls = [];
380380
for (let i = 0; i < ss.length; i++) {
381381
let s = ss[i];
@@ -391,12 +391,12 @@ globalThis.fixAdM3u8Ai = async function (m3u8_url, headers) {
391391
ss[i] = s.replace(/URI=\"(.*)\"/, 'URI="' + urljoin(m3u8_url, "$1") + '"')
392392
}
393393
}
394-
log("处理的m3u8地址:" + m3u8_url);
395-
log("----广告地址----");
396-
log(ad_urls);
394+
log("[fixAdM3u8Ai]处理的m3u8地址:" + m3u8_url);
395+
log("[fixAdM3u8Ai]----广告地址----");
396+
log("[fixAdM3u8Ai]广告地址列表:", ad_urls);
397397
m3u8 = ss.join("\n");
398-
log("处理耗时:" + ((new Date).getTime() - ts).toString());
399-
log(m3u8);
398+
log("[fixAdM3u8Ai]处理耗时:" + ((new Date).getTime() - ts).toString());
399+
log("[fixAdM3u8Ai]处理后的m3u8:", m3u8);
400400
return m3u8
401401
}
402402

@@ -431,7 +431,7 @@ globalThis.forceOrder = function (lists, key, option) {
431431
}
432432
first += '';
433433
second += '';
434-
// console.log(first,second);
434+
// log(first,second);
435435
if (first.match(/(\d+)/) && second.match(/(\d+)/)) {
436436
let num1 = Number(first.match(/(\d+)/)[1]);
437437
let num2 = Number(second.match(/(\d+)/)[1]);
@@ -462,7 +462,7 @@ globalThis.getQuery = function (url) {
462462
});
463463
return resObj;
464464
} catch (err) {
465-
log(`getQuery发生错误:${e.message}`)
465+
log(`[getQuery]getQuery发生错误:${e.message}`)
466466
return {};
467467
}
468468
}
@@ -599,7 +599,7 @@ globalThis.dealJson = function (html) {
599599
html = JSON.parse(html);
600600
} catch (e) {
601601
}
602-
// console.log(typeof(html));
602+
// log(typeof(html));
603603
return html;
604604
}
605605

@@ -616,7 +616,7 @@ globalThis.OcrApi = {
616616
// let html = request(this.api,{data:{img:img},headers:{'User-Agent':PC_UA},'method':'POST'},true);
617617
// html = JSON.parse(html);
618618
// code = html.url||'';
619-
log('通过drpy_ocr验证码接口过验证...');
619+
log('[OcrApi.classification]通过drpy_ocr验证码接口过验证...');
620620
let html = '';
621621
if (this.api.endsWith('drpy/text')) {
622622
html = (await req(this.api, {
@@ -629,7 +629,7 @@ globalThis.OcrApi = {
629629
}
630630
code = html || '';
631631
} catch (e) {
632-
log(`OCR识别验证码发生错误:${e.message}`)
632+
log(`[OcrApi.classification]OCR识别验证码发生错误:${e.message}`)
633633
}
634634
return code
635635
}

libs_drpy/drpyInject.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ const maxSockets = 64;
2828
const _axios = createAxiosInstance({maxSockets: maxSockets});
2929
let $axios;
3030
const dsReqLib = Number(process.env.DS_REQ_LIB) || 0;
31-
console.log('DS/CAT源底层req实现 DS_REQ_LIB (0 fetch 1 axios):', dsReqLib);
31+
console.log('[drpyInject]DS/CAT源底层req实现 DS_REQ_LIB (0 fetch 1 axios):', dsReqLib);
3232
// 配置 axios 使用代理
3333

3434
if (dsReqLib === 0) {
@@ -226,7 +226,7 @@ async function request(url, opt = {}) {
226226
return {code: resp.status, headers: resHeader, content: responseData};
227227
} catch (error) {
228228
const {response: resp} = error;
229-
console.error(`Request error: ${error.message}`);
229+
console.error(`[request]Request error: ${error.message}`);
230230
let responseData = '';
231231
// console.log('responseData:',responseData);
232232
try {
@@ -238,7 +238,7 @@ async function request(url, opt = {}) {
238238
responseData = buffer.toString('utf-8');
239239
}
240240
} catch (e) {
241-
console.error(`get error response Text failed: ${e.message}`);
241+
console.error(`[request]get error response Text failed: ${e.message}`);
242242
}
243243
// console.log('responseData:',responseData);
244244
return {
@@ -306,7 +306,7 @@ function aes(mode, encrypt, input, inBase64, key, iv, outBase64) {
306306
const outBuf = Buffer.concat([cipher.update(inBuf), cipher.final()]);
307307
return outBase64 ? base64EncodeBuf(outBuf) : outBuf.toString('utf8');
308308
} catch (error) {
309-
console.log(error);
309+
console.log('[aes]', error);
310310
}
311311
return '';
312312
}
@@ -333,7 +333,7 @@ function des(mode, encrypt, input, inBase64, key, iv, outBase64) {
333333
const outBuf = Buffer.concat([cipher.update(inBuf), cipher.final()]);
334334
return outBase64 ? base64EncodeBuf(outBuf) : outBuf.toString('utf8');
335335
} catch (error) {
336-
console.log(error);
336+
console.log('[des]', error);
337337
}
338338
return '';
339339
}
@@ -387,7 +387,7 @@ function rsa(mode, pub, encrypt, input, inBase64, key, outBase64) {
387387
}
388388
return outBase64 ? base64EncodeBuf(outBuf) : outBuf.toString('utf8');
389389
} catch (error) {
390-
console.log(error);
390+
console.log('[rsa]', error);
391391
}
392392
return '';
393393
}

libs_drpy/fetchAxios.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ class FetchAxios {
77
baseURL: '',
88
headers: {},
99
timeout: 0,
10-
responseType: 'json', // json 或 text
10+
responseType: 'json', // json, text 或 arraybuffer
1111
withCredentials: false,
1212
httpsAgent: null,
1313
...defaultConfig,
@@ -71,6 +71,8 @@ class FetchAxios {
7171
let responseData;
7272
if (finalConfig.responseType === 'json') {
7373
responseData = await response.json().catch(() => null);
74+
} else if (finalConfig.responseType === 'arraybuffer') {
75+
responseData = await response.arrayBuffer();
7476
} else {
7577
responseData = await response.text();
7678
}
@@ -134,7 +136,7 @@ export function createHttpsInstance() {
134136
return createInstance({
135137
headers: {'User-Agent': 'Mozilla/5.0'},
136138
timeout: 10000,
137-
responseType: 'text',
139+
responseType: 'arraybuffer',
138140
httpsAgent: httpsAgent
139141
});
140142
}

libs_drpy/req-extend.js

Lines changed: 32 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,4 @@
1-
// async function request(url, options) {
2-
// try {
3-
// log('rule:',typeof rule);
4-
// log('headers:',rule.headers);
5-
// log('title:',rule.title);
6-
// log('getHome:',typeof getHome);
7-
// log('gzip',typeof(gzip))
8-
// log('fetch_params',typeof(fetch_params))
9-
// return (await req(url, options)).content
10-
// } catch (e) {
11-
// log(`requestHtml error:${e.message}`);
12-
// return ''
13-
// }
14-
// }
15-
1+
// 注意:!!!此文件通过获取文本代码然后注入代码形式使用,不包含globalThis导出和export导出
162
// var key = '源的唯一ID' // 允许在源里自定义设置key,不设置就自动取title或者host
173
const RKEY = typeof (key) !== 'undefined' && key ? key : 'drpyS_' + (rule.title || rule.host); // 源的唯一标识
184

@@ -25,7 +11,7 @@ const RKEY = typeof (key) !== 'undefined' && key ? key : 'drpyS_' + (rule.title
2511
*/
2612
async function request(url, obj, ocr_flag) {
2713
ocr_flag = ocr_flag || false;
28-
if (typeof (obj) === 'undefined' || !obj || obj === {}) {
14+
if (typeof (obj) === 'undefined' || !obj || (typeof obj === 'object' && obj !== null && Object.keys(obj).length === 0)) {
2915
let fetch_params = {};
3016
let headers = {
3117
'User-Agent': MOBILE_UA,
@@ -77,16 +63,20 @@ async function request(url, obj, ocr_flag) {
7763
if (obj.headers.hasOwnProperty('Content-Type') || obj.headers.hasOwnProperty('content-type')) {
7864
let _contentType = obj.headers["Content-Type"] || obj.headers["content-type"] || "";
7965
if (_contentType.includes("application/x-www-form-urlencoded")) {
80-
log("custom body is application/x-www-form-urlencoded");
66+
log("[request] custom body is application/x-www-form-urlencoded");
8167
if (typeof obj.body == "string") {
8268
let temp_obj = parseQueryString(obj.body);
83-
console.log(JSON.stringify(temp_obj));
69+
log(`[request] body:${JSON.stringify(temp_obj)}`);
8470
}
8571
}
8672
}
73+
// 注意:POST请求通常需要保留body数据,这里注释掉可能有问题的删除逻辑
74+
// if (obj.method === 'POST') {
75+
// delete obj.body
76+
// }
8777

88-
console.log(JSON.stringify(obj.headers));
89-
console.log('request:' + url + ` |method:${obj.method || 'GET'} |body:${obj.body || ''}`);
78+
log(`[request] headers: ${JSON.stringify(obj.headers)}`);
79+
log('[request] url:' + url + ` |method:${obj.method || 'GET'} |body:${obj.body || ''}`);
9080
let res = await req(url, obj);
9181
let html = res.content || '';
9282
if (obj.withHeaders) {
@@ -98,7 +88,6 @@ async function request(url, obj, ocr_flag) {
9888
}
9989
}
10090

101-
var fetch = request;
10291

10392
/**
10493
* 快捷post请求
@@ -152,7 +141,7 @@ async function checkHtml(html, url, obj) {
152141
if (/\?btwaf=/.test(html)) {
153142
let btwaf = html.match(/btwaf(.*?)"/)[1];
154143
url = url.split('#')[0] + '?btwaf' + btwaf;
155-
log('宝塔验证访问链接:' + url);
144+
log('[checkHtml] 宝塔验证访问链接:' + url);
156145
html = await request(url, obj);
157146
}
158147
return html
@@ -166,7 +155,7 @@ async function checkHtml(html, url, obj) {
166155
*/
167156
async function getCode(url, obj) {
168157
let html = await request(url, obj);
169-
html = checkHtml(html, url, obj);
158+
html = await checkHtml(html, url, obj);
170159
return html
171160
}
172161

@@ -182,23 +171,22 @@ async function getHtml(url) {
182171
}
183172
let cookie = getItem(RULE_CK, '');
184173
if (cookie) {
185-
// log('有cookie:'+cookie);
174+
log(`[getHtml] ${RULE_CK}: ${cookie}`);
186175
if (obj.headers && !Object.keys(obj.headers).map(it => it.toLowerCase()).includes('cookie')) {
187-
log('历史无cookie,新增过验证后的cookie');
176+
log('[getHtml] 历史无cookie,新增过验证后的cookie');
188177
obj.headers['Cookie'] = cookie;
189178
} else if (obj.headers && obj.headers.cookie && obj.headers.cookie !== cookie) {
190179
obj.headers['Cookie'] = cookie;
191-
log('历史有小写过期的cookie,更新过验证后的cookie');
180+
log('[getHtml] 历史有小写过期的cookie,更新过验证后的cookie');
192181
} else if (obj.headers && obj.headers.Cookie && obj.headers.Cookie !== cookie) {
193182
obj.headers['Cookie'] = cookie;
194-
log('历史有大写过期的cookie,更新过验证后的cookie');
183+
log('[getHtml] 历史有大写过期的cookie,更新过验证后的cookie');
195184
} else if (!obj.headers) {
196185
obj.headers = {Cookie: cookie};
197-
log('历史无headers,更新过验证后的含cookie的headers');
186+
log('[getHtml] 历史无headers,更新过验证后的含cookie的headers');
198187
}
199188
}
200-
let html = getCode(url, obj);
201-
return html
189+
return getCode(url, obj);
202190
}
203191

204192
/**
@@ -214,7 +202,7 @@ async function verifyCode(url) {
214202
try {
215203
// let obj = {headers:headers,timeout:timeout};
216204
let yzm_url = `${host}/index.php/verify/index.html`;
217-
console.log(`验证码链接:${yzm_url}`);
205+
log(`[verifyCode] 验证码链接:${yzm_url}`);
218206
let hhtml = await request(yzm_url, {withHeaders: true, toBase64: true}, true);
219207
let json = JSON.parse(hhtml);
220208
if (!cookie) {
@@ -223,25 +211,25 @@ async function verifyCode(url) {
223211
// cookie = json['set-cookie']?json['set-cookie'].split(';')[0]:'';
224212
cookie = setCk ? json[setCk].split(';')[0] : '';
225213
}
226-
// console.log(hhtml);
227-
console.log('cookie:' + cookie);
214+
// log(hhtml);
215+
log(`[verifyCode] cookie:${cookie}`);
228216
let img = json.body;
229-
// console.log(img);
217+
// log(img);
230218
let code = await OcrApi.classification(img);
231-
console.log(`第${cnt + 1}次验证码识别结果:${code}`);
219+
log(`[verifyCode] ${cnt + 1}次验证码识别结果:${code}`);
232220
let submit_url = `${host}/index.php/ajax/verify_check?type=search&verify=${code}`;
233-
console.log(submit_url);
221+
log(`[verifyCode] 提交验证码链接: ${submit_url}`);
234222
let html = await request(submit_url, {headers: {Cookie: cookie}, 'method': 'POST'});
235-
// console.log(html);
223+
// log(`[verifyCode] 提交验证码结果: ${html}`);
236224
html = JSON.parse(html);
237225
if (html.msg === 'ok') {
238-
console.log(`第${cnt + 1}次验证码提交成功`);
226+
log(`[verifyCode] ${cnt + 1}次验证码提交成功`);
239227
return cookie // 需要返回cookie
240228
} else if (html.msg !== 'ok' && cnt + 1 >= OCR_RETRY) {
241229
cookie = ''; // 需要清空返回cookie
242230
}
243231
} catch (e) {
244-
console.log(`第${cnt + 1}次验证码提交失败:${e.message}`);
232+
log(`[verifyCode] ${cnt + 1}次验证码提交失败:${e.message}`);
245233
if (cnt + 1 >= OCR_RETRY) {
246234
cookie = '';
247235
}
@@ -258,7 +246,8 @@ async function verifyCode(url) {
258246
*/
259247
function setItem(k, v) {
260248
local.set(RKEY, k, v);
261-
console.log(`规则${RKEY}设置${k} => ${v}`)
249+
log(`[setItem] 规则${RKEY}设置${k} => ${v}`);
250+
return true
262251
}
263252

264253
/**
@@ -277,15 +266,8 @@ function getItem(k, v) {
277266
*/
278267
function clearItem(k) {
279268
local.delete(RKEY, k);
269+
return true
280270
}
281271

282-
// jsp系列函数改到drpyS代码中,执行完rule和预处理过后再次注入,可以保证在rule定义范围外也能使用。这里也可以注释掉,没太多必要
283-
globalThis.jsp = new jsoup(rule.host || '');
284-
globalThis.pdfh = pdfh;
285-
globalThis.pd = pd;
286-
globalThis.pdfa = pdfa;
287-
globalThis.setItem = setItem;
288-
globalThis.getItem = getItem;
289-
globalThis.clearItem = clearItem;
290-
globalThis.request = request;
291-
globalThis.fetch = fetch;
272+
// 定义沙箱里的全局变量alias别名
273+
var fetch = request;

0 commit comments

Comments
 (0)