aboutsummaryrefslogtreecommitdiffstats
path: root/app/spotify/client.ts
diff options
context:
space:
mode:
authorLeonardo Bishop <me@leonardobishop.com>2023-08-06 12:57:55 +0100
committerLeonardo Bishop <me@leonardobishop.com>2023-08-06 12:57:55 +0100
commit31569d1a78a0731ef9efc7d462ec39acd428d588 (patch)
tree8a17373f8b950c2e93872da293216e359403595b /app/spotify/client.ts
parentccb8ef7183e6d7af7bde4bb398c27379fdc7089f (diff)
Add spotify page
Diffstat (limited to 'app/spotify/client.ts')
-rw-r--r--app/spotify/client.ts158
1 files changed, 0 insertions, 158 deletions
diff --git a/app/spotify/client.ts b/app/spotify/client.ts
deleted file mode 100644
index 2cdf527..0000000
--- a/app/spotify/client.ts
+++ /dev/null
@@ -1,158 +0,0 @@
-import axios from 'axios';
-import { logger } from '../logger.js';
-import { WebSocket } from 'ws';
-
-export namespace SpotifyClient {
- let clients = new Set<WebSocket>();
- let interval: NodeJS.Timeout;
-
- let acceptingClients = false;
- let authenticationFailed = false;
-
- let accessToken: string;
- let refreshToken: string;
-
- export const addClient = (client: WebSocket) => {
- if (acceptingClients) {
- clients.add(client);
- } else {
- client.close();
- }
- }
-
- const apiTokenUrl = 'https://accounts.spotify.com/api/token';
-
- const spotifyClientHeaders = {
- 'Authorization': 'Basic ' + Buffer.from(process.env.SPOTIFY_CLIENT_ID + ':' + process.env.SPOTIFY_CLIENT_SECRET).toString('base64'),
- 'Content-Type': 'application/x-www-form-urlencoded',
- }
-
- const handleApiError = (err: any, verb: string) => {
- if (err.response?.data?.error) {
- logger.error(`Failed to ${verb} access token: ${err.message}: ${err.response.data.error}`);
- } else {
- logger.error(`Failed to get access token: ${err.message} (${err.response.status} ${err.response.statusText} ${err.response.data.error})`);
- }
- accessToken = undefined;
- refreshToken = undefined;
- }
-
- export const requestAccessToken = async () => {
- logger.info('Requesting access token from Spotify');
- await axios.post(apiTokenUrl, {
- grant_type: 'authorization_code',
- code: process.env.SPOTIFY_AUTH_CODE,
- redirect_uri: process.env.SPOTIFY_REDIRECT_URI,
- },
- { headers: spotifyClientHeaders,
- }).then(res => {
- logger.info('Authenticated with Spotify');
- accessToken = res.data.access_token;
- }).catch(err => {
- handleApiError(err, 'request');
- });
- }
-
- export const refreshAccessToken = async () => {
- logger.info('Refreshing access token from Spotify');
- await axios.post(apiTokenUrl, {
- grant_type: 'refresh_token',
- refresh_token: refreshToken,
- },
- { headers: spotifyClientHeaders,
- }).then(res => {
- logger.info('Refreshed access token from Spotify');
- accessToken = res.data.access_token;
- }).catch(err => {
- handleApiError(err, 'refresh');
- });
- }
-
-
- export const initialise = async () => {
- if (!accessToken) {
- await requestAccessToken();
- if (!accessToken) {
- logger.error('Failed to get access token, giving up permanently');
- authenticationFailed = true;
- return;
- }
- }
- await updateTimeout();
- acceptingClients = true;
- }
-
- const updateTimeout = async () => {
- await update();
- interval = setTimeout(updateTimeout, 5000);
- }
-
- export const update = async () => {
- if (authenticationFailed) {
- return;
- }
- clients.forEach(client => {
- if (client.readyState !== WebSocket.OPEN) {
- clients.delete(client);
- }
- });
- if (clients.size === 0) {
- return;
- }
- await axios.get('https://api.spotify.com/v1/me/player/currently-playing', {
- headers: {
- 'Authorization': 'Bearer ' + accessToken,
- }
- }).then(async (res) => {
- if (res.status === 401) {
- logger.info('Access token expired, refreshing');
- await refreshAccessToken();
- if (!accessToken) {
- authenticationFailed = true;
- logger.error('Failed to get access token, giving up permanently');
- stop();
- return;
- }
- await update();
- return;
- }
- if (res.status !== 200) {
- logger.error(`Failed to get current song: ${res.status} ${res.statusText}`);
- return;
- }
- try {
- let song = res.data.item.name;
- let duration = res.data.item.duration_ms;
- let artist = res.data.item.artists[0].name;
- let time = res.data.progress_ms;
- let album = res.data.item.album.name;
- let albumImage = res.data.item.album.images[0].url;
- clients.forEach(client => {
- client.send(JSON.stringify({
- song: song,
- artist: artist,
- time: time,
- duration: duration,
- album: album,
- albumImage: albumImage,
- }));
- });
- } catch (err) {
- logger.error(`Failed to parse and send current song: ${err.message}`);
- }
- }).catch(err => {
- if (err.response?.data?.error?.message) {
- logger.error(`Failed to get current song: ${err.message}: ${err.response.data.error.message}`);
- } else {
- logger.error(`Failed to get current song: ${err.message} (${err.response.status} ${err.response.statusText} ${err.response.data.error})`);
- }
- });
- }
-
- export const stop = () => {
- clearInterval(interval);
- acceptingClients = false;
- clients.forEach(client => client.close());
- }
-
-}