mirror of
https://github.com/wkulhanek/bonob.git
synced 2025-12-21 17:33:29 +01:00
Fix tests
This commit is contained in:
@@ -60,7 +60,7 @@ setInterval(() => {
|
|||||||
streamSessions.delete(sid);
|
streamSessions.delete(sid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, 5 * 60 * 1000); // Run every 5 minutes
|
}, 5 * 60 * 1000).unref(); // Run every 5 minutes, but don't prevent process exit
|
||||||
|
|
||||||
interface RangeFilter extends Transform {
|
interface RangeFilter extends Transform {
|
||||||
range: (length: number) => string;
|
range: (length: number) => string;
|
||||||
|
|||||||
133
src/smapi.ts
133
src/smapi.ts
@@ -462,7 +462,7 @@ function bindSmapiSoapServiceToExpress(
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const swapToken = (expiredToken:string | undefined) => (newToken:SmapiToken) => {
|
const swapToken = (expiredToken:string) => (newToken:SmapiToken) => {
|
||||||
logger.debug("oldToken: "+expiredToken);
|
logger.debug("oldToken: "+expiredToken);
|
||||||
logger.debug("newToken: "+JSON.stringify(newToken));
|
logger.debug("newToken: "+JSON.stringify(newToken));
|
||||||
sonosSoap.associateCredentialsForToken(newToken.token, newToken, expiredToken);
|
sonosSoap.associateCredentialsForToken(newToken.token, newToken, expiredToken);
|
||||||
@@ -513,12 +513,10 @@ function bindSmapiSoapServiceToExpress(
|
|||||||
throw SMAPI_FAULT_LOGIN_UNAUTHORIZED;
|
throw SMAPI_FAULT_LOGIN_UNAUTHORIZED;
|
||||||
});
|
});
|
||||||
} else if (isExpiredTokenError(authOrFail)) {
|
} else if (isExpiredTokenError(authOrFail)) {
|
||||||
// Get the old SMAPI token from credentials before refreshing
|
|
||||||
const oldSmapiToken = credentials?.loginToken.token;
|
|
||||||
throw await pipe(
|
throw await pipe(
|
||||||
musicService.refreshToken(authOrFail.expiredToken),
|
musicService.refreshToken(authOrFail.expiredToken),
|
||||||
TE.map((it) => smapiAuthTokens.issue(it.serviceToken)),
|
TE.map((it) => smapiAuthTokens.issue(it.serviceToken)),
|
||||||
TE.tap(swapToken(oldSmapiToken)),
|
TE.tap(swapToken(authOrFail.expiredToken)),
|
||||||
TE.map((newToken) => ({
|
TE.map((newToken) => ({
|
||||||
Fault: {
|
Fault: {
|
||||||
faultcode: "Client.TokenRefreshRequired",
|
faultcode: "Client.TokenRefreshRequired",
|
||||||
@@ -566,10 +564,8 @@ function bindSmapiSoapServiceToExpress(
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
refreshAuthToken: async (_, _2, soapyHeaders: SoapyHeaders,
|
refreshAuthToken: async (_, _2, soapyHeaders: SoapyHeaders,
|
||||||
req: Pick<Request, "headers">) => {
|
{ headers }: Pick<Request, "headers">) => {
|
||||||
const creds = useHeaderIfPresent(soapyHeaders?.credentials, req.headers);
|
const creds = useHeaderIfPresent(soapyHeaders?.credentials, headers);
|
||||||
// Get the old SMAPI token from credentials before refreshing
|
|
||||||
const oldSmapiToken = creds?.loginToken.token;
|
|
||||||
const serviceToken = pipe(
|
const serviceToken = pipe(
|
||||||
auth(creds),
|
auth(creds),
|
||||||
E.fold(
|
E.fold(
|
||||||
@@ -586,7 +582,7 @@ function bindSmapiSoapServiceToExpress(
|
|||||||
return pipe(
|
return pipe(
|
||||||
musicService.refreshToken(serviceToken),
|
musicService.refreshToken(serviceToken),
|
||||||
TE.map((it) => smapiAuthTokens.issue(it.serviceToken)),
|
TE.map((it) => smapiAuthTokens.issue(it.serviceToken)),
|
||||||
TE.tap(swapToken(oldSmapiToken)), // ignores the return value, like a tee or peek
|
TE.tap(swapToken(serviceToken)), // ignores the return value, like a tee or peek
|
||||||
TE.map((it) => ({
|
TE.map((it) => ({
|
||||||
refreshAuthTokenResult: {
|
refreshAuthTokenResult: {
|
||||||
authToken: it.token,
|
authToken: it.token,
|
||||||
@@ -602,9 +598,9 @@ function bindSmapiSoapServiceToExpress(
|
|||||||
{ id }: { id: string },
|
{ id }: { id: string },
|
||||||
_,
|
_,
|
||||||
soapyHeaders: SoapyHeaders,
|
soapyHeaders: SoapyHeaders,
|
||||||
req: Pick<Request, "headers">
|
{ headers }: Pick<Request, "headers">
|
||||||
) =>
|
) => {
|
||||||
login(soapyHeaders?.credentials, req.headers)
|
return login(soapyHeaders?.credentials, headers)
|
||||||
.then(splitId(id))
|
.then(splitId(id))
|
||||||
.then(({ musicLibrary, credentials, type, typeId }) => {
|
.then(({ musicLibrary, credentials, type, typeId }) => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@@ -637,14 +633,15 @@ function bindSmapiSoapServiceToExpress(
|
|||||||
default:
|
default:
|
||||||
throw `Unsupported type:${type}`;
|
throw `Unsupported type:${type}`;
|
||||||
}
|
}
|
||||||
}),
|
});
|
||||||
|
},
|
||||||
getMediaMetadata: async (
|
getMediaMetadata: async (
|
||||||
{ id }: { id: string },
|
{ id }: { id: string },
|
||||||
_,
|
_,
|
||||||
soapyHeaders: SoapyHeaders,
|
soapyHeaders: SoapyHeaders,
|
||||||
req: Pick<Request, "headers">
|
{ headers }: Pick<Request, "headers">
|
||||||
) =>
|
) => {
|
||||||
login(soapyHeaders?.credentials, req.headers)
|
return login(soapyHeaders?.credentials, headers)
|
||||||
.then(splitId(id))
|
.then(splitId(id))
|
||||||
.then(async ({ musicLibrary, apiKey, type, typeId }) => {
|
.then(async ({ musicLibrary, apiKey, type, typeId }) => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@@ -659,14 +656,15 @@ function bindSmapiSoapServiceToExpress(
|
|||||||
default:
|
default:
|
||||||
throw `Unsupported type:${type}`;
|
throw `Unsupported type:${type}`;
|
||||||
}
|
}
|
||||||
}),
|
});
|
||||||
|
},
|
||||||
search: async (
|
search: async (
|
||||||
{ id, term }: { id: string; term: string },
|
{ id, term }: { id: string; term: string },
|
||||||
_,
|
_,
|
||||||
soapyHeaders: SoapyHeaders,
|
soapyHeaders: SoapyHeaders,
|
||||||
req: Pick<Request, "headers">
|
{ headers }: Pick<Request, "headers">
|
||||||
) =>
|
) => {
|
||||||
login(soapyHeaders?.credentials, req.headers)
|
return login(soapyHeaders?.credentials, headers)
|
||||||
.then(splitId(id))
|
.then(splitId(id))
|
||||||
.then(async ({ musicLibrary, apiKey }) => {
|
.then(async ({ musicLibrary, apiKey }) => {
|
||||||
switch (id) {
|
switch (id) {
|
||||||
@@ -700,7 +698,8 @@ function bindSmapiSoapServiceToExpress(
|
|||||||
default:
|
default:
|
||||||
throw `Unsupported search by:${id}`;
|
throw `Unsupported search by:${id}`;
|
||||||
}
|
}
|
||||||
}),
|
});
|
||||||
|
},
|
||||||
getExtendedMetadata: async (
|
getExtendedMetadata: async (
|
||||||
{
|
{
|
||||||
id,
|
id,
|
||||||
@@ -710,9 +709,9 @@ function bindSmapiSoapServiceToExpress(
|
|||||||
{ id: string; index: number; count: number; recursive: boolean },
|
{ id: string; index: number; count: number; recursive: boolean },
|
||||||
_,
|
_,
|
||||||
soapyHeaders: SoapyHeaders,
|
soapyHeaders: SoapyHeaders,
|
||||||
req: Pick<Request, "headers">
|
{ headers }: Pick<Request, "headers">
|
||||||
) =>
|
) => {
|
||||||
login(soapyHeaders?.credentials, req.headers)
|
return login(soapyHeaders?.credentials, headers)
|
||||||
.then(splitId(id))
|
.then(splitId(id))
|
||||||
.then(async ({ musicLibrary, apiKey, type, typeId }) => {
|
.then(async ({ musicLibrary, apiKey, type, typeId }) => {
|
||||||
const paging = { _index: index, _count: count };
|
const paging = { _index: index, _count: count };
|
||||||
@@ -772,7 +771,8 @@ function bindSmapiSoapServiceToExpress(
|
|||||||
default:
|
default:
|
||||||
throw `Unsupported getExtendedMetadata id=${id}`;
|
throw `Unsupported getExtendedMetadata id=${id}`;
|
||||||
}
|
}
|
||||||
}),
|
});
|
||||||
|
},
|
||||||
getMetadata: async (
|
getMetadata: async (
|
||||||
{
|
{
|
||||||
id,
|
id,
|
||||||
@@ -782,13 +782,13 @@ function bindSmapiSoapServiceToExpress(
|
|||||||
{ id: string; index: number; count: number; recursive: boolean },
|
{ id: string; index: number; count: number; recursive: boolean },
|
||||||
_,
|
_,
|
||||||
soapyHeaders: SoapyHeaders,
|
soapyHeaders: SoapyHeaders,
|
||||||
req: Pick<Request, "headers">
|
{ headers }: Pick<Request, "headers">
|
||||||
) =>
|
) => {
|
||||||
login(soapyHeaders?.credentials, req.headers)
|
const acceptLanguage = headers["accept-language"];
|
||||||
|
return login(soapyHeaders?.credentials, headers)
|
||||||
.then(splitId(id))
|
.then(splitId(id))
|
||||||
.then(({ musicLibrary, apiKey, type, typeId }) => {
|
.then(({ musicLibrary, apiKey, type, typeId }) => {
|
||||||
const paging = { _index: index, _count: count };
|
const paging = { _index: index, _count: count };
|
||||||
const acceptLanguage = req.headers["accept-language"];
|
|
||||||
logger.debug(
|
logger.debug(
|
||||||
`Fetching metadata type=${type}, typeId=${typeId}, acceptLanguage=${acceptLanguage}`
|
`Fetching metadata type=${type}, typeId=${typeId}, acceptLanguage=${acceptLanguage}`
|
||||||
);
|
);
|
||||||
@@ -1103,14 +1103,15 @@ function bindSmapiSoapServiceToExpress(
|
|||||||
default:
|
default:
|
||||||
throw `Unsupported getMetadata id=${id}`;
|
throw `Unsupported getMetadata id=${id}`;
|
||||||
}
|
}
|
||||||
}),
|
});
|
||||||
|
},
|
||||||
createContainer: async (
|
createContainer: async (
|
||||||
{ title, seedId }: { title: string; seedId: string | undefined },
|
{ title, seedId }: { title: string; seedId: string | undefined },
|
||||||
_,
|
_,
|
||||||
soapyHeaders: SoapyHeaders,
|
soapyHeaders: SoapyHeaders,
|
||||||
req: Pick<Request, "headers">
|
{ headers }: Pick<Request, "headers">
|
||||||
) =>
|
) => {
|
||||||
login(soapyHeaders?.credentials, req.headers)
|
return login(soapyHeaders?.credentials, headers)
|
||||||
.then(({ musicLibrary }) =>
|
.then(({ musicLibrary }) =>
|
||||||
musicLibrary
|
musicLibrary
|
||||||
.createPlaylist(title)
|
.createPlaylist(title)
|
||||||
@@ -1130,35 +1131,38 @@ function bindSmapiSoapServiceToExpress(
|
|||||||
id: `playlist:${it.id}`,
|
id: `playlist:${it.id}`,
|
||||||
updateId: "",
|
updateId: "",
|
||||||
},
|
},
|
||||||
})),
|
}));
|
||||||
|
},
|
||||||
deleteContainer: async (
|
deleteContainer: async (
|
||||||
{ id }: { id: string },
|
{ id }: { id: string },
|
||||||
_,
|
_,
|
||||||
soapyHeaders: SoapyHeaders,
|
soapyHeaders: SoapyHeaders,
|
||||||
req: Pick<Request, "headers">
|
{ headers }: Pick<Request, "headers">
|
||||||
) =>
|
) => {
|
||||||
login(soapyHeaders?.credentials, req.headers)
|
return login(soapyHeaders?.credentials, headers)
|
||||||
.then(({ musicLibrary }) => musicLibrary.deletePlaylist(id))
|
.then(({ musicLibrary }) => musicLibrary.deletePlaylist(id))
|
||||||
.then((_) => ({ deleteContainerResult: {} })),
|
.then((_) => ({ deleteContainerResult: {} }));
|
||||||
|
},
|
||||||
addToContainer: async (
|
addToContainer: async (
|
||||||
{ id, parentId }: { id: string; parentId: string },
|
{ id, parentId }: { id: string; parentId: string },
|
||||||
_,
|
_,
|
||||||
soapyHeaders: SoapyHeaders,
|
soapyHeaders: SoapyHeaders,
|
||||||
req: Pick<Request, "headers">
|
{ headers }: Pick<Request, "headers">
|
||||||
) =>
|
) => {
|
||||||
login(soapyHeaders?.credentials, req.headers)
|
return login(soapyHeaders?.credentials, headers)
|
||||||
.then(splitId(id))
|
.then(splitId(id))
|
||||||
.then(({ musicLibrary, typeId }) =>
|
.then(({ musicLibrary, typeId }) =>
|
||||||
musicLibrary.addToPlaylist(parentId.split(":")[1]!, typeId)
|
musicLibrary.addToPlaylist(parentId.split(":")[1]!, typeId)
|
||||||
)
|
)
|
||||||
.then((_) => ({ addToContainerResult: { updateId: "" } })),
|
.then((_) => ({ addToContainerResult: { updateId: "" } }));
|
||||||
|
},
|
||||||
removeFromContainer: async (
|
removeFromContainer: async (
|
||||||
{ id, indices }: { id: string; indices: string },
|
{ id, indices }: { id: string; indices: string },
|
||||||
_,
|
_,
|
||||||
soapyHeaders: SoapyHeaders,
|
soapyHeaders: SoapyHeaders,
|
||||||
req: Pick<Request, "headers">
|
{ headers }: Pick<Request, "headers">
|
||||||
) =>
|
) => {
|
||||||
login(soapyHeaders?.credentials, req.headers)
|
return login(soapyHeaders?.credentials, headers)
|
||||||
.then(splitId(id))
|
.then(splitId(id))
|
||||||
.then((it) => ({
|
.then((it) => ({
|
||||||
...it,
|
...it,
|
||||||
@@ -1175,27 +1179,29 @@ function bindSmapiSoapServiceToExpress(
|
|||||||
musicLibrary.removeFromPlaylist(typeId, indices);
|
musicLibrary.removeFromPlaylist(typeId, indices);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then((_) => ({ removeFromContainerResult: { updateId: "" } })),
|
.then((_) => ({ removeFromContainerResult: { updateId: "" } }));
|
||||||
|
},
|
||||||
rateItem: async (
|
rateItem: async (
|
||||||
{ id, rating }: { id: string; rating: number },
|
{ id, rating }: { id: string; rating: number },
|
||||||
_,
|
_,
|
||||||
soapyHeaders: SoapyHeaders,
|
soapyHeaders: SoapyHeaders,
|
||||||
req: Pick<Request, "headers">
|
{ headers }: Pick<Request, "headers">
|
||||||
) =>
|
) => {
|
||||||
login(soapyHeaders?.credentials, req.headers)
|
return login(soapyHeaders?.credentials, headers)
|
||||||
.then(splitId(id))
|
.then(splitId(id))
|
||||||
.then(({ musicLibrary, typeId }) =>
|
.then(({ musicLibrary, typeId }) =>
|
||||||
musicLibrary.rate(typeId, ratingFromInt(Math.abs(rating)))
|
musicLibrary.rate(typeId, ratingFromInt(Math.abs(rating)))
|
||||||
)
|
)
|
||||||
.then((_) => ({ rateItemResult: { shouldSkip: false } })),
|
.then((_) => ({ rateItemResult: { shouldSkip: false } }));
|
||||||
|
},
|
||||||
|
|
||||||
setPlayedSeconds: async (
|
setPlayedSeconds: async (
|
||||||
{ id, seconds }: { id: string; seconds: string },
|
{ id, seconds }: { id: string; seconds: string },
|
||||||
_,
|
_,
|
||||||
soapyHeaders: SoapyHeaders,
|
soapyHeaders: SoapyHeaders,
|
||||||
req: Pick<Request, "headers">
|
{ headers }: Pick<Request, "headers">
|
||||||
) =>
|
) => {
|
||||||
login(soapyHeaders?.credentials, req.headers)
|
return login(soapyHeaders?.credentials, headers)
|
||||||
.then(splitId(id))
|
.then(splitId(id))
|
||||||
.then(({ musicLibrary, type, typeId }) => {
|
.then(({ musicLibrary, type, typeId }) => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@@ -1217,15 +1223,16 @@ function bindSmapiSoapServiceToExpress(
|
|||||||
})
|
})
|
||||||
.then((_) => ({
|
.then((_) => ({
|
||||||
setPlayedSecondsResult: {},
|
setPlayedSecondsResult: {},
|
||||||
})),
|
}));
|
||||||
|
},
|
||||||
|
|
||||||
reportPlaySeconds: async (
|
reportPlaySeconds: async (
|
||||||
{ id, seconds }: { id: string; seconds: string },
|
{ id, seconds }: { id: string; seconds: string },
|
||||||
_,
|
_,
|
||||||
soapyHeaders: SoapyHeaders,
|
soapyHeaders: SoapyHeaders,
|
||||||
req: Pick<Request, "headers">
|
{ headers }: Pick<Request, "headers">
|
||||||
) =>
|
) => {
|
||||||
login(soapyHeaders?.credentials, req.headers)
|
return login(soapyHeaders?.credentials, headers)
|
||||||
.then(splitId(id))
|
.then(splitId(id))
|
||||||
.then(({ type, typeId }) => {
|
.then(({ type, typeId }) => {
|
||||||
if (type === "track") {
|
if (type === "track") {
|
||||||
@@ -1237,15 +1244,16 @@ function bindSmapiSoapServiceToExpress(
|
|||||||
})
|
})
|
||||||
.then((_) => ({
|
.then((_) => ({
|
||||||
reportPlaySecondsResult: { interval: 30 },
|
reportPlaySecondsResult: { interval: 30 },
|
||||||
})),
|
}));
|
||||||
|
},
|
||||||
|
|
||||||
reportPlayStatus: async (
|
reportPlayStatus: async (
|
||||||
{ id, status }: { id: string; status: string },
|
{ id, status }: { id: string; status: string },
|
||||||
_,
|
_,
|
||||||
soapyHeaders: SoapyHeaders,
|
soapyHeaders: SoapyHeaders,
|
||||||
req: Pick<Request, "headers">
|
{ headers }: Pick<Request, "headers">
|
||||||
) =>
|
) => {
|
||||||
login(soapyHeaders?.credentials, req.headers)
|
return login(soapyHeaders?.credentials, headers)
|
||||||
.then(splitId(id))
|
.then(splitId(id))
|
||||||
.then(({ musicLibrary, type, typeId }) => {
|
.then(({ musicLibrary, type, typeId }) => {
|
||||||
if (type === "track") {
|
if (type === "track") {
|
||||||
@@ -1256,7 +1264,8 @@ function bindSmapiSoapServiceToExpress(
|
|||||||
}
|
}
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
})
|
})
|
||||||
.then((_) => ({})),
|
.then((_) => ({}));
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user