diff --git a/src/renderer/api/navidrome/navidrome-api.ts b/src/renderer/api/navidrome/navidrome-api.ts index 05bfed59..621160c3 100644 --- a/src/renderer/api/navidrome/navidrome-api.ts +++ b/src/renderer/api/navidrome/navidrome-api.ts @@ -4,7 +4,7 @@ import omitBy from 'lodash/omitBy'; import qs from 'qs'; import { ndType } from './navidrome-types'; import { resultWithHeaders } from '/@/renderer/api/utils'; -import { toast } from '/@/renderer/components'; +import { toast } from '/@/renderer/components/toast/index'; import { useAuthStore } from '/@/renderer/store'; import { ServerListItem } from '/@/renderer/types'; @@ -186,9 +186,12 @@ axiosClient.interceptors.response.use( message: 'Your session has expired.', }); - const serverId = useAuthStore.getState().currentServer?.id; + const currentServer = useAuthStore.getState().currentServer; - if (serverId) { + if (currentServer) { + const serverId = currentServer.id; + const token = currentServer.ndCredential; + console.log(`token is expired: ${token}`); useAuthStore.getState().actions.setCurrentServer(null); useAuthStore.getState().actions.updateServer(serverId, { ndCredential: undefined }); } @@ -211,7 +214,7 @@ const parsePath = (fullPath: string) => { }; export const ndApiClient = (args: { - server?: ServerListItem; + server: ServerListItem | null; signal?: AbortSignal; url?: string; }) => { diff --git a/src/renderer/api/navidrome/navidrome-controller.ts b/src/renderer/api/navidrome/navidrome-controller.ts index 90eb23ae..5630cddc 100644 --- a/src/renderer/api/navidrome/navidrome-controller.ts +++ b/src/renderer/api/navidrome/navidrome-controller.ts @@ -49,7 +49,7 @@ const authenticate = async ( ): Promise => { const cleanServerUrl = url.replace(/\/$/, ''); - const res = await ndApiClient({ url: cleanServerUrl }).authenticate({ + const res = await ndApiClient({ server: null, url: cleanServerUrl }).authenticate({ body: { password: body.password, username: body.username, @@ -148,10 +148,6 @@ const getAlbumArtistList = async (args: AlbumArtistListArgs): Promise ndNormalize.albumArtist(albumArtist, apiClientProps.server), @@ -219,8 +215,6 @@ const getAlbumList = async (args: AlbumListArgs): Promise => const getSongList = async (args: SongListArgs): Promise => { const { query, apiClientProps } = args; - console.log('query :>> ', query); - const res = await ndApiClient(apiClientProps).getSongList({ query: { _end: query.startIndex + (query.limit || -1), @@ -278,7 +272,9 @@ const createPlaylist = async (args: CreatePlaylistArgs): Promise => { diff --git a/src/renderer/api/navidrome/navidrome-normalize.ts b/src/renderer/api/navidrome/navidrome-normalize.ts index db3d63c5..5836702b 100644 --- a/src/renderer/api/navidrome/navidrome-normalize.ts +++ b/src/renderer/api/navidrome/navidrome-normalize.ts @@ -5,9 +5,9 @@ import z from 'zod'; import { ndType } from './navidrome-types'; const getCoverArtUrl = (args: { - baseUrl: string; + baseUrl: string | undefined; coverArtId: string; - credential: string; + credential: string | undefined; size: number; }) => { const size = args.size ? args.size : 250; @@ -28,7 +28,7 @@ const getCoverArtUrl = (args: { const normalizeSong = ( item: z.infer | z.infer, - server: ServerListItem, + server: ServerListItem | null, deviceId: string, imageSize?: number, ): Song => { @@ -44,9 +44,9 @@ const normalizeSong = ( } const imageUrl = getCoverArtUrl({ - baseUrl: server.url, + baseUrl: server?.url, coverArtId: id, - credential: server.credential, + credential: server?.credential, size: imageSize || 100, }); @@ -79,10 +79,10 @@ const normalizeSong = ( playlistItemId, releaseDate: new Date(item.year, 0, 1).toISOString(), releaseYear: String(item.year), - serverId: server.id, + serverId: server?.id || 'unknown', serverType: ServerType.NAVIDROME, size: item.size, - streamUrl: `${server.url}/rest/stream.view?id=${id}&v=1.13.0&c=feishin_${deviceId}&${server.credential}`, + streamUrl: `${server?.url}/rest/stream.view?id=${id}&v=1.13.0&c=feishin_${deviceId}&${server?.credential}`, trackNumber: item.trackNumber, uniqueId: nanoid(), updatedAt: item.updatedAt, @@ -95,13 +95,13 @@ const normalizeAlbum = ( item: z.infer & { songs?: z.infer; }, - server: ServerListItem, + server: ServerListItem | null, imageSize?: number, ): Album => { const imageUrl = getCoverArtUrl({ - baseUrl: server.url, + baseUrl: server?.url, coverArtId: item.coverArtId || item.id, - credential: server.credential, + credential: server?.credential, size: imageSize || 300, }); @@ -126,7 +126,7 @@ const normalizeAlbum = ( playCount: item.playCount, releaseDate: new Date(item.minYear, 0, 1).toISOString(), releaseYear: item.minYear, - serverId: server.id, + serverId: server?.id || 'unknown', serverType: ServerType.NAVIDROME, size: item.size, songCount: item.songCount, @@ -140,7 +140,7 @@ const normalizeAlbum = ( const normalizeAlbumArtist = ( item: z.infer, - server: ServerListItem, + server: ServerListItem | null, ): AlbumArtist => { const imageUrl = item.largeImageUrl === '/app/artist-placeholder.webp' ? null : item.largeImageUrl; @@ -157,7 +157,7 @@ const normalizeAlbumArtist = ( lastPlayedAt: item.playDate.includes('0001-') ? null : item.playDate, name: item.name, playCount: item.playCount, - serverId: server.id, + serverId: server?.id || 'unknown', serverType: ServerType.NAVIDROME, similarArtists: null, // similarArtists: @@ -174,13 +174,13 @@ const normalizeAlbumArtist = ( const normalizePlaylist = ( item: z.infer, - server: ServerListItem, + server: ServerListItem | null, imageSize?: number, ): Playlist => { const imageUrl = getCoverArtUrl({ - baseUrl: server.url, + baseUrl: server?.url, coverArtId: item.id, - credential: server.credential, + credential: server?.credential, size: imageSize || 300, }); @@ -199,7 +199,7 @@ const normalizePlaylist = ( ownerId: item.ownerId, public: item.public, rules: item?.rules || null, - serverId: server.id, + serverId: server?.id || 'unknown', serverType: ServerType.NAVIDROME, size: item.size, songCount: item.songCount, diff --git a/src/renderer/api/subsonic/subsonic-api.ts b/src/renderer/api/subsonic/subsonic-api.ts index 09b7adb0..601119be 100644 --- a/src/renderer/api/subsonic/subsonic-api.ts +++ b/src/renderer/api/subsonic/subsonic-api.ts @@ -1,8 +1,9 @@ import { initClient, initContract } from '@ts-rest/core'; import axios, { Method, AxiosError, isAxiosError, AxiosResponse } from 'axios'; +import { z } from 'zod'; import { ssType } from '/@/renderer/api/subsonic/subsonic-types'; import { ServerListItem } from '/@/renderer/api/types'; -import { toast } from '/@/renderer/components'; +import { toast } from '/@/renderer/components/toast/index'; const c = initContract(); @@ -88,7 +89,7 @@ axiosClient.interceptors.response.use( } } - return data['subsonic-response']; + return response; }, (error) => { return Promise.reject(error); @@ -96,7 +97,7 @@ axiosClient.interceptors.response.use( ); export const ssApiClient = (args: { - server?: ServerListItem; + server: ServerListItem | null; signal?: AbortSignal; url?: string; }) => { @@ -124,7 +125,7 @@ export const ssApiClient = (args: { } try { - const result = await axiosClient.request({ + const result = await axiosClient.request>({ data: body, headers, method: method as Method, @@ -137,8 +138,9 @@ export const ssApiClient = (args: { signal, url: `${baseUrl}/${path}`, }); + return { - body: { data: result.data, headers: result.headers }, + body: result.data['subsonic-response'], status: result.status, }; } catch (e: Error | AxiosError | any) { @@ -146,7 +148,7 @@ export const ssApiClient = (args: { const error = e as AxiosError; const response = error.response as AxiosResponse; return { - body: { data: response.data, headers: response.headers }, + body: response.data, status: response.status, }; } diff --git a/src/renderer/api/subsonic/subsonic-controller.ts b/src/renderer/api/subsonic/subsonic-controller.ts index 1e2302d4..e54adc24 100644 --- a/src/renderer/api/subsonic/subsonic-controller.ts +++ b/src/renderer/api/subsonic/subsonic-controller.ts @@ -55,7 +55,7 @@ const authenticate = async ( }; } - await ssApiClient({ url: cleanServerUrl }).authenticate({ + await ssApiClient({ server: null, url: cleanServerUrl }).authenticate({ query: { c: 'Feishin', f: 'json', @@ -261,9 +261,11 @@ const getTopSongList = async (args: TopSongListArgs): Promise } return { - items: res.body.topSongs.song.map((song) => ssNormalize.song(song, apiClientProps.server, '')), + items: + res.body.topSongs?.song?.map((song) => ssNormalize.song(song, apiClientProps.server, '')) || + [], startIndex: 0, - totalRecordCount: res.body.topSongs.song.length || 0, + totalRecordCount: res.body.topSongs?.song?.length || 0, }; }; diff --git a/src/renderer/api/subsonic/subsonic-normalize.ts b/src/renderer/api/subsonic/subsonic-normalize.ts index 48ecd97e..ffc10ad9 100644 --- a/src/renderer/api/subsonic/subsonic-normalize.ts +++ b/src/renderer/api/subsonic/subsonic-normalize.ts @@ -5,9 +5,9 @@ import { QueueSong, LibraryItem } from '/@/renderer/api/types'; import { ServerListItem, ServerType } from '/@/renderer/types'; const getCoverArtUrl = (args: { - baseUrl: string; + baseUrl: string | undefined; coverArtId?: string; - credential: string; + credential: string | undefined; size: number; }) => { const size = args.size ? args.size : 150; @@ -28,18 +28,18 @@ const getCoverArtUrl = (args: { const normalizeSong = ( item: z.infer, - server: ServerListItem, + server: ServerListItem | null, deviceId: string, ): QueueSong => { const imageUrl = getCoverArtUrl({ - baseUrl: server.url, + baseUrl: server?.url, coverArtId: item.coverArt, - credential: server.credential, - size: 300, + credential: server?.credential, + size: 100, }) || null; - const streamUrl = `${server.url}/rest/stream.view?id=${item.id}&v=1.13.0&c=feishin_${deviceId}&${server.credential}`; + const streamUrl = `${server?.url}/rest/stream.view?id=${item.id}&v=1.13.0&c=feishin_${deviceId}&${server?.credential}`; return { album: item.album || '', @@ -86,7 +86,7 @@ const normalizeSong = ( playCount: item?.playCount || 0, releaseDate: null, releaseYear: item.year ? String(item.year) : null, - serverId: server.id, + serverId: server?.id || 'unknown', serverType: ServerType.SUBSONIC, size: item.size, streamUrl, diff --git a/src/renderer/api/types.ts b/src/renderer/api/types.ts index 02b5bd20..65bd058e 100644 --- a/src/renderer/api/types.ts +++ b/src/renderer/api/types.ts @@ -276,7 +276,7 @@ export type ListSortOrder = NDOrder | JFSortOrder; type BaseEndpointArgs = { apiClientProps: { - server: ServerListItem; + server: ServerListItem | null; signal?: AbortSignal; }; }; @@ -776,7 +776,7 @@ export type RemoveFromPlaylistArgs = { } & BaseEndpointArgs; // Create Playlist -export type CreatePlaylistResponse = null | undefined; +export type CreatePlaylistResponse = { id: string } | undefined; export type CreatePlaylistBody = { _custom?: { @@ -918,6 +918,8 @@ export type PlaylistSongListArgs = { query: PlaylistSongListQuery } & BaseEndpoi // Music Folder List export type MusicFolderListResponse = BasePaginatedResponse; +export type MusicFolderListQuery = null; + export type MusicFolderListArgs = BaseEndpointArgs; // User list