Skip to content

Commit b57bb63

Browse files
committed
update:发布新版本
1 parent 17779ea commit b57bb63

21 files changed

+1149
-395
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,3 +136,4 @@ dist
136136
/json/UC分享.json
137137
/jx/奇奇.js
138138
/js/百忙无果[].js
139+
/data/settings/link_data.json

README.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# drpyS(drpy-node)
22

33
nodejs作为服务端的drpy实现。全面升级异步写法
4-
积极开发中,每日一更,当前进度 `40%`
4+
积极开发中,每日一更,当前进度 `42%`
55

66
* [本地配置接口-动态本地](/config?pwd=)
77
* [本地配置接口-动态外网/局域网](/config/1?pwd=)
@@ -18,6 +18,14 @@ nodejs作为服务端的drpy实现。全面升级异步写法
1818

1919
## 更新记录
2020

21+
### 20250121
22+
23+
更新至V1.1.14
24+
25+
1. 猫源ds在线配置支持接口密码
26+
2. 新增源
27+
3. 磁盘加速
28+
2129
### 20250120
2230

2331
更新至V1.1.13

controllers/api.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ export default (fastify, options, done) => {
257257
}
258258
// return proxyStreamMediaMulti(content, new_headers, request, reply); // 走 流式代理
259259
// 将查询参数构建为目标 URL
260-
const redirectUrl = `/mediaProxy?url=${encodeURIComponent(content)}&headers=${encodeURIComponent(new_headers)}&thread=${ENV.get('thread') || 1}`;
260+
const redirectUrl = `/mediaProxy?url=${encodeURIComponent(content)}&headers=${encodeURIComponent(JSON.stringify(new_headers))}&thread=${ENV.get('thread') || 1}`;
261261
// 执行重定向
262262
return reply.redirect(redirectUrl);
263263
}

controllers/config.js

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,13 @@ import batchExecute from '../libs_drpy/batchExecute.js';
1313
const {jsEncoder} = drpy;
1414

1515
// 工具函数:生成 JSON 数据
16-
async function generateSiteJSON(jsDir, dr2Dir, configDir, requestHost, sub, subFilePath, pwd) {
16+
async function generateSiteJSON(options, requestHost, sub, pwd) {
17+
const jsDir = options.jsDir;
18+
const dr2Dir = options.dr2Dir;
19+
const configDir = options.configDir;
20+
const subFilePath = options.subFilePath;
21+
const rootDir = options.rootDir;
22+
1723
const files = readdirSync(jsDir);
1824
let valid_files = files.filter((file) => file.endsWith('.js') && !file.startsWith('_')); // 筛选出不是 "_" 开头的 .js 文件
1925
let sort_list = [];
@@ -191,6 +197,40 @@ async function generateSiteJSON(jsDir, dr2Dir, configDir, requestHost, sub, subF
191197

192198
}
193199

200+
// 根据用户是否启用挂载数据源去生成对应配置
201+
if (ENV.get('enable_link_data', '1') === '1') {
202+
log(`开始挂载外部T4数据`);
203+
let link_sites = [];
204+
let link_url = ENV.get('link_url');
205+
let enable_link_push = ENV.get('enable_link_push');
206+
try {
207+
let link_data = readFileSync(path.join(rootDir, './data/settings/link_data.json'), 'utf-8');
208+
link_sites = JSON.parse(link_data).sites.filter(site => site.type = 4);
209+
link_sites.forEach((site) => {
210+
if (site.key === 'push_agent' && !enable_link_push) {
211+
return
212+
}
213+
if (site.api && !site.api.startsWith('http')) {
214+
site.api = urljoin(link_url, site.api)
215+
}
216+
if (site.ext && site.ext.startsWith('.')) {
217+
site.ext = urljoin(link_url, site.ext)
218+
}
219+
if (site.key === 'push_agent' && enable_link_push) { // 推送覆盖
220+
let pushIndex = sites.findIndex(s => s.key === 'push_agent');
221+
if (pushIndex > -1) {
222+
sites[pushIndex] = site;
223+
} else {
224+
sites.push(site);
225+
}
226+
} else {
227+
sites.push(site);
228+
}
229+
});
230+
} catch (e) {
231+
}
232+
}
233+
194234
// 订阅再次处理别名的情况
195235
if (sub) {
196236
if (sub.mode === 0) {
@@ -449,7 +489,7 @@ export default (fastify, options, done) => {
449489
}
450490
}
451491

452-
const siteJSON = await generateSiteJSON(options.jsDir, options.dr2Dir, options.configDir, requestHost, sub, options.subFilePath, pwd);
492+
const siteJSON = await generateSiteJSON(options, requestHost, sub, pwd);
453493
const parseJSON = await generateParseJSON(options.jxDir, requestHost);
454494
const livesJSON = generateLivesJSON(requestHost);
455495
const playerJSON = generatePlayerJSON(options.configDir, requestHost);

controllers/mediaProxy.js

Lines changed: 18 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import {base64Decode} from '../libs_drpy/crypto-util.js';
22
import '../utils/random-http-ua.js'
33
import {keysToLowerCase} from '../utils/utils.js';
4+
import {ENV} from "../utils/env.js";
5+
import chunkStream, {testSupport} from '../utils/chunk.js';
46
import http from 'http';
57
import https from 'https';
68
import axios from 'axios';
@@ -36,80 +38,30 @@ export default (fastify, options, done) => {
3638
: {};
3739

3840
// Call the proxy function, passing the decoded URL and headers
39-
// return await proxyStreamMedia(decodedUrl, decodedHeader, reply);
40-
return await proxyStreamMediaMulti(decodedUrl, decodedHeader, request, reply, thread, size, randUa);
41+
// return await proxyStreamMediaMulti(decodedUrl, decodedHeader, request, reply, thread, size, randUa);
42+
// return await chunkStream(request, reply, decodedUrl, ids[1], Object.assign({Cookie: cookie}, baseHeader));
43+
if (ENV.get('play_proxy_mode', '1') !== '2') { // 2磁盘加速 其他都是内存加速
44+
console.log('[mediaProxy] proxyStreamMediaMulti 内存加速:chunkSize:', sizeToBytes(size));
45+
return await proxyStreamMediaMulti(decodedUrl, decodedHeader, request, reply, thread, size, randUa);
46+
} else {
47+
console.log('[mediaProxy] chunkStream 磁盘加速 chunkSize:', sizeToBytes('256K'));
48+
return await chunkStream(request, reply, decodedUrl, null, decodedHeader,
49+
Object.assign({chunkSize: 1024 * 256, poolSize: 5, timeout: 1000 * 10}, {
50+
// chunkSize: sizeToBytes(size),
51+
poolSize: thread
52+
})
53+
);
54+
}
4155
} catch (error) {
42-
fastify.log.error(error);
56+
// fastify.log.error(error);
57+
fastify.log.error(error.message);
4358
reply.code(500).send({error: error.message});
4459
}
4560
});
4661

4762
done();
4863
};
4964

50-
// 媒体文件 流式代理,单线程管道方式发送数据,且存在bug,暂不使用
51-
function proxyStreamMedia(videoUrl, headers, reply) {
52-
console.log(`进入了流式代理: ${videoUrl} | headers: ${JSON.stringify(headers)}`);
53-
54-
const protocol = videoUrl.startsWith('https') ? https : http;
55-
const agent = videoUrl.startsWith('https') ? httpsAgent : httpAgent;
56-
57-
// 发起请求
58-
const proxyRequest = protocol.request(videoUrl, {headers, agent}, (videoResponse) => {
59-
console.log('videoResponse.statusCode:', videoResponse.statusCode);
60-
console.log('videoResponse.headers:', videoResponse.headers);
61-
62-
if (videoResponse.statusCode === 200 || videoResponse.statusCode === 206) {
63-
const resp_headers = {
64-
'Content-Type': videoResponse.headers['content-type'] || 'application/octet-stream',
65-
'Content-Length': videoResponse.headers['content-length'],
66-
...(videoResponse.headers['content-range'] ? {'Content-Range': videoResponse.headers['content-range']} : {}),
67-
};
68-
console.log('Response headers:', resp_headers);
69-
reply.headers(resp_headers).status(videoResponse.statusCode);
70-
71-
// 将响应流直接管道传输给客户端
72-
videoResponse.pipe(reply.raw);
73-
74-
videoResponse.on('data', (chunk) => {
75-
console.log('Data chunk received, size:', chunk.length);
76-
});
77-
78-
videoResponse.on('end', () => {
79-
console.log('Video data transmission complete.');
80-
});
81-
82-
videoResponse.on('error', (err) => {
83-
console.error('Error during video response:', err.message);
84-
reply.code(500).send({error: 'Error streaming video', details: err.message});
85-
});
86-
87-
reply.raw.on('finish', () => {
88-
console.log('Data fully sent to client');
89-
});
90-
91-
// 监听关闭事件,销毁视频响应流
92-
reply.raw.on('close', () => {
93-
console.log('Response stream closed.');
94-
videoResponse.destroy();
95-
});
96-
} else {
97-
console.error(`Unexpected status code: ${videoResponse.statusCode}`);
98-
reply.code(videoResponse.statusCode).send({error: 'Failed to fetch video'});
99-
}
100-
});
101-
102-
// 监听错误事件
103-
proxyRequest.on('error', (err) => {
104-
console.error('Proxy request error:', err.message);
105-
reply.code(500).send({error: 'Error fetching video', details: err.message});
106-
});
107-
108-
// 必须调用 .end() 才能发送请求
109-
proxyRequest.end();
110-
}
111-
112-
11365
// Helper function for range-based chunk downloading
11466
async function fetchStream(url, userHeaders, start, end, randUa) {
11567
const headers = keysToLowerCase({
@@ -315,7 +267,6 @@ async function proxyStreamMediaMulti(mediaUrl, reqHeaders, request, reply, threa
315267
}
316268
}
317269

318-
319270
// Helper function to convert size string (e.g., '128K', '1M') to bytes
320271
function sizeToBytes(size) {
321272
const sizeMap = {

0 commit comments

Comments
 (0)