Query albums by genre

This commit is contained in:
simojenki
2021-03-06 20:06:08 +11:00
parent 5f9c240cdf
commit 1e5d020a75
7 changed files with 639 additions and 208 deletions

View File

@@ -74,7 +74,26 @@ export type ArtistQuery = Paging
export type AlbumQuery = Paging & {
artistId?: string
genre?: string
}
export const artistToArtistSummary = (
it: Artist
): ArtistSummary => ({
id: it.id,
name: it.name,
image: it.image,
});
export const albumToAlbumSummary = (
it: Album
): AlbumSummary => ({
id: it.id,
name: it.name,
year: it.year,
genre: it.genre,
});
export interface MusicService {
generateToken(credentials: Credentials): Promise<AuthSuccess | AuthFailure>;
login(authToken: string): Promise<MusicLibrary>;
@@ -84,5 +103,5 @@ export interface MusicLibrary {
artists(q: ArtistQuery): Promise<Result<ArtistSummary>>;
artist(id: string): Promise<Artist>;
albums(q: AlbumQuery): Promise<Result<AlbumSummary>>;
// album(id: string): Promise<Album>;
album(id: string): Promise<Album>;
}

View File

@@ -1,3 +1,5 @@
import { option as O } from "fp-ts";
import { pipe } from "fp-ts/lib/function";
import { Md5 } from "ts-md5/dist/md5";
import {
Credentials,
@@ -19,6 +21,7 @@ import axios from "axios";
import { Encryption } from "./encryption";
import randomString from "./random_string";
export const t = (password: string, s: string) =>
Md5.hashStr(`${password}${s}`);
@@ -66,6 +69,12 @@ export type GetArtistsResponse = SubsonicResponse & {
};
};
export type GetAlbumListResponse = SubsonicResponse & {
albumList: {
album: album[];
};
};
export type SubsonicError = SubsonicResponse & {
error: {
_code: string;
@@ -105,6 +114,17 @@ export type IdName = {
name: string;
};
export type getAlbumListParams = {
type: string,
size?: number;
offet?: number;
fromYear?: string,
toYear?: string,
genre?: string
}
const MAX_ALBUM_LIST = 500;
export class Navidrome implements MusicService {
url: string;
encryption: Encryption;
@@ -235,8 +255,36 @@ export class Navidrome implements MusicService {
image: artistInfo.image,
albums: artist.albums,
})),
albums: (_: AlbumQuery): Promise<Result<AlbumSummary>> => {
return Promise.resolve({ results: [], total: 0 });
albums: (q: AlbumQuery): Promise<Result<AlbumSummary>> => {
const p = pipe(
O.fromNullable(q.genre),
O.map<string, getAlbumListParams>(genre => ({ type: "byGenre", genre })),
O.getOrElse<getAlbumListParams>(() => ({ type: "alphabeticalByArtist" })),
)
return navidrome
.get<GetAlbumListResponse>(credentials, "/rest/getAlbumList", {
...p,
size: MAX_ALBUM_LIST,
offset: 0,
})
.then((response) => response.albumList.album)
.then((albumList) =>
albumList.map((album) => ({
id: album._id,
name: album._name,
year: album._year,
genre: album._genre,
}))
)
.then(slice2(q))
.then(([page, total]) => ({
results: page,
total: Math.min(MAX_ALBUM_LIST, total),
}));
},
album: (_: string): Promise<Album> => {
return Promise.reject("not implemented");
},
};

View File

@@ -6,7 +6,12 @@ import path from "path";
import logger from "./logger";
import { LinkCodes } from "./link_codes";
import { AlbumSummary, MusicLibrary, MusicService, slice2 } from "./music_service";
import {
AlbumSummary,
MusicLibrary,
MusicService,
slice2,
} from "./music_service";
export const LOGIN_ROUTE = "/login";
export const SOAP_PATH = "/ws/sonos";
@@ -250,14 +255,14 @@ function bindSmapiSoapServiceToExpress(
total: result.total,
})
);
case "albums":
return await musicLibrary.albums(paging).then((result) =>
getMetadataResult({
mediaCollection: result.results.map(album),
index: paging._index,
total: result.total,
})
);
case "albums":
return await musicLibrary.albums(paging).then((result) =>
getMetadataResult({
mediaCollection: result.results.map(album),
index: paging._index,
total: result.total,
})
);
case "artist":
return await musicLibrary
.artist(typeId!)