Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/FoxxMD/multi-scrobbler. Scrobble plays from multiple sources to multiple clients docs.multi-scrobbler.app
deezer docker jellyfin koito lastfm listenbrainz maloja mopidy mpris music music-assistant plex scrobble self-hosted spotify subsonic tautulli youtube-music
Something went wrong. Try again.
4.4 kB · 114 lines
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114import type {Logger} from "@foxxmd/logging";import type ScrobbleClients from "../scrobblers/ScrobbleClients.ts";import type ScrobbleSources from "../sources/ScrobbleSources.ts";import type {Request, Response, NextFunction} from "express";import type AbstractSource from "../sources/AbstractSource.ts";import type AbstractScrobbleClient from "../scrobblers/AbstractScrobbleClient.ts";import type { TypedMiddleware } from "@minisylar/express-typed-router";
export const nonEmptyBody = (logger: Logger, origin: string = 'Origin'): TypedMiddleware => async (req, res, next) => { const bodyEmpty = req.body === undefined || req.body === null || (typeof req.body === 'object' && Object.keys(req.body).length === 0); if (bodyEmpty) { const length = req.header('content-length') !== undefined ? Number.parseInt(req.header('content-length')) : undefined; // can't think of a way a user would send an empty body for a payload but if they meant to do it don't spam them with errors... if (length === 0) { return; } if (length === undefined) { logger.warn(`${origin} is not sending a well-formatted request. It does not have valid headers (application/json - text/*) OR it is missing content-length header: Content-Type => '${req.header('content-type')}' | Length => ${length}`); } else { logger.warn(`${origin} is not sending a request with valid headers. Content-Type must be either application/json or a text/* wildcard (like text/plain) -- given: Content-Type => '${req.header('content-type')}'`); } res.status(400).send('Invalid Content-Type. Must be either application/json or a text wildcard (like text/plain)'); return; } next();}
export interface ComponentAwareRequest extends Request { component: AbstractSource | AbstractScrobbleClient}
export const makeComponentMiddle = (sources: ScrobbleSources, clients: ScrobbleClients): TypedMiddleware<{component: ComponentAwareRequest['component']}> => (req, res, next) => { const { params: { id } } = req;
const componentId = Number.parseInt(id as string); if (isNaN(componentId)) { res.status(400).json({ error: 'Component id must be a number' }); return; }
let component: AbstractSource | AbstractScrobbleClient; component = sources.sources.find(x => x.componentId === componentId); if (component === undefined) { component = clients.clients.find(x => x.componentId === componentId); }
if(component === undefined) { res.status(404).json({error: `No Component with the Id ${componentId} exists`}); return; }
(req as ComponentAwareRequest).component = component;
next();}
export interface SourceAwareRequest extends Request { component: AbstractSource}export interface ClientAwareRequest extends Request { component: AbstractScrobbleClient}
export const makeSourceNextMiddle = (sources: ScrobbleSources): TypedMiddleware<{component: AbstractSource}> => async (req: Request, res: Response, next: NextFunction) => { const { params: { id } } = req;
const componentId = Number.parseInt(id as string); if (isNaN(componentId)) { res.status(400).json({ error: 'Source Id must be a number' }); return; }
const component: AbstractSource = sources.sources.find(x => x.componentId === componentId); if(component === undefined) { res.status(404).json({error: `No Source with the Id ${componentId} exists`}); return; }
(req as SourceAwareRequest).component = component;
next();}
export const makeClientNextMiddle = (clients: ScrobbleClients): TypedMiddleware<{component: AbstractScrobbleClient}> => async (req: Request, res: Response, next: NextFunction) => { const { params: { id } } = req;
const componentId = Number.parseInt(id as string); if (isNaN(componentId)) { res.status(400).json({ error: 'Source Id must be a number' }); return; }
const component: AbstractScrobbleClient = clients.clients.find(x => x.componentId === componentId); if(component === undefined) { res.status(404).json({error: `No Client with the Id ${componentId} exists`}); return; }
(req as ClientAwareRequest).component = component;
next();}