mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-07 04:20:12 +02:00
add filepath replacement setting (#1402)
This commit is contained in:
@@ -83,6 +83,7 @@
|
||||
"edit": "edit",
|
||||
"enable": "enable",
|
||||
"expand": "expand",
|
||||
"example": "example",
|
||||
"externalLinks": "external links",
|
||||
"faster": "faster",
|
||||
"favorite": "favorite",
|
||||
@@ -872,6 +873,10 @@
|
||||
"neteaseTranslation": "Enable NetEase translations",
|
||||
"notify": "enable song notifications",
|
||||
"notify_description": "show notifications when changing the current song",
|
||||
"pathReplace": "file path replacement",
|
||||
"pathReplace_description": "replace your server's default filepath",
|
||||
"pathReplace_optionRemovePrefix": "remove prefix",
|
||||
"pathReplace_optionAddPrefix": "add prefix",
|
||||
"passwordStore_description": "what password/secret store to use. change this if you are having issues storing passwords",
|
||||
"passwordStore": "passwords/secret store",
|
||||
"playerFilters": "Filter songs from the queue",
|
||||
|
||||
+152
-105
@@ -3,7 +3,7 @@ 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 } from '/@/renderer/store';
|
||||
import { getServerById, useAuthStore, useSettingsStore } from '/@/renderer/store';
|
||||
import { toast } from '/@/shared/components/toast/toast';
|
||||
import {
|
||||
AuthenticationResponse,
|
||||
@@ -60,6 +60,22 @@ const apiController = <K extends keyof ControllerEndpoint>(
|
||||
return controllerFn;
|
||||
};
|
||||
|
||||
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,
|
||||
@@ -81,7 +97,7 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'addToPlaylist',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
authenticate(url, body, type) {
|
||||
return apiController('authenticate', type)(url, body);
|
||||
@@ -98,7 +114,7 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'createFavorite',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
createInternetRadioStation(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -112,7 +128,7 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'createInternetRadioStation',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
createPlaylist(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -126,7 +142,7 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'createPlaylist',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
deleteFavorite(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -140,7 +156,7 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'deleteFavorite',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
deleteInternetRadioStation(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -154,7 +170,7 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'deleteInternetRadioStation',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
deletePlaylist(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -168,7 +184,7 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'deletePlaylist',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
getAlbumArtistDetail(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -182,7 +198,7 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'getAlbumArtistDetail',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
getAlbumArtistList(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -196,11 +212,13 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'getAlbumArtistList',
|
||||
server.type,
|
||||
)?.({
|
||||
...args,
|
||||
apiClientProps: { ...args.apiClientProps, server },
|
||||
query: mergeMusicFolderId(args.query, server),
|
||||
});
|
||||
)?.(
|
||||
addContext({
|
||||
...args,
|
||||
apiClientProps: { ...args.apiClientProps, server },
|
||||
query: mergeMusicFolderId(args.query, server),
|
||||
}),
|
||||
);
|
||||
},
|
||||
getAlbumArtistListCount(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -214,11 +232,13 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'getAlbumArtistListCount',
|
||||
server.type,
|
||||
)?.({
|
||||
...args,
|
||||
apiClientProps: { ...args.apiClientProps, server },
|
||||
query: mergeMusicFolderId(args.query, server),
|
||||
});
|
||||
)?.(
|
||||
addContext({
|
||||
...args,
|
||||
apiClientProps: { ...args.apiClientProps, server },
|
||||
query: mergeMusicFolderId(args.query, server),
|
||||
}),
|
||||
);
|
||||
},
|
||||
getAlbumDetail(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -232,7 +252,7 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'getAlbumDetail',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
getAlbumInfo(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -246,7 +266,7 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'getAlbumInfo',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
getAlbumList(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -260,11 +280,13 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'getAlbumList',
|
||||
server.type,
|
||||
)?.({
|
||||
...args,
|
||||
apiClientProps: { ...args.apiClientProps, server },
|
||||
query: mergeMusicFolderId(args.query, server),
|
||||
});
|
||||
)?.(
|
||||
addContext({
|
||||
...args,
|
||||
apiClientProps: { ...args.apiClientProps, server },
|
||||
query: mergeMusicFolderId(args.query, server),
|
||||
}),
|
||||
);
|
||||
},
|
||||
getAlbumListCount(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -278,11 +300,13 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'getAlbumListCount',
|
||||
server.type,
|
||||
)?.({
|
||||
...args,
|
||||
apiClientProps: { ...args.apiClientProps, server },
|
||||
query: mergeMusicFolderId(args.query, server),
|
||||
});
|
||||
)?.(
|
||||
addContext({
|
||||
...args,
|
||||
apiClientProps: { ...args.apiClientProps, server },
|
||||
query: mergeMusicFolderId(args.query, server),
|
||||
}),
|
||||
);
|
||||
},
|
||||
getArtistList(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -296,11 +320,13 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'getArtistList',
|
||||
server.type,
|
||||
)?.({
|
||||
...args,
|
||||
apiClientProps: { ...args.apiClientProps, server },
|
||||
query: mergeMusicFolderId(args.query, server),
|
||||
});
|
||||
)?.(
|
||||
addContext({
|
||||
...args,
|
||||
apiClientProps: { ...args.apiClientProps, server },
|
||||
query: mergeMusicFolderId(args.query, server),
|
||||
}),
|
||||
);
|
||||
},
|
||||
getArtistListCount(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -314,11 +340,13 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'getArtistListCount',
|
||||
server.type,
|
||||
)?.({
|
||||
...args,
|
||||
apiClientProps: { ...args.apiClientProps, server },
|
||||
query: mergeMusicFolderId(args.query, server),
|
||||
});
|
||||
)?.(
|
||||
addContext({
|
||||
...args,
|
||||
apiClientProps: { ...args.apiClientProps, server },
|
||||
query: mergeMusicFolderId(args.query, server),
|
||||
}),
|
||||
);
|
||||
},
|
||||
getArtistRadio(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -332,7 +360,7 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'getArtistRadio',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
getDownloadUrl(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -346,7 +374,7 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'getDownloadUrl',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
getFolder(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -360,11 +388,13 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'getFolder',
|
||||
server.type,
|
||||
)?.({
|
||||
...args,
|
||||
apiClientProps: { ...args.apiClientProps, server },
|
||||
query: mergeMusicFolderId(args.query, server),
|
||||
});
|
||||
)?.(
|
||||
addContext({
|
||||
...args,
|
||||
apiClientProps: { ...args.apiClientProps, server },
|
||||
query: mergeMusicFolderId(args.query, server),
|
||||
}),
|
||||
);
|
||||
},
|
||||
getGenreList(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -378,11 +408,13 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'getGenreList',
|
||||
server.type,
|
||||
)?.({
|
||||
...args,
|
||||
apiClientProps: { ...args.apiClientProps, server },
|
||||
query: mergeMusicFolderId(args.query, server),
|
||||
});
|
||||
)?.(
|
||||
addContext({
|
||||
...args,
|
||||
apiClientProps: { ...args.apiClientProps, server },
|
||||
query: mergeMusicFolderId(args.query, server),
|
||||
}),
|
||||
);
|
||||
},
|
||||
getImageUrl(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -395,7 +427,12 @@ export const controller: GeneralController = {
|
||||
apiController(
|
||||
'getImageUrl',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } }) || null
|
||||
)?.(
|
||||
addContext({
|
||||
...args,
|
||||
apiClientProps: { ...args.apiClientProps, server },
|
||||
}),
|
||||
) || null
|
||||
);
|
||||
},
|
||||
getInternetRadioStations(args) {
|
||||
@@ -409,7 +446,7 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'getInternetRadioStations',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
getLyrics(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -423,7 +460,7 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'getLyrics',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
getMusicFolderList(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -437,7 +474,7 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'getMusicFolderList',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
getPlaylistDetail(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -451,7 +488,7 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'getPlaylistDetail',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
getPlaylistList(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -465,7 +502,7 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'getPlaylistList',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
getPlaylistListCount(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -479,7 +516,7 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'getPlaylistListCount',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
getPlaylistSongList(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -493,7 +530,7 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'getPlaylistSongList',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
getPlayQueue(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -507,7 +544,7 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'getPlayQueue',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
getRandomSongList(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -521,11 +558,13 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'getRandomSongList',
|
||||
server.type,
|
||||
)?.({
|
||||
...args,
|
||||
apiClientProps: { ...args.apiClientProps, server },
|
||||
query: mergeMusicFolderId(args.query, server),
|
||||
});
|
||||
)?.(
|
||||
addContext({
|
||||
...args,
|
||||
apiClientProps: { ...args.apiClientProps, server },
|
||||
query: mergeMusicFolderId(args.query, server),
|
||||
}),
|
||||
);
|
||||
},
|
||||
getRoles(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -539,7 +578,7 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'getRoles',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
getServerInfo(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -553,7 +592,7 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'getServerInfo',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
getSimilarSongs(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -567,11 +606,13 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'getSimilarSongs',
|
||||
server.type,
|
||||
)?.({
|
||||
...args,
|
||||
apiClientProps: { ...args.apiClientProps, server },
|
||||
query: mergeMusicFolderId(args.query, server),
|
||||
});
|
||||
)?.(
|
||||
addContext({
|
||||
...args,
|
||||
apiClientProps: { ...args.apiClientProps, server },
|
||||
query: mergeMusicFolderId(args.query, server),
|
||||
}),
|
||||
);
|
||||
},
|
||||
getSongDetail(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -585,7 +626,7 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'getSongDetail',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
getSongList(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -599,11 +640,13 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'getSongList',
|
||||
server.type,
|
||||
)?.({
|
||||
...args,
|
||||
apiClientProps: { ...args.apiClientProps, server },
|
||||
query: mergeMusicFolderId(args.query, server),
|
||||
});
|
||||
)?.(
|
||||
addContext({
|
||||
...args,
|
||||
apiClientProps: { ...args.apiClientProps, server },
|
||||
query: mergeMusicFolderId(args.query, server),
|
||||
}),
|
||||
);
|
||||
},
|
||||
getSongListCount(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -617,11 +660,13 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'getSongListCount',
|
||||
server.type,
|
||||
)?.({
|
||||
...args,
|
||||
apiClientProps: { ...args.apiClientProps, server },
|
||||
query: mergeMusicFolderId(args.query, server),
|
||||
});
|
||||
)?.(
|
||||
addContext({
|
||||
...args,
|
||||
apiClientProps: { ...args.apiClientProps, server },
|
||||
query: mergeMusicFolderId(args.query, server),
|
||||
}),
|
||||
);
|
||||
},
|
||||
getStreamUrl(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -633,7 +678,7 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'getStreamUrl',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
getStructuredLyrics(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -647,7 +692,7 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'getStructuredLyrics',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
getTagList(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -661,7 +706,7 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'getTagList',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
getTopSongs(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -675,7 +720,7 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'getTopSongs',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
getUserInfo(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -689,7 +734,7 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'getUserInfo',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
getUserList(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -703,7 +748,7 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'getUserList',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
movePlaylistItem(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -717,7 +762,7 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'movePlaylistItem',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
removeFromPlaylist(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -731,7 +776,7 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'removeFromPlaylist',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
replacePlaylist(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -745,7 +790,7 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'replacePlaylist',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
savePlayQueue(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -759,7 +804,7 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'savePlayQueue',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
scrobble(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -773,7 +818,7 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'scrobble',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
search(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -787,11 +832,13 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'search',
|
||||
server.type,
|
||||
)?.({
|
||||
...args,
|
||||
apiClientProps: { ...args.apiClientProps, server },
|
||||
query: mergeMusicFolderId(args.query, server),
|
||||
});
|
||||
)?.(
|
||||
addContext({
|
||||
...args,
|
||||
apiClientProps: { ...args.apiClientProps, server },
|
||||
query: mergeMusicFolderId(args.query, server),
|
||||
}),
|
||||
);
|
||||
},
|
||||
setRating(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -805,7 +852,7 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'setRating',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
shareItem(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -819,7 +866,7 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'shareItem',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
updateInternetRadioStation(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -833,7 +880,7 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'updateInternetRadioStation',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
updatePlaylist(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
@@ -847,6 +894,6 @@ export const controller: GeneralController = {
|
||||
return apiController(
|
||||
'updatePlaylist',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
};
|
||||
|
||||
@@ -447,7 +447,14 @@ export const JellyfinController: InternalControllerEndpoint = {
|
||||
throw new Error('Failed to get artist radio songs');
|
||||
}
|
||||
|
||||
return res.body.Items.map((song) => jfNormalize.song(song, apiClientProps.server));
|
||||
return res.body.Items.map((song) =>
|
||||
jfNormalize.song(
|
||||
song,
|
||||
apiClientProps.server,
|
||||
args.context?.pathReplace,
|
||||
args.context?.pathReplaceWith,
|
||||
),
|
||||
);
|
||||
},
|
||||
getDownloadUrl: (args) => {
|
||||
const { apiClientProps, query } = args;
|
||||
@@ -858,7 +865,14 @@ export const JellyfinController: InternalControllerEndpoint = {
|
||||
}
|
||||
|
||||
return {
|
||||
items: res.body.Items.map((item) => jfNormalize.song(item, apiClientProps.server)),
|
||||
items: res.body.Items.map((item) =>
|
||||
jfNormalize.song(
|
||||
item,
|
||||
apiClientProps.server,
|
||||
args.context?.pathReplace,
|
||||
args.context?.pathReplaceWith,
|
||||
),
|
||||
),
|
||||
startIndex: 0,
|
||||
totalRecordCount: res.body.TotalRecordCount,
|
||||
};
|
||||
@@ -911,7 +925,14 @@ export const JellyfinController: InternalControllerEndpoint = {
|
||||
}
|
||||
|
||||
return {
|
||||
items: res.body.Items.map((item) => jfNormalize.song(item, apiClientProps.server)),
|
||||
items: res.body.Items.map((item) =>
|
||||
jfNormalize.song(
|
||||
item,
|
||||
apiClientProps.server,
|
||||
args.context?.pathReplace,
|
||||
args.context?.pathReplaceWith,
|
||||
),
|
||||
),
|
||||
startIndex: 0,
|
||||
totalRecordCount: res.body.Items.length || 0,
|
||||
};
|
||||
@@ -961,7 +982,14 @@ export const JellyfinController: InternalControllerEndpoint = {
|
||||
if (res.status === 200 && res.body.Items.length) {
|
||||
const results = res.body.Items.reduce<Song[]>((acc, song) => {
|
||||
if (song.Id !== query.songId) {
|
||||
acc.push(jfNormalize.song(song, apiClientProps.server));
|
||||
acc.push(
|
||||
jfNormalize.song(
|
||||
song,
|
||||
apiClientProps.server,
|
||||
args.context?.pathReplace,
|
||||
args.context?.pathReplaceWith,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return acc;
|
||||
@@ -990,7 +1018,14 @@ export const JellyfinController: InternalControllerEndpoint = {
|
||||
|
||||
return mix.body.Items.reduce<Song[]>((acc, song) => {
|
||||
if (song.Id !== query.songId) {
|
||||
acc.push(jfNormalize.song(song, apiClientProps.server));
|
||||
acc.push(
|
||||
jfNormalize.song(
|
||||
song,
|
||||
apiClientProps.server,
|
||||
args.context?.pathReplace,
|
||||
args.context?.pathReplaceWith,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return acc;
|
||||
@@ -1010,7 +1045,12 @@ export const JellyfinController: InternalControllerEndpoint = {
|
||||
throw new Error('Failed to get song detail');
|
||||
}
|
||||
|
||||
return jfNormalize.song(res.body, apiClientProps.server);
|
||||
return jfNormalize.song(
|
||||
res.body,
|
||||
apiClientProps.server,
|
||||
args.context?.pathReplace,
|
||||
args.context?.pathReplaceWith,
|
||||
);
|
||||
},
|
||||
getSongList: async (args) => {
|
||||
const { apiClientProps, query } = args;
|
||||
@@ -1122,7 +1162,14 @@ export const JellyfinController: InternalControllerEndpoint = {
|
||||
}
|
||||
|
||||
return {
|
||||
items: items.map((item) => jfNormalize.song(item, apiClientProps.server)),
|
||||
items: items.map((item) =>
|
||||
jfNormalize.song(
|
||||
item,
|
||||
apiClientProps.server,
|
||||
args.context?.pathReplace,
|
||||
args.context?.pathReplaceWith,
|
||||
),
|
||||
),
|
||||
startIndex: query.startIndex,
|
||||
totalRecordCount,
|
||||
};
|
||||
@@ -1221,7 +1268,14 @@ export const JellyfinController: InternalControllerEndpoint = {
|
||||
}
|
||||
|
||||
return {
|
||||
items: res.body.Items.map((item) => jfNormalize.song(item, apiClientProps.server)),
|
||||
items: res.body.Items.map((item) =>
|
||||
jfNormalize.song(
|
||||
item,
|
||||
apiClientProps.server,
|
||||
args.context?.pathReplace,
|
||||
args.context?.pathReplaceWith,
|
||||
),
|
||||
),
|
||||
startIndex: 0,
|
||||
totalRecordCount: res.body.TotalRecordCount,
|
||||
};
|
||||
@@ -1306,7 +1360,12 @@ export const JellyfinController: InternalControllerEndpoint = {
|
||||
}
|
||||
|
||||
const existingSongs = existingSongsRes.body.Items.map((item) =>
|
||||
jfNormalize.song(item, apiClientProps.server),
|
||||
jfNormalize.song(
|
||||
item,
|
||||
apiClientProps.server,
|
||||
args.context?.pathReplace,
|
||||
args.context?.pathReplaceWith,
|
||||
),
|
||||
);
|
||||
|
||||
// 2. Get playlist detail to get the name
|
||||
@@ -1546,7 +1605,14 @@ export const JellyfinController: InternalControllerEndpoint = {
|
||||
jfNormalize.albumArtist(item, apiClientProps.server),
|
||||
),
|
||||
albums: albums.map((item) => jfNormalize.album(item, apiClientProps.server)),
|
||||
songs: songs.map((item) => jfNormalize.song(item, apiClientProps.server)),
|
||||
songs: songs.map((item) =>
|
||||
jfNormalize.song(
|
||||
item,
|
||||
apiClientProps.server,
|
||||
args.context?.pathReplace,
|
||||
args.context?.pathReplaceWith,
|
||||
),
|
||||
),
|
||||
};
|
||||
},
|
||||
updateInternetRadioStation: async (args) => {
|
||||
|
||||
@@ -268,7 +268,7 @@ export const NavidromeController: InternalControllerEndpoint = {
|
||||
query: { ...query, limit: 1, startIndex: 0 },
|
||||
}).then((result) => result!.totalRecordCount!),
|
||||
getAlbumDetail: async (args) => {
|
||||
const { apiClientProps, query } = args;
|
||||
const { apiClientProps, context, query } = args;
|
||||
|
||||
const albumRes = await ndApiClient(apiClientProps).getAlbumDetail({
|
||||
params: {
|
||||
@@ -294,6 +294,8 @@ export const NavidromeController: InternalControllerEndpoint = {
|
||||
return ndNormalize.album(
|
||||
{ ...albumRes.body.data, songs: songsData.body.data },
|
||||
apiClientProps.server,
|
||||
context?.pathReplace,
|
||||
context?.pathReplaceWith,
|
||||
);
|
||||
},
|
||||
getAlbumInfo: async (args) => {
|
||||
@@ -317,7 +319,7 @@ export const NavidromeController: InternalControllerEndpoint = {
|
||||
};
|
||||
},
|
||||
getAlbumList: async (args) => {
|
||||
const { apiClientProps, query } = args;
|
||||
const { apiClientProps, context, query } = args;
|
||||
|
||||
const genres = hasFeature(apiClientProps.server, ServerFeature.BFR)
|
||||
? query.genreIds
|
||||
@@ -352,7 +354,14 @@ export const NavidromeController: InternalControllerEndpoint = {
|
||||
}
|
||||
|
||||
return {
|
||||
items: res.body.data.map((album) => ndNormalize.album(album, apiClientProps.server)),
|
||||
items: res.body.data.map((album) =>
|
||||
ndNormalize.album(
|
||||
album,
|
||||
apiClientProps.server,
|
||||
context?.pathReplace,
|
||||
context?.pathReplaceWith,
|
||||
),
|
||||
),
|
||||
startIndex: query?.startIndex || 0,
|
||||
totalRecordCount: Number(res.body.headers.get('x-total-count') || 0),
|
||||
};
|
||||
@@ -560,7 +569,14 @@ export const NavidromeController: InternalControllerEndpoint = {
|
||||
}
|
||||
|
||||
return {
|
||||
items: res.body.data.map((item) => ndNormalize.song(item, apiClientProps.server)),
|
||||
items: res.body.data.map((item) =>
|
||||
ndNormalize.song(
|
||||
item,
|
||||
apiClientProps.server,
|
||||
args.context?.pathReplace,
|
||||
args.context?.pathReplaceWith,
|
||||
),
|
||||
),
|
||||
startIndex: 0,
|
||||
totalRecordCount: Number(res.body.headers.get('x-total-count') || 0),
|
||||
};
|
||||
@@ -577,7 +593,14 @@ export const NavidromeController: InternalControllerEndpoint = {
|
||||
|
||||
const { changedBy, current, items, position, updatedAt } = res.body.data;
|
||||
|
||||
const entries = items.map((song) => ndNormalize.song(song, apiClientProps.server));
|
||||
const entries = items.map((song) =>
|
||||
ndNormalize.song(
|
||||
song,
|
||||
apiClientProps.server,
|
||||
args.context?.pathReplace,
|
||||
args.context?.pathReplaceWith,
|
||||
),
|
||||
);
|
||||
|
||||
return {
|
||||
changed: updatedAt,
|
||||
@@ -668,7 +691,12 @@ export const NavidromeController: InternalControllerEndpoint = {
|
||||
throw new Error('Failed to get song detail');
|
||||
}
|
||||
|
||||
return ndNormalize.song(res.body.data, apiClientProps.server);
|
||||
return ndNormalize.song(
|
||||
res.body.data,
|
||||
apiClientProps.server,
|
||||
args.context?.pathReplace,
|
||||
args.context?.pathReplaceWith,
|
||||
);
|
||||
},
|
||||
getSongList: async (args) => {
|
||||
const { apiClientProps, query } = args;
|
||||
@@ -696,7 +724,14 @@ export const NavidromeController: InternalControllerEndpoint = {
|
||||
}
|
||||
|
||||
return {
|
||||
items: res.body.data.map((song) => ndNormalize.song(song, apiClientProps.server)),
|
||||
items: res.body.data.map((song) =>
|
||||
ndNormalize.song(
|
||||
song,
|
||||
apiClientProps.server,
|
||||
args.context?.pathReplace,
|
||||
args.context?.pathReplaceWith,
|
||||
),
|
||||
),
|
||||
startIndex: query?.startIndex || 0,
|
||||
totalRecordCount: Number(res.body.headers.get('x-total-count') || 0),
|
||||
};
|
||||
@@ -847,7 +882,12 @@ export const NavidromeController: InternalControllerEndpoint = {
|
||||
}
|
||||
|
||||
const existingSongs = existingSongsRes.body.data.map((item) =>
|
||||
ndNormalize.song(item, apiClientProps.server),
|
||||
ndNormalize.song(
|
||||
item,
|
||||
apiClientProps.server,
|
||||
args.context?.pathReplace,
|
||||
args.context?.pathReplaceWith,
|
||||
),
|
||||
);
|
||||
|
||||
// 2. Get playlist detail to get the name
|
||||
|
||||
@@ -282,7 +282,14 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
|
||||
return {
|
||||
...ssNormalize.albumArtist(artist, apiClientProps.server),
|
||||
albums: artist.album?.map((album) => ssNormalize.album(album, apiClientProps.server)),
|
||||
albums: artist.album?.map((album) =>
|
||||
ssNormalize.album(
|
||||
album,
|
||||
apiClientProps.server,
|
||||
args.context?.pathReplace,
|
||||
args.context?.pathReplaceWith,
|
||||
),
|
||||
),
|
||||
similarArtists:
|
||||
artistInfo?.similarArtist?.map((artist) =>
|
||||
ssNormalize.albumArtist(artist, apiClientProps.server),
|
||||
@@ -327,6 +334,7 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
getAlbumArtistListCount: (args) =>
|
||||
SubsonicController.getAlbumArtistList({
|
||||
...args,
|
||||
context: args.context,
|
||||
query: { ...args.query, startIndex: 0 },
|
||||
}).then((res) => res!.totalRecordCount!),
|
||||
getAlbumDetail: async (args) => {
|
||||
@@ -342,7 +350,12 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
throw new Error('Failed to get album detail');
|
||||
}
|
||||
|
||||
return ssNormalize.album(res.body.album, apiClientProps.server);
|
||||
return ssNormalize.album(
|
||||
res.body.album,
|
||||
apiClientProps.server,
|
||||
args.context?.pathReplace,
|
||||
args.context?.pathReplaceWith,
|
||||
);
|
||||
},
|
||||
getAlbumList: async (args) => {
|
||||
const { apiClientProps, query } = args;
|
||||
@@ -367,7 +380,12 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
|
||||
const results =
|
||||
res.body.searchResult3?.album?.map((album) =>
|
||||
ssNormalize.album(album, apiClientProps.server),
|
||||
ssNormalize.album(
|
||||
album,
|
||||
apiClientProps.server,
|
||||
args.context?.pathReplace,
|
||||
args.context?.pathReplaceWith,
|
||||
),
|
||||
) || [];
|
||||
|
||||
return {
|
||||
@@ -402,7 +420,14 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
return artist.body.artist.album ?? [];
|
||||
});
|
||||
|
||||
const items = albums.map((album) => ssNormalize.album(album, apiClientProps.server));
|
||||
const items = albums.map((album) =>
|
||||
ssNormalize.album(
|
||||
album,
|
||||
apiClientProps.server,
|
||||
args.context?.pathReplace,
|
||||
args.context?.pathReplaceWith,
|
||||
),
|
||||
);
|
||||
|
||||
return {
|
||||
items: sortAlbumList(items, query.sortBy, query.sortOrder),
|
||||
@@ -424,7 +449,12 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
|
||||
const allResults =
|
||||
res.body.starred?.album?.map((album) =>
|
||||
ssNormalize.album(album, apiClientProps.server),
|
||||
ssNormalize.album(
|
||||
album,
|
||||
apiClientProps.server,
|
||||
args.context?.pathReplace,
|
||||
args.context?.pathReplaceWith,
|
||||
),
|
||||
) || [];
|
||||
|
||||
return sortAndPaginate(allResults, {
|
||||
@@ -489,7 +519,12 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
return {
|
||||
items:
|
||||
res.body.albumList2.album?.map((album) =>
|
||||
ssNormalize.album(album, apiClientProps.server),
|
||||
ssNormalize.album(
|
||||
album,
|
||||
apiClientProps.server,
|
||||
args.context?.pathReplace,
|
||||
args.context?.pathReplaceWith,
|
||||
),
|
||||
) || [],
|
||||
startIndex: query.startIndex,
|
||||
totalRecordCount: null,
|
||||
@@ -682,10 +717,11 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
getArtistListCount: async (args) =>
|
||||
SubsonicController.getArtistList({
|
||||
...args,
|
||||
context: args.context,
|
||||
query: { ...args.query, startIndex: 0 },
|
||||
}).then((res) => res!.totalRecordCount!),
|
||||
getArtistRadio: async (args) => {
|
||||
const { apiClientProps, query } = args;
|
||||
const { apiClientProps, context, query } = args;
|
||||
|
||||
const res = await ssApiClient(apiClientProps).getSimilarSongs2({
|
||||
query: {
|
||||
@@ -703,7 +739,12 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
}
|
||||
|
||||
return res.body.similarSongs2.song.map((song) =>
|
||||
ssNormalize.song(song, apiClientProps.server),
|
||||
ssNormalize.song(
|
||||
song,
|
||||
apiClientProps.server,
|
||||
context?.pathReplace,
|
||||
context?.pathReplaceWith,
|
||||
),
|
||||
);
|
||||
},
|
||||
getDownloadUrl: (args) => {
|
||||
@@ -717,7 +758,7 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
'&c=Feishin'
|
||||
);
|
||||
},
|
||||
getFolder: async ({ apiClientProps, query }) => {
|
||||
getFolder: async ({ apiClientProps, context, query }) => {
|
||||
const sortOrder = (query.sortOrder?.toLowerCase() ?? 'asc') as 'asc' | 'desc';
|
||||
|
||||
const isRootFolderId = /^\d+$/.test(query.id);
|
||||
@@ -749,7 +790,14 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
});
|
||||
}
|
||||
|
||||
let folders = items.map((item) => ssNormalize.folder(item, apiClientProps.server));
|
||||
let folders = items.map((item) =>
|
||||
ssNormalize.folder(
|
||||
item,
|
||||
apiClientProps.server,
|
||||
context?.pathReplace,
|
||||
context?.pathReplaceWith,
|
||||
),
|
||||
);
|
||||
|
||||
folders = orderBy(folders, [(v) => v.name.toLowerCase()], [sortOrder]);
|
||||
|
||||
@@ -777,7 +825,12 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
throw new Error('Failed to get folder');
|
||||
}
|
||||
|
||||
const folder = ssNormalize.folder(directoryRes.body.directory, apiClientProps.server);
|
||||
const folder = ssNormalize.folder(
|
||||
directoryRes.body.directory,
|
||||
apiClientProps.server,
|
||||
context?.pathReplace,
|
||||
context?.pathReplaceWith,
|
||||
);
|
||||
|
||||
let filteredFolders = folder.children?.folders || [];
|
||||
let filteredSongs = folder.children?.songs || [];
|
||||
@@ -991,7 +1044,7 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
|
||||
return results.length;
|
||||
},
|
||||
getPlaylistSongList: async ({ apiClientProps, query }) => {
|
||||
getPlaylistSongList: async ({ apiClientProps, context, query }) => {
|
||||
const res = await ssApiClient(apiClientProps).getPlaylist({
|
||||
query: {
|
||||
id: query.id,
|
||||
@@ -1003,8 +1056,14 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
}
|
||||
|
||||
const items =
|
||||
res.body.playlist.entry?.map((song) => ssNormalize.song(song, apiClientProps.server)) ||
|
||||
[];
|
||||
res.body.playlist.entry?.map((song) =>
|
||||
ssNormalize.song(
|
||||
song,
|
||||
apiClientProps.server,
|
||||
context?.pathReplace,
|
||||
context?.pathReplaceWith,
|
||||
),
|
||||
) || [];
|
||||
|
||||
return {
|
||||
items,
|
||||
@@ -1012,7 +1071,7 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
totalRecordCount: items.length,
|
||||
};
|
||||
},
|
||||
getPlayQueue: async ({ apiClientProps }) => {
|
||||
getPlayQueue: async ({ apiClientProps, context }) => {
|
||||
if (hasFeature(apiClientProps.server, ServerFeature.SERVER_PLAY_QUEUE)) {
|
||||
const res = await ssApiClient(apiClientProps).getPlayQueueByIndex();
|
||||
|
||||
@@ -1027,7 +1086,15 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
changed,
|
||||
changedBy,
|
||||
currentIndex: currentIndex ?? 0,
|
||||
entry: entry?.map((song) => ssNormalize.song(song, apiClientProps.server)) || [],
|
||||
entry:
|
||||
entry?.map((song) =>
|
||||
ssNormalize.song(
|
||||
song,
|
||||
apiClientProps.server,
|
||||
context?.pathReplace,
|
||||
context?.pathReplaceWith,
|
||||
),
|
||||
) || [],
|
||||
positionMs: position ?? 0,
|
||||
username,
|
||||
};
|
||||
@@ -1044,14 +1111,22 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
changed,
|
||||
changedBy,
|
||||
currentIndex: current ? entry.findIndex((item) => item.id === current) : 0,
|
||||
entry: entry?.map((song) => ssNormalize.song(song, apiClientProps.server)) || [],
|
||||
entry:
|
||||
entry?.map((song) =>
|
||||
ssNormalize.song(
|
||||
song,
|
||||
apiClientProps.server,
|
||||
context?.pathReplace,
|
||||
context?.pathReplaceWith,
|
||||
),
|
||||
) || [],
|
||||
positionMs: position ?? 0,
|
||||
username,
|
||||
};
|
||||
}
|
||||
},
|
||||
getRandomSongList: async (args) => {
|
||||
const { apiClientProps, query } = args;
|
||||
const { apiClientProps, context, query } = args;
|
||||
|
||||
const res = await ssApiClient(apiClientProps).getRandomSongList({
|
||||
query: {
|
||||
@@ -1069,7 +1144,12 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
|
||||
const results = res.body.randomSongs?.song || [];
|
||||
const normalizedResults = results.map((song) =>
|
||||
ssNormalize.song(song, apiClientProps.server),
|
||||
ssNormalize.song(
|
||||
song,
|
||||
apiClientProps.server,
|
||||
context?.pathReplace,
|
||||
context?.pathReplaceWith,
|
||||
),
|
||||
);
|
||||
|
||||
return {
|
||||
@@ -1147,7 +1227,7 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
return { features, id: apiClientProps.server?.id, version: ping.body.serverVersion };
|
||||
},
|
||||
getSimilarSongs: async (args) => {
|
||||
const { apiClientProps, query } = args;
|
||||
const { apiClientProps, context, query } = args;
|
||||
|
||||
const res = await ssApiClient(apiClientProps).getSimilarSongs({
|
||||
query: {
|
||||
@@ -1166,14 +1246,21 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
|
||||
return res.body.similarSongs.song.reduce<Song[]>((acc, song) => {
|
||||
if (song.id !== query.songId) {
|
||||
acc.push(ssNormalize.song(song, apiClientProps.server));
|
||||
acc.push(
|
||||
ssNormalize.song(
|
||||
song,
|
||||
apiClientProps.server,
|
||||
context?.pathReplace,
|
||||
context?.pathReplaceWith,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
},
|
||||
getSongDetail: async (args) => {
|
||||
const { apiClientProps, query } = args;
|
||||
const { apiClientProps, context, query } = args;
|
||||
|
||||
const res = await ssApiClient(apiClientProps).getSong({
|
||||
query: {
|
||||
@@ -1185,9 +1272,14 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
throw new Error('Failed to get song detail');
|
||||
}
|
||||
|
||||
return ssNormalize.song(res.body.song, apiClientProps.server);
|
||||
return ssNormalize.song(
|
||||
res.body.song,
|
||||
apiClientProps.server,
|
||||
context?.pathReplace,
|
||||
context?.pathReplaceWith,
|
||||
);
|
||||
},
|
||||
getSongList: async ({ apiClientProps, query }) => {
|
||||
getSongList: async ({ apiClientProps, context, query }) => {
|
||||
const fromAlbumPromises: Promise<ServerInferResponses<typeof contract.getAlbum>>[] = [];
|
||||
const artistDetailPromises: Promise<ServerInferResponses<typeof contract.getArtist>>[] = [];
|
||||
|
||||
@@ -1212,7 +1304,12 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
return {
|
||||
items:
|
||||
res.body.searchResult3?.song?.map((song) =>
|
||||
ssNormalize.song(song, apiClientProps.server),
|
||||
ssNormalize.song(
|
||||
song,
|
||||
apiClientProps.server,
|
||||
context?.pathReplace,
|
||||
context?.pathReplaceWith,
|
||||
),
|
||||
) || [],
|
||||
startIndex: query.startIndex,
|
||||
totalRecordCount: null,
|
||||
@@ -1236,7 +1333,15 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
const results = res.body.songsByGenre?.song || [];
|
||||
|
||||
return {
|
||||
items: results.map((song) => ssNormalize.song(song, apiClientProps.server)) || [],
|
||||
items:
|
||||
results.map((song) =>
|
||||
ssNormalize.song(
|
||||
song,
|
||||
apiClientProps.server,
|
||||
context?.pathReplace,
|
||||
context?.pathReplaceWith,
|
||||
),
|
||||
) || [],
|
||||
startIndex: 0,
|
||||
totalRecordCount: null,
|
||||
};
|
||||
@@ -1255,7 +1360,12 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
|
||||
const allResults =
|
||||
(res.body.starred?.song || []).map((song) =>
|
||||
ssNormalize.song(song, apiClientProps.server),
|
||||
ssNormalize.song(
|
||||
song,
|
||||
apiClientProps.server,
|
||||
context?.pathReplace,
|
||||
context?.pathReplaceWith,
|
||||
),
|
||||
) || [];
|
||||
|
||||
return sortAndPaginate(allResults, {
|
||||
@@ -1331,7 +1441,15 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
}
|
||||
|
||||
return {
|
||||
items: results.map((song) => ssNormalize.song(song, apiClientProps.server)) || [],
|
||||
items:
|
||||
results.map((song) =>
|
||||
ssNormalize.song(
|
||||
song,
|
||||
apiClientProps.server,
|
||||
context?.pathReplace,
|
||||
context?.pathReplaceWith,
|
||||
),
|
||||
) || [],
|
||||
startIndex: 0,
|
||||
totalRecordCount: results.length,
|
||||
};
|
||||
@@ -1357,7 +1475,12 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
return {
|
||||
items:
|
||||
res.body.searchResult3?.song?.map((song) =>
|
||||
ssNormalize.song(song, apiClientProps.server),
|
||||
ssNormalize.song(
|
||||
song,
|
||||
apiClientProps.server,
|
||||
context?.pathReplace,
|
||||
context?.pathReplaceWith,
|
||||
),
|
||||
) || [],
|
||||
startIndex: 0,
|
||||
totalRecordCount: null,
|
||||
@@ -1596,7 +1719,7 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
});
|
||||
},
|
||||
getTopSongs: async (args) => {
|
||||
const { apiClientProps, query } = args;
|
||||
const { apiClientProps, context, query } = args;
|
||||
|
||||
const res = await ssApiClient(apiClientProps).getTopSongsList({
|
||||
query: {
|
||||
@@ -1612,7 +1735,12 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
return {
|
||||
items:
|
||||
res.body.topSongs?.song?.map((song) =>
|
||||
ssNormalize.song(song, apiClientProps.server),
|
||||
ssNormalize.song(
|
||||
song,
|
||||
apiClientProps.server,
|
||||
context?.pathReplace,
|
||||
context?.pathReplaceWith,
|
||||
),
|
||||
) || [],
|
||||
startIndex: 0,
|
||||
totalRecordCount: res.body.topSongs?.song?.length || 0,
|
||||
@@ -1652,7 +1780,7 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
return null;
|
||||
},
|
||||
replacePlaylist: async (args) => {
|
||||
const { apiClientProps, body, query } = args;
|
||||
const { apiClientProps, body, context, query } = args;
|
||||
|
||||
// 1. Fetch existing songs from the playlist
|
||||
const existingSongsRes = await ssApiClient(apiClientProps).getPlaylist({
|
||||
@@ -1667,7 +1795,12 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
|
||||
const existingSongs =
|
||||
existingSongsRes.body.playlist.entry?.map((song) =>
|
||||
ssNormalize.song(song, apiClientProps.server),
|
||||
ssNormalize.song(
|
||||
song,
|
||||
apiClientProps.server,
|
||||
context?.pathReplace,
|
||||
context?.pathReplaceWith,
|
||||
),
|
||||
) || [];
|
||||
|
||||
// 2. Get playlist detail to get the name
|
||||
@@ -1779,7 +1912,7 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
return null;
|
||||
},
|
||||
search: async (args) => {
|
||||
const { apiClientProps, query } = args;
|
||||
const { apiClientProps, context, query } = args;
|
||||
|
||||
const res = await ssApiClient(apiClientProps).search3({
|
||||
query: {
|
||||
@@ -1803,10 +1936,20 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
ssNormalize.albumArtist(artist, apiClientProps.server),
|
||||
),
|
||||
albums: (res.body.searchResult3?.album || []).map((album) =>
|
||||
ssNormalize.album(album, apiClientProps.server),
|
||||
ssNormalize.album(
|
||||
album,
|
||||
apiClientProps.server,
|
||||
args.context?.pathReplace,
|
||||
args.context?.pathReplaceWith,
|
||||
),
|
||||
),
|
||||
songs: (res.body.searchResult3?.song || []).map((song) =>
|
||||
ssNormalize.song(song, apiClientProps.server),
|
||||
ssNormalize.song(
|
||||
song,
|
||||
apiClientProps.server,
|
||||
context?.pathReplace,
|
||||
context?.pathReplaceWith,
|
||||
),
|
||||
),
|
||||
};
|
||||
},
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
ArtistSettings,
|
||||
} from '/@/renderer/features/settings/components/general/artist-settings';
|
||||
import { HomeSettings } from '/@/renderer/features/settings/components/general/home-settings';
|
||||
import { PathSettings } from '/@/renderer/features/settings/components/general/path-settings';
|
||||
import {
|
||||
SettingOption,
|
||||
SettingsSection,
|
||||
@@ -610,6 +611,7 @@ export const ApplicationSettings = () => {
|
||||
<HomeSettings />
|
||||
<ArtistSettings />
|
||||
<ArtistReleaseTypeSettings />
|
||||
<PathSettings />
|
||||
</>
|
||||
}
|
||||
options={options}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { songsQueries } from '/@/renderer/features/songs/api/songs-api';
|
||||
import {
|
||||
useCurrentServerId,
|
||||
useGeneralSettings,
|
||||
useSettingsStore,
|
||||
useSettingsStoreActions,
|
||||
} from '/@/renderer/store';
|
||||
import { ActionIcon } from '/@/shared/components/action-icon/action-icon';
|
||||
import { Code } from '/@/shared/components/code/code';
|
||||
import { Group } from '/@/shared/components/group/group';
|
||||
import { Stack } from '/@/shared/components/stack/stack';
|
||||
import { TextInput } from '/@/shared/components/text-input/text-input';
|
||||
import { Text } from '/@/shared/components/text/text';
|
||||
import { Played } from '/@/shared/types/domain-types';
|
||||
|
||||
export const PathSettings = () => {
|
||||
const { t } = useTranslation();
|
||||
const serverId = useCurrentServerId();
|
||||
const randomSong = useQuery({
|
||||
...songsQueries.random({
|
||||
query: { limit: 1, played: Played.All },
|
||||
serverId,
|
||||
}),
|
||||
gcTime: Infinity,
|
||||
staleTime: Infinity,
|
||||
});
|
||||
|
||||
const { pathReplace, pathReplaceWith } = useGeneralSettings();
|
||||
const { setSettings } = useSettingsStoreActions();
|
||||
|
||||
return (
|
||||
<Stack>
|
||||
<Group>
|
||||
<Text>{t('setting.pathReplace', { postProcess: 'sentenceCase' })}</Text>
|
||||
<ActionIcon
|
||||
icon="refresh"
|
||||
loading={randomSong.isFetching}
|
||||
onClick={() => randomSong.refetch()}
|
||||
size="xs"
|
||||
variant="transparent"
|
||||
/>
|
||||
</Group>
|
||||
<Code>
|
||||
<Text isMuted size="md">
|
||||
{randomSong.data?.items[0]?.path || ''}
|
||||
</Text>
|
||||
</Code>
|
||||
<Group grow>
|
||||
<TextInput
|
||||
onChange={(e) =>
|
||||
setSettings({
|
||||
general: {
|
||||
...useSettingsStore.getState().general,
|
||||
pathReplace: e.currentTarget.value,
|
||||
},
|
||||
})
|
||||
}
|
||||
placeholder={t('setting.pathReplace_optionRemovePrefix', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
value={pathReplace}
|
||||
/>
|
||||
<TextInput
|
||||
onChange={(e) =>
|
||||
setSettings({
|
||||
general: {
|
||||
...useSettingsStore.getState().general,
|
||||
pathReplaceWith: e.currentTarget.value,
|
||||
},
|
||||
})
|
||||
}
|
||||
placeholder={t('setting.pathReplace_optionAddPrefix', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
value={pathReplaceWith}
|
||||
/>
|
||||
</Group>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
@@ -400,6 +400,8 @@ export const GeneralSettingsSchema = z.object({
|
||||
musicBrainz: z.boolean(),
|
||||
nativeAspectRatio: z.boolean(),
|
||||
passwordStore: z.string().optional(),
|
||||
pathReplace: z.string(),
|
||||
pathReplaceWith: z.string(),
|
||||
playButtonBehavior: z.nativeEnum(Play),
|
||||
playerbarOpenDrawer: z.boolean(),
|
||||
playerbarSlider: PlayerbarSliderSchema,
|
||||
@@ -953,6 +955,8 @@ const initialState: SettingsState = {
|
||||
musicBrainz: true,
|
||||
nativeAspectRatio: false,
|
||||
passwordStore: undefined,
|
||||
pathReplace: '',
|
||||
pathReplaceWith: '',
|
||||
playButtonBehavior: Play.NOW,
|
||||
playerbarOpenDrawer: false,
|
||||
playerbarSlider: {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { jfType } from '/@/shared/api/jellyfin/jellyfin-types';
|
||||
import { replacePathPrefix } from '/@/shared/api/utils';
|
||||
import {
|
||||
Album,
|
||||
AlbumArtist,
|
||||
@@ -108,6 +109,8 @@ const getPlaylistImageId = (item: z.infer<typeof jfType._response.playlist>): nu
|
||||
const normalizeSong = (
|
||||
item: z.infer<typeof jfType._response.song>,
|
||||
server: null | ServerListItem,
|
||||
pathReplace?: string,
|
||||
pathReplaceWith?: string,
|
||||
): Song => {
|
||||
let bitRate = 0;
|
||||
let channels: null | number = null;
|
||||
@@ -208,7 +211,10 @@ const normalizeSong = (
|
||||
mbzTrackId: item.ProviderIds?.MusicBrainzTrack || null,
|
||||
name: item.Name,
|
||||
participants: getPeople(item),
|
||||
path,
|
||||
path:
|
||||
path && (pathReplace || pathReplaceWith)
|
||||
? replacePathPrefix(path, pathReplace || '', pathReplaceWith || '')
|
||||
: path,
|
||||
peak: null,
|
||||
playCount: (item.UserData && item.UserData.PlayCount) || 0,
|
||||
playlistItemId: item.PlaylistItemId,
|
||||
|
||||
@@ -2,6 +2,7 @@ import z from 'zod';
|
||||
|
||||
import { ndType } from '/@/shared/api/navidrome/navidrome-types';
|
||||
import { ssType } from '/@/shared/api/subsonic/subsonic-types';
|
||||
import { replacePathPrefix } from '/@/shared/api/utils';
|
||||
import {
|
||||
Album,
|
||||
AlbumArtist,
|
||||
@@ -139,6 +140,8 @@ const getArtists = (
|
||||
const normalizeSong = (
|
||||
item: z.infer<typeof ndType._response.playlistSong> | z.infer<typeof ndType._response.song>,
|
||||
server?: null | ServerListItem,
|
||||
pathReplace?: string,
|
||||
pathReplaceWith?: string,
|
||||
): Song => {
|
||||
let id;
|
||||
let playlistItemId;
|
||||
@@ -202,7 +205,7 @@ const normalizeSong = (
|
||||
name: item.title,
|
||||
// Thankfully, Windows is merciful and allows a mix of separators. So, we can use the
|
||||
// POSIX separator here instead
|
||||
path: (item.libraryPath ? item.libraryPath + '/' : '') + item.path,
|
||||
path: item.path ? replacePathPrefix(item.path, pathReplace, pathReplaceWith) : null,
|
||||
peak:
|
||||
item.rgAlbumPeak || item.rgTrackPeak
|
||||
? { album: item.rgAlbumPeak, track: item.rgTrackPeak }
|
||||
@@ -267,6 +270,8 @@ const normalizeAlbum = (
|
||||
songs?: z.infer<typeof ndType._response.songList>;
|
||||
},
|
||||
server?: null | ServerListItem,
|
||||
pathReplace?: string,
|
||||
pathReplaceWith?: string,
|
||||
): Album => {
|
||||
return {
|
||||
...parseAlbumTags(item),
|
||||
@@ -309,7 +314,9 @@ const normalizeAlbum = (
|
||||
releaseYear: item.maxYear || null,
|
||||
size: item.size,
|
||||
songCount: item.songCount,
|
||||
songs: item.songs ? item.songs.map((song) => normalizeSong(song, server)) : undefined,
|
||||
songs: item.songs
|
||||
? item.songs.map((song) => normalizeSong(song, server, pathReplace, pathReplaceWith))
|
||||
: undefined,
|
||||
tags: item.tags || null,
|
||||
updatedAt: item.updatedAt,
|
||||
userFavorite: item.starred || false,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { ssType } from '/@/shared/api/subsonic/subsonic-types';
|
||||
import { replacePathPrefix } from '/@/shared/api/utils';
|
||||
import {
|
||||
Album,
|
||||
AlbumArtist,
|
||||
@@ -117,6 +118,8 @@ const getGenres = (
|
||||
const normalizeSong = (
|
||||
item: z.infer<typeof ssType._response.song>,
|
||||
server?: null | ServerListItemWithCredential,
|
||||
pathReplace?: string,
|
||||
pathReplaceWith?: string,
|
||||
): Song => {
|
||||
return {
|
||||
_itemType: LibraryItem.SONG,
|
||||
@@ -162,7 +165,10 @@ const normalizeSong = (
|
||||
mbzTrackId: null,
|
||||
name: item.title,
|
||||
participants: getParticipants(item),
|
||||
path: item.path,
|
||||
path:
|
||||
pathReplace || pathReplaceWith
|
||||
? replacePathPrefix(item.path || '', pathReplace, pathReplaceWith)
|
||||
: item.path,
|
||||
peak:
|
||||
item.replayGain && (item.replayGain.albumPeak || item.replayGain.trackPeak)
|
||||
? {
|
||||
@@ -243,6 +249,8 @@ const getReleaseType = (
|
||||
const normalizeAlbum = (
|
||||
item: z.infer<typeof ssType._response.album> | z.infer<typeof ssType._response.albumListEntry>,
|
||||
server?: null | ServerListItemWithCredential,
|
||||
pathReplace?: string,
|
||||
pathReplaceWith?: string,
|
||||
): Album => {
|
||||
return {
|
||||
_itemType: LibraryItem.ALBUM,
|
||||
@@ -286,7 +294,7 @@ const normalizeAlbum = (
|
||||
songCount: item.songCount,
|
||||
songs:
|
||||
(item as z.infer<typeof ssType._response.album>).song?.map((song) =>
|
||||
normalizeSong(song, server),
|
||||
normalizeSong(song, server, pathReplace, pathReplaceWith),
|
||||
) || [],
|
||||
tags: null,
|
||||
updatedAt: item.created,
|
||||
@@ -341,6 +349,8 @@ const normalizeGenre = (
|
||||
const normalizeFolder = (
|
||||
item: z.infer<typeof ssType._response.directory>,
|
||||
server?: null | ServerListItemWithCredential,
|
||||
pathReplace?: string,
|
||||
pathReplaceWith?: string,
|
||||
): Folder => {
|
||||
const results = item.child?.reduce(
|
||||
(acc: { folders: Folder[]; songs: Song[] }, item) => {
|
||||
@@ -350,7 +360,7 @@ const normalizeFolder = (
|
||||
const folder = normalizeFolder(item, server);
|
||||
acc.folders.push(folder);
|
||||
} else {
|
||||
const song = normalizeSong(item, server);
|
||||
const song = normalizeSong(item, server, pathReplace, pathReplaceWith);
|
||||
acc.songs.push(song);
|
||||
}
|
||||
|
||||
|
||||
@@ -471,3 +471,11 @@ export const sortRadioList = (
|
||||
|
||||
return results;
|
||||
};
|
||||
|
||||
export const replacePathPrefix = (path: string, replacePrefix?: string, addPrefix?: string) => {
|
||||
if (replacePrefix && path.startsWith(replacePrefix)) {
|
||||
return path.slice(replacePrefix.length);
|
||||
}
|
||||
|
||||
return addPrefix ? addPrefix + path : path;
|
||||
};
|
||||
|
||||
@@ -403,6 +403,10 @@ type BaseEndpointArgs = {
|
||||
serverId: string;
|
||||
signal?: AbortSignal;
|
||||
};
|
||||
context?: {
|
||||
pathReplace?: string;
|
||||
pathReplaceWith?: string;
|
||||
};
|
||||
};
|
||||
|
||||
type GenreListSortMap = {
|
||||
@@ -1652,4 +1656,8 @@ type BaseEndpointArgsWithServer = {
|
||||
serverId: string;
|
||||
signal?: AbortSignal;
|
||||
};
|
||||
context?: {
|
||||
pathReplace?: string;
|
||||
pathReplaceWith?: string;
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user