mirror of
https://github.com/antebudimir/feishin.git
synced 2026-01-03 03:11:40 +00:00
reorganize global types to shared directory
This commit is contained in:
parent
26c02e03c5
commit
9db2e51d2d
17 changed files with 160 additions and 144 deletions
327
src/shared/api/subsonic/subsonic-normalize.ts
Normal file
327
src/shared/api/subsonic/subsonic-normalize.ts
Normal file
|
|
@ -0,0 +1,327 @@
|
|||
import { nanoid } from 'nanoid';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { ssType } from '/@/shared/api/subsonic/subsonic-types';
|
||||
import {
|
||||
Album,
|
||||
AlbumArtist,
|
||||
Genre,
|
||||
LibraryItem,
|
||||
Playlist,
|
||||
QueueSong,
|
||||
RelatedArtist,
|
||||
ServerListItem,
|
||||
ServerType,
|
||||
} from '/@/shared/types/domain-types';
|
||||
|
||||
const getCoverArtUrl = (args: {
|
||||
baseUrl: string | undefined;
|
||||
coverArtId?: string;
|
||||
credential: string | undefined;
|
||||
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 getArtists = (
|
||||
item:
|
||||
| z.infer<typeof ssType._response.album>
|
||||
| z.infer<typeof ssType._response.albumListEntry>
|
||||
| z.infer<typeof ssType._response.song>,
|
||||
) => {
|
||||
const albumArtists: RelatedArtist[] = item.albumArtists
|
||||
? item.albumArtists.map((item) => ({
|
||||
id: item.id.toString(),
|
||||
imageUrl: null,
|
||||
name: item.name,
|
||||
}))
|
||||
: [
|
||||
{
|
||||
id: item.artistId?.toString() || '',
|
||||
imageUrl: null,
|
||||
name: item.artist || '',
|
||||
},
|
||||
];
|
||||
|
||||
const artists: RelatedArtist[] = item.artists
|
||||
? item.artists.map((item) => ({
|
||||
id: item.id.toString(),
|
||||
imageUrl: null,
|
||||
name: item.name,
|
||||
}))
|
||||
: [
|
||||
{
|
||||
id: item.artistId?.toString() || '',
|
||||
imageUrl: null,
|
||||
name: item.artist || '',
|
||||
},
|
||||
];
|
||||
|
||||
let participants: null | Record<string, RelatedArtist[]> = null;
|
||||
|
||||
if (item.contributors) {
|
||||
participants = {};
|
||||
|
||||
for (const contributor of item.contributors) {
|
||||
const artist = {
|
||||
id: contributor.artist.id?.toString() || '',
|
||||
imageUrl: null,
|
||||
name: contributor.artist.name || '',
|
||||
};
|
||||
|
||||
const role = contributor.subRole
|
||||
? `${contributor.role} (${contributor.subRole})`
|
||||
: contributor.role;
|
||||
|
||||
if (role in participants) {
|
||||
participants[role].push(artist);
|
||||
} else {
|
||||
participants[role] = [artist];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { albumArtists, artists, participants };
|
||||
};
|
||||
|
||||
const getGenres = (
|
||||
item:
|
||||
| z.infer<typeof ssType._response.album>
|
||||
| z.infer<typeof ssType._response.albumListEntry>
|
||||
| z.infer<typeof ssType._response.song>,
|
||||
): Genre[] => {
|
||||
return item.genres
|
||||
? item.genres.map((genre) => ({
|
||||
id: genre.name,
|
||||
imageUrl: null,
|
||||
itemType: LibraryItem.GENRE,
|
||||
name: genre.name,
|
||||
}))
|
||||
: item.genre
|
||||
? [
|
||||
{
|
||||
id: item.genre,
|
||||
imageUrl: null,
|
||||
itemType: LibraryItem.GENRE,
|
||||
name: item.genre,
|
||||
},
|
||||
]
|
||||
: [];
|
||||
};
|
||||
|
||||
const normalizeSong = (
|
||||
item: z.infer<typeof ssType._response.song>,
|
||||
server: null | ServerListItem,
|
||||
size?: number,
|
||||
): QueueSong => {
|
||||
const imageUrl =
|
||||
getCoverArtUrl({
|
||||
baseUrl: server?.url,
|
||||
coverArtId: item.coverArt?.toString(),
|
||||
credential: server?.credential,
|
||||
size: size || 300,
|
||||
}) || null;
|
||||
|
||||
const streamUrl = `${server?.url}/rest/stream.view?id=${item.id}&v=1.13.0&c=Feishin&${server?.credential}`;
|
||||
|
||||
return {
|
||||
album: item.album || '',
|
||||
albumId: item.albumId?.toString() || '',
|
||||
artistName: item.artist || '',
|
||||
...getArtists(item),
|
||||
bitRate: item.bitRate || 0,
|
||||
bpm: item.bpm || null,
|
||||
channels: null,
|
||||
comment: null,
|
||||
compilation: null,
|
||||
container: item.contentType,
|
||||
createdAt: item.created,
|
||||
discNumber: item.discNumber || 1,
|
||||
discSubtitle: null,
|
||||
duration: item.duration ? item.duration * 1000 : 0,
|
||||
gain:
|
||||
item.replayGain && (item.replayGain.albumGain || item.replayGain.trackGain)
|
||||
? {
|
||||
album: item.replayGain.albumGain,
|
||||
track: item.replayGain.trackGain,
|
||||
}
|
||||
: null,
|
||||
genres: getGenres(item),
|
||||
id: item.id.toString(),
|
||||
imagePlaceholderUrl: null,
|
||||
imageUrl,
|
||||
itemType: LibraryItem.SONG,
|
||||
lastPlayedAt: null,
|
||||
lyrics: null,
|
||||
name: item.title,
|
||||
path: item.path,
|
||||
peak:
|
||||
item.replayGain && (item.replayGain.albumPeak || item.replayGain.trackPeak)
|
||||
? {
|
||||
album: item.replayGain.albumPeak,
|
||||
track: item.replayGain.trackPeak,
|
||||
}
|
||||
: null,
|
||||
playCount: item?.playCount || 0,
|
||||
releaseDate: null,
|
||||
releaseYear: item.year ? String(item.year) : null,
|
||||
serverId: server?.id || 'unknown',
|
||||
serverType: ServerType.SUBSONIC,
|
||||
size: item.size,
|
||||
streamUrl,
|
||||
tags: null,
|
||||
trackNumber: item.track || 1,
|
||||
uniqueId: nanoid(),
|
||||
updatedAt: '',
|
||||
userFavorite: item.starred || false,
|
||||
userRating: item.userRating || null,
|
||||
};
|
||||
};
|
||||
|
||||
const normalizeAlbumArtist = (
|
||||
item:
|
||||
| z.infer<typeof ssType._response.albumArtist>
|
||||
| z.infer<typeof ssType._response.artistListEntry>,
|
||||
server: null | ServerListItem,
|
||||
imageSize?: number,
|
||||
): AlbumArtist => {
|
||||
const imageUrl =
|
||||
getCoverArtUrl({
|
||||
baseUrl: server?.url,
|
||||
coverArtId: item.coverArt?.toString(),
|
||||
credential: server?.credential,
|
||||
size: imageSize || 100,
|
||||
}) || null;
|
||||
|
||||
return {
|
||||
albumCount: item.albumCount ? Number(item.albumCount) : 0,
|
||||
backgroundImageUrl: null,
|
||||
biography: null,
|
||||
duration: null,
|
||||
genres: [],
|
||||
id: item.id.toString(),
|
||||
imageUrl,
|
||||
itemType: LibraryItem.ALBUM_ARTIST,
|
||||
lastPlayedAt: null,
|
||||
mbz: null,
|
||||
name: item.name,
|
||||
playCount: null,
|
||||
serverId: server?.id || 'unknown',
|
||||
serverType: ServerType.SUBSONIC,
|
||||
similarArtists: [],
|
||||
songCount: null,
|
||||
userFavorite: false,
|
||||
userRating: null,
|
||||
};
|
||||
};
|
||||
|
||||
const normalizeAlbum = (
|
||||
item: z.infer<typeof ssType._response.album> | z.infer<typeof ssType._response.albumListEntry>,
|
||||
server: null | ServerListItem,
|
||||
imageSize?: number,
|
||||
): Album => {
|
||||
const imageUrl =
|
||||
getCoverArtUrl({
|
||||
baseUrl: server?.url,
|
||||
coverArtId: item.coverArt?.toString(),
|
||||
credential: server?.credential,
|
||||
size: imageSize || 300,
|
||||
}) || null;
|
||||
|
||||
return {
|
||||
albumArtist: item.artist,
|
||||
...getArtists(item),
|
||||
backdropImageUrl: null,
|
||||
comment: null,
|
||||
createdAt: item.created,
|
||||
duration: item.duration * 1000,
|
||||
genres: getGenres(item),
|
||||
id: item.id.toString(),
|
||||
imagePlaceholderUrl: null,
|
||||
imageUrl,
|
||||
isCompilation: null,
|
||||
itemType: LibraryItem.ALBUM,
|
||||
lastPlayedAt: null,
|
||||
mbzId: null,
|
||||
name: item.name,
|
||||
originalDate: null,
|
||||
playCount: null,
|
||||
releaseDate: item.year ? new Date(Date.UTC(item.year, 0, 1)).toISOString() : null,
|
||||
releaseYear: item.year ? Number(item.year) : null,
|
||||
serverId: server?.id || 'unknown',
|
||||
serverType: ServerType.SUBSONIC,
|
||||
size: null,
|
||||
songCount: item.songCount,
|
||||
songs:
|
||||
(item as z.infer<typeof ssType._response.album>).song?.map((song) =>
|
||||
normalizeSong(song, server),
|
||||
) || [],
|
||||
tags: item.tags || null,
|
||||
uniqueId: nanoid(),
|
||||
updatedAt: item.created,
|
||||
userFavorite: item.starred || false,
|
||||
userRating: item.userRating || null,
|
||||
};
|
||||
};
|
||||
|
||||
const normalizePlaylist = (
|
||||
item:
|
||||
| z.infer<typeof ssType._response.playlist>
|
||||
| z.infer<typeof ssType._response.playlistListEntry>,
|
||||
server: null | ServerListItem,
|
||||
): Playlist => {
|
||||
return {
|
||||
description: item.comment || null,
|
||||
duration: item.duration,
|
||||
genres: [],
|
||||
id: item.id.toString(),
|
||||
imagePlaceholderUrl: null,
|
||||
imageUrl: getCoverArtUrl({
|
||||
baseUrl: server?.url,
|
||||
coverArtId: item.coverArt?.toString(),
|
||||
credential: server?.credential,
|
||||
size: 300,
|
||||
}),
|
||||
itemType: LibraryItem.PLAYLIST,
|
||||
name: item.name,
|
||||
owner: item.owner,
|
||||
ownerId: item.owner,
|
||||
public: item.public,
|
||||
serverId: server?.id || 'unknown',
|
||||
serverType: ServerType.SUBSONIC,
|
||||
size: null,
|
||||
songCount: item.songCount,
|
||||
};
|
||||
};
|
||||
|
||||
const normalizeGenre = (item: z.infer<typeof ssType._response.genre>): Genre => {
|
||||
return {
|
||||
albumCount: item.albumCount,
|
||||
id: item.value,
|
||||
imageUrl: null,
|
||||
itemType: LibraryItem.GENRE,
|
||||
name: item.value,
|
||||
songCount: item.songCount,
|
||||
};
|
||||
};
|
||||
|
||||
export const ssNormalize = {
|
||||
album: normalizeAlbum,
|
||||
albumArtist: normalizeAlbumArtist,
|
||||
genre: normalizeGenre,
|
||||
playlist: normalizePlaylist,
|
||||
song: normalizeSong,
|
||||
};
|
||||
609
src/shared/api/subsonic/subsonic-types.ts
Normal file
609
src/shared/api/subsonic/subsonic-types.ts
Normal file
|
|
@ -0,0 +1,609 @@
|
|||
import { z } from 'zod';
|
||||
|
||||
const baseResponse = z.object({
|
||||
'subsonic-response': z.object({
|
||||
status: z.string(),
|
||||
version: z.string(),
|
||||
}),
|
||||
});
|
||||
|
||||
const authenticate = z.null();
|
||||
|
||||
const authenticateParameters = z.object({
|
||||
c: z.string(),
|
||||
f: z.string(),
|
||||
p: z.string().optional(),
|
||||
s: z.string().optional(),
|
||||
t: z.string().optional(),
|
||||
u: z.string(),
|
||||
v: z.string(),
|
||||
});
|
||||
|
||||
const id = z.number().or(z.string());
|
||||
|
||||
const createFavoriteParameters = z.object({
|
||||
albumId: z.array(z.string()).optional(),
|
||||
artistId: z.array(z.string()).optional(),
|
||||
id: z.array(z.string()).optional(),
|
||||
});
|
||||
|
||||
const createFavorite = z.null();
|
||||
|
||||
const removeFavoriteParameters = z.object({
|
||||
albumId: z.array(z.string()).optional(),
|
||||
artistId: z.array(z.string()).optional(),
|
||||
id: z.array(z.string()).optional(),
|
||||
});
|
||||
|
||||
const removeFavorite = z.null();
|
||||
|
||||
const setRatingParameters = z.object({
|
||||
id: z.string(),
|
||||
rating: z.number(),
|
||||
});
|
||||
|
||||
const setRating = z.null();
|
||||
|
||||
const musicFolder = z.object({
|
||||
id,
|
||||
name: z.string(),
|
||||
});
|
||||
|
||||
const musicFolderList = z.object({
|
||||
musicFolders: z.object({
|
||||
musicFolder: z.array(musicFolder),
|
||||
}),
|
||||
});
|
||||
|
||||
const songGain = z.object({
|
||||
albumGain: z.number().optional(),
|
||||
albumPeak: z.number().optional(),
|
||||
trackGain: z.number().optional(),
|
||||
trackPeak: z.number().optional(),
|
||||
});
|
||||
|
||||
const genreItem = z.object({
|
||||
name: z.string(),
|
||||
});
|
||||
|
||||
const simpleArtist = z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
});
|
||||
|
||||
const contributor = z.object({
|
||||
artist: simpleArtist,
|
||||
role: z.string(),
|
||||
subRole: z.string().optional(),
|
||||
});
|
||||
|
||||
const song = z.object({
|
||||
album: z.string().optional(),
|
||||
albumArtists: z.array(simpleArtist),
|
||||
albumId: id.optional(),
|
||||
artist: z.string().optional(),
|
||||
artistId: id.optional(),
|
||||
artists: z.array(simpleArtist),
|
||||
averageRating: z.number().optional(),
|
||||
bitRate: z.number().optional(),
|
||||
bpm: z.number().optional(),
|
||||
contentType: z.string(),
|
||||
contributors: z.array(contributor).optional(),
|
||||
coverArt: z.string().optional(),
|
||||
created: z.string(),
|
||||
discNumber: z.number(),
|
||||
duration: z.number().optional(),
|
||||
genre: z.string().optional(),
|
||||
genres: z.array(genreItem).optional(),
|
||||
id,
|
||||
isDir: z.boolean(),
|
||||
isVideo: z.boolean(),
|
||||
musicBrainzId: z.string().optional(),
|
||||
parent: z.string(),
|
||||
path: z.string(),
|
||||
playCount: z.number().optional(),
|
||||
replayGain: songGain.optional(),
|
||||
size: z.number(),
|
||||
starred: z.boolean().optional(),
|
||||
suffix: z.string(),
|
||||
title: z.string(),
|
||||
track: z.number().optional(),
|
||||
type: z.string(),
|
||||
userRating: z.number().optional(),
|
||||
year: z.number().optional(),
|
||||
});
|
||||
|
||||
const album = z.object({
|
||||
album: z.string(),
|
||||
albumArtists: z.array(simpleArtist),
|
||||
artist: z.string(),
|
||||
artistId: id,
|
||||
artists: z.array(simpleArtist),
|
||||
contributors: z.array(contributor).optional(),
|
||||
coverArt: z.string(),
|
||||
created: z.string(),
|
||||
duration: z.number(),
|
||||
genre: z.string().optional(),
|
||||
genres: z.array(genreItem).optional(),
|
||||
id,
|
||||
isCompilation: z.boolean().optional(),
|
||||
isDir: z.boolean(),
|
||||
isVideo: z.boolean(),
|
||||
name: z.string(),
|
||||
parent: z.string(),
|
||||
song: z.array(song),
|
||||
songCount: z.number(),
|
||||
starred: z.boolean().optional(),
|
||||
title: z.string(),
|
||||
userRating: z.number().optional(),
|
||||
year: z.number().optional(),
|
||||
});
|
||||
|
||||
const albumListEntry = album.omit({
|
||||
song: true,
|
||||
});
|
||||
|
||||
const albumListParameters = z.object({
|
||||
fromYear: z.number().optional(),
|
||||
genre: z.string().optional(),
|
||||
musicFolderId: z.string().optional(),
|
||||
offset: z.number().optional(),
|
||||
size: z.number().optional(),
|
||||
toYear: z.number().optional(),
|
||||
type: z.string().optional(),
|
||||
});
|
||||
|
||||
const albumList = z.array(album.omit({ song: true }));
|
||||
|
||||
const albumArtist = z.object({
|
||||
album: z.array(album).optional(),
|
||||
albumCount: z.string(),
|
||||
artistImageUrl: z.string().optional(),
|
||||
coverArt: z.string().optional(),
|
||||
id,
|
||||
name: z.string(),
|
||||
roles: z.array(z.string()).optional(),
|
||||
starred: z.string().optional(),
|
||||
});
|
||||
|
||||
const albumArtistList = z.object({
|
||||
artist: z.array(albumArtist),
|
||||
name: z.string(),
|
||||
});
|
||||
|
||||
const artistListEntry = albumArtist.pick({
|
||||
albumCount: true,
|
||||
coverArt: true,
|
||||
id: true,
|
||||
name: true,
|
||||
roles: true,
|
||||
starred: true,
|
||||
});
|
||||
|
||||
const artistInfoParameters = z.object({
|
||||
count: z.number().optional(),
|
||||
id: z.string(),
|
||||
includeNotPresent: z.boolean().optional(),
|
||||
});
|
||||
|
||||
const artistInfo = z.object({
|
||||
artistInfo: z.object({
|
||||
biography: z.string().optional(),
|
||||
largeImageUrl: z.string().optional(),
|
||||
lastFmUrl: z.string().optional(),
|
||||
mediumImageUrl: z.string().optional(),
|
||||
musicBrainzId: z.string().optional(),
|
||||
similarArtist: z.array(
|
||||
z.object({
|
||||
albumCount: z.string(),
|
||||
artistImageUrl: z.string().optional(),
|
||||
coverArt: z.string().optional(),
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
}),
|
||||
),
|
||||
smallImageUrl: z.string().optional(),
|
||||
}),
|
||||
});
|
||||
|
||||
const topSongsListParameters = z.object({
|
||||
artist: z.string(), // The name of the artist, not the artist ID
|
||||
count: z.number().optional(),
|
||||
});
|
||||
|
||||
const topSongsList = z.object({
|
||||
topSongs: z
|
||||
.object({
|
||||
song: z.array(song),
|
||||
})
|
||||
.optional(),
|
||||
});
|
||||
|
||||
const scrobbleParameters = z.object({
|
||||
id: z.string(),
|
||||
submission: z.boolean().optional(),
|
||||
time: z.number().optional(), // The time (in milliseconds since 1 Jan 1970) at which the song was listened to.
|
||||
});
|
||||
|
||||
const scrobble = z.null();
|
||||
|
||||
const search3 = z.object({
|
||||
searchResult3: z
|
||||
.object({
|
||||
album: z.array(album).optional(),
|
||||
artist: z.array(albumArtist).optional(),
|
||||
song: z.array(song).optional(),
|
||||
})
|
||||
.optional(),
|
||||
});
|
||||
|
||||
const search3Parameters = z.object({
|
||||
albumCount: z.number().optional(),
|
||||
albumOffset: z.number().optional(),
|
||||
artistCount: z.number().optional(),
|
||||
artistOffset: z.number().optional(),
|
||||
musicFolderId: z.string().optional(),
|
||||
query: z.string().optional(),
|
||||
songCount: z.number().optional(),
|
||||
songOffset: z.number().optional(),
|
||||
});
|
||||
|
||||
const randomSongListParameters = z.object({
|
||||
fromYear: z.number().optional(),
|
||||
genre: z.string().optional(),
|
||||
musicFolderId: z.string().optional(),
|
||||
size: z.number().optional(),
|
||||
toYear: z.number().optional(),
|
||||
});
|
||||
|
||||
const randomSongList = z.object({
|
||||
randomSongs: z
|
||||
.object({
|
||||
song: z.array(song),
|
||||
})
|
||||
.optional(),
|
||||
});
|
||||
|
||||
const ping = z.object({
|
||||
openSubsonic: z.boolean().optional(),
|
||||
serverVersion: z.string().optional(),
|
||||
version: z.string(),
|
||||
});
|
||||
|
||||
const extension = z.object({
|
||||
name: z.string(),
|
||||
versions: z.number().array(),
|
||||
});
|
||||
|
||||
const serverInfo = z.object({
|
||||
openSubsonicExtensions: z.array(extension).optional(),
|
||||
});
|
||||
|
||||
const structuredLyricsParameters = z.object({
|
||||
id: z.string(),
|
||||
});
|
||||
|
||||
const lyricLine = z.object({
|
||||
start: z.number().optional(),
|
||||
value: z.string(),
|
||||
});
|
||||
|
||||
const structuredLyric = z.object({
|
||||
displayArtist: z.string().optional(),
|
||||
displayTitle: z.string().optional(),
|
||||
lang: z.string(),
|
||||
line: z.array(lyricLine),
|
||||
offset: z.number().optional(),
|
||||
synced: z.boolean(),
|
||||
});
|
||||
|
||||
const structuredLyrics = z.object({
|
||||
lyricsList: z
|
||||
.object({
|
||||
structuredLyrics: z.array(structuredLyric).optional(),
|
||||
})
|
||||
.optional(),
|
||||
});
|
||||
|
||||
const similarSongsParameters = z.object({
|
||||
count: z.number().optional(),
|
||||
id: z.string(),
|
||||
});
|
||||
|
||||
const similarSongs = z.object({
|
||||
similarSongs: z
|
||||
.object({
|
||||
song: z.array(song),
|
||||
})
|
||||
.optional(),
|
||||
});
|
||||
|
||||
export enum SubsonicExtensions {
|
||||
FORM_POST = 'formPost',
|
||||
SONG_LYRICS = 'songLyrics',
|
||||
TRANSCODE_OFFSET = 'transcodeOffset',
|
||||
}
|
||||
|
||||
const updatePlaylistParameters = z.object({
|
||||
comment: z.string().optional(),
|
||||
name: z.string().optional(),
|
||||
playlistId: z.string(),
|
||||
public: z.boolean().optional(),
|
||||
songIdToAdd: z.array(z.string()).optional(),
|
||||
songIndexToRemove: z.array(z.string()).optional(),
|
||||
});
|
||||
|
||||
const getStarredParameters = z.object({
|
||||
musicFolderId: z.string().optional(),
|
||||
});
|
||||
|
||||
const getStarred = z.object({
|
||||
starred: z
|
||||
.object({
|
||||
album: z.array(albumListEntry),
|
||||
artist: z.array(artistListEntry),
|
||||
song: z.array(song),
|
||||
})
|
||||
.optional(),
|
||||
});
|
||||
|
||||
const getSongsByGenreParameters = z.object({
|
||||
count: z.number().optional(),
|
||||
genre: z.string(),
|
||||
musicFolderId: z.string().optional(),
|
||||
offset: z.number().optional(),
|
||||
});
|
||||
|
||||
const getSongsByGenre = z.object({
|
||||
songsByGenre: z
|
||||
.object({
|
||||
song: z.array(song),
|
||||
})
|
||||
.optional(),
|
||||
});
|
||||
|
||||
const getAlbumParameters = z.object({
|
||||
id: z.string(),
|
||||
musicFolderId: z.string().optional(),
|
||||
});
|
||||
|
||||
const getAlbum = z.object({
|
||||
album,
|
||||
});
|
||||
|
||||
const getArtistParameters = z.object({
|
||||
id: z.string(),
|
||||
});
|
||||
|
||||
const getArtist = z.object({
|
||||
artist: albumArtist,
|
||||
});
|
||||
|
||||
const getSongParameters = z.object({
|
||||
id: z.string(),
|
||||
});
|
||||
|
||||
const getSong = z.object({
|
||||
song,
|
||||
});
|
||||
|
||||
const getArtistsParameters = z.object({
|
||||
musicFolderId: z.string().optional(),
|
||||
});
|
||||
|
||||
const getArtists = z.object({
|
||||
artists: z.object({
|
||||
ignoredArticles: z.string(),
|
||||
index: z.array(
|
||||
z.object({
|
||||
artist: z.array(artistListEntry),
|
||||
name: z.string(),
|
||||
}),
|
||||
),
|
||||
}),
|
||||
});
|
||||
|
||||
const deletePlaylistParameters = z.object({
|
||||
id: z.string(),
|
||||
});
|
||||
|
||||
const createPlaylistParameters = z.object({
|
||||
name: z.string(),
|
||||
playlistId: z.string().optional(),
|
||||
songId: z.array(z.string()).optional(),
|
||||
});
|
||||
|
||||
const playlist = z.object({
|
||||
changed: z.string().optional(),
|
||||
comment: z.string().optional(),
|
||||
coverArt: z.string().optional(),
|
||||
created: z.string(),
|
||||
duration: z.number(),
|
||||
entry: z.array(song).optional(),
|
||||
id,
|
||||
name: z.string(),
|
||||
owner: z.string(),
|
||||
public: z.boolean(),
|
||||
songCount: z.number(),
|
||||
});
|
||||
|
||||
const createPlaylist = z.object({
|
||||
playlist,
|
||||
});
|
||||
|
||||
const getPlaylistsParameters = z.object({
|
||||
username: z.string().optional(),
|
||||
});
|
||||
|
||||
const playlistListEntry = playlist.omit({
|
||||
entry: true,
|
||||
});
|
||||
|
||||
const getPlaylists = z.object({
|
||||
playlists: z
|
||||
.object({
|
||||
playlist: z.array(playlistListEntry),
|
||||
})
|
||||
.optional(),
|
||||
});
|
||||
|
||||
const getPlaylistParameters = z.object({
|
||||
id: z.string(),
|
||||
});
|
||||
|
||||
const getPlaylist = z.object({
|
||||
playlist,
|
||||
});
|
||||
|
||||
const genre = z.object({
|
||||
albumCount: z.number(),
|
||||
songCount: z.number(),
|
||||
value: z.string(),
|
||||
});
|
||||
|
||||
const getGenresParameters = z.object({});
|
||||
|
||||
const getGenres = z.object({
|
||||
genres: z
|
||||
.object({
|
||||
genre: z.array(genre),
|
||||
})
|
||||
.optional(),
|
||||
});
|
||||
|
||||
export enum AlbumListSortType {
|
||||
ALPHABETICAL_BY_ARTIST = 'alphabeticalByArtist',
|
||||
ALPHABETICAL_BY_NAME = 'alphabeticalByName',
|
||||
BY_GENRE = 'byGenre',
|
||||
BY_YEAR = 'byYear',
|
||||
FREQUENT = 'frequent',
|
||||
NEWEST = 'newest',
|
||||
RANDOM = 'random',
|
||||
RECENT = 'recent',
|
||||
STARRED = 'starred',
|
||||
}
|
||||
|
||||
const getAlbumList2Parameters = z
|
||||
.object({
|
||||
fromYear: z.number().optional(),
|
||||
genre: z.string().optional(),
|
||||
musicFolderId: z.string().optional(),
|
||||
offset: z.number().optional(),
|
||||
size: z.number().optional(),
|
||||
toYear: z.number().optional(),
|
||||
type: z.nativeEnum(AlbumListSortType),
|
||||
})
|
||||
.refine(
|
||||
(val) => {
|
||||
if (val.type === AlbumListSortType.BY_YEAR) {
|
||||
return val.fromYear !== undefined && val.toYear !== undefined;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
{
|
||||
message: 'Parameters "fromYear" and "toYear" are required when using sort "byYear"',
|
||||
},
|
||||
)
|
||||
.refine(
|
||||
(val) => {
|
||||
if (val.type === AlbumListSortType.BY_GENRE) {
|
||||
return val.genre !== undefined;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
{ message: 'Parameter "genre" is required when using sort "byGenre"' },
|
||||
);
|
||||
|
||||
const getAlbumList2 = z.object({
|
||||
albumList2: z.object({
|
||||
album: z.array(albumListEntry),
|
||||
}),
|
||||
});
|
||||
|
||||
const albumInfoParameters = z.object({
|
||||
id: z.string(),
|
||||
});
|
||||
|
||||
const albumInfo = z.object({
|
||||
albumInfo: z.object({
|
||||
largeImageUrl: z.string().optional(),
|
||||
lastFmUrl: z.string().optional(),
|
||||
mediumImageUrl: z.string().optional(),
|
||||
musicBrainzId: z.string().optional(),
|
||||
notes: z.string().optional(),
|
||||
smallImageUrl: z.string().optional(),
|
||||
}),
|
||||
});
|
||||
|
||||
export const ssType = {
|
||||
_parameters: {
|
||||
albumInfo: albumInfoParameters,
|
||||
albumList: albumListParameters,
|
||||
artistInfo: artistInfoParameters,
|
||||
authenticate: authenticateParameters,
|
||||
createFavorite: createFavoriteParameters,
|
||||
createPlaylist: createPlaylistParameters,
|
||||
deletePlaylist: deletePlaylistParameters,
|
||||
getAlbum: getAlbumParameters,
|
||||
getAlbumList2: getAlbumList2Parameters,
|
||||
getArtist: getArtistParameters,
|
||||
getArtists: getArtistsParameters,
|
||||
getGenre: getGenresParameters,
|
||||
getGenres: getGenresParameters,
|
||||
getPlaylist: getPlaylistParameters,
|
||||
getPlaylists: getPlaylistsParameters,
|
||||
getSong: getSongParameters,
|
||||
getSongsByGenre: getSongsByGenreParameters,
|
||||
getStarred: getStarredParameters,
|
||||
randomSongList: randomSongListParameters,
|
||||
removeFavorite: removeFavoriteParameters,
|
||||
scrobble: scrobbleParameters,
|
||||
search3: search3Parameters,
|
||||
setRating: setRatingParameters,
|
||||
similarSongs: similarSongsParameters,
|
||||
structuredLyrics: structuredLyricsParameters,
|
||||
topSongsList: topSongsListParameters,
|
||||
updatePlaylist: updatePlaylistParameters,
|
||||
},
|
||||
_response: {
|
||||
album,
|
||||
albumArtist,
|
||||
albumArtistList,
|
||||
albumInfo,
|
||||
albumList,
|
||||
albumListEntry,
|
||||
artistInfo,
|
||||
artistListEntry,
|
||||
authenticate,
|
||||
baseResponse,
|
||||
createFavorite,
|
||||
createPlaylist,
|
||||
genre,
|
||||
getAlbum,
|
||||
getAlbumList2,
|
||||
getArtist,
|
||||
getArtists,
|
||||
getGenres,
|
||||
getPlaylist,
|
||||
getPlaylists,
|
||||
getSong,
|
||||
getSongsByGenre,
|
||||
getStarred,
|
||||
musicFolderList,
|
||||
ping,
|
||||
playlist,
|
||||
playlistListEntry,
|
||||
randomSongList,
|
||||
removeFavorite,
|
||||
scrobble,
|
||||
search3,
|
||||
serverInfo,
|
||||
setRating,
|
||||
similarSongs,
|
||||
song,
|
||||
structuredLyrics,
|
||||
topSongsList,
|
||||
},
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue