Compare commits
No commits in common. "9335e3e32f96ddf6f79fd966beb9e65fe80fc470" and "0bfbc369520ba3b97ab008c8cb07289ce76fb323" have entirely different histories.
9335e3e32f
...
0bfbc36952
2
app.js
2
app.js
@ -10,7 +10,7 @@ const Recorder = require("./services/recorder");
|
|||||||
const MalojaScrobbler = require("./services/scrobblers/maloja-scrobbler");
|
const MalojaScrobbler = require("./services/scrobblers/maloja-scrobbler");
|
||||||
|
|
||||||
|
|
||||||
const maloja = new MalojaScrobbler(config.maloja, logger);
|
const maloja = new MalojaScrobbler(config.maloja);
|
||||||
const spotify = new SpotifyTracker(config.spotify);
|
const spotify = new SpotifyTracker(config.spotify);
|
||||||
(async () => await spotify.loadCredentials())();
|
(async () => await spotify.loadCredentials())();
|
||||||
const plex = new PlexTracker(config.plex);
|
const plex = new PlexTracker(config.plex);
|
||||||
|
7
package-lock.json
generated
7
package-lock.json
generated
@ -10,7 +10,6 @@
|
|||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ajv": "^8.17.1",
|
"ajv": "^8.17.1",
|
||||||
"async-await-queue": "^2.1.4",
|
|
||||||
"axios": "^1.7.8",
|
"axios": "^1.7.8",
|
||||||
"express": "^4.21.1",
|
"express": "^4.21.1",
|
||||||
"express-rate-limit": "^7.4.1",
|
"express-rate-limit": "^7.4.1",
|
||||||
@ -60,12 +59,6 @@
|
|||||||
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
|
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/async-await-queue": {
|
|
||||||
"version": "2.1.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/async-await-queue/-/async-await-queue-2.1.4.tgz",
|
|
||||||
"integrity": "sha512-3DpDtxkKO0O/FPlWbk/CrbexjuSxWm1CH1bXlVNVyMBIkKHhT5D85gzHmGJokG3ibNGWQ7pHBmStxUW/z/0LYQ==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/asynckit": {
|
"node_modules/asynckit": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
"description": "",
|
"description": "",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ajv": "^8.17.1",
|
"ajv": "^8.17.1",
|
||||||
"async-await-queue": "^2.1.4",
|
|
||||||
"axios": "^1.7.8",
|
"axios": "^1.7.8",
|
||||||
"express": "^4.21.1",
|
"express": "^4.21.1",
|
||||||
"express-rate-limit": "^7.4.1",
|
"express-rate-limit": "^7.4.1",
|
||||||
|
@ -62,7 +62,7 @@ class Recorder {
|
|||||||
this.#sessions.add(session);
|
this.#sessions.add(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
return { session, media, tracker, extraDuration: 0, scrobble: null }
|
return { session, media, tracker, extraDuration: 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
#listen(context, timestamp) {
|
#listen(context, timestamp) {
|
||||||
@ -85,15 +85,11 @@ class Recorder {
|
|||||||
const progressDiff = Math.max(0, Math.min(current.progress - previous.progress, timeDiff));
|
const progressDiff = Math.max(0, Math.min(current.progress - previous.progress, timeDiff));
|
||||||
session.playDuration += progressDiff;
|
session.playDuration += progressDiff;
|
||||||
session.pauseDuration += timeDiff - progressDiff;
|
session.pauseDuration += timeDiff - progressDiff;
|
||||||
|
|
||||||
const canScrobble = this.#canScrobble(session, current, previous);
|
const canScrobble = this.#canScrobble(session, current, previous);
|
||||||
if (canScrobble || current.id != previous.id) {
|
if (canScrobble || current.id != previous.id) {
|
||||||
context.extraDuration = Math.max(Math.min(current.progress, timeDiff - (previous.duration - previous.progress)), 0);
|
context.extraDuration = Math.min(current.progress, timeDiff - (previous.duration - previous.progress));
|
||||||
context.extraDuration += Math.max(0, session.playDuration - previous.duration);
|
|
||||||
session.lastScrobbleTimestamp = timestamp;
|
session.lastScrobbleTimestamp = timestamp;
|
||||||
|
|
||||||
if (canScrobble)
|
|
||||||
context.scrobble = previous;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
session.lastUpdateTimestamp = timestamp;
|
session.lastUpdateTimestamp = timestamp;
|
||||||
@ -110,11 +106,11 @@ class Recorder {
|
|||||||
const newPlayback = current == null || current.progress < previous.progress;
|
const newPlayback = current == null || current.progress < previous.progress;
|
||||||
const canBeScrobbled = session.playDuration > scrobbleDuration * 1000 || session.playDuration / previous.duration > scrobblePercent / 100.0;
|
const canBeScrobbled = session.playDuration > scrobbleDuration * 1000 || session.playDuration / previous.duration > scrobblePercent / 100.0;
|
||||||
|
|
||||||
return newPlayback && canBeScrobbled || session.playDuration >= previous.duration;
|
return newPlayback && canBeScrobbled;
|
||||||
}
|
}
|
||||||
|
|
||||||
async #scrobble(context) {
|
async #scrobble(context) {
|
||||||
this.#logger.info(context.scrobble, "Scrobble");
|
this.#logger.info(context, "Scrobble");
|
||||||
|
|
||||||
for (var scrobblerName of context.tracker.scrobblerNames) {
|
for (var scrobblerName of context.tracker.scrobblerNames) {
|
||||||
const scrobbler = this.#scrobblers.find(s => s.name == scrobblerName);
|
const scrobbler = this.#scrobblers.find(s => s.name == scrobblerName);
|
||||||
@ -124,9 +120,7 @@ class Recorder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const duration = context.session.playDuration;
|
await scrobbler.scrobble(context.media, Date.now() - Math.min(context.media.duration, context.session.playDuration));
|
||||||
const start = Date.now() - context.session.playDuration - context.session.pauseDuration;
|
|
||||||
await scrobbler.queue(context.scrobble, duration, start);
|
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
this.#logger.error(ex, "Could not send to maloja.");
|
this.#logger.error(ex, "Could not send to maloja.");
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
const axios = require("axios");
|
const axios = require("axios");
|
||||||
const Scrobbler = require("./scrobbler");
|
|
||||||
|
|
||||||
class MalojaScrobbler extends Scrobbler {
|
class MalojaScrobbler {
|
||||||
#config = null;
|
#config = null;
|
||||||
#counter = 0;
|
#counter = 0;
|
||||||
|
|
||||||
constructor(config, logger) {
|
constructor(config) {
|
||||||
super(logger);
|
|
||||||
this.#config = config;
|
this.#config = config;
|
||||||
|
|
||||||
if (!config.name)
|
if (!config.name)
|
||||||
@ -14,7 +12,7 @@ class MalojaScrobbler extends Scrobbler {
|
|||||||
if (!config.url)
|
if (!config.url)
|
||||||
throw new Error(`Invalid url for Maloja scrobbler '${this.name}'.`);
|
throw new Error(`Invalid url for Maloja scrobbler '${this.name}'.`);
|
||||||
if (!config.token)
|
if (!config.token)
|
||||||
throw new Error(`Invalid token for Maloja scrobbler '${this.name}'.`);
|
throw new Error(`Invalid token for Maloja scrobbler '${this.name}'.`)
|
||||||
}
|
}
|
||||||
|
|
||||||
get counter() {
|
get counter() {
|
||||||
@ -25,18 +23,17 @@ class MalojaScrobbler extends Scrobbler {
|
|||||||
return this.#config.name;
|
return this.#config.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
async scrobble(song, duration, start) {
|
async scrobble(song, progress, start) {
|
||||||
const url = new URL(this.#config.url);
|
const url = new URL(this.#config.url);
|
||||||
url.pathname += "/apis/mlj_1/newscrobble";
|
url.pathname += "/apis/mlj_1/newscrobble";
|
||||||
url.search = "?key=" + this.#config.token;
|
url.search = "?key=" + this.#config.token;
|
||||||
|
|
||||||
await axios.post(url.toString(), {
|
await axios.post(url.toString(), {
|
||||||
title: song.name,
|
title: song.name,
|
||||||
album: song.album,
|
album: song.album,
|
||||||
artists: song.artists,
|
artists: song.artists,
|
||||||
duration: Math.round(duration / 1000),
|
duration: Math.round(progress / 1000),
|
||||||
length: Math.round(song.duration / 1000),
|
length: Math.round(song.duration / 1000),
|
||||||
time: Math.round(start / 1000)
|
//time: start
|
||||||
});
|
});
|
||||||
|
|
||||||
this.#counter++;
|
this.#counter++;
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
const { Queue } = require("async-await-queue");
|
|
||||||
|
|
||||||
class Scrobbler {
|
|
||||||
#queue = null;
|
|
||||||
#logger = null;
|
|
||||||
|
|
||||||
constructor(logger) {
|
|
||||||
this.#queue = new Queue(1, 300);
|
|
||||||
this.#logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
async queue(media, duration, start) {
|
|
||||||
const id = Symbol();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await this.#queue.wait(id, 0);
|
|
||||||
|
|
||||||
await this.scrobble(media, duration, start);
|
|
||||||
} catch (ex) {
|
|
||||||
this.#logger.console.error(media, "Failed to scrobble: " + ex.message);
|
|
||||||
} finally {
|
|
||||||
this.#queue.end(id, duration, start);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async scrobble(media, duration, start) {
|
|
||||||
console.log("This should not be running, ever.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = Scrobbler;
|
|
@ -2,7 +2,7 @@ const axios = require("axios");
|
|||||||
const config = require("../config/configuration")
|
const config = require("../config/configuration")
|
||||||
const logger = require("./logging");
|
const logger = require("./logging");
|
||||||
const fs = require("fs/promises");
|
const fs = require("fs/promises");
|
||||||
const fss = require("fs");
|
const fss = require("fs")
|
||||||
|
|
||||||
let token = null;
|
let token = null;
|
||||||
let cache = {}
|
let cache = {}
|
||||||
|
Loading…
Reference in New Issue
Block a user