feishin/src/renderer/api/navidrome.api.ts

753 lines
20 KiB
TypeScript
Raw Normal View History

2022-12-19 15:59:14 -08:00
import { nanoid } from 'nanoid/non-secure';
import ky from 'ky';
import type {
NDGenreListResponse,
NDArtistListResponse,
NDAlbumDetail,
NDAlbumListParams,
NDAlbumList,
NDSongDetailResponse,
NDAlbum,
NDSong,
NDAuthenticationResponse,
NDAlbumDetailResponse,
NDSongDetail,
NDGenreList,
NDAlbumArtistListParams,
NDAlbumArtistDetail,
NDAlbumListResponse,
NDAlbumArtistDetailResponse,
NDAlbumArtistList,
NDSongListParams,
NDCreatePlaylistParams,
NDCreatePlaylistResponse,
NDDeletePlaylist,
NDDeletePlaylistResponse,
NDPlaylistListParams,
NDPlaylistDetail,
NDPlaylistList,
NDPlaylistListResponse,
NDPlaylistDetailResponse,
NDSongList,
NDSongListResponse,
2022-12-30 21:04:06 -08:00
NDAlbumArtist,
2022-12-31 03:46:12 -08:00
NDPlaylist,
NDUpdatePlaylistParams,
NDUpdatePlaylistResponse,
2022-12-31 20:08:39 -08:00
NDPlaylistSongListResponse,
NDPlaylistSongList,
NDPlaylistSong,
NDUserList,
NDUserListResponse,
NDUserListParams,
NDUser,
NDAddToPlaylist,
NDAddToPlaylistBody,
NDAddToPlaylistResponse,
NDRemoveFromPlaylistParams,
NDRemoveFromPlaylistResponse,
NDRemoveFromPlaylist,
2022-12-19 15:59:14 -08:00
} from '/@/renderer/api/navidrome.types';
import { NDSongListSort, NDSortOrder } from '/@/renderer/api/navidrome.types';
import {
2022-12-19 15:59:14 -08:00
Album,
Song,
AuthenticationResponse,
AlbumDetailArgs,
GenreListArgs,
AlbumListArgs,
AlbumArtistListArgs,
AlbumArtistDetailArgs,
SongListArgs,
SongDetailArgs,
CreatePlaylistArgs,
DeletePlaylistArgs,
PlaylistListArgs,
PlaylistDetailArgs,
CreatePlaylistResponse,
PlaylistSongListArgs,
2022-12-30 21:04:06 -08:00
AlbumArtist,
2022-12-31 03:46:12 -08:00
Playlist,
UpdatePlaylistResponse,
UpdatePlaylistArgs,
UserListArgs,
userListSortMap,
2022-12-19 15:59:14 -08:00
playlistListSortMap,
albumArtistListSortMap,
songListSortMap,
albumListSortMap,
sortOrderMap,
User,
2023-01-06 00:39:49 -08:00
LibraryItem,
AddToPlaylistArgs,
RemoveFromPlaylistArgs,
2022-12-19 15:59:14 -08:00
} from '/@/renderer/api/types';
2022-12-20 04:11:18 -08:00
import { toast } from '/@/renderer/components/toast';
2022-12-19 15:59:14 -08:00
import { useAuthStore } from '/@/renderer/store';
import { ServerListItem, ServerType } from '/@/renderer/types';
import { parseSearchParams } from '/@/renderer/utils';
2023-01-12 18:43:25 -08:00
import { subsonicApi } from '/@/renderer/api/subsonic.api';
2022-12-19 15:59:14 -08:00
const api = ky.create({
hooks: {
afterResponse: [
async (_request, _options, response) => {
const serverId = useAuthStore.getState().currentServer?.id;
if (serverId) {
useAuthStore.getState().actions.updateServer(serverId, {
ndCredential: response.headers.get('x-nd-authorization') as string,
});
}
return response;
},
],
beforeError: [
(error) => {
if (error.response && error.response.status === 401) {
toast.error({
message: 'Your session has expired.',
});
const serverId = useAuthStore.getState().currentServer?.id;
if (serverId) {
useAuthStore.getState().actions.setCurrentServer(null);
useAuthStore.getState().actions.updateServer(serverId, { ndCredential: undefined });
}
}
return error;
},
],
},
});
const authenticate = async (
url: string,
body: { password: string; username: string },
): Promise<AuthenticationResponse> => {
const cleanServerUrl = url.replace(/\/$/, '');
const data = await ky
.post(`${cleanServerUrl}/auth/login`, {
json: {
password: body.password,
username: body.username,
},
})
.json<NDAuthenticationResponse>();
return {
credential: `u=${body.username}&s=${data.subsonicSalt}&t=${data.subsonicToken}`,
ndCredential: data.token,
userId: data.id,
username: data.username,
};
};
const getUserList = async (args: UserListArgs): Promise<NDUserList> => {
const { query, server, signal } = args;
const searchParams: NDUserListParams = {
_end: query.startIndex + (query.limit || 0),
_order: sortOrderMap.navidrome[query.sortOrder],
_sort: userListSortMap.navidrome[query.sortBy],
_start: query.startIndex,
...query.ndParams,
};
const res = await api.get('api/user', {
headers: { 'x-nd-authorization': `Bearer ${server?.ndCredential}` },
prefixUrl: server?.url,
searchParams: parseSearchParams(searchParams),
signal,
});
const data = await res.json<NDUserListResponse>();
const itemCount = res.headers.get('x-total-count');
return {
items: data,
startIndex: query?.startIndex || 0,
totalRecordCount: Number(itemCount),
};
};
2022-12-19 15:59:14 -08:00
const getGenreList = async (args: GenreListArgs): Promise<NDGenreList> => {
const { server, signal } = args;
const data = await api
.get('api/genre', {
headers: { 'x-nd-authorization': `Bearer ${server?.ndCredential}` },
prefixUrl: server?.url,
signal,
})
.json<NDGenreListResponse>();
return data;
};
const getAlbumArtistDetail = async (args: AlbumArtistDetailArgs): Promise<NDAlbumArtistDetail> => {
const { query, server, signal } = args;
2023-01-12 18:43:25 -08:00
const artistInfo = await subsonicApi.getArtistInfo({
query: {
artistId: query.id,
limit: 15,
},
server,
signal,
});
2022-12-19 15:59:14 -08:00
const data = await api
.get(`api/artist/${query.id}`, {
headers: { 'x-nd-authorization': `Bearer ${server?.ndCredential}` },
prefixUrl: server?.url,
signal,
})
.json<NDAlbumArtistDetailResponse>();
2023-01-12 18:43:25 -08:00
return { ...data, similarArtists: artistInfo.similarArtist };
2022-12-19 15:59:14 -08:00
};
const getAlbumArtistList = async (args: AlbumArtistListArgs): Promise<NDAlbumArtistList> => {
const { query, server, signal } = args;
const searchParams: NDAlbumArtistListParams = {
_end: query.startIndex + (query.limit || 0),
_order: sortOrderMap.navidrome[query.sortOrder],
_sort: albumArtistListSortMap.navidrome[query.sortBy],
_start: query.startIndex,
2022-12-30 22:54:00 -08:00
name: query.searchTerm,
2022-12-19 15:59:14 -08:00
...query.ndParams,
};
2022-12-30 21:04:06 -08:00
const res = await api.get('api/artist', {
headers: { 'x-nd-authorization': `Bearer ${server?.ndCredential}` },
prefixUrl: server?.url,
searchParams: parseSearchParams(searchParams),
signal,
});
2022-12-19 15:59:14 -08:00
2022-12-30 21:04:06 -08:00
const data = await res.json<NDArtistListResponse>();
const itemCount = res.headers.get('x-total-count');
return {
items: data,
startIndex: query.startIndex,
totalRecordCount: Number(itemCount),
};
2022-12-19 15:59:14 -08:00
};
const getAlbumDetail = async (args: AlbumDetailArgs): Promise<NDAlbumDetail> => {
const { query, server, signal } = args;
const data = await api
.get(`api/album/${query.id}`, {
headers: { 'x-nd-authorization': `Bearer ${server?.ndCredential}` },
prefixUrl: server?.url,
signal,
})
.json<NDAlbumDetailResponse>();
const songsData = await api
.get('api/song', {
headers: { 'x-nd-authorization': `Bearer ${server?.ndCredential}` },
prefixUrl: server?.url,
searchParams: {
_end: 0,
_order: NDSortOrder.ASC,
_sort: 'album',
_start: 0,
album_id: query.id,
},
signal,
})
.json<NDSongListResponse>();
return { ...data, songs: songsData };
};
const getAlbumList = async (args: AlbumListArgs): Promise<NDAlbumList> => {
const { query, server, signal } = args;
const searchParams: NDAlbumListParams = {
_end: query.startIndex + (query.limit || 0),
_order: sortOrderMap.navidrome[query.sortOrder],
_sort: albumListSortMap.navidrome[query.sortBy],
_start: query.startIndex,
2022-12-21 01:27:19 -08:00
name: query.searchTerm,
2022-12-19 15:59:14 -08:00
...query.ndParams,
};
const res = await api.get('api/album', {
headers: { 'x-nd-authorization': `Bearer ${server?.ndCredential}` },
prefixUrl: server?.url,
2022-12-22 01:58:11 -08:00
searchParams: parseSearchParams(searchParams),
2022-12-19 15:59:14 -08:00
signal,
});
const data = await res.json<NDAlbumListResponse>();
const itemCount = res.headers.get('x-total-count');
return {
items: data,
startIndex: query?.startIndex || 0,
totalRecordCount: Number(itemCount),
};
};
const getSongList = async (args: SongListArgs): Promise<NDSongList> => {
const { query, server, signal } = args;
const searchParams: NDSongListParams = {
_end: query.startIndex + (query.limit || -1),
2022-12-19 15:59:14 -08:00
_order: sortOrderMap.navidrome[query.sortOrder],
_sort: songListSortMap.navidrome[query.sortBy],
_start: query.startIndex,
2022-12-28 19:17:55 -08:00
album_id: query.albumIds,
2022-12-30 21:04:06 -08:00
artist_id: query.artistIds,
2022-12-27 13:20:22 -08:00
title: query.searchTerm,
2022-12-19 15:59:14 -08:00
...query.ndParams,
};
const res = await api.get('api/song', {
headers: { 'x-nd-authorization': `Bearer ${server?.ndCredential}` },
prefixUrl: server?.url,
2022-12-27 13:20:22 -08:00
searchParams: parseSearchParams(searchParams),
2022-12-19 15:59:14 -08:00
signal,
});
const data = await res.json<NDSongListResponse>();
const itemCount = res.headers.get('x-total-count');
return {
items: data,
startIndex: query?.startIndex || 0,
totalRecordCount: Number(itemCount),
};
};
const getSongDetail = async (args: SongDetailArgs): Promise<NDSongDetail> => {
const { query, server, signal } = args;
const data = await api
.get(`api/song/${query.id}`, {
headers: { 'x-nd-authorization': `Bearer ${server?.ndCredential}` },
prefixUrl: server?.url,
signal,
})
.json<NDSongDetailResponse>();
return data;
};
const createPlaylist = async (args: CreatePlaylistArgs): Promise<CreatePlaylistResponse> => {
const { body, server } = args;
2022-12-19 15:59:14 -08:00
const json: NDCreatePlaylistParams = {
comment: body.comment,
name: body.name,
...body.ndParams,
public: body.ndParams?.public || false,
rules: body.ndParams?.rules ? body.ndParams.rules : undefined,
2022-12-19 15:59:14 -08:00
};
const data = await api
.post('api/playlist', {
headers: { 'x-nd-authorization': `Bearer ${server?.ndCredential}` },
json,
prefixUrl: server?.url,
})
.json<NDCreatePlaylistResponse>();
return {
id: data.id,
name: body.name,
2022-12-19 15:59:14 -08:00
};
};
const updatePlaylist = async (args: UpdatePlaylistArgs): Promise<UpdatePlaylistResponse> => {
2022-12-31 18:03:26 -08:00
const { query, body, server, signal } = args;
const json: NDUpdatePlaylistParams = {
2022-12-31 18:03:26 -08:00
comment: body.comment || '',
name: body.name,
ownerId: body.ndParams?.ownerId || undefined,
ownerName: body.ndParams?.owner || undefined,
public: body.ndParams?.public || false,
rules: body.ndParams?.rules ? body.ndParams?.rules : undefined,
sync: body.ndParams?.sync || undefined,
};
const data = await api
2023-01-03 00:28:09 -08:00
.put(`api/playlist/${query.id}`, {
headers: { 'x-nd-authorization': `Bearer ${server?.ndCredential}` },
json,
prefixUrl: server?.url,
signal,
})
.json<NDUpdatePlaylistResponse>();
return {
id: data.id,
};
};
2022-12-19 15:59:14 -08:00
const deletePlaylist = async (args: DeletePlaylistArgs): Promise<NDDeletePlaylist> => {
const { query, server, signal } = args;
const data = await api
.delete(`api/playlist/${query.id}`, {
headers: { 'x-nd-authorization': `Bearer ${server?.ndCredential}` },
prefixUrl: server?.url,
signal,
})
.json<NDDeletePlaylistResponse>();
return data;
};
const getPlaylistList = async (args: PlaylistListArgs): Promise<NDPlaylistList> => {
const { query, server, signal } = args;
const searchParams: NDPlaylistListParams = {
_end: query.startIndex + (query.limit || 0),
_order: query.sortOrder ? sortOrderMap.navidrome[query.sortOrder] : undefined,
_sort: query.sortBy ? playlistListSortMap.navidrome[query.sortBy] : undefined,
2022-12-19 15:59:14 -08:00
_start: query.startIndex,
2022-12-31 03:46:12 -08:00
...query.ndParams,
2022-12-19 15:59:14 -08:00
};
const res = await api.get('api/playlist', {
headers: { 'x-nd-authorization': `Bearer ${server?.ndCredential}` },
prefixUrl: server?.url,
2022-12-31 03:46:12 -08:00
searchParams: parseSearchParams(searchParams),
2022-12-19 15:59:14 -08:00
signal,
});
const data = await res.json<NDPlaylistListResponse>();
const itemCount = res.headers.get('x-total-count');
return {
items: data,
startIndex: query?.startIndex || 0,
totalRecordCount: Number(itemCount),
};
};
const getPlaylistDetail = async (args: PlaylistDetailArgs): Promise<NDPlaylistDetail> => {
const { query, server, signal } = args;
const data = await api
.get(`api/playlist/${query.id}`, {
headers: { 'x-nd-authorization': `Bearer ${server?.ndCredential}` },
prefixUrl: server?.url,
signal,
})
.json<NDPlaylistDetailResponse>();
return data;
};
2022-12-31 20:08:39 -08:00
const getPlaylistSongList = async (args: PlaylistSongListArgs): Promise<NDPlaylistSongList> => {
2022-12-19 15:59:14 -08:00
const { query, server, signal } = args;
const searchParams: NDSongListParams & { playlist_id: string } = {
_end: query.startIndex + (query.limit || 0),
_order: query.sortOrder ? sortOrderMap.navidrome[query.sortOrder] : NDSortOrder.ASC,
_sort: query.sortBy ? songListSortMap.navidrome[query.sortBy] : NDSongListSort.ID,
_start: query.startIndex,
playlist_id: query.id,
};
2022-12-31 18:03:26 -08:00
const res = await api.get(`api/playlist/${query.id}/tracks`, {
headers: { 'x-nd-authorization': `Bearer ${server?.ndCredential}` },
prefixUrl: server?.url,
searchParams: parseSearchParams(searchParams),
signal,
});
2022-12-31 20:08:39 -08:00
const data = await res.json<NDPlaylistSongListResponse>();
2022-12-31 18:03:26 -08:00
const itemCount = res.headers.get('x-total-count');
2022-12-19 15:59:14 -08:00
return {
items: data,
startIndex: query?.startIndex || 0,
2022-12-31 18:03:26 -08:00
totalRecordCount: Number(itemCount),
2022-12-19 15:59:14 -08:00
};
};
const addToPlaylist = async (args: AddToPlaylistArgs): Promise<NDAddToPlaylist> => {
const { query, body, server, signal } = args;
const json: NDAddToPlaylistBody = {
ids: body.songId,
};
await api
.post(`api/playlist/${query.id}/tracks`, {
headers: { 'x-nd-authorization': `Bearer ${server?.ndCredential}` },
json,
prefixUrl: server?.url,
signal,
})
.json<NDAddToPlaylistResponse>();
return null;
};
const removeFromPlaylist = async (args: RemoveFromPlaylistArgs): Promise<NDRemoveFromPlaylist> => {
const { query, server, signal } = args;
const searchParams: NDRemoveFromPlaylistParams = {
id: query.songId,
};
await api
.delete(`api/playlist/${query.id}/tracks`, {
headers: { 'x-nd-authorization': `Bearer ${server?.ndCredential}` },
prefixUrl: server?.url,
searchParams: parseSearchParams(searchParams),
signal,
})
.json<NDRemoveFromPlaylistResponse>();
return null;
};
2022-12-19 15:59:14 -08:00
const getCoverArtUrl = (args: {
baseUrl: string;
coverArtId: string;
credential: string;
size: number;
}) => {
const size = args.size ? args.size : 250;
if (!args.coverArtId || args.coverArtId.match('2a96cbd8b46e442fc41c2b86b821562f')) {
return null;
}
return (
`${args.baseUrl}/rest/getCoverArt.view` +
`?id=${args.coverArtId}` +
`&${args.credential}` +
'&v=1.13.0' +
'&c=feishin' +
`&size=${size}`
);
};
const normalizeSong = (
2022-12-31 20:08:39 -08:00
item: NDSong | NDPlaylistSong,
2022-12-19 15:59:14 -08:00
server: ServerListItem,
deviceId: string,
imageSize?: number,
): Song => {
let id;
let playlistItemId;
// Dynamically determine the id field based on whether or not the item is a playlist song
if ('mediaFileId' in item) {
id = item.mediaFileId;
playlistItemId = item.id;
} else {
id = item.id;
}
2022-12-19 15:59:14 -08:00
const imageUrl = getCoverArtUrl({
baseUrl: server.url,
coverArtId: id,
2022-12-19 15:59:14 -08:00
credential: server.credential,
size: imageSize || 100,
2022-12-19 15:59:14 -08:00
});
2023-01-03 02:26:43 -08:00
const imagePlaceholderUrl = null;
2022-12-19 15:59:14 -08:00
return {
album: item.album,
2023-01-12 18:43:25 -08:00
albumArtists: [{ id: item.artistId, imageUrl: null, name: item.artist }],
2022-12-19 15:59:14 -08:00
albumId: item.albumId,
artistName: item.artist,
2023-01-12 18:43:25 -08:00
artists: [{ id: item.artistId, imageUrl: null, name: item.artist }],
2022-12-19 15:59:14 -08:00
bitRate: item.bitRate,
2022-12-27 02:00:39 -08:00
bpm: item.bpm ? item.bpm : null,
channels: item.channels ? item.channels : null,
2023-01-05 20:32:02 -08:00
comment: item.comment ? item.comment : null,
2022-12-19 15:59:14 -08:00
compilation: item.compilation,
container: item.suffix,
2022-12-24 13:32:27 -08:00
createdAt: item.createdAt.split('T')[0],
2022-12-19 15:59:14 -08:00
discNumber: item.discNumber,
duration: item.duration,
genres: item.genres,
2022-12-31 20:08:39 -08:00
id,
imagePlaceholderUrl,
2022-12-19 15:59:14 -08:00
imageUrl,
2023-01-06 00:39:49 -08:00
itemType: LibraryItem.SONG,
2023-01-05 20:32:02 -08:00
lastPlayedAt: item.playDate.includes('0001-') ? null : item.playDate,
2022-12-19 15:59:14 -08:00
name: item.title,
path: item.path,
playCount: item.playCount,
playlistItemId,
2022-12-19 15:59:14 -08:00
releaseDate: new Date(item.year, 0, 1).toISOString(),
releaseYear: String(item.year),
serverId: server.id,
2023-01-06 00:39:49 -08:00
serverType: ServerType.NAVIDROME,
2022-12-19 15:59:14 -08:00
size: item.size,
2022-12-31 20:08:39 -08:00
streamUrl: `${server.url}/rest/stream.view?id=${id}&v=1.13.0&c=feishin_${deviceId}&${server.credential}`,
2022-12-19 15:59:14 -08:00
trackNumber: item.trackNumber,
uniqueId: nanoid(),
updatedAt: item.updatedAt,
2023-01-06 00:39:49 -08:00
userFavorite: item.starred || false,
userRating: item.rating || null,
2022-12-19 15:59:14 -08:00
};
};
2022-12-29 17:11:25 -08:00
const normalizeAlbum = (item: NDAlbum, server: ServerListItem, imageSize?: number): Album => {
const imageUrl = getCoverArtUrl({
baseUrl: server.url,
2023-01-02 01:58:31 -08:00
coverArtId: item.coverArtId || item.id,
2022-12-29 17:11:25 -08:00
credential: server.credential,
size: imageSize || 300,
});
const imagePlaceholderUrl = null;
2022-12-30 21:31:13 -08:00
2022-12-29 17:11:25 -08:00
const imageBackdropUrl = imageUrl?.replace(/size=\d+/, 'size=1000') || null;
return {
2023-01-12 18:43:25 -08:00
albumArtists: [{ id: item.albumArtistId, imageUrl: null, name: item.albumArtist }],
artists: [{ id: item.artistId, imageUrl: null, name: item.artist }],
2022-12-29 17:11:25 -08:00
backdropImageUrl: imageBackdropUrl,
createdAt: item.createdAt.split('T')[0],
duration: item.duration * 1000 || null,
2022-12-29 17:11:25 -08:00
genres: item.genres,
id: item.id,
imagePlaceholderUrl,
imageUrl,
isCompilation: item.compilation,
2023-01-06 00:39:49 -08:00
itemType: LibraryItem.ALBUM,
2023-01-05 20:32:02 -08:00
lastPlayedAt: item.playDate.includes('0001-') ? null : item.playDate,
2022-12-29 17:11:25 -08:00
name: item.name,
playCount: item.playCount,
releaseDate: new Date(item.minYear, 0, 1).toISOString(),
releaseYear: item.minYear,
2023-01-06 00:39:49 -08:00
serverId: server.id,
2022-12-29 17:11:25 -08:00
serverType: ServerType.NAVIDROME,
size: item.size,
songCount: item.songCount,
songs: item.songs ? item.songs.map((song) => normalizeSong(song, server, '')) : undefined,
uniqueId: nanoid(),
updatedAt: item.updatedAt,
2023-01-06 00:39:49 -08:00
userFavorite: item.starred,
userRating: item.rating,
2022-12-29 17:11:25 -08:00
};
};
2023-01-06 00:39:49 -08:00
const normalizeAlbumArtist = (item: NDAlbumArtist, server: ServerListItem): AlbumArtist => {
const imageUrl =
item.largeImageUrl === '/app/artist-placeholder.webp' ? null : item.largeImageUrl;
2022-12-30 21:04:06 -08:00
return {
albumCount: item.albumCount,
backgroundImageUrl: null,
2023-01-05 20:32:02 -08:00
biography: item.biography || null,
2022-12-30 21:04:06 -08:00
duration: null,
genres: item.genres,
id: item.id,
imageUrl: imageUrl || null,
2023-01-06 00:39:49 -08:00
itemType: LibraryItem.ALBUM_ARTIST,
2023-01-05 20:32:02 -08:00
lastPlayedAt: item.playDate.includes('0001-') ? null : item.playDate,
2022-12-30 21:04:06 -08:00
name: item.name,
playCount: item.playCount,
2023-01-06 00:39:49 -08:00
serverId: server.id,
serverType: ServerType.NAVIDROME,
2023-01-12 18:43:25 -08:00
similarArtists:
item.similarArtists?.map((artist) => ({
id: artist.id,
imageUrl: artist?.artistImageUrl || null,
name: artist.name,
})) || null,
2022-12-30 21:04:06 -08:00
songCount: item.songCount,
2023-01-06 00:39:49 -08:00
userFavorite: item.starred,
userRating: item.rating,
2022-12-30 21:04:06 -08:00
};
};
2023-01-02 01:58:31 -08:00
const normalizePlaylist = (
item: NDPlaylist,
server: ServerListItem,
imageSize?: number,
): Playlist => {
const imageUrl = getCoverArtUrl({
baseUrl: server.url,
coverArtId: item.id,
credential: server.credential,
size: imageSize || 300,
});
const imagePlaceholderUrl = null;
2023-01-02 01:58:31 -08:00
2022-12-31 03:46:12 -08:00
return {
2023-01-03 00:28:09 -08:00
description: item.comment,
duration: item.duration * 1000,
2023-01-03 03:25:21 -08:00
genres: [],
2022-12-31 03:46:12 -08:00
id: item.id,
2023-01-02 01:58:31 -08:00
imagePlaceholderUrl,
imageUrl,
2023-01-06 00:39:49 -08:00
itemType: LibraryItem.PLAYLIST,
2022-12-31 03:46:12 -08:00
name: item.name,
owner: item.ownerName,
ownerId: item.ownerId,
2022-12-31 03:46:12 -08:00
public: item.public,
rules: item?.rules || null,
2023-01-06 00:39:49 -08:00
serverId: server.id,
serverType: ServerType.NAVIDROME,
2022-12-31 03:46:12 -08:00
size: item.size,
songCount: item.songCount,
sync: item.sync,
};
};
const normalizeUser = (item: NDUser): User => {
return {
createdAt: item.createdAt,
email: item.email,
id: item.id,
isAdmin: item.isAdmin,
lastLoginAt: item.lastLoginAt,
name: item.userName,
updatedAt: item.updatedAt,
2022-12-31 03:46:12 -08:00
};
};
2022-12-19 15:59:14 -08:00
export const navidromeApi = {
addToPlaylist,
2022-12-19 15:59:14 -08:00
authenticate,
createPlaylist,
deletePlaylist,
getAlbumArtistDetail,
getAlbumArtistList,
getAlbumDetail,
getAlbumList,
getGenreList,
getPlaylistDetail,
getPlaylistList,
getPlaylistSongList,
getSongDetail,
getSongList,
getUserList,
removeFromPlaylist,
updatePlaylist,
2022-12-19 15:59:14 -08:00
};
export const ndNormalize = {
album: normalizeAlbum,
2022-12-30 21:04:06 -08:00
albumArtist: normalizeAlbumArtist,
2022-12-31 03:46:12 -08:00
playlist: normalizePlaylist,
2022-12-19 15:59:14 -08:00
song: normalizeSong,
user: normalizeUser,
2022-12-19 15:59:14 -08:00
};