mirror of
https://github.com/jeffvli/feishin.git
synced 2026-08-08 05:12:57 +02:00
fd9380a149
* Adds Top Rating option songs to Artist's favorite songs section
1134 lines
35 KiB
TypeScript
1134 lines
35 KiB
TypeScript
import i18n from '/@/i18n/i18n';
|
|
import { JellyfinController } from '/@/renderer/api/jellyfin/jellyfin-controller';
|
|
import { NavidromeController } from '/@/renderer/api/navidrome/navidrome-controller';
|
|
import { SubsonicController } from '/@/renderer/api/subsonic/subsonic-controller';
|
|
import { mergeMusicFolderId } from '/@/renderer/api/utils-music-folder';
|
|
import { getServerById, useAuthStore, useSettingsStore } from '/@/renderer/store';
|
|
import { logger } from '/@/renderer/utils/logger';
|
|
import { toast } from '/@/shared/components/toast/toast';
|
|
import {
|
|
AuthenticationResponse,
|
|
ControllerEndpoint,
|
|
InternalControllerEndpoint,
|
|
ServerType,
|
|
SetPlaylistSongsArgs,
|
|
SetPlaylistSongsResponse,
|
|
} from '/@/shared/types/domain-types';
|
|
|
|
type ApiController = {
|
|
jellyfin: InternalControllerEndpoint;
|
|
navidrome: InternalControllerEndpoint;
|
|
subsonic: InternalControllerEndpoint;
|
|
};
|
|
|
|
const endpoints: ApiController = {
|
|
jellyfin: JellyfinController,
|
|
navidrome: NavidromeController,
|
|
subsonic: SubsonicController,
|
|
};
|
|
|
|
const SENSITIVE_KEY_PATTERN = /password|token|credential|authorization|secret|cookie/i;
|
|
const MAX_ARRAY_ITEMS = 20;
|
|
const MAX_STRING_LENGTH = 200;
|
|
|
|
const sanitizeValue = (value: unknown, depth = 0): unknown => {
|
|
if (value === null || value === undefined) {
|
|
return value;
|
|
}
|
|
|
|
if (typeof value === 'string') {
|
|
return value.length > MAX_STRING_LENGTH
|
|
? `${value.slice(0, MAX_STRING_LENGTH)}…(${value.length})`
|
|
: value;
|
|
}
|
|
|
|
if (typeof value !== 'object') {
|
|
return value;
|
|
}
|
|
|
|
if (depth >= 4) {
|
|
return '[Truncated]';
|
|
}
|
|
|
|
if (Array.isArray(value)) {
|
|
const items = value.slice(0, MAX_ARRAY_ITEMS).map((item) => sanitizeValue(item, depth + 1));
|
|
if (value.length > MAX_ARRAY_ITEMS) {
|
|
items.push(`…(+${value.length - MAX_ARRAY_ITEMS} more)`);
|
|
}
|
|
return items;
|
|
}
|
|
|
|
const result: Record<string, unknown> = {};
|
|
for (const [key, nested] of Object.entries(value as Record<string, unknown>)) {
|
|
if (SENSITIVE_KEY_PATTERN.test(key)) {
|
|
result[key] = '[Redacted]';
|
|
continue;
|
|
}
|
|
result[key] = sanitizeValue(nested, depth + 1);
|
|
}
|
|
return result;
|
|
};
|
|
|
|
const OMITTED_CONTROLLER_ARG_KEYS = new Set([
|
|
'apiClientProps',
|
|
'body',
|
|
'context',
|
|
'query',
|
|
'signal',
|
|
]);
|
|
|
|
const sanitizeControllerArgs = (endpoint: string, args: unknown[]): unknown => {
|
|
if (endpoint === 'authenticate') {
|
|
const [url] = args;
|
|
return { url: typeof url === 'string' ? url : undefined };
|
|
}
|
|
|
|
const first = args[0];
|
|
if (!first || typeof first !== 'object') {
|
|
return args.length === 0 ? undefined : sanitizeValue(args);
|
|
}
|
|
|
|
const input = first as Record<string, unknown>;
|
|
const sanitized: Record<string, unknown> = {};
|
|
|
|
if (input.query !== undefined) {
|
|
sanitized.query = sanitizeValue(input.query);
|
|
}
|
|
|
|
if (input.body !== undefined) {
|
|
sanitized.body = sanitizeValue(input.body);
|
|
}
|
|
|
|
for (const [key, value] of Object.entries(input)) {
|
|
if (OMITTED_CONTROLLER_ARG_KEYS.has(key)) {
|
|
continue;
|
|
}
|
|
sanitized[key] = sanitizeValue(value);
|
|
}
|
|
|
|
return sanitized;
|
|
};
|
|
|
|
const OMITTED_CONTROLLER_LOG_ENDPOINTS = new Set<keyof ControllerEndpoint>([
|
|
'getDownloadUrl',
|
|
'getImageRequest',
|
|
'getImageUrl',
|
|
'getStreamUrl',
|
|
]);
|
|
|
|
const apiController = <K extends keyof ControllerEndpoint>(
|
|
endpoint: K,
|
|
type?: ServerType,
|
|
): NonNullable<InternalControllerEndpoint[K]> => {
|
|
const serverType = type || useAuthStore.getState().currentServer?.type;
|
|
|
|
if (!serverType) {
|
|
toast.error({
|
|
message: i18n.t('error.serverNotSelectedError') as string,
|
|
title: i18n.t('error.apiRouteError') as string,
|
|
});
|
|
|
|
logger.error('No server selected', {
|
|
serverType,
|
|
});
|
|
throw new Error(`No server selected`);
|
|
}
|
|
|
|
const controllerFn = endpoints?.[serverType]?.[endpoint];
|
|
|
|
if (typeof controllerFn !== 'function') {
|
|
logger.error(`Endpoint ${endpoint} is not implemented for ${serverType}`, {
|
|
endpoint,
|
|
serverType,
|
|
});
|
|
|
|
throw new Error(
|
|
i18n.t('error.endpointNotImplementedError', {
|
|
endpoint,
|
|
serverType,
|
|
}) as string,
|
|
);
|
|
}
|
|
|
|
if (OMITTED_CONTROLLER_LOG_ENDPOINTS.has(endpoint)) {
|
|
return controllerFn;
|
|
}
|
|
|
|
return ((...args: unknown[]) => {
|
|
const started = performance.now();
|
|
const serverId = (args[0] as undefined | { apiClientProps?: { serverId?: string } })
|
|
?.apiClientProps?.serverId;
|
|
|
|
const logResult = (error?: unknown, value?: unknown) => {
|
|
logger.debug(`Controller ${String(endpoint)}${error != null ? ' failed' : ''}`, {
|
|
args: sanitizeControllerArgs(String(endpoint), args),
|
|
durationMs: Math.round(performance.now() - started),
|
|
serverId,
|
|
serverType,
|
|
...(error != null
|
|
? { error: error instanceof Error ? error.message : String(error) }
|
|
: { result: sanitizeValue(value) }),
|
|
});
|
|
};
|
|
|
|
try {
|
|
const result = (controllerFn as (...a: unknown[]) => unknown)(...args);
|
|
if (result instanceof Promise) {
|
|
return result.then(
|
|
(value) => {
|
|
logResult(undefined, value);
|
|
return value;
|
|
},
|
|
(error) => {
|
|
logResult(error);
|
|
throw error;
|
|
},
|
|
);
|
|
}
|
|
logResult(undefined, result);
|
|
return result;
|
|
} catch (error) {
|
|
logResult(error);
|
|
throw error;
|
|
}
|
|
}) as NonNullable<InternalControllerEndpoint[K]>;
|
|
};
|
|
|
|
const getPathReplaceSettings = () => {
|
|
const { pathReplace, pathReplaceWith } = useSettingsStore.getState().general;
|
|
return { pathReplace, pathReplaceWith };
|
|
};
|
|
|
|
const addContext = <T extends { apiClientProps: any; context?: any }>(args: T): T => {
|
|
const pathSettings = getPathReplaceSettings();
|
|
|
|
return {
|
|
...args,
|
|
context: {
|
|
...(args.context || {}),
|
|
...pathSettings,
|
|
},
|
|
};
|
|
};
|
|
|
|
export interface GeneralController extends Omit<Required<ControllerEndpoint>, 'authenticate'> {
|
|
authenticate: (
|
|
url: string,
|
|
body: { legacy?: boolean; password: string; username: string },
|
|
type: ServerType,
|
|
) => Promise<AuthenticationResponse>;
|
|
}
|
|
|
|
export const controller: GeneralController = {
|
|
addToPlaylist(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: addToPlaylist`);
|
|
}
|
|
|
|
return apiController(
|
|
'addToPlaylist',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
authenticate(url, body, type) {
|
|
return apiController('authenticate', type)(url, body);
|
|
},
|
|
createFavorite(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: createFavorite`);
|
|
}
|
|
|
|
return apiController(
|
|
'createFavorite',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
createInternetRadioStation(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: createInternetRadioStation`);
|
|
}
|
|
|
|
return apiController(
|
|
'createInternetRadioStation',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
createPlaylist(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: createPlaylist`);
|
|
}
|
|
|
|
return apiController(
|
|
'createPlaylist',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
deleteArtistImage(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: deleteArtistImage`);
|
|
}
|
|
|
|
return apiController(
|
|
'deleteArtistImage',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
deleteFavorite(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: deleteFavorite`);
|
|
}
|
|
|
|
return apiController(
|
|
'deleteFavorite',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
deleteInternetRadioStation(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: deleteInternetRadioStation`);
|
|
}
|
|
|
|
return apiController(
|
|
'deleteInternetRadioStation',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
deleteInternetRadioStationImage(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: deleteInternetRadioStationImage`);
|
|
}
|
|
|
|
return apiController(
|
|
'deleteInternetRadioStationImage',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
deletePlaylist(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: deletePlaylist`);
|
|
}
|
|
|
|
return apiController(
|
|
'deletePlaylist',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
deletePlaylistImage(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: deletePlaylistImage`);
|
|
}
|
|
|
|
return apiController(
|
|
'deletePlaylistImage',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
getAlbumArtistDetail(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: getAlbumArtistDetail`);
|
|
}
|
|
|
|
return apiController(
|
|
'getAlbumArtistDetail',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
getAlbumArtistInfo(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
return Promise.resolve(null);
|
|
}
|
|
|
|
const fn = apiController('getAlbumArtistInfo', server.type);
|
|
return fn
|
|
? fn(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }))
|
|
: Promise.resolve(null);
|
|
},
|
|
getAlbumArtistList(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: getAlbumArtistList`);
|
|
}
|
|
|
|
return apiController(
|
|
'getAlbumArtistList',
|
|
server.type,
|
|
)?.(
|
|
addContext({
|
|
...args,
|
|
apiClientProps: { ...args.apiClientProps, server },
|
|
query: mergeMusicFolderId(args.query, server),
|
|
}),
|
|
);
|
|
},
|
|
getAlbumArtistListCount(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: getAlbumArtistListCount`);
|
|
}
|
|
|
|
return apiController(
|
|
'getAlbumArtistListCount',
|
|
server.type,
|
|
)?.(
|
|
addContext({
|
|
...args,
|
|
apiClientProps: { ...args.apiClientProps, server },
|
|
query: mergeMusicFolderId(args.query, server),
|
|
}),
|
|
);
|
|
},
|
|
getAlbumDetail(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: getAlbumDetail`);
|
|
}
|
|
|
|
return apiController(
|
|
'getAlbumDetail',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
getAlbumInfo(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: getAlbumInfo`);
|
|
}
|
|
|
|
return apiController(
|
|
'getAlbumInfo',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
getAlbumList(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: getAlbumList`);
|
|
}
|
|
|
|
return apiController(
|
|
'getAlbumList',
|
|
server.type,
|
|
)?.(
|
|
addContext({
|
|
...args,
|
|
apiClientProps: { ...args.apiClientProps, server },
|
|
query: mergeMusicFolderId(args.query, server),
|
|
}),
|
|
);
|
|
},
|
|
getAlbumListCount(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: getAlbumListCount`);
|
|
}
|
|
|
|
return apiController(
|
|
'getAlbumListCount',
|
|
server.type,
|
|
)?.(
|
|
addContext({
|
|
...args,
|
|
apiClientProps: { ...args.apiClientProps, server },
|
|
query: mergeMusicFolderId(args.query, server),
|
|
}),
|
|
);
|
|
},
|
|
getAlbumRadio(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: getAlbumRadio`);
|
|
}
|
|
|
|
return apiController(
|
|
'getAlbumRadio',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
getArtistList(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: getArtistList`);
|
|
}
|
|
|
|
return apiController(
|
|
'getArtistList',
|
|
server.type,
|
|
)?.(
|
|
addContext({
|
|
...args,
|
|
apiClientProps: { ...args.apiClientProps, server },
|
|
query: mergeMusicFolderId(args.query, server),
|
|
}),
|
|
);
|
|
},
|
|
getArtistListCount(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: getArtistListCount`);
|
|
}
|
|
|
|
return apiController(
|
|
'getArtistListCount',
|
|
server.type,
|
|
)?.(
|
|
addContext({
|
|
...args,
|
|
apiClientProps: { ...args.apiClientProps, server },
|
|
query: mergeMusicFolderId(args.query, server),
|
|
}),
|
|
);
|
|
},
|
|
getArtistRadio(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: getArtistRadio`);
|
|
}
|
|
|
|
return apiController(
|
|
'getArtistRadio',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
getDownloadUrl(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: getDownloadUrl`);
|
|
}
|
|
|
|
return apiController(
|
|
'getDownloadUrl',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
getFavoriteSongs(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: getFavoriteSongs`);
|
|
}
|
|
|
|
return apiController(
|
|
'getFavoriteSongs',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
getFolder(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: getFolder`);
|
|
}
|
|
|
|
return apiController(
|
|
'getFolder',
|
|
server.type,
|
|
)?.(
|
|
addContext({
|
|
...args,
|
|
apiClientProps: { ...args.apiClientProps, server },
|
|
query: mergeMusicFolderId(args.query, server),
|
|
}),
|
|
);
|
|
},
|
|
getGenreList(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: getGenreList`);
|
|
}
|
|
|
|
return apiController(
|
|
'getGenreList',
|
|
server.type,
|
|
)?.(
|
|
addContext({
|
|
...args,
|
|
apiClientProps: { ...args.apiClientProps, server },
|
|
query: mergeMusicFolderId(args.query, server),
|
|
}),
|
|
);
|
|
},
|
|
getImageRequest(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
apiController(
|
|
'getImageRequest',
|
|
server.type,
|
|
)?.(
|
|
addContext({
|
|
...args,
|
|
apiClientProps: { ...args.apiClientProps, server },
|
|
}),
|
|
) || null
|
|
);
|
|
},
|
|
getImageUrl(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
apiController(
|
|
'getImageUrl',
|
|
server.type,
|
|
)?.(
|
|
addContext({
|
|
...args,
|
|
apiClientProps: { ...args.apiClientProps, server },
|
|
}),
|
|
) || null
|
|
);
|
|
},
|
|
getInternetRadioStations(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: getInternetRadioStations`);
|
|
}
|
|
return apiController(
|
|
'getInternetRadioStations',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
getLyrics(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: getLyrics`);
|
|
}
|
|
|
|
return apiController(
|
|
'getLyrics',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
getMusicFolderList(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: getMusicFolderList`);
|
|
}
|
|
|
|
return apiController(
|
|
'getMusicFolderList',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
getPlaylistDetail(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: getPlaylistDetail`);
|
|
}
|
|
|
|
return apiController(
|
|
'getPlaylistDetail',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
getPlaylistList(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: getPlaylistList`);
|
|
}
|
|
|
|
return apiController(
|
|
'getPlaylistList',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
getPlaylistListCount(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: getPlaylistListCount`);
|
|
}
|
|
|
|
return apiController(
|
|
'getPlaylistListCount',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
getPlaylistSongIds(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: getPlaylistSongIds`);
|
|
}
|
|
|
|
return apiController(
|
|
'getPlaylistSongIds',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
getPlaylistSongList(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: getPlaylistSongList`);
|
|
}
|
|
|
|
return apiController(
|
|
'getPlaylistSongList',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
getPlayQueue(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: getPlayQueue`);
|
|
}
|
|
|
|
return apiController(
|
|
'getPlayQueue',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
getRandomSongList(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: getRandomSongList`);
|
|
}
|
|
|
|
return apiController(
|
|
'getRandomSongList',
|
|
server.type,
|
|
)?.(
|
|
addContext({
|
|
...args,
|
|
apiClientProps: { ...args.apiClientProps, server },
|
|
query: mergeMusicFolderId(args.query, server),
|
|
}),
|
|
);
|
|
},
|
|
getRoles(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: getRoles`);
|
|
}
|
|
|
|
return apiController(
|
|
'getRoles',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
getScanStatus(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: getScanStatus`);
|
|
}
|
|
|
|
return apiController(
|
|
'getScanStatus',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
getServerInfo(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: getServerInfo`);
|
|
}
|
|
|
|
return apiController(
|
|
'getServerInfo',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
getSimilarSongs(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: getSimilarSongs`);
|
|
}
|
|
|
|
return apiController(
|
|
'getSimilarSongs',
|
|
server.type,
|
|
)?.(
|
|
addContext({
|
|
...args,
|
|
apiClientProps: { ...args.apiClientProps, server },
|
|
query: mergeMusicFolderId(args.query, server),
|
|
}),
|
|
);
|
|
},
|
|
getSongDetail(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: getSongDetail`);
|
|
}
|
|
|
|
return apiController(
|
|
'getSongDetail',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
getSongList(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: getSongList`);
|
|
}
|
|
|
|
return apiController(
|
|
'getSongList',
|
|
server.type,
|
|
)?.(
|
|
addContext({
|
|
...args,
|
|
apiClientProps: { ...args.apiClientProps, server },
|
|
query: mergeMusicFolderId(args.query, server),
|
|
}),
|
|
);
|
|
},
|
|
getSongListCount(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: getSongListCount`);
|
|
}
|
|
|
|
return apiController(
|
|
'getSongListCount',
|
|
server.type,
|
|
)?.(
|
|
addContext({
|
|
...args,
|
|
apiClientProps: { ...args.apiClientProps, server },
|
|
query: mergeMusicFolderId(args.query, server),
|
|
}),
|
|
);
|
|
},
|
|
getStreamUrl(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: getStreamUrl`);
|
|
}
|
|
|
|
return apiController(
|
|
'getStreamUrl',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
getStructuredLyrics(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: getStructuredLyrics`);
|
|
}
|
|
|
|
return apiController(
|
|
'getStructuredLyrics',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
getTagList(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: getTags`);
|
|
}
|
|
|
|
return apiController(
|
|
'getTagList',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
getTopSongs(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: getTopSongs`);
|
|
}
|
|
|
|
return apiController(
|
|
'getTopSongs',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
getUserInfo(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: getUserInfo`);
|
|
}
|
|
|
|
return apiController(
|
|
'getUserInfo',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
getUserList(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: getUserList`);
|
|
}
|
|
|
|
return apiController(
|
|
'getUserList',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
jukeboxControl(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: jukeboxControl`);
|
|
}
|
|
|
|
const fn = apiController('jukeboxControl', server.type);
|
|
return fn
|
|
? fn(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }))
|
|
: Promise.resolve(null);
|
|
},
|
|
movePlaylistItem(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: movePlaylistItem`);
|
|
}
|
|
|
|
return apiController(
|
|
'movePlaylistItem',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
refreshItems(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: refreshItems`);
|
|
}
|
|
|
|
return apiController(
|
|
'refreshItems',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
removeFromPlaylist(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: removeFromPlaylist`);
|
|
}
|
|
|
|
return apiController(
|
|
'removeFromPlaylist',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
replacePlaylist(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: replacePlaylist`);
|
|
}
|
|
|
|
return apiController(
|
|
'replacePlaylist',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
savePlayQueue(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: savePlayQueue`);
|
|
}
|
|
|
|
return apiController(
|
|
'savePlayQueue',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
scrobble(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: scrobble`);
|
|
}
|
|
|
|
return apiController(
|
|
'scrobble',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
search(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: search`);
|
|
}
|
|
|
|
return apiController(
|
|
'search',
|
|
server.type,
|
|
)?.(
|
|
addContext({
|
|
...args,
|
|
apiClientProps: { ...args.apiClientProps, server },
|
|
query: mergeMusicFolderId(args.query, server),
|
|
}),
|
|
);
|
|
},
|
|
setPlaylistSongs: function (args: SetPlaylistSongsArgs): Promise<SetPlaylistSongsResponse> {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: setPlaylistSongs`);
|
|
}
|
|
|
|
return apiController(
|
|
'setPlaylistSongs',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
setRating(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: setRating`);
|
|
}
|
|
|
|
return apiController(
|
|
'setRating',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
shareItem(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: shareItem`);
|
|
}
|
|
|
|
return apiController(
|
|
'shareItem',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
startLibraryScan(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: startLibraryScan`);
|
|
}
|
|
|
|
return apiController(
|
|
'startLibraryScan',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
updateInternetRadioStation(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: updateInternetRadioStation`);
|
|
}
|
|
|
|
return apiController(
|
|
'updateInternetRadioStation',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
updatePlaylist(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: updatePlaylist`);
|
|
}
|
|
|
|
return apiController(
|
|
'updatePlaylist',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
uploadArtistImage(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: uploadArtistImage`);
|
|
}
|
|
|
|
return apiController(
|
|
'uploadArtistImage',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
uploadInternetRadioStationImage(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: uploadInternetRadioStationImage`);
|
|
}
|
|
|
|
return apiController(
|
|
'uploadInternetRadioStationImage',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
uploadPlaylistImage(args) {
|
|
const server = getServerById(args.apiClientProps.serverId);
|
|
|
|
if (!server) {
|
|
throw new Error(`${i18n.t('error.apiRouteError')}: uploadPlaylistImage`);
|
|
}
|
|
|
|
return apiController(
|
|
'uploadPlaylistImage',
|
|
server.type,
|
|
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
|
},
|
|
};
|