This commit is contained in:
simojenki
2022-04-23 16:54:30 +10:00
parent 730524d7a1
commit eb66393fe6
4 changed files with 20 additions and 76 deletions

View File

@@ -1,19 +1,17 @@
import { AxiosPromise, AxiosRequestConfig, ResponseType } from "axios"; import { AxiosPromise, AxiosRequestConfig, ResponseType } from "axios";
import _ from "underscore";
export interface RequestModifier {
(config: AxiosRequestConfig): AxiosRequestConfig;
}
export const no_op = (config: AxiosRequestConfig) => config;
export interface Http { export interface Http {
(config: AxiosRequestConfig): AxiosPromise<any>; (config: AxiosRequestConfig): AxiosPromise<any>;
} }
export type RequestParams = { baseURL: string; url: string, params: any, headers: any, responseType: ResponseType } export type RequestParams = {
baseURL: string;
url: string;
params: any;
headers: any;
responseType: ResponseType;
};
// todo: rename to http
export const http = export const http =
(base: Http, defaults: Partial<RequestParams>): Http => (base: Http, defaults: Partial<RequestParams>): Http =>
(config: AxiosRequestConfig) => { (config: AxiosRequestConfig) => {

View File

@@ -101,7 +101,7 @@ export class Subsonic implements MusicService {
// todo: why is this in here? // todo: why is this in here?
externalImageFetcher: ImageFetcher; externalImageFetcher: ImageFetcher;
base: Http; subsonicHttp: Http;
constructor( constructor(
url: string, url: string,
@@ -111,15 +111,15 @@ export class Subsonic implements MusicService {
this.url = url; this.url = url;
this.streamClientApplication = streamClientApplication; this.streamClientApplication = streamClientApplication;
this.externalImageFetcher = externalImageFetcher; this.externalImageFetcher = externalImageFetcher;
this.base = http2(axios, { this.subsonicHttp = http2(axios, {
baseURL: this.url, baseURL: this.url,
params: { v: "1.16.1", c: DEFAULT_CLIENT_APPLICATION }, params: { v: "1.16.1", c: DEFAULT_CLIENT_APPLICATION },
headers: { "User-Agent": "bonob" }, headers: { "User-Agent": "bonob" },
}); });
} }
authenticated = (credentials: Credentials, wrap: Http = this.base) => authenticatedSubsonicHttp = (credentials: Credentials) =>
http2(wrap, { http2(this.subsonicHttp, {
params: { params: {
u: credentials.username, u: credentials.username,
...t_and_s(credentials.password), ...t_and_s(credentials.password),
@@ -130,12 +130,12 @@ export class Subsonic implements MusicService {
credentials: Credentials, credentials: Credentials,
url: string, url: string,
params: {} = {} params: {} = {}
): Promise<T> => getJSON2(http2(this.authenticated(credentials), { url, params })); ): Promise<T> => getJSON2(http2(this.authenticatedSubsonicHttp(credentials), { url, params }));
generateToken = (credentials: Credentials) => generateToken = (credentials: Credentials) =>
pipe( pipe(
TE.tryCatch( TE.tryCatch(
() => getJSON2<PingResponse>(http2(this.authenticated(credentials), { url: "/rest/ping.view" })), () => getJSON2<PingResponse>(http2(this.authenticatedSubsonicHttp(credentials), { url: "/rest/ping.view" })),
(e) => new AuthFailure(e as string) (e) => new AuthFailure(e as string)
), ),
TE.chain(({ type }) => TE.chain(({ type }) =>
@@ -170,7 +170,7 @@ export class Subsonic implements MusicService {
): Promise<SubsonicMusicLibrary> => { ): Promise<SubsonicMusicLibrary> => {
const subsonicGenericLibrary = new SubsonicGenericMusicLibrary( const subsonicGenericLibrary = new SubsonicGenericMusicLibrary(
this.streamClientApplication, this.streamClientApplication,
this.authenticated(credentials, this.base) this.authenticatedSubsonicHttp(credentials)
); );
if (credentials.type == "navidrome") { if (credentials.type == "navidrome") {
return Promise.resolve( return Promise.resolve(

View File

@@ -277,19 +277,19 @@ const maybeAsGenre = (genreName: string | undefined): Genre | undefined =>
export class SubsonicGenericMusicLibrary implements SubsonicMusicLibrary { export class SubsonicGenericMusicLibrary implements SubsonicMusicLibrary {
streamClientApplication: StreamClientApplication; streamClientApplication: StreamClientApplication;
http: Http; subsonicHttp: Http;
constructor( constructor(
streamClientApplication: StreamClientApplication, streamClientApplication: StreamClientApplication,
http: Http subsonicHttp: Http
) { ) {
this.streamClientApplication = streamClientApplication; this.streamClientApplication = streamClientApplication;
this.http = http; this.subsonicHttp = subsonicHttp;
} }
GET = (query: Partial<RequestParams>) => ({ GET = (query: Partial<RequestParams>) => ({
asRAW: () => getRaw2(http2(this.http, query)), asRAW: () => getRaw2(http2(this.subsonicHttp, query)),
asJSON: <T>() => getJSON2<T>(http2(this.http, query)), asJSON: <T>() => getJSON2<T>(http2(this.subsonicHttp, query)),
}); });
flavour = () => "subsonic"; flavour = () => "subsonic";

View File

@@ -1,45 +1,9 @@
import axios, { AxiosPromise, AxiosRequestConfig } from "axios";
import { import {
DEFAULT_CLIENT_APPLICATION,
isError, isError,
SubsonicEnvelope, SubsonicEnvelope,
t_and_s,
USER_AGENT,
} from "."; } from ".";
// todo: rename http2 to http // todo: rename http2 to http
import { Http, http as http2 } from "../http"; import { Http, http as http2 } from "../http";
import { Credentials } from "../music_service";
import { asURLSearchParams } from "../utils";
export const http = (base: string, credentials: Credentials): HTTP => ({
get: async (
path: string,
params: Partial<{ q: {}; config: AxiosRequestConfig | undefined }>
) =>
axios
.get(`${base}${path}`, {
params: asURLSearchParams({
u: credentials.username,
v: "1.16.1",
c: DEFAULT_CLIENT_APPLICATION,
...t_and_s(credentials.password),
f: "json",
...(params.q || {}),
}),
headers: {
"User-Agent": USER_AGENT,
},
...(params.config || {}),
})
.catch((e) => {
throw `Subsonic failed with: ${e}`;
})
.then((response) => {
if (response.status != 200 && response.status != 206) {
throw `Subsonic failed with a ${response.status || "no!"} status`;
} else return response;
}),
});
export type HttpResponse = { export type HttpResponse = {
data: any; data: any;
@@ -47,24 +11,6 @@ export type HttpResponse = {
headers: any; headers: any;
}; };
export interface HTTP {
get(
path: string,
params: Partial<{ q: {}; config: AxiosRequestConfig | undefined }>
): Promise<HttpResponse>;
}
export const raw = (response: AxiosPromise<any>) =>
response
.catch((e) => {
throw `Subsonic failed with: ${e}`;
})
.then((response) => {
if (response.status != 200 && response.status != 206) {
throw `Subsonic failed with a ${response.status || "no!"} status`;
} else return response;
});
export const getRaw2 = (http: Http) => export const getRaw2 = (http: Http) =>
http({ method: "get" }) http({ method: "get" })
.catch((e) => { .catch((e) => {
@@ -88,4 +34,4 @@ export const asJSON = <T>(response: HttpResponse): T => {
else return subsonicResponse as unknown as T; else return subsonicResponse as unknown as T;
}; };
export default http;