mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-08 04:50:12 +02:00
Add internet radio (#1384)
This commit is contained in:
@@ -100,6 +100,20 @@ export const controller: GeneralController = {
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
},
|
||||
createInternetRadioStation(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
|
||||
if (!server) {
|
||||
throw new Error(
|
||||
`${i18n.t('error.apiRouteError', { postProcess: 'sentenceCase' })}: createInternetRadioStation`,
|
||||
);
|
||||
}
|
||||
|
||||
return apiController(
|
||||
'createInternetRadioStation',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
},
|
||||
createPlaylist(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
|
||||
@@ -128,6 +142,20 @@ export const controller: GeneralController = {
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
},
|
||||
deleteInternetRadioStation(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
|
||||
if (!server) {
|
||||
throw new Error(
|
||||
`${i18n.t('error.apiRouteError', { postProcess: 'sentenceCase' })}: deleteInternetRadioStation`,
|
||||
);
|
||||
}
|
||||
|
||||
return apiController(
|
||||
'deleteInternetRadioStation',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
},
|
||||
deletePlaylist(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
|
||||
@@ -342,6 +370,19 @@ export const controller: GeneralController = {
|
||||
query: mergeMusicFolderId(args.query, server),
|
||||
});
|
||||
},
|
||||
getInternetRadioStations(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
|
||||
if (!server) {
|
||||
throw new Error(
|
||||
`${i18n.t('error.apiRouteError', { postProcess: 'sentenceCase' })}: getInternetRadioStations`,
|
||||
);
|
||||
}
|
||||
return apiController(
|
||||
'getInternetRadioStations',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
},
|
||||
getLyrics(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
|
||||
@@ -744,6 +785,20 @@ export const controller: GeneralController = {
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
},
|
||||
updateInternetRadioStation(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
|
||||
if (!server) {
|
||||
throw new Error(
|
||||
`${i18n.t('error.apiRouteError', { postProcess: 'sentenceCase' })}: updateInternetRadioStation`,
|
||||
);
|
||||
}
|
||||
|
||||
return apiController(
|
||||
'updateInternetRadioStation',
|
||||
server.type,
|
||||
)?.({ ...args, apiClientProps: { ...args.apiClientProps, server } });
|
||||
},
|
||||
updatePlaylist(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import orderBy from 'lodash/orderBy';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { jfApiClient } from '/@/renderer/api/jellyfin/jellyfin-api';
|
||||
import { useRadioStore } from '/@/renderer/features/radio/store/radio-store';
|
||||
import { jfNormalize } from '/@/shared/api/jellyfin/jellyfin-normalize';
|
||||
import { JFSongListSort, JFSortOrder, jfType } from '/@/shared/api/jellyfin/jellyfin-types';
|
||||
import { getFeatures, hasFeature, sortSongList, VersionInfo } from '/@/shared/api/utils';
|
||||
@@ -115,6 +116,26 @@ export const JellyfinController: InternalControllerEndpoint = {
|
||||
|
||||
return null;
|
||||
},
|
||||
createInternetRadioStation: async (args) => {
|
||||
const { apiClientProps, body } = args;
|
||||
|
||||
if (!apiClientProps.serverId) {
|
||||
throw new Error('No serverId found');
|
||||
}
|
||||
|
||||
const state = useRadioStore.getState();
|
||||
if (!state?.actions?.createStation) {
|
||||
throw new Error('Radio store not initialized');
|
||||
}
|
||||
|
||||
state.actions.createStation(apiClientProps.serverId, {
|
||||
homepageUrl: body.homepageUrl || null,
|
||||
name: body.name,
|
||||
streamUrl: body.streamUrl,
|
||||
});
|
||||
|
||||
return null;
|
||||
},
|
||||
createPlaylist: async (args) => {
|
||||
const { apiClientProps, body } = args;
|
||||
|
||||
@@ -158,6 +179,22 @@ export const JellyfinController: InternalControllerEndpoint = {
|
||||
|
||||
return null;
|
||||
},
|
||||
deleteInternetRadioStation: async (args) => {
|
||||
const { apiClientProps, query } = args;
|
||||
|
||||
if (!apiClientProps.serverId) {
|
||||
throw new Error('No serverId found');
|
||||
}
|
||||
|
||||
const state = useRadioStore.getState();
|
||||
if (!state?.actions?.deleteStation) {
|
||||
throw new Error('Radio store not initialized');
|
||||
}
|
||||
|
||||
state.actions.deleteStation(apiClientProps.serverId, query.id);
|
||||
|
||||
return null;
|
||||
},
|
||||
deletePlaylist: async (args) => {
|
||||
const { apiClientProps, query } = args;
|
||||
|
||||
@@ -633,6 +670,20 @@ export const JellyfinController: InternalControllerEndpoint = {
|
||||
totalRecordCount: res.body?.TotalRecordCount || 0,
|
||||
};
|
||||
},
|
||||
getInternetRadioStations: async (args) => {
|
||||
const { apiClientProps } = args;
|
||||
|
||||
if (!apiClientProps.serverId) {
|
||||
throw new Error('No serverId found');
|
||||
}
|
||||
|
||||
const state = useRadioStore.getState();
|
||||
if (!state?.actions?.getStations) {
|
||||
throw new Error('Radio store not initialized');
|
||||
}
|
||||
|
||||
return state.actions.getStations(apiClientProps.serverId);
|
||||
},
|
||||
getLyrics: async (args) => {
|
||||
const { apiClientProps, query } = args;
|
||||
|
||||
@@ -1455,6 +1506,26 @@ export const JellyfinController: InternalControllerEndpoint = {
|
||||
songs: songs.map((item) => jfNormalize.song(item, apiClientProps.server)),
|
||||
};
|
||||
},
|
||||
updateInternetRadioStation: async (args) => {
|
||||
const { apiClientProps, body, query } = args;
|
||||
|
||||
if (!apiClientProps.serverId) {
|
||||
throw new Error('No serverId found');
|
||||
}
|
||||
|
||||
const state = useRadioStore.getState();
|
||||
if (!state?.actions?.updateStation) {
|
||||
throw new Error('Radio store not initialized');
|
||||
}
|
||||
|
||||
state.actions.updateStation(apiClientProps.serverId, query.id, {
|
||||
homepageUrl: body.homepageUrl || null,
|
||||
name: body.name,
|
||||
streamUrl: body.streamUrl,
|
||||
});
|
||||
|
||||
return null;
|
||||
},
|
||||
updatePlaylist: async (args) => {
|
||||
const { apiClientProps, body, query } = args;
|
||||
|
||||
|
||||
@@ -141,6 +141,7 @@ export const NavidromeController: InternalControllerEndpoint = {
|
||||
};
|
||||
},
|
||||
createFavorite: SubsonicController.createFavorite,
|
||||
createInternetRadioStation: SubsonicController.createInternetRadioStation,
|
||||
createPlaylist: async (args) => {
|
||||
const { apiClientProps, body } = args;
|
||||
|
||||
@@ -164,6 +165,7 @@ export const NavidromeController: InternalControllerEndpoint = {
|
||||
};
|
||||
},
|
||||
deleteFavorite: SubsonicController.deleteFavorite,
|
||||
deleteInternetRadioStation: SubsonicController.deleteInternetRadioStation,
|
||||
deletePlaylist: async (args) => {
|
||||
const { apiClientProps, query } = args;
|
||||
|
||||
@@ -459,6 +461,7 @@ export const NavidromeController: InternalControllerEndpoint = {
|
||||
totalRecordCount: Number(res.body.headers.get('x-total-count') || 0),
|
||||
};
|
||||
},
|
||||
getInternetRadioStations: SubsonicController.getInternetRadioStations,
|
||||
getLyrics: SubsonicController.getLyrics,
|
||||
getMusicFolderList: SubsonicController.getMusicFolderList,
|
||||
getPlaylistDetail: async (args) => {
|
||||
@@ -931,6 +934,7 @@ export const NavidromeController: InternalControllerEndpoint = {
|
||||
id: res.body.data.id,
|
||||
};
|
||||
},
|
||||
updateInternetRadioStation: SubsonicController.updateInternetRadioStation,
|
||||
updatePlaylist: async (args) => {
|
||||
const { apiClientProps, body, query } = args;
|
||||
|
||||
|
||||
@@ -322,6 +322,10 @@ export const queryKeys: Record<
|
||||
return [serverId, 'playlists', 'songList'] as const;
|
||||
},
|
||||
},
|
||||
radio: {
|
||||
list: (serverId: string) => [serverId, 'radio', 'list'] as const,
|
||||
root: (serverId: string) => [serverId, 'radio'] as const,
|
||||
},
|
||||
roles: {
|
||||
list: (serverId: string) => [serverId, 'roles'] as const,
|
||||
},
|
||||
|
||||
@@ -30,6 +30,14 @@ export const contract = c.router({
|
||||
200: ssType._response.createFavorite,
|
||||
},
|
||||
},
|
||||
createInternetRadioStation: {
|
||||
method: 'GET',
|
||||
path: 'createInternetRadioStation.view',
|
||||
query: ssType._parameters.createInternetRadioStation,
|
||||
responses: {
|
||||
200: ssType._response.createInternetRadioStation,
|
||||
},
|
||||
},
|
||||
createPlaylist: {
|
||||
method: 'GET',
|
||||
path: 'createPlaylist.view',
|
||||
@@ -38,6 +46,14 @@ export const contract = c.router({
|
||||
200: ssType._response.createPlaylist,
|
||||
},
|
||||
},
|
||||
deleteInternetRadioStation: {
|
||||
method: 'GET',
|
||||
path: 'deleteInternetRadioStation.view',
|
||||
query: ssType._parameters.deleteInternetRadioStation,
|
||||
responses: {
|
||||
200: ssType._response.deleteInternetRadioStation,
|
||||
},
|
||||
},
|
||||
deletePlaylist: {
|
||||
method: 'GET',
|
||||
path: 'deletePlaylist.view',
|
||||
@@ -110,6 +126,13 @@ export const contract = c.router({
|
||||
200: ssType._response.getIndexes,
|
||||
},
|
||||
},
|
||||
getInternetRadioStations: {
|
||||
method: 'GET',
|
||||
path: 'getInternetRadioStations.view',
|
||||
responses: {
|
||||
200: ssType._response.getInternetRadioStations,
|
||||
},
|
||||
},
|
||||
getMusicDirectory: {
|
||||
method: 'GET',
|
||||
path: 'getMusicDirectory.view',
|
||||
@@ -281,6 +304,14 @@ export const contract = c.router({
|
||||
200: ssType._response.setRating,
|
||||
},
|
||||
},
|
||||
updateInternetRadioStation: {
|
||||
method: 'GET',
|
||||
path: 'updateInternetRadioStation.view',
|
||||
query: ssType._parameters.updateInternetRadioStation,
|
||||
responses: {
|
||||
200: ssType._response.updateInternetRadioStation,
|
||||
},
|
||||
},
|
||||
updatePlaylist: {
|
||||
method: 'GET',
|
||||
path: 'updatePlaylist.view',
|
||||
|
||||
@@ -166,6 +166,23 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
|
||||
return null;
|
||||
},
|
||||
createInternetRadioStation: async (args) => {
|
||||
const { apiClientProps, body } = args;
|
||||
|
||||
const res = await ssApiClient(apiClientProps).createInternetRadioStation({
|
||||
query: {
|
||||
homepageUrl: body.homepageUrl,
|
||||
name: body.name,
|
||||
streamUrl: body.streamUrl,
|
||||
},
|
||||
});
|
||||
|
||||
if (res.status !== 200) {
|
||||
throw new Error('Failed to create internet radio station');
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
createPlaylist: async ({ apiClientProps, body }) => {
|
||||
const res = await ssApiClient(apiClientProps).createPlaylist({
|
||||
query: {
|
||||
@@ -199,6 +216,21 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
|
||||
return null;
|
||||
},
|
||||
deleteInternetRadioStation: async (args) => {
|
||||
const { apiClientProps, query } = args;
|
||||
|
||||
const res = await ssApiClient(apiClientProps).deleteInternetRadioStation({
|
||||
query: {
|
||||
id: query.id,
|
||||
},
|
||||
});
|
||||
|
||||
if (res.status !== 200) {
|
||||
throw new Error('Failed to delete internet radio station');
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
deletePlaylist: async (args) => {
|
||||
const { apiClientProps, query } = args;
|
||||
|
||||
@@ -789,6 +821,19 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
startIndex: query.startIndex,
|
||||
});
|
||||
},
|
||||
getInternetRadioStations: async (args) => {
|
||||
const { apiClientProps } = args;
|
||||
|
||||
const res = await ssApiClient(apiClientProps).getInternetRadioStations();
|
||||
|
||||
if (res.status !== 200) {
|
||||
throw new Error('Failed to get internet radio stations');
|
||||
}
|
||||
|
||||
const stations = res.body.internetRadioStations?.internetRadioStation || [];
|
||||
|
||||
return stations.map((station) => ssNormalize.internetRadioStation(station));
|
||||
},
|
||||
getMusicFolderList: async (args) => {
|
||||
const { apiClientProps } = args;
|
||||
|
||||
@@ -822,6 +867,7 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
|
||||
return ssNormalize.playlist(res.body.playlist, apiClientProps.server);
|
||||
},
|
||||
|
||||
getPlaylistList: async ({ apiClientProps, query }) => {
|
||||
const sortOrder = query.sortOrder.toLowerCase() as 'asc' | 'desc';
|
||||
|
||||
@@ -1005,7 +1051,6 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
final.splice(0, 0, { label: 'all artists', value: '' });
|
||||
return final;
|
||||
},
|
||||
|
||||
getServerInfo: async (args) => {
|
||||
const { apiClientProps } = args;
|
||||
|
||||
@@ -1722,6 +1767,24 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
|
||||
return null;
|
||||
},
|
||||
updateInternetRadioStation: async (args) => {
|
||||
const { apiClientProps, body, query } = args;
|
||||
|
||||
const res = await ssApiClient(apiClientProps).updateInternetRadioStation({
|
||||
query: {
|
||||
homepageUrl: body.homepageUrl,
|
||||
id: query.id,
|
||||
name: body.name,
|
||||
streamUrl: body.streamUrl,
|
||||
},
|
||||
});
|
||||
|
||||
if (res.status !== 200) {
|
||||
throw new Error('Failed to update internet radio station');
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
updatePlaylist: async (args) => {
|
||||
const { apiClientProps, body, query } = args;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user