mirror of
https://github.com/kilyabin/psysonic.git
synced 2026-07-22 14:35:41 +00:00
72030f17fd
First Phase F slice. Splits the 1333-LOC `api/subsonic.ts` along its two most obvious axes: - `subsonicTypes.ts` — all ~24 exported interfaces + type aliases (album/song/artist/playlist/directory/genre/now-playing/radio, random-songs filters, three statistics shapes, search + starred results, AlbumInfo, structured-lyrics types, etc.) plus the `RADIO_PAGE_SIZE` constant. - `subsonicClient.ts` — token-auth + `getClient` + `api<T>()` + `libraryFilterParams` + `secureRandomSalt` / `getAuthParams` / `SUBSONIC_CLIENT`. The credential-bearing API helpers (`pingWithCredentials`, `apiWithCredentials`, `restBaseFromUrl`, `probeInstantMixWithCredentials`) stay in `subsonic.ts` for now — they could move into the client module in a follow-up. 66 external call sites migrated to direct imports from the new modules (no re-export shims in `subsonic.ts`). Pure code-move; contract test stays green. subsonic.ts: 1333 → 1078 LOC (−255).
245 lines
5.5 KiB
TypeScript
245 lines
5.5 KiB
TypeScript
import type { SubsonicServerIdentity } from '../utils/subsonicServerIdentity';
|
|
|
|
export interface SubsonicAlbum {
|
|
id: string;
|
|
name: string;
|
|
artist: string;
|
|
artistId: string;
|
|
coverArt?: string;
|
|
songCount: number;
|
|
duration: number;
|
|
playCount?: number;
|
|
year?: number;
|
|
genre?: string;
|
|
starred?: string;
|
|
recordLabel?: string;
|
|
created?: string;
|
|
/** Present on some servers (e.g. OpenSubsonic) for album-level rating. */
|
|
userRating?: number;
|
|
/** OpenSubsonic: true when the album is tagged as a compilation. */
|
|
isCompilation?: boolean;
|
|
/** OpenSubsonic: release types from MusicBrainz tags (e.g. "Album", "EP", "Single", "Compilation", "Live"). */
|
|
releaseTypes?: string[];
|
|
}
|
|
|
|
/** OpenSubsonic `artists` / `albumArtists` entries on a child song (may include `userRating`). */
|
|
export interface SubsonicOpenArtistRef {
|
|
id?: string;
|
|
name?: string;
|
|
userRating?: number;
|
|
/** Navidrome / alternate OpenSubsonic payloads (same meaning as `userRating`). */
|
|
rating?: number;
|
|
}
|
|
|
|
export interface SubsonicSong {
|
|
id: string;
|
|
title: string;
|
|
artist: string;
|
|
album: string;
|
|
albumId: string;
|
|
artistId?: string;
|
|
duration: number;
|
|
track?: number;
|
|
discNumber?: number;
|
|
coverArt?: string;
|
|
year?: number;
|
|
userRating?: number;
|
|
/** Some OpenSubsonic responses attach parent ratings on child songs. */
|
|
albumUserRating?: number;
|
|
artistUserRating?: number;
|
|
artists?: SubsonicOpenArtistRef[];
|
|
albumArtists?: SubsonicOpenArtistRef[];
|
|
// Audio technical info
|
|
bitRate?: number;
|
|
suffix?: string;
|
|
contentType?: string;
|
|
size?: number;
|
|
samplingRate?: number;
|
|
bitDepth?: number;
|
|
channelCount?: number;
|
|
starred?: string;
|
|
genre?: string;
|
|
path?: string;
|
|
albumArtist?: string;
|
|
/** ISRC code when available (e.g., Navidrome) */
|
|
isrc?: string;
|
|
replayGain?: {
|
|
trackGain?: number;
|
|
albumGain?: number;
|
|
trackPeak?: number;
|
|
albumPeak?: number;
|
|
};
|
|
/** OpenSubsonic: structured composer credit (string for back-compat). */
|
|
displayComposer?: string;
|
|
/** OpenSubsonic: structured contributors list — Navidrome ≥ 0.55. */
|
|
contributors?: Array<{
|
|
role: string;
|
|
subRole?: string;
|
|
artist: { id?: string; name: string };
|
|
}>;
|
|
}
|
|
|
|
export interface InternetRadioStation {
|
|
id: string;
|
|
name: string;
|
|
streamUrl: string;
|
|
homepageUrl?: string;
|
|
coverArt?: string; // Navidrome v0.61.0+
|
|
}
|
|
|
|
export interface RadioBrowserStation {
|
|
stationuuid: string;
|
|
name: string;
|
|
url: string;
|
|
favicon: string;
|
|
tags: string;
|
|
}
|
|
|
|
export interface SubsonicPlaylist {
|
|
id: string;
|
|
name: string;
|
|
songCount: number;
|
|
duration: number;
|
|
created: string;
|
|
changed: string;
|
|
owner?: string;
|
|
public?: boolean;
|
|
comment?: string;
|
|
coverArt?: string;
|
|
}
|
|
|
|
export interface SubsonicNowPlaying extends SubsonicSong {
|
|
username: string;
|
|
minutesAgo: number;
|
|
playerId: number;
|
|
playerName: string;
|
|
}
|
|
|
|
export interface SubsonicArtist {
|
|
id: string;
|
|
name: string;
|
|
albumCount?: number;
|
|
coverArt?: string;
|
|
starred?: string;
|
|
/** Present on some servers (e.g. OpenSubsonic) for artist-level rating. */
|
|
userRating?: number;
|
|
}
|
|
|
|
export interface SubsonicGenre {
|
|
value: string;
|
|
songCount: number;
|
|
albumCount: number;
|
|
}
|
|
|
|
export interface SubsonicMusicFolder {
|
|
id: string;
|
|
name: string;
|
|
}
|
|
|
|
export interface SubsonicArtistInfo {
|
|
biography?: string;
|
|
musicBrainzId?: string;
|
|
lastFmUrl?: string;
|
|
smallImageUrl?: string;
|
|
mediumImageUrl?: string;
|
|
largeImageUrl?: string;
|
|
similarArtist?: Array<{ id: string; name: string; albumCount?: number }>;
|
|
}
|
|
|
|
export interface SubsonicDirectoryEntry {
|
|
id: string;
|
|
parent?: string;
|
|
title: string;
|
|
isDir: boolean;
|
|
album?: string;
|
|
artist?: string;
|
|
albumId?: string;
|
|
artistId?: string;
|
|
coverArt?: string;
|
|
duration?: number;
|
|
track?: number;
|
|
year?: number;
|
|
bitRate?: number;
|
|
suffix?: string;
|
|
size?: number;
|
|
genre?: string;
|
|
starred?: string;
|
|
userRating?: number;
|
|
}
|
|
|
|
export interface SubsonicDirectory {
|
|
id: string;
|
|
parent?: string;
|
|
name: string;
|
|
child: SubsonicDirectoryEntry[];
|
|
}
|
|
|
|
export type PingWithCredentialsResult = SubsonicServerIdentity & { ok: boolean };
|
|
|
|
export interface RandomSongsFilters {
|
|
size?: number;
|
|
genre?: string;
|
|
fromYear?: number;
|
|
toYear?: number;
|
|
}
|
|
|
|
export interface StatisticsLibraryAggregates {
|
|
playtimeSec: number;
|
|
albumsCounted: number;
|
|
songsCounted: number;
|
|
capped: boolean;
|
|
genres: SubsonicGenre[];
|
|
}
|
|
|
|
export interface StatisticsOverviewData {
|
|
recent: SubsonicAlbum[];
|
|
frequent: SubsonicAlbum[];
|
|
highest: SubsonicAlbum[];
|
|
artistCount: number;
|
|
}
|
|
|
|
export interface StatisticsFormatSample {
|
|
rows: { format: string; count: number }[];
|
|
sampleSize: number;
|
|
}
|
|
|
|
export interface SearchResults {
|
|
artists: SubsonicArtist[];
|
|
albums: SubsonicAlbum[];
|
|
songs: SubsonicSong[];
|
|
}
|
|
|
|
export interface StarredResults {
|
|
artists: SubsonicArtist[];
|
|
albums: SubsonicAlbum[];
|
|
songs: SubsonicSong[];
|
|
}
|
|
|
|
export type EntityRatingSupportLevel = 'track_only' | 'full';
|
|
|
|
export interface AlbumInfo {
|
|
largeImageUrl?: string;
|
|
mediumImageUrl?: string;
|
|
smallImageUrl?: string;
|
|
notes?: string;
|
|
}
|
|
|
|
export const RADIO_PAGE_SIZE = 25;
|
|
|
|
export interface SubsonicLyricLine {
|
|
start?: number; // milliseconds — absent when unsynced
|
|
value: string;
|
|
}
|
|
|
|
export interface SubsonicStructuredLyrics {
|
|
/** OpenSubsonic spec field name (Navidrome ≥ 0.50.0 / any OpenSubsonic server). */
|
|
synced?: boolean;
|
|
/** Legacy / alternate casing used by some older Subsonic-compatible servers. */
|
|
issynced?: boolean;
|
|
lang?: string;
|
|
offset?: number;
|
|
displayArtist?: string;
|
|
displayTitle?: string;
|
|
line: SubsonicLyricLine[];
|
|
}
|