Added song data class. Added trackers.

This commit is contained in:
Tom 2024-12-05 04:18:35 +00:00
parent 539b9a5055
commit 6e43d681da
4 changed files with 171 additions and 0 deletions

16
models/song.js Normal file
View File

@ -0,0 +1,16 @@
class Song {
constructor(id, name, album, artists, year, duration, progress, session, state, source) {
this.id = id;
this.name = name;
this.album = album;
this.artists = artists;
this.year = year;
this.duration = duration;
this.progress = progress;
this.session = session;
this.state = state;
this.source = source;
}
}
module.exports = Song;

View File

@ -0,0 +1,13 @@
class AggregateTracker {
constructor(trackers) {
this._trackers = trackers;
}
poll() {
const media = []
for (let tracker of this._trackers)
media.push.apply(tracker.poll());
return media;
}
}

View File

@ -0,0 +1,59 @@
const axios = require("axios");
const Song = require("../../models/song");
class PlexTracker {
constructor(config) {
this._config = config;
this._cache = []
}
async poll(useCache = false) {
if (!this._config.token || !this._config.url)
return [];
if (useCache)
return cache;
const response = await axios.get(this._config.url + "/status/sessions", {
headers: {
"Accept": "application/json",
"X-Plex-Token": this._config.token
}
});
if (!response.data.MediaContainer?.Metadata) {
cache = [];
return cache;
}
const filtered = response.data.MediaContainer?.Metadata.filter(m => this.#filter(m));
cache = filtered.map(this.#transform);
return cache;
}
#filter(data) {
if (!this._config.filters || this._config.filters.length == 0)
return true;
for (let filter of this._config.filters) {
if (filter.library && !filter.library.some(l => l == data.librarySectionTitle))
continue;
if (filter.ip && !filter.ip.some(l => l == data.address))
continue;
if (filter.deviceId && !filter.deviceId.some(l => l == data.machineIdentifier))
continue;
if (filter.platform && !filter.platform.some(l => l == data.Player.platform))
continue;
if (filter.product && !filter.product.some(l => l == data.Player.product))
continue;
return true;
}
return false;
}
#transform(data) {
const id = data.guid.substring(data.guid.lastIndexOf('/') + 1);
return new Song(id, data.title, data.parentTitle, data.grandparentTitle, data.parentYear, data.duration, data.viewOffset, data.sessionKey, data.Player.state, "plex");
}
}
module.exports = PlexTracker;

View File

@ -0,0 +1,83 @@
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;