Files
MoonTVPlus/src/lib/emby-manager.ts
T
2026-01-23 16:41:49 +08:00

193 lines
5.1 KiB
TypeScript

/* eslint-disable @typescript-eslint/no-explicit-any */
import { AdminConfig } from './admin.types';
import { getConfig } from './config';
import { EmbyClient } from './emby.client';
interface EmbySourceConfig {
key: string;
name: string;
enabled: boolean;
ServerURL: string;
ApiKey?: string;
Username?: string;
Password?: string;
UserId?: string;
AuthToken?: string;
Libraries?: string[];
LastSyncTime?: number;
ItemCount?: number;
isDefault?: boolean;
// 高级流媒体选项
removeEmbyPrefix?: boolean;
appendMediaSourceId?: boolean;
transcodeMp4?: boolean;
proxyPlay?: boolean; // 视频播放代理开关
}
class EmbyManager {
private static instance: EmbyManager;
private clients: Map<string, EmbyClient> = new Map();
private constructor() {}
static getInstance(): EmbyManager {
if (!EmbyManager.instance) {
EmbyManager.instance = new EmbyManager();
}
return EmbyManager.instance;
}
/**
* 从配置中获取所有Emby源(支持新旧格式)
*/
private async getSources(): Promise<EmbySourceConfig[]> {
const config = await getConfig();
// 如果是新格式(Sources数组)
if (config.EmbyConfig?.Sources && Array.isArray(config.EmbyConfig.Sources)) {
return config.EmbyConfig.Sources;
}
// 如果是旧格式(单源配置),转换为数组格式
if (config.EmbyConfig?.ServerURL) {
return [{
key: 'default',
name: 'Emby',
enabled: config.EmbyConfig.Enabled ?? false,
ServerURL: config.EmbyConfig.ServerURL,
ApiKey: config.EmbyConfig.ApiKey,
Username: config.EmbyConfig.Username,
Password: config.EmbyConfig.Password,
UserId: config.EmbyConfig.UserId,
AuthToken: config.EmbyConfig.AuthToken,
Libraries: config.EmbyConfig.Libraries,
LastSyncTime: config.EmbyConfig.LastSyncTime,
ItemCount: config.EmbyConfig.ItemCount,
isDefault: true,
}];
}
return [];
}
/**
* 获取指定key的EmbyClient
* @param key Emby源的key,如果不指定则使用默认源
*/
async getClient(key?: string): Promise<EmbyClient> {
const sources = await this.getSources();
if (sources.length === 0) {
throw new Error('未配置 Emby 源');
}
// 如果没有指定key,使用默认源(第一个或标记为default的)
if (!key) {
const defaultSource = sources.find(s => s.isDefault) || sources[0];
key = defaultSource.key;
}
// 从缓存获取或创建新实例
if (!this.clients.has(key)) {
const sourceConfig = sources.find(s => s.key === key);
if (!sourceConfig) {
throw new Error(`未找到 Emby 源: ${key}`);
}
if (!sourceConfig.enabled) {
throw new Error(`Emby 源已禁用: ${sourceConfig.name}`);
}
this.clients.set(key, new EmbyClient(sourceConfig));
}
return this.clients.get(key)!;
}
/**
* 获取所有启用的EmbyClient
*/
async getAllClients(): Promise<Map<string, { client: EmbyClient; config: EmbySourceConfig }>> {
const sources = await this.getSources();
const enabledSources = sources.filter(s => s.enabled);
const result = new Map<string, { client: EmbyClient; config: EmbySourceConfig }>();
for (const source of enabledSources) {
if (!this.clients.has(source.key)) {
this.clients.set(source.key, new EmbyClient(source));
}
result.set(source.key, {
client: this.clients.get(source.key)!,
config: source,
});
}
return result;
}
/**
* 获取所有启用的Emby源配置
*/
async getEnabledSources(): Promise<EmbySourceConfig[]> {
const sources = await this.getSources();
return sources.filter(s => s.enabled);
}
/**
* 检查是否配置了Emby
*/
async hasEmby(): Promise<boolean> {
const sources = await this.getSources();
return sources.some(s => s.enabled && s.ServerURL);
}
/**
* 清除缓存的客户端实例
*/
clearCache() {
this.clients.clear();
}
}
export const embyManager = EmbyManager.getInstance();
/**
* 配置迁移函数:将旧格式配置迁移到新格式
*/
export function migrateEmbyConfig(config: AdminConfig): AdminConfig {
// 如果已经是新格式,直接返回
if (config.EmbyConfig?.Sources) {
return config;
}
// 如果是旧格式,迁移到新格式
if (config.EmbyConfig && config.EmbyConfig.ServerURL) {
const oldConfig = config.EmbyConfig;
config.EmbyConfig = {
Sources: [{
key: 'default',
name: 'Emby',
enabled: oldConfig.Enabled ?? false,
ServerURL: oldConfig.ServerURL || '',
ApiKey: oldConfig.ApiKey,
Username: oldConfig.Username,
Password: oldConfig.Password,
UserId: oldConfig.UserId,
AuthToken: oldConfig.AuthToken,
Libraries: oldConfig.Libraries,
LastSyncTime: oldConfig.LastSyncTime,
ItemCount: oldConfig.ItemCount,
isDefault: true,
// 高级选项默认值
removeEmbyPrefix: false,
appendMediaSourceId: false,
transcodeMp4: false,
proxyPlay: false,
}],
};
}
return config;
}