Added song data class. Added trackers.
This commit is contained in:
parent
539b9a5055
commit
6e43d681da
16
models/song.js
Normal file
16
models/song.js
Normal 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;
|
13
services/trackers/AggregateTracker.js
Normal file
13
services/trackers/AggregateTracker.js
Normal 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;
|
||||
}
|
||||
}
|
59
services/trackers/PlexTracker.js
Normal file
59
services/trackers/PlexTracker.js
Normal 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;
|
83
services/trackers/SpotifyTracker.js
Normal file
83
services/trackers/SpotifyTracker.js
Normal 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;
|
Loading…
Reference in New Issue
Block a user