mirror of
https://github.com/wkulhanek/bonob.git
synced 2025-12-21 17:33:29 +01:00
Pull auth code out into function
This commit is contained in:
469
src/smapi.ts
469
src/smapi.ts
@@ -12,7 +12,6 @@ import {
|
|||||||
AlbumSummary,
|
AlbumSummary,
|
||||||
ArtistSummary,
|
ArtistSummary,
|
||||||
Genre,
|
Genre,
|
||||||
MusicLibrary,
|
|
||||||
MusicService,
|
MusicService,
|
||||||
slice2,
|
slice2,
|
||||||
Track,
|
Track,
|
||||||
@@ -255,6 +254,42 @@ export const artist = (
|
|||||||
albumArtURI: defaultArtistArtURI(webAddress, accessToken, artist),
|
albumArtURI: defaultArtistArtURI(webAddress, accessToken, artist),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const auth = async (
|
||||||
|
musicService: MusicService,
|
||||||
|
accessTokens: AccessTokens,
|
||||||
|
id: string,
|
||||||
|
headers?: SoapyHeaders
|
||||||
|
) => {
|
||||||
|
if (!headers?.credentials) {
|
||||||
|
throw {
|
||||||
|
Fault: {
|
||||||
|
faultcode: "Client.LoginUnsupported",
|
||||||
|
faultstring: "Missing credentials...",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const authToken = headers.credentials.loginToken.token;
|
||||||
|
const accessToken = accessTokens.mint(authToken);
|
||||||
|
const [type, typeId] = id.split(":");
|
||||||
|
return musicService
|
||||||
|
.login(authToken)
|
||||||
|
.then((musicLibrary) => ({
|
||||||
|
musicLibrary,
|
||||||
|
authToken,
|
||||||
|
accessToken,
|
||||||
|
type,
|
||||||
|
typeId,
|
||||||
|
}))
|
||||||
|
.catch((_) => {
|
||||||
|
throw {
|
||||||
|
Fault: {
|
||||||
|
faultcode: "Client.LoginUnauthorized",
|
||||||
|
faultstring: "Credentials not found...",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
type SoapyHeaders = {
|
type SoapyHeaders = {
|
||||||
credentials?: Credentials;
|
credentials?: Credentials;
|
||||||
};
|
};
|
||||||
@@ -281,73 +316,29 @@ function bindSmapiSoapServiceToExpress(
|
|||||||
{ id }: { id: string },
|
{ id }: { id: string },
|
||||||
_,
|
_,
|
||||||
headers?: SoapyHeaders
|
headers?: SoapyHeaders
|
||||||
) => {
|
) =>
|
||||||
if (!headers?.credentials) {
|
auth(musicService, accessTokens, id, headers).then(
|
||||||
throw {
|
({ accessToken, type, typeId }) => ({
|
||||||
Fault: {
|
getMediaURIResult: `${webAddress}/stream/${type}/${typeId}`,
|
||||||
faultcode: "Client.LoginUnsupported",
|
httpHeaders: [
|
||||||
faultstring: "Missing credentials...",
|
{
|
||||||
},
|
header: BONOB_ACCESS_TOKEN_HEADER,
|
||||||
};
|
value: accessToken,
|
||||||
}
|
|
||||||
await musicService
|
|
||||||
.login(headers.credentials.loginToken.token)
|
|
||||||
.catch((_) => {
|
|
||||||
throw {
|
|
||||||
Fault: {
|
|
||||||
faultcode: "Client.LoginUnauthorized",
|
|
||||||
faultstring: "Credentials not found...",
|
|
||||||
},
|
},
|
||||||
};
|
],
|
||||||
});
|
})
|
||||||
|
),
|
||||||
const [type, typeId] = id.split(":");
|
|
||||||
return {
|
|
||||||
getMediaURIResult: `${webAddress}/stream/${type}/${typeId}`,
|
|
||||||
httpHeaders: [
|
|
||||||
{
|
|
||||||
header: BONOB_ACCESS_TOKEN_HEADER,
|
|
||||||
value: accessTokens.mint(
|
|
||||||
headers?.credentials?.loginToken.token
|
|
||||||
),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
},
|
|
||||||
getMediaMetadata: async (
|
getMediaMetadata: async (
|
||||||
{ id }: { id: string },
|
{ id }: { id: string },
|
||||||
_,
|
_,
|
||||||
headers?: SoapyHeaders
|
headers?: SoapyHeaders
|
||||||
) => {
|
) =>
|
||||||
if (!headers?.credentials) {
|
auth(musicService, accessTokens, id, headers).then(
|
||||||
throw {
|
async ({ musicLibrary, accessToken, typeId }) =>
|
||||||
Fault: {
|
musicLibrary.track(typeId!).then((it) => ({
|
||||||
faultcode: "Client.LoginUnsupported",
|
getMediaMetadataResult: track(webAddress, accessToken, it),
|
||||||
faultstring: "Missing credentials...",
|
}))
|
||||||
},
|
),
|
||||||
};
|
|
||||||
}
|
|
||||||
const authToken = headers.credentials.loginToken.token;
|
|
||||||
const login = await musicService
|
|
||||||
.login(headers.credentials.loginToken.token)
|
|
||||||
.catch((_) => {
|
|
||||||
throw {
|
|
||||||
Fault: {
|
|
||||||
faultcode: "Client.LoginUnauthorized",
|
|
||||||
faultstring: "Credentials not found...",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const typeId = id.split(":")[1];
|
|
||||||
const musicLibrary = login as MusicLibrary;
|
|
||||||
return musicLibrary.track(typeId!).then((it) => {
|
|
||||||
const accessToken = accessTokens.mint(authToken);
|
|
||||||
return {
|
|
||||||
getMediaMetadataResult: track(webAddress, accessToken, it),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
},
|
|
||||||
getExtendedMetadata: async (
|
getExtendedMetadata: async (
|
||||||
{
|
{
|
||||||
id,
|
id,
|
||||||
@@ -357,59 +348,41 @@ function bindSmapiSoapServiceToExpress(
|
|||||||
{ id: string; index: number; count: number; recursive: boolean },
|
{ id: string; index: number; count: number; recursive: boolean },
|
||||||
_,
|
_,
|
||||||
headers?: SoapyHeaders
|
headers?: SoapyHeaders
|
||||||
) => {
|
) =>
|
||||||
if (!headers?.credentials) {
|
auth(musicService, accessTokens, id, headers).then(
|
||||||
throw {
|
async ({ musicLibrary, accessToken, type, typeId }) => {
|
||||||
Fault: {
|
const paging = { _index: index, _count: count };
|
||||||
faultcode: "Client.LoginUnsupported",
|
switch (type) {
|
||||||
faultstring: "Missing credentials...",
|
case "artist":
|
||||||
},
|
return musicLibrary.artist(typeId!).then((artist) => {
|
||||||
};
|
const [page, total] = slice2<Album>(paging)(
|
||||||
}
|
artist.albums
|
||||||
const authToken = headers.credentials.loginToken.token;
|
);
|
||||||
const login = await musicService.login(authToken).catch((_) => {
|
return {
|
||||||
throw {
|
getExtendedMetadataResult: {
|
||||||
Fault: {
|
count: page.length,
|
||||||
faultcode: "Client.LoginUnauthorized",
|
index: paging._index,
|
||||||
faultstring: "Credentials not found...",
|
total,
|
||||||
},
|
mediaCollection: page.map((it) =>
|
||||||
};
|
album(webAddress, accessToken, it)
|
||||||
});
|
),
|
||||||
|
relatedBrowse:
|
||||||
const musicLibrary = login as MusicLibrary;
|
artist.similarArtists.length > 0
|
||||||
|
? [
|
||||||
const [type, typeId] = id.split(":");
|
{
|
||||||
const paging = { _index: index, _count: count };
|
id: `relatedArtists:${artist.id}`,
|
||||||
switch (type) {
|
type: "RELATED_ARTISTS",
|
||||||
case "artist":
|
},
|
||||||
return await musicLibrary.artist(typeId!).then((artist) => {
|
]
|
||||||
const [page, total] = slice2<Album>(paging)(artist.albums);
|
: [],
|
||||||
const accessToken = accessTokens.mint(authToken);
|
},
|
||||||
|
};
|
||||||
return {
|
});
|
||||||
getExtendedMetadataResult: {
|
default:
|
||||||
count: page.length,
|
throw `Unsupported id:${id}`;
|
||||||
index: paging._index,
|
}
|
||||||
total,
|
}
|
||||||
mediaCollection: page.map((it) =>
|
),
|
||||||
album(webAddress, accessToken, it)
|
|
||||||
),
|
|
||||||
relatedBrowse:
|
|
||||||
artist.similarArtists.length > 0
|
|
||||||
? [
|
|
||||||
{
|
|
||||||
id: `relatedArtists:${artist.id}`,
|
|
||||||
type: "RELATED_ARTISTS",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
: [],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
});
|
|
||||||
default:
|
|
||||||
throw `Unsupported id:${id}`;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getMetadata: async (
|
getMetadata: async (
|
||||||
{
|
{
|
||||||
id,
|
id,
|
||||||
@@ -419,157 +392,139 @@ function bindSmapiSoapServiceToExpress(
|
|||||||
{ id: string; index: number; count: number; recursive: boolean },
|
{ id: string; index: number; count: number; recursive: boolean },
|
||||||
_,
|
_,
|
||||||
headers?: SoapyHeaders
|
headers?: SoapyHeaders
|
||||||
) => {
|
) =>
|
||||||
if (!headers?.credentials) {
|
auth(musicService, accessTokens, id, headers).then(
|
||||||
throw {
|
({ musicLibrary, accessToken, type, typeId }) => {
|
||||||
Fault: {
|
const paging = { _index: index, _count: count };
|
||||||
faultcode: "Client.LoginUnsupported",
|
logger.debug(
|
||||||
faultstring: "Missing credentials...",
|
`Fetching metadata type=${type}, typeId=${typeId}`
|
||||||
},
|
);
|
||||||
};
|
|
||||||
}
|
|
||||||
const authToken = headers.credentials.loginToken.token;
|
|
||||||
const login = await musicService.login(authToken).catch((_) => {
|
|
||||||
throw {
|
|
||||||
Fault: {
|
|
||||||
faultcode: "Client.LoginUnauthorized",
|
|
||||||
faultstring: "Credentials not found...",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const musicLibrary = login as MusicLibrary;
|
const albums = (q: AlbumQuery): Promise<GetMetadataResponse> =>
|
||||||
|
musicLibrary.albums(q).then((result) => {
|
||||||
const [type, typeId] = id.split(":");
|
|
||||||
const paging = { _index: index, _count: count };
|
|
||||||
logger.debug(`Fetching metadata type=${type}, typeId=${typeId}`);
|
|
||||||
|
|
||||||
const albums = (q: AlbumQuery): Promise<GetMetadataResponse> =>
|
|
||||||
musicLibrary.albums(q).then((result) => {
|
|
||||||
const accessToken = accessTokens.mint(authToken);
|
|
||||||
return getMetadataResult({
|
|
||||||
mediaCollection: result.results.map((it) =>
|
|
||||||
album(webAddress, accessToken, it)
|
|
||||||
),
|
|
||||||
index: paging._index,
|
|
||||||
total: result.total,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case "root":
|
|
||||||
return getMetadataResult({
|
|
||||||
mediaCollection: [
|
|
||||||
container({ id: "artists", title: "Artists" }),
|
|
||||||
container({ id: "albums", title: "Albums" }),
|
|
||||||
container({ id: "genres", title: "Genres" }),
|
|
||||||
container({ id: "randomAlbums", title: "Random" }),
|
|
||||||
container({ id: "recentlyAdded", title: "Recently Added" }),
|
|
||||||
container({
|
|
||||||
id: "recentlyPlayed",
|
|
||||||
title: "Recently Played",
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
index: 0,
|
|
||||||
total: 6,
|
|
||||||
});
|
|
||||||
case "artists":
|
|
||||||
return await musicLibrary.artists(paging).then((result) => {
|
|
||||||
const accessToken = accessTokens.mint(authToken);
|
|
||||||
return getMetadataResult({
|
|
||||||
mediaCollection: result.results.map((it) =>
|
|
||||||
artist(webAddress, accessToken, it)
|
|
||||||
),
|
|
||||||
index: paging._index,
|
|
||||||
total: result.total,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
case "albums": {
|
|
||||||
return await albums({
|
|
||||||
type: "alphabeticalByArtist",
|
|
||||||
...paging,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
case "randomAlbums":
|
|
||||||
return await albums({
|
|
||||||
type: "random",
|
|
||||||
...paging,
|
|
||||||
});
|
|
||||||
case "genre":
|
|
||||||
return await albums({
|
|
||||||
type: "byGenre",
|
|
||||||
genre: typeId,
|
|
||||||
...paging,
|
|
||||||
});
|
|
||||||
case "recentlyAdded":
|
|
||||||
return await albums({
|
|
||||||
type: "newest",
|
|
||||||
...paging,
|
|
||||||
});
|
|
||||||
case "recentlyPlayed":
|
|
||||||
return await albums({
|
|
||||||
type: "frequent",
|
|
||||||
...paging,
|
|
||||||
});
|
|
||||||
case "genres":
|
|
||||||
return await musicLibrary
|
|
||||||
.genres()
|
|
||||||
.then(slice2(paging))
|
|
||||||
.then(([page, total]) =>
|
|
||||||
getMetadataResult({
|
|
||||||
mediaCollection: page.map(genre),
|
|
||||||
index: paging._index,
|
|
||||||
total,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
case "artist":
|
|
||||||
return await musicLibrary
|
|
||||||
.artist(typeId!)
|
|
||||||
.then((artist) => artist.albums)
|
|
||||||
.then(slice2(paging))
|
|
||||||
.then(([page, total]) => {
|
|
||||||
const accessToken = accessTokens.mint(authToken);
|
|
||||||
return getMetadataResult({
|
return getMetadataResult({
|
||||||
mediaCollection: page.map((it) =>
|
mediaCollection: result.results.map((it) =>
|
||||||
album(webAddress, accessToken, it)
|
album(webAddress, accessToken, it)
|
||||||
),
|
),
|
||||||
index: paging._index,
|
index: paging._index,
|
||||||
total,
|
total: result.total,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
case "relatedArtists":
|
|
||||||
return await musicLibrary
|
switch (type) {
|
||||||
.artist(typeId!)
|
case "root":
|
||||||
.then((artist) => artist.similarArtists)
|
|
||||||
.then(slice2(paging))
|
|
||||||
.then(([page, total]) => {
|
|
||||||
const accessToken = accessTokens.mint(authToken);
|
|
||||||
return getMetadataResult({
|
return getMetadataResult({
|
||||||
mediaCollection: page.map((it) =>
|
mediaCollection: [
|
||||||
artist(webAddress, accessToken, it)
|
container({ id: "artists", title: "Artists" }),
|
||||||
),
|
container({ id: "albums", title: "Albums" }),
|
||||||
index: paging._index,
|
container({ id: "genres", title: "Genres" }),
|
||||||
total,
|
container({ id: "randomAlbums", title: "Random" }),
|
||||||
|
container({
|
||||||
|
id: "recentlyAdded",
|
||||||
|
title: "Recently Added",
|
||||||
|
}),
|
||||||
|
container({
|
||||||
|
id: "recentlyPlayed",
|
||||||
|
title: "Recently Played",
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
index: 0,
|
||||||
|
total: 6,
|
||||||
});
|
});
|
||||||
});
|
case "artists":
|
||||||
case "album":
|
return musicLibrary.artists(paging).then((result) => {
|
||||||
return await musicLibrary
|
return getMetadataResult({
|
||||||
.tracks(typeId!)
|
mediaCollection: result.results.map((it) =>
|
||||||
.then(slice2(paging))
|
artist(webAddress, accessToken, it)
|
||||||
.then(([page, total]) => {
|
),
|
||||||
const accessToken = accessTokens.mint(authToken);
|
index: paging._index,
|
||||||
return getMetadataResult({
|
total: result.total,
|
||||||
mediaMetadata: page.map((it) =>
|
});
|
||||||
track(webAddress, accessToken, it)
|
|
||||||
),
|
|
||||||
index: paging._index,
|
|
||||||
total,
|
|
||||||
});
|
});
|
||||||
});
|
case "albums": {
|
||||||
default:
|
return albums({
|
||||||
throw `Unsupported id:${id}`;
|
type: "alphabeticalByArtist",
|
||||||
}
|
...paging,
|
||||||
},
|
});
|
||||||
|
}
|
||||||
|
case "randomAlbums":
|
||||||
|
return albums({
|
||||||
|
type: "random",
|
||||||
|
...paging,
|
||||||
|
});
|
||||||
|
case "genre":
|
||||||
|
return albums({
|
||||||
|
type: "byGenre",
|
||||||
|
genre: typeId,
|
||||||
|
...paging,
|
||||||
|
});
|
||||||
|
case "recentlyAdded":
|
||||||
|
return albums({
|
||||||
|
type: "newest",
|
||||||
|
...paging,
|
||||||
|
});
|
||||||
|
case "recentlyPlayed":
|
||||||
|
return albums({
|
||||||
|
type: "frequent",
|
||||||
|
...paging,
|
||||||
|
});
|
||||||
|
case "genres":
|
||||||
|
return musicLibrary
|
||||||
|
.genres()
|
||||||
|
.then(slice2(paging))
|
||||||
|
.then(([page, total]) =>
|
||||||
|
getMetadataResult({
|
||||||
|
mediaCollection: page.map(genre),
|
||||||
|
index: paging._index,
|
||||||
|
total,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
case "artist":
|
||||||
|
return musicLibrary
|
||||||
|
.artist(typeId!)
|
||||||
|
.then((artist) => artist.albums)
|
||||||
|
.then(slice2(paging))
|
||||||
|
.then(([page, total]) => {
|
||||||
|
return getMetadataResult({
|
||||||
|
mediaCollection: page.map((it) =>
|
||||||
|
album(webAddress, accessToken, it)
|
||||||
|
),
|
||||||
|
index: paging._index,
|
||||||
|
total,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
case "relatedArtists":
|
||||||
|
return musicLibrary
|
||||||
|
.artist(typeId!)
|
||||||
|
.then((artist) => artist.similarArtists)
|
||||||
|
.then(slice2(paging))
|
||||||
|
.then(([page, total]) => {
|
||||||
|
return getMetadataResult({
|
||||||
|
mediaCollection: page.map((it) =>
|
||||||
|
artist(webAddress, accessToken, it)
|
||||||
|
),
|
||||||
|
index: paging._index,
|
||||||
|
total,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
case "album":
|
||||||
|
return musicLibrary
|
||||||
|
.tracks(typeId!)
|
||||||
|
.then(slice2(paging))
|
||||||
|
.then(([page, total]) => {
|
||||||
|
return getMetadataResult({
|
||||||
|
mediaMetadata: page.map((it) =>
|
||||||
|
track(webAddress, accessToken, it)
|
||||||
|
),
|
||||||
|
index: paging._index,
|
||||||
|
total,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
default:
|
||||||
|
throw `Unsupported id:${id}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user