apollo/services/trackers/SpotifyTracker.js

83 lines
2.3 KiB
JavaScript

const axios = require("axios");
const logger = require("./logging");
const fs = require("fs/promises");
const Song = require("../../models/song");
class SpotifyTracker {
constructor(config, token) {
this._token = token;
this._cache = null;
this._config = config;
this._auth = new Buffer.from(config.client_id + ':' + config.client_secret).toString('base64');
}
async poll(useCache = false) {
if (token == null)
return null;
if (useCache)
return cache;
if (token.expires_at < Date.now() + 300)
await this.#refreshTokenIfNeeded();
try {
const response = await axios.get("https://api.spotify.com/v1/me/player/currently-playing",
{
headers: {
"Authorization": "Bearer " + token["access_token"]
}
}
);
if (!response.data) {
cache = null;
return null;
}
cache = [this.#transform(response.data)];
return cache;
} catch (ex) {
logger.error(ex, "Failed to get currently playing data from Spotify.");
return [];
}
}
#transform(data) {
const item = data.item;
const artists = item.artists.map(a => a.name);
const year = null;
const state = data.is_playing ? "playing" : "paused";
return new Song(item.id, item.name, item.album.name, artists, year, item.duration_ms, data.progress_ms, "spotify", state, "spotify");
}
async #refreshTokenIfNeeded() {
if (!this._token || this._token.expires_at && this._token.expires_at - Date.now() > 900)
return false;
const response = await axios.post("https://accounts.spotify.com/api/token",
{
client_id: this._config.client_id,
refresh_token: this._token.refresh_token,
grant_type: "refresh_token"
},
{
headers: {
"Authorization": "Basic " + this._auth,
"Content-Type": "application/x-www-form-urlencoded"
}
}
);
const data = response.data;
data["expires_at"] = Date.now() + data["expires_in"] * 1000;
if (!data["refresh_token"])
data["refresh_token"] = this._token.refresh_token;
this._token = data;
await fs.writeFile("credentials.spotify.json", JSON.stringify(data));
logger.debug("Updated access token for Spotify.");
return true;
}
}
module.exports = SpotifyTracker;