Files
bonob/src/app.ts
2022-07-30 17:28:30 +10:00

128 lines
3.4 KiB
TypeScript

import path from "path";
import fs from "fs";
import server from "./server";
import logger from "./logger";
import {
appendMimeTypeToClientFor,
axiosImageFetcher,
cachingImageFetcher,
DEFAULT,
Subsonic,
} from "./subsonic";
import { InMemoryAPITokens, sha256 } from "./api_tokens";
import { InMemoryLinkCodes } from "./link_codes";
import readConfig from "./config";
import sonos, { bonobService } from "./sonos";
import { MusicService } from "./music_service";
import { SystemClock } from "./clock";
import { JWTSmapiLoginTokens } from "./smapi_auth";
const config = readConfig();
const clock = SystemClock;
logger.info(`Starting bonob with config ${JSON.stringify({ ...config, secret: "*******" })}`);
const bonob = bonobService(
config.sonos.serviceName,
config.sonos.sid,
config.bonobUrl,
"AppLink"
);
const sonosSystem = sonos(config.sonos.discovery);
const streamUserAgent = config.subsonic.customClientsFor
? appendMimeTypeToClientFor(config.subsonic.customClientsFor.split(","))
: DEFAULT;
const artistImageFetcher = config.subsonic.artistImageCache
? cachingImageFetcher(config.subsonic.artistImageCache, axiosImageFetcher)
: axiosImageFetcher;
const subsonic = new Subsonic(
config.subsonic.url,
streamUserAgent,
artistImageFetcher
);
const featureFlagAwareMusicService: MusicService = {
generateToken: subsonic.generateToken,
refreshToken: subsonic.refreshToken,
login: (serviceToken: string) =>
subsonic.login(serviceToken).then((library) => {
return {
...library,
scrobble: (id: string) => {
if (config.scrobbleTracks) return library.scrobble(id);
else {
logger.info("Track Scrobbling not enabled");
return Promise.resolve(true);
}
},
nowPlaying: (id: string) => {
if (config.reportNowPlaying) return library.nowPlaying(id);
else {
logger.info("Reporting track now playing not enabled");
return Promise.resolve(true);
}
},
};
}),
};
export const GIT_INFO = path.join(__dirname, "..", ".gitinfo");
const version = fs.existsSync(GIT_INFO)
? fs.readFileSync(GIT_INFO).toString().trim()
: "v??";
const app = server(
sonosSystem,
bonob,
config.bonobUrl,
featureFlagAwareMusicService,
{
linkCodes: () => new InMemoryLinkCodes(),
apiTokens: () => new InMemoryAPITokens(sha256(config.secret)),
clock,
iconColors: config.icons,
applyContextPath: true,
logRequests: true,
version,
smapiAuthTokens: new JWTSmapiLoginTokens(clock, config.secret, config.authTimeout),
externalImageResolver: artistImageFetcher
}
);
const expressServer = app.listen(config.port, () => {
logger.info(`Listening on ${config.port} available @ ${config.bonobUrl}`);
});
if (config.sonos.autoRegister) {
sonosSystem.register(bonob).then((success) => {
if (success) {
logger.info(
`Successfully registered ${bonob.name}(SID:${bonob.sid}) with sonos`
);
}
});
} else if (config.sonos.discovery.enabled) {
sonosSystem.devices().then((devices) => {
devices.forEach((d) => {
logger.info(`Found device ${d.name}(${d.group}) @ ${d.ip}:${d.port}`);
});
});
};
process.on('SIGTERM', () => {
logger.info('SIGTERM signal received: closing HTTP server');
expressServer.close(() => {
logger.info('HTTP server closed');
});
process.exit(0);
});
export default app;