mirror of
https://github.com/wkulhanek/bonob.git
synced 2025-12-21 17:33:29 +01:00
Add index.ts for subsonic
This commit is contained in:
@@ -10,9 +10,10 @@ import { b64Decode, b64Encode } from "../b64";
|
||||
import { assertSystem, BUrn } from "../burn";
|
||||
|
||||
import { Album, AlbumQuery, AlbumQueryType, AlbumSummary, Artist, ArtistQuery, ArtistSummary, AuthFailure, Credentials, Genre, IdName, Rating, Result, slice2, Sortable, Track } from "../music_service";
|
||||
import Subsonic, { artistSummaryFromNDArtist, DODGY_IMAGE_NAME, NDArtist, SubsonicCredentials, SubsonicMusicLibrary, SubsonicResponse, USER_AGENT } from "../subsonic";
|
||||
import Subsonic, { DODGY_IMAGE_NAME, SubsonicCredentials, SubsonicMusicLibrary, SubsonicResponse, USER_AGENT } from "../subsonic";
|
||||
import axios from "axios";
|
||||
import { asURLSearchParams } from "../utils";
|
||||
import { artistSummaryFromNDArtist, NDArtist } from "./navidrome";
|
||||
|
||||
|
||||
type album = {
|
||||
|
||||
@@ -1,23 +1,21 @@
|
||||
import { taskEither as TE } from "fp-ts";
|
||||
import { pipe } from "fp-ts/lib/function";
|
||||
import { Md5 } from "ts-md5/dist/md5";
|
||||
import axios, { AxiosRequestConfig } from "axios";
|
||||
import randomstring from "randomstring";
|
||||
import _ from "underscore";
|
||||
|
||||
import {
|
||||
Credentials,
|
||||
MusicService,
|
||||
MusicLibrary,
|
||||
Track,
|
||||
AuthFailure,
|
||||
Sortable,
|
||||
ArtistSummary,
|
||||
} from "./music_service";
|
||||
import _ from "underscore";
|
||||
|
||||
import axios, { AxiosRequestConfig } from "axios";
|
||||
import randomstring from "randomstring";
|
||||
import { b64Encode, b64Decode } from "./b64";
|
||||
import { axiosImageFetcher, ImageFetcher } from "./images";
|
||||
import { asURLSearchParams } from "./utils";
|
||||
import { artistImageURN, NaivdromeMusicLibrary, SubsonicGenericMusicLibrary } from "./subsonic/generic";
|
||||
} from "../music_service";
|
||||
import { b64Encode, b64Decode } from "../b64";
|
||||
import { axiosImageFetcher, ImageFetcher } from "../images";
|
||||
import { asURLSearchParams } from "../utils";
|
||||
import { NaivdromeMusicLibrary, SubsonicGenericMusicLibrary } from "./generic";
|
||||
|
||||
export const t = (password: string, s: string) =>
|
||||
Md5.hashStr(`${password}${s}`);
|
||||
@@ -63,12 +61,6 @@ export function isError(
|
||||
return (subsonicResponse as SubsonicError).error !== undefined;
|
||||
}
|
||||
|
||||
export type NDArtist = {
|
||||
id: string;
|
||||
name: string;
|
||||
orderArtistName: string | undefined;
|
||||
largeImageUrl: string | undefined;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -104,18 +96,6 @@ export interface SubsonicMusicLibrary extends MusicLibrary {
|
||||
): TE.TaskEither<Error, string | undefined>;
|
||||
}
|
||||
|
||||
export const artistSummaryFromNDArtist = (
|
||||
artist: NDArtist
|
||||
): ArtistSummary & Sortable => ({
|
||||
id: artist.id,
|
||||
name: artist.name,
|
||||
sortName: artist.orderArtistName || artist.name,
|
||||
image: artistImageURN({
|
||||
artistId: artist.id,
|
||||
artistImageURL: artist.largeImageUrl,
|
||||
}),
|
||||
});
|
||||
|
||||
export class Subsonic implements MusicService {
|
||||
url: string;
|
||||
streamClientApplication: StreamClientApplication;
|
||||
22
src/subsonic/navidrome.ts
Normal file
22
src/subsonic/navidrome.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { ArtistSummary, Sortable } from "../music_service";
|
||||
import { artistImageURN } from "./generic";
|
||||
|
||||
export type NDArtist = {
|
||||
id: string;
|
||||
name: string;
|
||||
orderArtistName: string | undefined;
|
||||
largeImageUrl: string | undefined;
|
||||
};
|
||||
|
||||
export const artistSummaryFromNDArtist = (
|
||||
artist: NDArtist
|
||||
): ArtistSummary & Sortable => ({
|
||||
id: artist.id,
|
||||
name: artist.name,
|
||||
sortName: artist.orderArtistName || artist.name,
|
||||
image: artistImageURN({
|
||||
artistId: artist.id,
|
||||
artistImageURL: artist.largeImageUrl,
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -7,12 +7,10 @@ import { taskEither as TE, task as T, either as E } from "fp-ts";
|
||||
import {
|
||||
Subsonic,
|
||||
t,
|
||||
DODGY_IMAGE_NAME,
|
||||
appendMimeTypeToClientFor,
|
||||
PingResponse,
|
||||
parseToken,
|
||||
asToken,
|
||||
artistSummaryFromNDArtist,
|
||||
SubsonicCredentials,
|
||||
} from "../src/subsonic";
|
||||
|
||||
@@ -30,7 +28,6 @@ import {
|
||||
aTrack,
|
||||
} from "./builders";
|
||||
import { asURLSearchParams } from "../src/utils";
|
||||
import { artistImageURN } from "../src/subsonic/generic";
|
||||
|
||||
describe("t", () => {
|
||||
it("should be an md5 of the password and the salt", () => {
|
||||
@@ -131,78 +128,6 @@ const pingJson = (pingResponse: Partial<PingResponse> = {}) => ({
|
||||
|
||||
const PING_OK = pingJson({ status: "ok" });
|
||||
|
||||
describe("artistSummaryFromNDArtist", () => {
|
||||
describe("when the orderArtistName is undefined", () => {
|
||||
it("should use name", () => {
|
||||
const artist = {
|
||||
id: uuid(),
|
||||
name: `name ${uuid()}`,
|
||||
orderArtistName: undefined,
|
||||
largeImageUrl: 'http://example.com/something.jpg'
|
||||
}
|
||||
expect(artistSummaryFromNDArtist(artist)).toEqual({
|
||||
id: artist.id,
|
||||
name: artist.name,
|
||||
sortName: artist.name,
|
||||
image: artistImageURN({ artistId: artist.id, artistImageURL: artist.largeImageUrl })
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
describe("when the artist image is valid", () => {
|
||||
it("should create an ArtistSummary with Sortable", () => {
|
||||
const artist = {
|
||||
id: uuid(),
|
||||
name: `name ${uuid()}`,
|
||||
orderArtistName: `orderArtistName ${uuid()}`,
|
||||
largeImageUrl: 'http://example.com/something.jpg'
|
||||
}
|
||||
expect(artistSummaryFromNDArtist(artist)).toEqual({
|
||||
id: artist.id,
|
||||
name: artist.name,
|
||||
sortName: artist.orderArtistName,
|
||||
image: artistImageURN({ artistId: artist.id, artistImageURL: artist.largeImageUrl })
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
describe("when the artist image is not valid", () => {
|
||||
it("should create an ArtistSummary with Sortable", () => {
|
||||
const artist = {
|
||||
id: uuid(),
|
||||
name: `name ${uuid()}`,
|
||||
orderArtistName: `orderArtistName ${uuid()}`,
|
||||
largeImageUrl: `http://example.com/${DODGY_IMAGE_NAME}`
|
||||
}
|
||||
|
||||
expect(artistSummaryFromNDArtist(artist)).toEqual({
|
||||
id: artist.id,
|
||||
name: artist.name,
|
||||
sortName: artist.orderArtistName,
|
||||
image: artistImageURN({ artistId: artist.id, artistImageURL: artist.largeImageUrl })
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("when the artist image is missing", () => {
|
||||
it("should create an ArtistSummary with Sortable", () => {
|
||||
const artist = {
|
||||
id: uuid(),
|
||||
name: `name ${uuid()}`,
|
||||
orderArtistName: `orderArtistName ${uuid()}`,
|
||||
largeImageUrl: undefined
|
||||
}
|
||||
|
||||
expect(artistSummaryFromNDArtist(artist)).toEqual({
|
||||
id: artist.id,
|
||||
name: artist.name,
|
||||
sortName: artist.orderArtistName,
|
||||
image: artistImageURN({ artistId: artist.id, artistImageURL: artist.largeImageUrl })
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("Subsonic", () => {
|
||||
const url = "http://127.0.0.22:4567";
|
||||
const username = `user1-${uuid()}`;
|
||||
|
||||
78
tests/subsonic/navidrome.test.ts
Normal file
78
tests/subsonic/navidrome.test.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
import { v4 as uuid } from "uuid";
|
||||
import { DODGY_IMAGE_NAME } from "../../src/subsonic";
|
||||
import { artistImageURN } from "../../src/subsonic/generic";
|
||||
import { artistSummaryFromNDArtist } from "../../src/subsonic/navidrome";
|
||||
|
||||
|
||||
describe("artistSummaryFromNDArtist", () => {
|
||||
describe("when the orderArtistName is undefined", () => {
|
||||
it("should use name", () => {
|
||||
const artist = {
|
||||
id: uuid(),
|
||||
name: `name ${uuid()}`,
|
||||
orderArtistName: undefined,
|
||||
largeImageUrl: 'http://example.com/something.jpg'
|
||||
}
|
||||
expect(artistSummaryFromNDArtist(artist)).toEqual({
|
||||
id: artist.id,
|
||||
name: artist.name,
|
||||
sortName: artist.name,
|
||||
image: artistImageURN({ artistId: artist.id, artistImageURL: artist.largeImageUrl })
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
describe("when the artist image is valid", () => {
|
||||
it("should create an ArtistSummary with Sortable", () => {
|
||||
const artist = {
|
||||
id: uuid(),
|
||||
name: `name ${uuid()}`,
|
||||
orderArtistName: `orderArtistName ${uuid()}`,
|
||||
largeImageUrl: 'http://example.com/something.jpg'
|
||||
}
|
||||
expect(artistSummaryFromNDArtist(artist)).toEqual({
|
||||
id: artist.id,
|
||||
name: artist.name,
|
||||
sortName: artist.orderArtistName,
|
||||
image: artistImageURN({ artistId: artist.id, artistImageURL: artist.largeImageUrl })
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
describe("when the artist image is not valid", () => {
|
||||
it("should create an ArtistSummary with Sortable", () => {
|
||||
const artist = {
|
||||
id: uuid(),
|
||||
name: `name ${uuid()}`,
|
||||
orderArtistName: `orderArtistName ${uuid()}`,
|
||||
largeImageUrl: `http://example.com/${DODGY_IMAGE_NAME}`
|
||||
}
|
||||
|
||||
expect(artistSummaryFromNDArtist(artist)).toEqual({
|
||||
id: artist.id,
|
||||
name: artist.name,
|
||||
sortName: artist.orderArtistName,
|
||||
image: artistImageURN({ artistId: artist.id, artistImageURL: artist.largeImageUrl })
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("when the artist image is missing", () => {
|
||||
it("should create an ArtistSummary with Sortable", () => {
|
||||
const artist = {
|
||||
id: uuid(),
|
||||
name: `name ${uuid()}`,
|
||||
orderArtistName: `orderArtistName ${uuid()}`,
|
||||
largeImageUrl: undefined
|
||||
}
|
||||
|
||||
expect(artistSummaryFromNDArtist(artist)).toEqual({
|
||||
id: artist.id,
|
||||
name: artist.name,
|
||||
sortName: artist.orderArtistName,
|
||||
image: artistImageURN({ artistId: artist.id, artistImageURL: artist.largeImageUrl })
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user