const axios = require("axios"); const Song = require("../../models/song"); class PlexTracker { #config = null; #cache = []; provider = "plex"; constructor(config) { this.#config = config; } get name() { return this.#config.name; } get scrobblerNames() { return this.#config.scrobblers; } async poll(useCache = false) { if (!this.#config.token || !this.#config.url) return []; if (useCache) return this.#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) { this.#cache = []; return this.#cache; } const filtered = response.data.MediaContainer?.Metadata.filter(m => this.#filter(m)); this.#cache = filtered.map(m => this.#transform(m, this.#config.name)); return this.#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, source) { const id = data.guid.substring(data.guid.lastIndexOf('/') + 1); const artists = data.grandparentTitle.split(',').map(a => a.trim()); return new Song(id, data.title, data.parentTitle, artists, data.parentYear, data.duration, data.viewOffset, data.sessionKey, data.Player.state, source, "plex"); } } module.exports = PlexTracker;