aboutsummaryrefslogtreecommitdiffstats
path: root/app
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
parentccb8ef7183e6d7af7bde4bb398c27379fdc7089f (diff)
Add spotify page
Diffstat (limited to 'app')
-rw-r--r--app/index.ts14
-rw-r--r--app/routes/spotify/router.ts26
-rw-r--r--app/spotify/client.ts158
-rw-r--r--app/websocket/spotify.ts18
4 files changed, 0 insertions, 216 deletions
diff --git a/app/index.ts b/app/index.ts
index 3558d1f..664a751 100644
--- a/app/index.ts
+++ b/app/index.ts
@@ -4,12 +4,6 @@ import * as page from './routes/page/router.js';
import * as blog from './routes/blog/router.js';
import { logger } from './logger.js'
import { PageDirectory } from './pages.js';
-// import { SpotifyClient } from './spotify/client.js';
-// import { WebSocketServer } from 'ws';
-// import * as spotifyauth from './routes/spotify/router.js';
-// import * as spotifyWs from './websocket/spotify.js';
-
-// TODO: Figure out Spotify's tedious auth flow
dotenv.config()
@@ -24,7 +18,6 @@ app.use(express.static('static', {
app.use(blog.router);
app.use(page.router);
-// app.use(spotifyauth.router);
app.use((req, res) => {
res.render('error.ejs', {
@@ -35,14 +28,9 @@ app.use((req, res) => {
const server = app.listen(process.env.PORT, () => {
logger.info(`App listening on port ${process.env.PORT}`);
});
-// const websocketServer: WebSocketServer = spotifyWs.createWebsocketServer(server);
const exit = () => {
logger.info('Stopping server...');
- // websocketServer.clients.forEach(client => {
- // client.terminate();
- // });
- // websocketServer.close();
server.close(() => {
process.exit(0);
})
@@ -50,7 +38,5 @@ const exit = () => {
PageDirectory.rebuild('pages');
-// SpotifyClient.initialise();
-
process.on('SIGINT', exit);
process.on('SIGTERM', exit);
diff --git a/app/routes/spotify/router.ts b/app/routes/spotify/router.ts
deleted file mode 100644
index faf8f6d..0000000
--- a/app/routes/spotify/router.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import express from 'express';
-
-export const router = express.Router({ mergeParams: true });
-
-router.get('/spotify/auth', (req, res, next) => {
- let scope = 'user-read-currently-playing';
- let params = new URLSearchParams();
- params.append('response_type', 'code');
- params.append('client_id', process.env.SPOTIFY_CLIENT_ID);
- params.append('scope', scope);
- params.append('redirect_uri', process.env.SPOTIFY_REDIRECT_URI);
-
- res.redirect('https://accounts.spotify.com/authorize?' + params.toString());
-});
-
-router.get('/spotify/auth/callback', (req, res, next) => {
- if (req.query.error) {
- res.send('Error: ' + req.query.error);
- return;
- }
- if (!req.query.code) {
- res.send('No code');
- return;
- }
- res.send('Your authentication code: ' + req.query.code);
-});
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());
- }
-
-}
diff --git a/app/websocket/spotify.ts b/app/websocket/spotify.ts
deleted file mode 100644
index 4b81fe0..0000000
--- a/app/websocket/spotify.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { Server } from 'http';
-import { WebSocketServer } from 'ws';
-import { SpotifyClient } from '../spotify/client.js';
-
-export const createWebsocketServer = (server: Server): WebSocketServer => {
- const wss = new WebSocketServer({ noServer: true });
- server.on('upgrade', (req, socket, head) => {
- wss.handleUpgrade(req, socket, head, (ws) => {
- wss.emit('connection', ws, req)
- })
- })
-
- wss.on('connection', (ws) => {
- SpotifyClient.addClient(ws);
- });
-
- return wss;
-}