Skip to content

Commit d040028

Browse files
committed
update:ds猫源已完美支持
1 parent 1ac9260 commit d040028

14 files changed

+339
-141
lines changed

Diff for: README.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,15 @@ nodejs作为服务端的drpy实现。全面升级异步写法
1414
* [本站防止爬虫协议](/robots.txt)
1515
* [本项目主页-免翻](https://github.com/hjdhnx/drpy-node)
1616
* [DS源适配猫影视](https://github.com/hjdhnx/CatPawOpen/tree/ds-cat)
17-
* [在线猫ds源-复制链接后手动改地址加授权](/config/index.js.md5)
17+
* [在线猫ds源主页](/cat/index.html)
1818

1919
## 更新记录
2020

21-
### 20250119
21+
### 20250120
2222

23-
更新至V1.1.12
23+
更新至V1.1.13
2424

25-
1. 支持猫源在线配置
25+
1. 完善猫在线配置
2626

2727
### 20250117
2828

Diff for: controllers/config.js

+74-22
Original file line numberDiff line numberDiff line change
@@ -360,32 +360,84 @@ export default (fastify, options, done) => {
360360
const hostname = request.hostname; // 主机名,不包含端口
361361
const port = request.socket.localPort; // 获取当前服务的端口
362362
console.log(`cfg_path:${cfg_path},port:${port}`);
363-
let requestHost = (cfg_path.startsWith('/1') || cfg_path.startsWith('/index')) ? `${protocol}://${hostname}` : `http://127.0.0.1:${options.PORT}`; // 动态生成根地址
364-
let requestUrl = (cfg_path.startsWith('/1') || cfg_path.startsWith('/index')) ? `${protocol}://${hostname}${request.url}` : `http://127.0.0.1:${options.PORT}${request.url}`; // 动态生成请求链接
363+
let not_local = cfg_path.startsWith('/1') || cfg_path.startsWith('/index');
364+
let requestHost = not_local ? `${protocol}://${hostname}` : `http://127.0.0.1:${options.PORT}`; // 动态生成根地址
365+
let requestUrl = not_local ? `${protocol}://${hostname}${request.url}` : `http://127.0.0.1:${options.PORT}${request.url}`; // 动态生成请求链接
365366
// console.log('requestUrl:', requestUrl);
366-
if (cfg_path.endsWith('.js')) {
367-
if (cfg_path.includes('index.js')) {
368-
return reply.sendFile('index.js', path.join(options.rootDir, 'data/cat'));
369-
} else if (cfg_path.includes('index.config.js')) {
370-
let content = readFileSync(path.join(options.rootDir, 'data/cat/index.config.js'), 'utf-8');
371-
// console.log(content);
372-
content = jinja.render(content, {config_url: requestUrl.replace(cfg_path, '/1')});
373-
return reply.type('application/javascript;charset=utf-8').send(content);
367+
// if (cfg_path.endsWith('.js')) {
368+
// if (cfg_path.includes('index.js')) {
369+
// // return reply.sendFile('index.js', path.join(options.rootDir, 'data/cat'));
370+
// let content = readFileSync(path.join(options.rootDir, 'data/cat/index.js'), 'utf-8');
371+
// // content = jinja.render(content, {config_url: requestUrl.replace(cfg_path, `/1?sub=all&pwd=${process.env.API_PWD || ''}`)});
372+
// content = content.replace('$config_url', requestUrl.replace(cfg_path, `/1?sub=all&pwd=${process.env.API_PWD || ''}`));
373+
// return reply.type('application/javascript;charset=utf-8').send(content);
374+
// } else if (cfg_path.includes('index.config.js')) {
375+
// let content = readFileSync(path.join(options.rootDir, 'data/cat/index.config.js'), 'utf-8');
376+
// // content = jinja.render(content, {config_url: requestUrl.replace(cfg_path, `/1?sub=all&pwd=${process.env.API_PWD || ''}`)});
377+
// content = content.replace('$config_url', requestUrl.replace(cfg_path, `/1?sub=all&pwd=${process.env.API_PWD || ''}`));
378+
// return reply.type('application/javascript;charset=utf-8').send(content);
379+
// }
380+
// }
381+
// if (cfg_path.endsWith('.js.md5')) {
382+
// if (cfg_path.includes('index.js')) {
383+
// let content = readFileSync(path.join(options.rootDir, 'data/cat/index.js'), 'utf-8');
384+
// // content = jinja.render(content, {config_url: requestUrl.replace(cfg_path, `/1?sub=all&pwd=${process.env.API_PWD || ''}`)});
385+
// content = content.replace('$config_url', requestUrl.replace(cfg_path, `/1?sub=all&pwd=${process.env.API_PWD || ''}`));
386+
// let contentHash = md5(content);
387+
// console.log('index.js contentHash:', contentHash);
388+
// return reply.type('text/plain;charset=utf-8').send(contentHash);
389+
// } else if (cfg_path.includes('index.config.js')) {
390+
// let content = readFileSync(path.join(options.rootDir, 'data/cat/index.config.js'), 'utf-8');
391+
// // content = jinja.render(content, {config_url: requestUrl.replace(cfg_path, `/1?sub=all&pwd=${process.env.API_PWD || ''}`)});
392+
// content = content.replace('$config_url', requestUrl.replace(cfg_path, `/1?sub=all&pwd=${process.env.API_PWD || ''}`));
393+
// let contentHash = md5(content);
394+
// console.log('index.config.js contentHash:', contentHash);
395+
// return reply.type('text/plain;charset=utf-8').send(contentHash);
396+
// }
397+
// }
398+
const getFilePath = (cfgPath, rootDir, fileName) => path.join(rootDir, `data/cat/${fileName}`);
399+
const processContent = (content, cfgPath, requestUrl) =>
400+
content.replace('$config_url', requestUrl.replace(cfgPath, `/1?sub=all&pwd=${process.env.API_PWD || ''}`));
401+
402+
const handleJavaScript = (cfgPath, requestUrl, options, reply) => {
403+
const fileMap = {
404+
'index.js': 'index.js',
405+
'index.config.js': 'index.config.js'
406+
};
407+
408+
for (const [key, fileName] of Object.entries(fileMap)) {
409+
if (cfgPath.includes(key)) {
410+
const filePath = getFilePath(cfgPath, options.rootDir, fileName);
411+
let content = readFileSync(filePath, 'utf-8');
412+
content = processContent(content, cfgPath, requestUrl);
413+
return reply.type('application/javascript;charset=utf-8').send(content);
414+
}
374415
}
416+
};
417+
418+
const handleJsMd5 = (cfgPath, requestUrl, options, reply) => {
419+
const fileMap = {
420+
'index.js': 'index.js',
421+
'index.config.js': 'index.config.js'
422+
};
423+
424+
for (const [key, fileName] of Object.entries(fileMap)) {
425+
if (cfgPath.includes(key)) {
426+
const filePath = getFilePath(cfgPath, options.rootDir, fileName);
427+
let content = readFileSync(filePath, 'utf-8');
428+
content = processContent(content, cfgPath, requestUrl);
429+
const contentHash = md5(content);
430+
console.log(`${fileName} contentHash:`, contentHash);
431+
return reply.type('text/plain;charset=utf-8').send(contentHash);
432+
}
433+
}
434+
};
435+
if (cfg_path.endsWith('.js')) {
436+
return handleJavaScript(cfg_path, requestUrl, options, reply);
375437
}
438+
376439
if (cfg_path.endsWith('.js.md5')) {
377-
if (cfg_path.includes('index.js')) {
378-
let content = readFileSync(path.join(options.rootDir, 'data/cat/index.js.md5'), 'utf-8');
379-
return reply.type('text/plain;charset=utf-8').send(content);
380-
// return reply.sendFile('index.js.md5', path.join(options.rootDir, 'data/cat'));
381-
} else if (cfg_path.includes('index.config.js')) {
382-
let content = readFileSync(path.join(options.rootDir, 'data/cat/index.config.js'), 'utf-8');
383-
// console.log(content);
384-
content = jinja.render(content, {config_url: requestUrl.replace(cfg_path, '/1')});
385-
let contentHash = md5(content);
386-
console.log('contentHash:', contentHash);
387-
return reply.type('text/plain;charset=utf-8').send(contentHash);
388-
}
440+
return handleJsMd5(cfg_path, requestUrl, options, reply);
389441
}
390442
let sub = null;
391443
if (sub_code) {

Diff for: controllers/root.js

+24
Original file line numberDiff line numberDiff line change
@@ -84,5 +84,29 @@ export default (fastify, options, done) => {
8484
reply.status(500).send({error: 'Failed to fetch favicon', details: error.message});
8585
}
8686
});
87+
88+
fastify.get('/cat/index.html', {preHandler: validateBasicAuth}, async (request, reply) => {
89+
try {
90+
// 设置文件路径
91+
const catHtmlPath = path.join(options.rootDir, 'data/cat/index.html');
92+
93+
if (existsSync(catHtmlPath)) {
94+
const protocol = request.headers['x-forwarded-proto'] || (request.socket.encrypted ? 'https' : 'http'); // http 或 https
95+
const hostname = request.hostname;
96+
// const port = request.socket.localPort; // 获取当前服务的端口
97+
// let requestUrl = `${protocol}://${hostname}${request.url}`;
98+
let content = readFileSync(catHtmlPath, 'utf-8');
99+
const validUsername = process.env.API_AUTH_NAME || 'admin';
100+
const validPassword = process.env.API_AUTH_CODE || 'drpys';
101+
let catLink = `${protocol}://${validUsername}:${validPassword}@${hostname}/config/index.js.md5`;
102+
content = content.replace('$catLink', catLink);
103+
return reply.type('text/html').send(content);
104+
} else {
105+
reply.status(404).send({error: 'Favicon not found'}); // 如果文件不存在,返回 404 错误
106+
}
107+
} catch (error) {
108+
reply.status(500).send({error: 'Failed to fetch cat', details: error.message});
109+
}
110+
});
87111
done();
88112
};

Diff for: custom.json

+8-8
Original file line numberDiff line numberDiff line change
@@ -284,21 +284,21 @@
284284
"ext": ""
285285
},
286286
{
287-
"key": "drpyS_哔哩影视[官]",
288-
"name": "哔哩影视[官](DS)",
287+
"key": "drpyS_哔哩直播[官]",
288+
"name": "哔哩直播[官](DS)",
289289
"type": 4,
290-
"api": "http://localhost:5757/api/哔哩影视[官]",
291-
"searchable": 1,
290+
"api": "http://localhost:5757/api/哔哩直播[官]",
291+
"searchable": 2,
292292
"filterable": 1,
293293
"quickSearch": 0,
294294
"ext": ""
295295
},
296296
{
297-
"key": "drpyS_哔哩直播[官]",
298-
"name": "哔哩直播[官](DS)",
297+
"key": "drpyS_哔哩影视[官]",
298+
"name": "哔哩影视[官](DS)",
299299
"type": 4,
300-
"api": "http://localhost:5757/api/哔哩直播[官]",
301-
"searchable": 2,
300+
"api": "http://localhost:5757/api/哔哩影视[官]",
301+
"searchable": 1,
302302
"filterable": 1,
303303
"quickSearch": 0,
304304
"ext": ""

Diff for: data/cat/index.config.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ __export(index_config_exports, {
2424
module.exports = __toCommonJS(index_config_exports);
2525
var index_config_default = {
2626
drpyS: {
27-
// config_url: "http://localhost:5757/config/1?sub=all&pwd=",
28-
config_url: "{{config_url}}",
27+
config_url: "$config_url",
2928
// 本地ds 支持
3029
// config_url: 'http://localhost:5707/config/0?sub=dzyyds', // 本地hipy-t4 支持
3130
home_site: "http://localhost:5757/api/设置中心",

Diff for: data/cat/index.config.js.md5

-1
This file was deleted.

Diff for: data/cat/index.html

+116
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>ds猫源在线配置主页</title>
7+
<style>
8+
body {
9+
margin: 0;
10+
font-family: Arial, sans-serif;
11+
display: flex;
12+
justify-content: center;
13+
align-items: center;
14+
min-height: 100vh;
15+
background-color: #f3f4f6;
16+
color: #333;
17+
text-align: center;
18+
}
19+
20+
.container {
21+
padding: 20px;
22+
border: 1px solid #ddd;
23+
border-radius: 8px;
24+
background-color: #fff;
25+
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
26+
max-width: 90%;
27+
width: 400px;
28+
}
29+
30+
h1 {
31+
font-size: 24px;
32+
margin-bottom: 20px;
33+
}
34+
35+
.link {
36+
display: inline-block;
37+
font-size: 16px;
38+
color: #007bff;
39+
text-decoration: none;
40+
margin-bottom: 10px;
41+
word-wrap: break-word;
42+
}
43+
44+
.link:hover {
45+
text-decoration: underline;
46+
}
47+
48+
.copy-button {
49+
display: inline-block;
50+
padding: 8px 16px;
51+
font-size: 14px;
52+
color: #fff;
53+
background-color: #007bff;
54+
border: none;
55+
border-radius: 4px;
56+
cursor: pointer;
57+
transition: background-color 0.3s;
58+
}
59+
60+
.copy-button:hover {
61+
background-color: #0056b3;
62+
}
63+
64+
.message {
65+
margin-top: 10px;
66+
font-size: 14px;
67+
color: #28a745;
68+
}
69+
</style>
70+
</head>
71+
<body>
72+
<div class="container">
73+
<h1>欢迎使用DS猫源</h1>
74+
<a href="#" class="link" id="link">$catLink</a>
75+
<button class="copy-button" id="copyButton">复制地址</button>
76+
<div class="message" id="message" style="display: none;">链接已复制到剪切板!</div>
77+
</div>
78+
79+
<script>
80+
function copyToClipboard(text) {
81+
if (navigator.clipboard && navigator.clipboard.writeText) {
82+
navigator.clipboard.writeText(text)
83+
.then(() => {
84+
console.log('Text copied to clipboard!');
85+
})
86+
.catch(err => {
87+
console.error('Failed to copy text: ', err);
88+
});
89+
} else {
90+
console.warn('Clipboard API not supported. Falling back to legacy method.');
91+
fallbackCopyToClipboard(text);
92+
}
93+
}
94+
95+
function fallbackCopyToClipboard(text) {
96+
const textarea = document.createElement('textarea');
97+
textarea.value = text;
98+
document.body.appendChild(textarea);
99+
textarea.select();
100+
try {
101+
document.execCommand('copy');
102+
console.log('Fallback: Text copied to clipboard!');
103+
} catch (err) {
104+
console.error('Fallback: Failed to copy text: ', err);
105+
}
106+
document.body.removeChild(textarea);
107+
}
108+
109+
document.getElementById('copyButton').addEventListener('click', function () {
110+
const link = document.getElementById('link').textContent;
111+
copyToClipboard(link);
112+
alert('已复制到剪切板');
113+
});
114+
</script>
115+
</body>
116+
</html>

0 commit comments

Comments
 (0)