mirror of
https://github.com/wkulhanek/bonob.git
synced 2025-12-22 09:53:32 +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 { 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 { 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 axios from "axios";
|
||||||
import { asURLSearchParams } from "../utils";
|
import { asURLSearchParams } from "../utils";
|
||||||
|
import { artistSummaryFromNDArtist, NDArtist } from "./navidrome";
|
||||||
|
|
||||||
|
|
||||||
type album = {
|
type album = {
|
||||||
|
|||||||
@@ -1,23 +1,21 @@
|
|||||||
import { taskEither as TE } from "fp-ts";
|
import { taskEither as TE } from "fp-ts";
|
||||||
import { pipe } from "fp-ts/lib/function";
|
import { pipe } from "fp-ts/lib/function";
|
||||||
import { Md5 } from "ts-md5/dist/md5";
|
import { Md5 } from "ts-md5/dist/md5";
|
||||||
|
import axios, { AxiosRequestConfig } from "axios";
|
||||||
|
import randomstring from "randomstring";
|
||||||
|
import _ from "underscore";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Credentials,
|
Credentials,
|
||||||
MusicService,
|
MusicService,
|
||||||
MusicLibrary,
|
MusicLibrary,
|
||||||
Track,
|
Track,
|
||||||
AuthFailure,
|
AuthFailure,
|
||||||
Sortable,
|
} from "../music_service";
|
||||||
ArtistSummary,
|
import { b64Encode, b64Decode } from "../b64";
|
||||||
} from "./music_service";
|
import { axiosImageFetcher, ImageFetcher } from "../images";
|
||||||
import _ from "underscore";
|
import { asURLSearchParams } from "../utils";
|
||||||
|
import { NaivdromeMusicLibrary, SubsonicGenericMusicLibrary } from "./generic";
|
||||||
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";
|
|
||||||
|
|
||||||
export const t = (password: string, s: string) =>
|
export const t = (password: string, s: string) =>
|
||||||
Md5.hashStr(`${password}${s}`);
|
Md5.hashStr(`${password}${s}`);
|
||||||
@@ -63,12 +61,6 @@ export function isError(
|
|||||||
return (subsonicResponse as SubsonicError).error !== undefined;
|
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>;
|
): 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 {
|
export class Subsonic implements MusicService {
|
||||||
url: string;
|
url: string;
|
||||||
streamClientApplication: StreamClientApplication;
|
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 {
|
import {
|
||||||
Subsonic,
|
Subsonic,
|
||||||
t,
|
t,
|
||||||
DODGY_IMAGE_NAME,
|
|
||||||
appendMimeTypeToClientFor,
|
appendMimeTypeToClientFor,
|
||||||
PingResponse,
|
PingResponse,
|
||||||
parseToken,
|
parseToken,
|
||||||
asToken,
|
asToken,
|
||||||
artistSummaryFromNDArtist,
|
|
||||||
SubsonicCredentials,
|
SubsonicCredentials,
|
||||||
} from "../src/subsonic";
|
} from "../src/subsonic";
|
||||||
|
|
||||||
@@ -30,7 +28,6 @@ import {
|
|||||||
aTrack,
|
aTrack,
|
||||||
} from "./builders";
|
} from "./builders";
|
||||||
import { asURLSearchParams } from "../src/utils";
|
import { asURLSearchParams } from "../src/utils";
|
||||||
import { artistImageURN } from "../src/subsonic/generic";
|
|
||||||
|
|
||||||
describe("t", () => {
|
describe("t", () => {
|
||||||
it("should be an md5 of the password and the salt", () => {
|
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" });
|
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", () => {
|
describe("Subsonic", () => {
|
||||||
const url = "http://127.0.0.22:4567";
|
const url = "http://127.0.0.22:4567";
|
||||||
const username = `user1-${uuid()}`;
|
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