-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathembyAlist.tar
309 lines (278 loc) · 20 KB
/
embyAlist.tar
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
nginx/ 0000777 0001750 0001750 00000000000 14240347770 010001 5 ustar hj hj nginx/conf.d/ 0000777 0001750 0001750 00000000000 14236223132 011136 5 ustar hj hj nginx/conf.d/emby.conf 0000777 0001750 0001750 00000011274 14245402406 012754 0 ustar hj hj # Load the njs script
js_path /etc/nginx/conf.d/;
js_import emby2Pan from emby.js;
# Cache images, subtitles
proxy_cache_path /var/cache/nginx/emby levels=1:2 keys_zone=emby:100m max_size=1g inactive=30d use_temp_path=off;
proxy_cache_path /var/cache/nginx/emby/subs levels=1:2 keys_zone=embysubs:10m max_size=1g inactive=30d use_temp_path=off;
server{
gzip on;
listen 80;
server_name default;
## The default `client_max_body_size` is 1M, this might not be enough for some posters, etc.
client_max_body_size 20M;
# # Security / XSS Mitigation Headers
# add_header X-Frame-Options "SAMEORIGIN";
# add_header X-XSS-Protection "1; mode=block";
# add_header X-Content-Type-Options "nosniff";
# External Javascript (such as cast_sender.js for Chromecast) must be whitelisted.
add_header Content-Security-Policy "default-src https: data: blob: http://image.tmdb.org; style-src 'self' 'unsafe-inline' https://gcore.jsdelivr.net/gh/prayag17/JellyFlix@latest/default.css https://gcore.jsdelivr.net/gh/prayag17/JellyFlix@latest/addons/Logo.css https://gcore.jsdelivr.net/gh/prayag17/JellySkin/default.css https://gcore.jsdelivr.net/gh/prayag17/JellySkin/addons/Logo.css https://gcore.jsdelivr.net/gh/prayag17/JellySkin/addons/imp-per.css https://gcore.jsdelivr.net/gh/prayag17/JellySkin/addons/compact-poster.css https://gcore.jsdelivr.net/gh/prayag17/JellySkin/addons/progress-bar.css; script-src 'self' 'unsafe-inline' https://www.gstatic.com/cv/js/sender/v1/cast_sender.js https://www.gstatic.com/eureka/clank/95/cast_sender.js https://www.gstatic.com/eureka/clank/96/cast_sender.js https://www.gstatic.com/eureka/clank/97/cast_sender.js https://www.youtube.com blob:; worker-src 'self' blob:; connect-src 'self'; object-src 'none'; frame-ancestors 'self'";
# aliDrive direct stream need no-referrer
add_header 'Referrer-Policy' 'no-referrer';
set $emby http://172.17.0.1:8096; #emby/jellyfin address
# Proxy sockets traffic for jellyfin-mpv-shim and webClient
location ~ /(socket|embywebsocket) {
# Proxy emby/jellyfin Websockets traffic
proxy_pass $emby;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Protocol $scheme;
proxy_set_header X-Forwarded-Host $http_host;
}
# Redirect the stream to njs
location ~* /videos/(.*)/stream {
js_content emby2Pan.redirect2Pan;
}
# for webClient download ,android is SyncService api
location ~* /Items/(.*)/Download {
js_content emby2Pan.redirect2Pan;
}
# Cache the Subtitles
location ~* /videos/(.*)/Subtitles {
proxy_pass $emby;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Protocol $scheme;
proxy_set_header X-Forwarded-Host $http_host;
proxy_cache embysubs;
proxy_cache_revalidate on;
proxy_cache_lock_timeout 10s;
proxy_cache_lock on;
proxy_cache_valid 200 30d;
proxy_cache_key $proxy_host$uri;
# add_header X-Cache-Status $upstream_cache_status; # This is only to check if cache is working
}
# Cache the images
location ~ /Items/(.*)/Images {
proxy_pass $emby;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Protocol $scheme;
proxy_set_header X-Forwarded-Host $http_host;
proxy_cache emby;
proxy_cache_revalidate on;
proxy_cache_lock_timeout 10s;
proxy_cache_lock on;
# add_header X-Cache-Status $upstream_cache_status; # This is only to check if cache is working
}
location / {
# Proxy main emby/jellyfin traffic
proxy_pass $emby;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Protocol $scheme;
proxy_set_header X-Forwarded-Host $http_host;
# Disable buffering when the nginx proxy gets very resource heavy upon streaming
proxy_buffering off;
}
} nginx/conf.d/emby.js 0000777 0001750 0001750 00000012706 14245400221 012435 0 ustar hj hj //查看日志: "docker logs -f -n 10 emby-nginx 2>&1 | grep js:"
async function redirect2Pan(r) {
//根据实际情况修改下面4个设置
const embyHost = 'http://172.17.0.1:8096'; //这里默认emby/jellyfin的地址是宿主机,要注意iptables给容器放行端口
const embyMountPath = '/mnt'; // rclone 的挂载目录, 例如将od, gd挂载到/mnt目录下: /mnt/onedrive /mnt/gd ,那么这里 就填写 /mnt
const alistPwd = 'alist'; //alist password
const alistApiPath = 'http://172.17.0.1:5244/api/public/path'; //访问宿主机上5244端口的alist api, 要注意iptables给容 器放行端口
//fetch mount emby/jellyfin file path
const regex = /[A-Za-z0-9]+/g;
const itemId = r.uri.replace('emby', '').replace(/-/g, '').match(regex)[1];
const mediaSourceId = r.args.MediaSourceId;
let api_key = r.args.api_key;
//infuse用户需要填写下面的api_key, 感谢@amwamw968
if ((api_key === null) || (api_key === undefined)) {
api_key = 'b49f7dbdb788483ca1f4fa12edf05cfc';//这里填自己的emby/jellyfin API KEY
r.warn(`api key for Infuse: ${api_key}`);
}
const itemInfoUri = `${embyHost}/Items/${itemId}/PlaybackInfo?MediaSourceId=${mediaSourceId}&api_key=${api_key}`;
r.warn(`itemInfoUri: ${itemInfoUri}`);
const embyRes = await fetchEmbyFilePath(itemInfoUri);
if (embyRes.startsWith('error')) {
r.error(embyRes);
r.return(500, embyRes);
return;
}
r.warn(`mount emby file path: ${embyRes}`);
//fetch alist direct link
const alistFilePath = embyRes.replace(embyMountPath, '');
const alistRes = await fetchAlistPathApi(alistApiPath, alistFilePath, alistPwd);
if (!alistRes.startsWith('error')) {
r.warn(`redirect to: ${alistRes}`);
r.return(302, alistRes);
return;
}
if (alistRes.startsWith('error401')) {
r.error(alistRes);
r.return(401, alistRes);
return;
}
if (alistRes.startsWith('error404')) {
const filePath = alistFilePath.substring(alistFilePath.indexOf('/', 1));
const foldersRes = await fetchAlistPathApi(alistApiPath, '/', alistPwd);
if (foldersRes.startsWith('error')) {
r.error(foldersRes);
r.return(500, foldersRes);
return;
}
const folders = foldersRes.split(',').sort();
for (let i = 0; i < folders.length; i++) {
r.warn(`try to fetch alist path from /${folders[i]}${filePath}`);
const driverRes = await fetchAlistPathApi(alistApiPath, `/${folders[i]}${filePath}`, alistPwd);
if (!driverRes.startsWith('error')) {
r.warn(`redirect to: ${driverRes}`);
r.return(302, driverRes);
return;
}
}
r.error(alistRes);
r.return(404, alistRes);
return;
}
r.error(alistRes);
r.return(500, alistRes);
return;
}
async function fetchAlistPathApi(alistApiPath, alistFilePath, alistPwd) {
const alistRequestBody = {
"path": alistFilePath,
"password": alistPwd
}
try {
const response = await ngx.fetch(alistApiPath, {
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=utf-8'
},
max_response_body_size: 65535,
body: JSON.stringify(alistRequestBody)
})
if (response.ok) {
const result = await response.json();
if (result === null || result === undefined) {
return `error: alist_path_api response is null`;
}
if (result.message == 'success') {
if (result.data.type == 'file') {
return result.data.files[0].url;
}
if (result.data.type == 'folder') {
return result.data.files.map(item => item.name).join(',');
}
}
if (result.code == 401) {
return `error401: alist_path_api ${result.message}`;
}
if (result.message.includes('account')) {
return `error404: alist_path_api ${result.code} ${result.message}`;
}
if (result.message == 'file not found' || result.message == 'path not found') {
return `error404: alist_path_api ${result.message}`;
}
return `error: alist_path_api ${result.code} ${result.message}`;
}
else {
return `error: alist_path_api ${response.status} ${response.statusText}`;
}
} catch (error) {
return (`error: alist_path_api fetchAlistFiled ${error}`);
}
}
async function fetchEmbyFilePath(itemInfoUri) {
try {
const res = await ngx.fetch(itemInfoUri, {
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=utf-8',
'Content-Length': 0,
},
max_response_body_size: 65535,
});
if (res.ok) {
const result = await res.json();
if (result === null || result === undefined) {
return `error: emby_api itemInfoUri response is null`;
}
return result.MediaSources[0].Path;
}
else {
return (`error: emby_api ${res.status} ${res.statusText}`);
}
}
catch (error) {
return (`error: emby_api fetch mediaItemInfo failed, ${error}`);
}
}
export default { redirect2Pan }; nginx/nginx.conf 0000777 0001750 0001750 00000001362 14167514627 012005 0 ustar hj hj load_module modules/ngx_http_js_module.so;
#load_module modules/ngx_stream_js_module.so; # don't need this
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
} docker-compose.yml 0000777 0001750 0001750 00000001603 14237464533 012321 0 ustar hj hj version: '3.5'
services:
service.nginx:
image: nginx:alpine
container_name: emby-nginx
ports:
- 8095:80
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/conf.d:/etc/nginx/conf.d
- ./nginx/embyCache:/var/cache/nginx/emby
restart: always
depends_on:
- service.ali
service.ali:
image: xhofe/alist:v2
container_name: alist
ports:
- 5244:5244
volumes:
- ./alist:/opt/alist/data
restart: always
service.ali-webdav:
image: messense/aliyundrive-webdav
container_name: ali-webdav
ports:
- 8080:8080
volumes:
- ./aliyundrive-webdav/:/etc/aliyundrive-webdav/
environment:
- REFRESH_TOKEN=1111111111111aaaaaaaaaa
- WEBDAV_AUTH_USER=admin
- WEBDAV_AUTH_PASSWORD=admin
restart: always