mirror of
https://github.com/wkulhanek/bonob.git
synced 2025-12-21 17:33:29 +01:00
moving things around
This commit is contained in:
@@ -31,6 +31,7 @@ const bonob = bonobService(
|
||||
|
||||
const sonosSystem = sonos(config.sonos.discovery);
|
||||
|
||||
// todo: just pass in the customClientsForStringArray into subsonic and make it sort it out.
|
||||
const streamUserAgent = config.subsonic.customClientsFor
|
||||
? appendMimeTypeToClientFor(config.subsonic.customClientsFor.split(","))
|
||||
: DEFAULT;
|
||||
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
import { b64Encode, b64Decode } from "../b64";
|
||||
import { axiosImageFetcher, ImageFetcher } from "../images";
|
||||
import { asURLSearchParams } from "../utils";
|
||||
import { NaivdromeMusicLibrary, SubsonicGenericMusicLibrary } from "./generic";
|
||||
import { navidromeMusicLibrary, SubsonicGenericMusicLibrary } from "./library";
|
||||
|
||||
export const t = (password: string, s: string) =>
|
||||
Md5.hashStr(`${password}${s}`);
|
||||
@@ -194,10 +194,11 @@ export class Subsonic implements MusicService {
|
||||
private libraryFor = (
|
||||
credentials: SubsonicCredentials
|
||||
): Promise<SubsonicMusicLibrary> => {
|
||||
const subsonicGenericLibrary = new SubsonicGenericMusicLibrary(this, credentials);
|
||||
if (credentials.type == "navidrome") {
|
||||
return Promise.resolve(new NaivdromeMusicLibrary(this, credentials));
|
||||
return Promise.resolve(navidromeMusicLibrary(this.url, subsonicGenericLibrary, credentials));
|
||||
} else {
|
||||
return Promise.resolve(new SubsonicGenericMusicLibrary(this, credentials));
|
||||
return Promise.resolve(subsonicGenericLibrary);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ 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, { DODGY_IMAGE_NAME, SubsonicCredentials, SubsonicMusicLibrary, SubsonicResponse, USER_AGENT } from "../subsonic";
|
||||
import Subsonic, { DODGY_IMAGE_NAME, SubsonicCredentials, SubsonicMusicLibrary, SubsonicResponse, USER_AGENT } from ".";
|
||||
import axios from "axios";
|
||||
import { asURLSearchParams } from "../utils";
|
||||
import { artistSummaryFromNDArtist, NDArtist } from "./navidrome";
|
||||
@@ -725,65 +725,59 @@ export class SubsonicGenericMusicLibrary implements SubsonicMusicLibrary {
|
||||
}));
|
||||
};
|
||||
|
||||
export class NaivdromeMusicLibrary extends SubsonicGenericMusicLibrary {
|
||||
|
||||
constructor(subsonic: Subsonic, credentials: SubsonicCredentials) {
|
||||
super(subsonic, credentials);
|
||||
}
|
||||
|
||||
flavour = () => "navidrome";
|
||||
|
||||
bearerToken = (credentials: Credentials): TE.TaskEither<Error, string | undefined> =>
|
||||
export const navidromeMusicLibrary = (url: string, subsonicLibrary: SubsonicMusicLibrary, subsonicCredentials: SubsonicCredentials): SubsonicMusicLibrary => ({
|
||||
...subsonicLibrary,
|
||||
flavour: () => "navidrome",
|
||||
bearerToken: (credentials: Credentials): TE.TaskEither<Error, string | undefined> =>
|
||||
pipe(
|
||||
TE.tryCatch(
|
||||
() =>
|
||||
axios.post(
|
||||
`${this.subsonic.url}/auth/login`,
|
||||
`${url}/auth/login`,
|
||||
_.pick(credentials, "username", "password")
|
||||
),
|
||||
() => new AuthFailure("Failed to get bearerToken")
|
||||
),
|
||||
TE.map((it) => it.data.token as string | undefined)
|
||||
);
|
||||
|
||||
artists = async (
|
||||
q: ArtistQuery
|
||||
): Promise<Result<ArtistSummary & Sortable>> => {
|
||||
let params: any = {
|
||||
_sort: "name",
|
||||
_order: "ASC",
|
||||
_start: q._index || "0",
|
||||
};
|
||||
if (q._count) {
|
||||
params = {
|
||||
...params,
|
||||
_end: (q._index || 0) + q._count,
|
||||
),
|
||||
artists: async (
|
||||
q: ArtistQuery
|
||||
): Promise<Result<ArtistSummary & Sortable>> => {
|
||||
let params: any = {
|
||||
_sort: "name",
|
||||
_order: "ASC",
|
||||
_start: q._index || "0",
|
||||
};
|
||||
}
|
||||
|
||||
const x: Promise<Result<ArtistSummary & Sortable>> = axios
|
||||
.get(`${this.subsonic.url}/api/artist`, {
|
||||
params: asURLSearchParams(params),
|
||||
headers: {
|
||||
"User-Agent": USER_AGENT,
|
||||
"x-nd-authorization": `Bearer ${this.credentials.bearer}`,
|
||||
},
|
||||
})
|
||||
.catch((e) => {
|
||||
throw `Navidrome failed with: ${e}`;
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.status != 200 && response.status != 206) {
|
||||
throw `Navidrome failed with a ${
|
||||
response.status || "no!"
|
||||
} status`;
|
||||
} else return response;
|
||||
})
|
||||
.then((it) => ({
|
||||
results: (it.data as NDArtist[]).map(artistSummaryFromNDArtist),
|
||||
total: Number.parseInt(it.headers["x-total-count"] || "0"),
|
||||
}));
|
||||
|
||||
return x;
|
||||
}
|
||||
}
|
||||
if (q._count) {
|
||||
params = {
|
||||
...params,
|
||||
_end: (q._index || 0) + q._count,
|
||||
};
|
||||
}
|
||||
|
||||
const x: Promise<Result<ArtistSummary & Sortable>> = axios
|
||||
.get(`${url}/api/artist`, {
|
||||
params: asURLSearchParams(params),
|
||||
headers: {
|
||||
"User-Agent": USER_AGENT,
|
||||
"x-nd-authorization": `Bearer ${subsonicCredentials.bearer}`,
|
||||
},
|
||||
})
|
||||
.catch((e) => {
|
||||
throw `Navidrome failed with: ${e}`;
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.status != 200 && response.status != 206) {
|
||||
throw `Navidrome failed with a ${
|
||||
response.status || "no!"
|
||||
} status`;
|
||||
} else return response;
|
||||
})
|
||||
.then((it) => ({
|
||||
results: (it.data as NDArtist[]).map(artistSummaryFromNDArtist),
|
||||
total: Number.parseInt(it.headers["x-total-count"] || "0"),
|
||||
}));
|
||||
|
||||
return x;
|
||||
}
|
||||
})
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ArtistSummary, Sortable } from "../music_service";
|
||||
import { artistImageURN } from "./generic";
|
||||
import { artistImageURN } from "./library";
|
||||
|
||||
export type NDArtist = {
|
||||
id: string;
|
||||
|
||||
@@ -28,4 +28,4 @@ export function takeWithRepeats<T>(things:T[], count: number) {
|
||||
result.push(things[i % things.length])
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
} from "../src/music_service";
|
||||
|
||||
import { b64Encode } from "../src/b64";
|
||||
import { artistImageURN } from "../src/subsonic/generic";
|
||||
import { artistImageURN } from "../src/subsonic/library";
|
||||
|
||||
const randomInt = (max: number) => Math.floor(Math.random() * Math.floor(max));
|
||||
const randomIpAddress = () => `127.0.${randomInt(255)}.${randomInt(255)}`;
|
||||
|
||||
@@ -12,7 +12,7 @@ jest.mock("randomstring");
|
||||
import { aGenre, anAlbum, anArtist, aPlaylist, aPlaylistSummary, aSimilarArtist, aTrack, POP, ROCK } from "../builders";
|
||||
import { BUrn } from "../../src/burn";
|
||||
import { Album, AlbumQuery, AlbumSummary, albumToAlbumSummary, Artist, artistToArtistSummary, asArtistAlbumPairs, Playlist, PlaylistSummary, Rating, SimilarArtist, Track } from "../../src/music_service";
|
||||
import { artistImageURN, asGenre, asTrack, images, isValidImage, song, SubsonicGenericMusicLibrary } from "../../src/subsonic/generic";
|
||||
import { artistImageURN, asGenre, asTrack, images, isValidImage, song, SubsonicGenericMusicLibrary } from "../../src/subsonic/library";
|
||||
import { EMPTY, error, FAILURE, subsonicOK, ok } from "../subsonic.test";
|
||||
import Subsonic, { DODGY_IMAGE_NAME, t } from "../../src/subsonic";
|
||||
import { asURLSearchParams } from "../../src/utils";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { v4 as uuid } from "uuid";
|
||||
import { DODGY_IMAGE_NAME } from "../../src/subsonic";
|
||||
import { artistImageURN } from "../../src/subsonic/generic";
|
||||
import { artistImageURN } from "../../src/subsonic/library";
|
||||
import { artistSummaryFromNDArtist } from "../../src/subsonic/navidrome";
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user