emby增加自定义ua和图片代理
This commit is contained in:
@@ -201,6 +201,7 @@ export interface AdminConfig {
|
||||
appendMediaSourceId?: boolean; // 拼接MediaSourceId参数
|
||||
transcodeMp4?: boolean; // 转码mp4
|
||||
proxyPlay?: boolean; // 视频播放代理开关
|
||||
customUserAgent?: string; // 自定义User-Agent
|
||||
}>;
|
||||
// 旧格式:单源配置(向后兼容)
|
||||
Enabled?: boolean;
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import { NextRequest } from 'next/server';
|
||||
import { getAuthInfoFromCookie } from './auth';
|
||||
|
||||
/**
|
||||
* 获取用于代理的 token
|
||||
* 优先级:全局 token > 用户 token > null
|
||||
*/
|
||||
export async function getProxyToken(request?: NextRequest): Promise<string | null> {
|
||||
// 1. 尝试获取全局 token
|
||||
const globalToken = process.env.TVBOX_SUBSCRIBE_TOKEN;
|
||||
if (globalToken) {
|
||||
return globalToken;
|
||||
}
|
||||
|
||||
// 2. 如果提供了 request,尝试从用户登录信息获取用户的 tvbox token
|
||||
if (request) {
|
||||
const authInfo = getAuthInfoFromCookie(request);
|
||||
if (authInfo && authInfo.username) {
|
||||
try {
|
||||
const { db } = await import('./db');
|
||||
const userInfo = await db.getUserInfoV2(authInfo.username);
|
||||
if (userInfo && userInfo.tvboxToken && !userInfo.banned) {
|
||||
return userInfo.tvboxToken;
|
||||
}
|
||||
} catch (error) {
|
||||
// 忽略错误,继续
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 没有可用的 token
|
||||
return null;
|
||||
}
|
||||
+26
-1
@@ -12,6 +12,7 @@ interface EmbyConfig {
|
||||
appendMediaSourceId?: boolean;
|
||||
transcodeMp4?: boolean;
|
||||
proxyPlay?: boolean; // 视频播放代理开关
|
||||
customUserAgent?: string; // 自定义User-Agent
|
||||
key?: string; // Emby源的唯一标识
|
||||
}
|
||||
|
||||
@@ -75,6 +76,7 @@ export class EmbyClient {
|
||||
private transcodeMp4: boolean;
|
||||
private proxyPlay: boolean;
|
||||
private embyKey?: string;
|
||||
private customUserAgent: string;
|
||||
|
||||
constructor(config: EmbyConfig) {
|
||||
let serverUrl = config.ServerURL.replace(/\/$/, '');
|
||||
@@ -85,6 +87,8 @@ export class EmbyClient {
|
||||
this.transcodeMp4 = config.transcodeMp4 || false;
|
||||
this.proxyPlay = config.proxyPlay || false;
|
||||
this.embyKey = config.key;
|
||||
// 设置自定义UA,如果没有设置则使用默认浏览器UA
|
||||
this.customUserAgent = config.customUserAgent || 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36';
|
||||
|
||||
// 如果 URL 不包含 /emby 路径,自动添加(除非启用了 removeEmbyPrefix)
|
||||
if (!serverUrl.endsWith('/emby') && !this.removeEmbyPrefix) {
|
||||
@@ -122,6 +126,7 @@ export class EmbyClient {
|
||||
private getHeaders(): Record<string, string> {
|
||||
const headers: Record<string, string> = {
|
||||
'Content-Type': 'application/json',
|
||||
'User-Agent': this.customUserAgent,
|
||||
};
|
||||
|
||||
if (this.apiKey) {
|
||||
@@ -146,6 +151,7 @@ export class EmbyClient {
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
'X-Emby-Authorization': 'MediaBrowser Client="LunaTV", Device="Web", DeviceId="lunatv-web", Version="1.0.0"',
|
||||
'User-Agent': this.customUserAgent,
|
||||
},
|
||||
body: params.toString(),
|
||||
});
|
||||
@@ -420,7 +426,18 @@ export class EmbyClient {
|
||||
}
|
||||
}
|
||||
|
||||
getImageUrl(itemId: string, imageType: 'Primary' | 'Backdrop' | 'Logo' = 'Primary', maxWidth?: number): string {
|
||||
getImageUrl(itemId: string, imageType: 'Primary' | 'Backdrop' | 'Logo' = 'Primary', maxWidth?: number, proxyToken?: string): string {
|
||||
// 如果启用了代理播放且提供了 token,返回代理 URL
|
||||
if (this.proxyPlay && proxyToken) {
|
||||
const params = new URLSearchParams();
|
||||
params.set('imageType', imageType);
|
||||
if (maxWidth) params.set('maxWidth', maxWidth.toString());
|
||||
if (this.embyKey) params.set('embyKey', this.embyKey);
|
||||
|
||||
return `/api/emby/image/${proxyToken}/${itemId}?${params.toString()}`;
|
||||
}
|
||||
|
||||
// 否则返回直连 URL
|
||||
const params = new URLSearchParams();
|
||||
const token = this.apiKey || this.authToken;
|
||||
|
||||
@@ -551,4 +568,12 @@ export class EmbyClient {
|
||||
|
||||
return subtitles;
|
||||
}
|
||||
|
||||
getUserAgent(): string {
|
||||
return this.customUserAgent;
|
||||
}
|
||||
|
||||
isProxyEnabled(): boolean {
|
||||
return this.proxyPlay;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,8 @@ import { SearchResult } from '@/lib/types';
|
||||
*/
|
||||
export async function getEmbyDetail(
|
||||
source: string,
|
||||
id: string
|
||||
id: string,
|
||||
proxyToken?: string | null
|
||||
): Promise<SearchResult> {
|
||||
const config = await getConfig();
|
||||
|
||||
@@ -44,7 +45,7 @@ export async function getEmbyDetail(
|
||||
source_name: sourceName,
|
||||
id: item.Id,
|
||||
title: item.Name,
|
||||
poster: client.getImageUrl(item.Id, 'Primary'),
|
||||
poster: client.getImageUrl(item.Id, 'Primary', undefined, client.isProxyEnabled() ? proxyToken || undefined : undefined),
|
||||
year: item.ProductionYear?.toString() || '',
|
||||
douban_id: 0,
|
||||
desc: item.Overview || '',
|
||||
@@ -76,7 +77,7 @@ export async function getEmbyDetail(
|
||||
source_name: sourceName,
|
||||
id: item.Id,
|
||||
title: item.Name,
|
||||
poster: client.getImageUrl(item.Id, 'Primary'),
|
||||
poster: client.getImageUrl(item.Id, 'Primary', undefined, client.isProxyEnabled() ? proxyToken || undefined : undefined),
|
||||
year: item.ProductionYear?.toString() || '',
|
||||
douban_id: 0,
|
||||
desc: item.Overview || '',
|
||||
|
||||
Reference in New Issue
Block a user