Added basic filtering to Plex scrobbling detection.

This commit is contained in:
Tom 2024-12-03 23:58:15 +00:00
parent 277df90d56
commit 3112a29bb3
4 changed files with 71 additions and 24 deletions

7
app.js
View File

@ -1,11 +1,8 @@
const dotenv = require('dotenv'); const config = require("./config/configuration");
const express = require('express'); const express = require('express');
const helmet = require("helmet"); const helmet = require("helmet");
const rateLimit = require("express-rate-limit");
const config = require("./config/configuration");
const logger = require("./services/logging"); const logger = require("./services/logging");
const rateLimit = require("express-rate-limit");
dotenv.config();
const poll = require("./services/poll"); const poll = require("./services/poll");
setInterval(poll, 5000); setInterval(poll, 5000);

View File

@ -6,8 +6,21 @@ const configuration = {
token: null token: null
}, },
scrobble: { scrobble: {
percent: null, minimum: {
duration: null percent: null,
duration: null
},
plex: {
delay: null,
filters: []
/* A filter will have the following properties:
library: [""],
ip: [""],
deviceId: [""],
platform: [""],
product: [""]
*/
},
}, },
web: { web: {
host: null, host: null,
@ -20,10 +33,15 @@ if (config.has("plex.url"))
if (config.has("plex.token")) if (config.has("plex.token"))
configuration.plex.token = config.get("plex.token"); configuration.plex.token = config.get("plex.token");
if (config.has("scrobble.duration")) if (config.has("scrobble.plex.delay"))
configuration.scrobble.duration = config.get("scrobble.duration"); configuration.scrobble.plex.delay = config.get("scrobble.plex.delay");
if (config.has("scrobble.percent")) if (config.has("scrobble.plex.filters"))
configuration.scrobble.percent = config.get("scrobble.percent"); configuration.scrobble.plex.filters = config.get("scrobble.plex.filters");
if (config.has("scrobble.minimum.duration"))
configuration.scrobble.minimum.duration = config.get("scrobble.minimum.duration");
if (config.has("scrobble.minimum.percent"))
configuration.scrobble.minimum.percent = config.get("scrobble.minimum.percent");
if (config.has("web.host")) if (config.has("web.host"))
configuration.web.host = config.get("web.host"); configuration.web.host = config.get("web.host");

View File

@ -43,6 +43,7 @@ async function getCurrentlyPlaying(cached = false) {
"platformVersion": media.Player.platformVersion, "platformVersion": media.Player.platformVersion,
"product": media.Player.product, "product": media.Player.product,
"version": media.Player.version, "version": media.Player.version,
"source": "plex"
})); }));
return cache[key]; return cache[key];
} }

View File

@ -17,22 +17,30 @@ async function poll() {
return; return;
} }
for (let media of playing) { for (let current of playing) {
if (!lastScrobbleTimes[media.mediaKey]) { const previous = lastPlaying[current.sessionKey];
lastScrobbleTimes[media.mediaKey] = 1; lastPlaying[current.sessionKey] = current;
if (previous == null) {
continue;
} }
const lastTrack = lastPlaying[media.sessionKey]; let filters = [];
if (!lastTrack) { if (previous.source == 'plex')
logger.info(media, "A new session has started."); filters = config.scrobble.plex.filters;
if (!applyFilter(previous, filters)) {
logger.debug(previous, 'No filters got triggered. Ignoring.');
continue;
}
if (!previous) {
logger.info(current, "A new session has started.");
} else { } else {
if (checkIfCanScrobble(media, lastTrack, now)) { if (checkIfCanScrobble(current, previous, now)) {
logger.info(lastTrack, "Scrobble"); logger.info(previous, "Scrobble");
lastScrobbleTimes[lastTrack.mediaKey] = now; lastScrobbleTimes[previous.mediaKey] = now;
} }
} }
lastPlaying[media.sessionKey] = media;
} }
// Scrobble then remove lingering sessions // Scrobble then remove lingering sessions
@ -49,9 +57,32 @@ async function poll() {
} }
} }
function applyFilter(track, filters) {
if (!filters)
return;
for (let filter of filters) {
if (filter.library && !filter.library.some(l => l == track.library))
continue;
if (filter.ip && !filter.ip.some(l => l == track.ip))
continue;
if (filter.deviceId && !filter.deviceId.some(l => l == track.deviceId))
continue;
if (filter.platform && !filter.platform.some(l => l == track.platform))
continue;
if (filter.product && !filter.product.some(l => l == track.product))
continue;
return true;
}
return false;
}
function checkIfCanScrobble(current, last, now) { function checkIfCanScrobble(current, last, now) {
const scrobbleDuration = isInt(config.scrobble.duration) ? Number(config.scrobble.duration) : 30; if (!last)
const scrobblePercent = isInt(config.scrobble.percent) ? Number(config.scrobble.percent) : 30; return;
const scrobbleDuration = isInt(config.scrobble.minimum.duration) ? Number(config.scrobble.minimum.duration) : 30;
const scrobblePercent = isInt(config.scrobble.minimum.percent) ? Number(config.scrobble.minimum.percent) : 30;
if (last) { if (last) {
const newPlayback = current == null || current.playtime < last.playtime; const newPlayback = current == null || current.playtime < last.playtime;