kpinquan commited on
Commit
9e1deec
·
verified ·
1 Parent(s): 1ae698f

Upload 4 files

Browse files
Files changed (4) hide show
  1. manifest.json +18 -0
  2. middleware.js +61 -0
  3. nodemon.json +21 -0
  4. render.yaml +8 -0
manifest.json ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "LibreTV",
3
+ "short_name": "LibreTV",
4
+ "description": "免费在线视频搜索与观看平台",
5
+ "start_url": ".",
6
+ "display": "standalone",
7
+ "background_color": "#0f1622",
8
+ "theme_color": "#000000",
9
+ "apple-mobile-web-app-capable": "yes",
10
+ "apple-mobile-web-app-status-bar-style": "black",
11
+ "icons": [
12
+ {
13
+ "src": "image/logo-black.png",
14
+ "sizes": "512x512",
15
+ "type": "image/png"
16
+ }
17
+ ]
18
+ }
middleware.js ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { sha256 } from './js/sha256.js'; // 需新建或引入SHA-256实现
2
+
3
+ // Vercel Middleware to inject environment variables
4
+ export default async function middleware(request) {
5
+ // Get the URL from the request
6
+ const url = new URL(request.url);
7
+
8
+ // Only process HTML pages
9
+ const isHtmlPage = url.pathname.endsWith('.html') || url.pathname.endsWith('/');
10
+ if (!isHtmlPage) {
11
+ return; // Let the request pass through unchanged
12
+ }
13
+
14
+ // Fetch the original response
15
+ const response = await fetch(request);
16
+
17
+ // Check if it's an HTML response
18
+ const contentType = response.headers.get('content-type') || '';
19
+ if (!contentType.includes('text/html')) {
20
+ return response; // Return the original response if not HTML
21
+ }
22
+
23
+ // Get the HTML content
24
+ const originalHtml = await response.text();
25
+
26
+ // Replace the placeholder with actual environment variable
27
+ // If PASSWORD is not set, replace with empty string
28
+ const password = process.env.PASSWORD || '';
29
+ let passwordHash = '';
30
+ if (password) {
31
+ passwordHash = await sha256(password);
32
+ }
33
+
34
+ const adminpassword = process.env.ADMINPASSWORD || '';
35
+ let adminpasswordHash = '';
36
+ if (adminpassword) {
37
+ adminpasswordHash = await sha256(adminpassword); // 修复变量名
38
+ }
39
+
40
+ // 合并两次替换为一次操作
41
+ let modifiedHtml = originalHtml
42
+ .replace(
43
+ 'window.__ENV__.PASSWORD = "{{PASSWORD}}";',
44
+ `window.__ENV__.PASSWORD = "${passwordHash}"; // SHA-256 hash`
45
+ )
46
+ .replace(
47
+ 'window.__ENV__.ADMINPASSWORD = "{{ADMINPASSWORD}}";',
48
+ `window.__ENV__.ADMINPASSWORD = "${adminpasswordHash}"; // SHA-256 hash`
49
+ );
50
+
51
+ // 修复Response构造
52
+ return new Response(modifiedHtml, {
53
+ status: response.status,
54
+ statusText: response.statusText,
55
+ headers: response.headers
56
+ });
57
+ }
58
+
59
+ export const config = {
60
+ matcher: ['/', '/((?!api|_next/static|_vercel|favicon.ico).*)'],
61
+ };
nodemon.json ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "watch": [
3
+ "server.mjs",
4
+ "*.html",
5
+ ".env"
6
+ ],
7
+ "ext": "js,mjs,json,html,css",
8
+ "ignore": [
9
+ "node_modules/**/*",
10
+ ".git/**/*"
11
+ ],
12
+ "delay": "500",
13
+ "env": {
14
+ "NODE_ENV": "development"
15
+ },
16
+ "execMap": {
17
+ "mjs": "node"
18
+ },
19
+ "verbose": true,
20
+ "restartable": "rs"
21
+ }
render.yaml ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ services:
2
+ - type: web
3
+ name: libretv
4
+ runtime: node
5
+ plan: free
6
+ buildCommand: 'npm install'
7
+ startCommand: 'node server.mjs'
8
+ autoDeploy: true