mirror of
https://github.com/FoxxMD/multi-scrobbler.git
synced 2026-09-03 05:10:00 +03:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8be08a5c29 | ||
|
|
9fe5b9b671 | ||
|
|
720c07b008 | ||
|
|
7fdf93c5d3 | ||
|
|
a0fd466bcf | ||
|
|
35d62c913a |
Vendored
+19
@@ -16,6 +16,25 @@
|
||||
"${workspaceFolder}/node_modules/**",
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "dev (ENV Only)",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
// Debug app in VSCode
|
||||
"program": "${workspaceFolder}/src/backend/index.ts",
|
||||
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/tsx",
|
||||
"console": "integratedTerminal",
|
||||
"envFile": "${workspaceFolder}/.env",
|
||||
"env": {
|
||||
"CONFIG_DIR": "./not-real"
|
||||
},
|
||||
"internalConsoleOptions": "neverOpen",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**",
|
||||
// Ignore all dependencies (optional)
|
||||
"${workspaceFolder}/node_modules/**",
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "tsx",
|
||||
"type": "node",
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "multi-scrobbler",
|
||||
"version": "0.9.5",
|
||||
"version": "0.9.6",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "multi-scrobbler",
|
||||
"version": "0.9.5",
|
||||
"version": "0.9.6",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "multi-scrobbler",
|
||||
"version": "0.9.5",
|
||||
"version": "0.9.6",
|
||||
"type": "module",
|
||||
"description": "scrobble plays from multiple sources to multiple clients",
|
||||
"scripts": {
|
||||
|
||||
+44
-4
@@ -74,8 +74,21 @@ export interface AdditionalTrackInfoResponse extends AdditionalTrackInfo {
|
||||
recording_msid?: string
|
||||
}
|
||||
|
||||
// using submit-listens example from openapi https://rain0r.github.io/listenbrainz-openapi/index.html#/lbCore/submitListens
|
||||
// which is documented in official docs https://listenbrainz.readthedocs.io/en/latest/users/api/index.html#openapi-specification
|
||||
// and based on this LZ developer comment https://github.com/lyarenei/jellyfin-plugin-listenbrainz/issues/10#issuecomment-1253867941
|
||||
export interface SubmitListenAdditionalTrackInfo extends AdditionalTrackInfo {
|
||||
artist_names?: string[]
|
||||
release_artist_name?: string
|
||||
release_artist_names?: string[]
|
||||
spotify_album_id?: string
|
||||
spotify_album_artist_ids?: string[]
|
||||
spotify_artist_ids?: string[]
|
||||
albumartist?: string
|
||||
}
|
||||
|
||||
export interface TrackPayload extends MinimumTrack {
|
||||
additional_info?: AdditionalTrackInfo
|
||||
additional_info?: SubmitListenAdditionalTrackInfo
|
||||
}
|
||||
|
||||
export interface ListenPayload {
|
||||
@@ -339,14 +352,40 @@ export class ListenbrainzApiClient extends AbstractApiClient {
|
||||
track,
|
||||
duration,
|
||||
meta: {
|
||||
brainz = {}
|
||||
brainz = {},
|
||||
spotify = {}
|
||||
} = {}
|
||||
}
|
||||
} = play;
|
||||
// using submit-listens exmaple from openapi https://rain0r.github.io/listenbrainz-openapi/index.html#/lbCore/submitListens
|
||||
// which is documented in official docs https://listenbrainz.readthedocs.io/en/latest/users/api/index.html#openapi-specification
|
||||
// and based on this LZ developer comment https://github.com/lyarenei/jellyfin-plugin-listenbrainz/issues/10#issuecomment-1253867941
|
||||
|
||||
const addInfo: SubmitListenAdditionalTrackInfo = {
|
||||
// all artists
|
||||
artist_names: Array.from(new Set([...artists, ...albumArtists])),
|
||||
// primary artist
|
||||
release_artist_name: artists[0],
|
||||
release_artist_names: [artists[0]],
|
||||
};
|
||||
|
||||
if(spotify.track !== undefined) {
|
||||
addInfo.spotify_id = spotify.track;
|
||||
}
|
||||
if(spotify.album !== undefined) {
|
||||
addInfo.spotify_album_id = spotify.album;
|
||||
}
|
||||
if(spotify.albumArtist !== undefined && spotify.albumArtist.length > 0) {
|
||||
addInfo.spotify_album_artist_ids = spotify.albumArtist;
|
||||
}
|
||||
if(spotify.artist !== undefined) {
|
||||
addInfo.spotify_artist_ids = spotify.artist;
|
||||
}
|
||||
|
||||
return {
|
||||
listened_at: getScrobbleTsSOCDate(play).unix(),
|
||||
track_metadata: {
|
||||
artist_name: artists[0],
|
||||
artist_name: Array.from(new Set([...artists, ...albumArtists])).join(', '),
|
||||
track_name: track,
|
||||
release_name: album,
|
||||
additional_info: {
|
||||
@@ -354,7 +393,8 @@ export class ListenbrainzApiClient extends AbstractApiClient {
|
||||
track_mbid: brainz.track,
|
||||
artist_mbids: brainz.artist,
|
||||
release_mbid: brainz.album,
|
||||
release_group_mbid: brainz.releaseGroup
|
||||
release_group_mbid: brainz.releaseGroup,
|
||||
...addInfo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,6 +121,11 @@ export default class ScrobbleClients {
|
||||
clientDefaults = cd;
|
||||
for (const [index, c] of mainConfigClientConfigs.entries()) {
|
||||
const {name = 'unnamed'} = c;
|
||||
if(c.type === undefined) {
|
||||
const invalidMsgType = `Client config ${index + 1} (${name}) in config.json does not have a "type" property! "type": "[clientType]" must be one of ${clientTypes.join(' | ')}`;
|
||||
this.logger.error(invalidMsgType);
|
||||
continue;
|
||||
}
|
||||
if(!isClientType(c.type.toLocaleLowerCase())) {
|
||||
const invalidTypeMsg = `Client config ${index + 1} (${name}) in config.json has an invalid client type of '${c.type}'. Must be one of ${clientTypes.join(' | ')}`;
|
||||
//this.emitter.emit('error', new Error(invalidTypeMsg));
|
||||
|
||||
@@ -265,8 +265,14 @@ export default class ScrobbleSources {
|
||||
sourceDefaults = this.buildSourceDefaults(sd);
|
||||
for (const [index, c] of mainConfigSourcesConfigs.entries()) {
|
||||
const {name = 'unnamed'} = c;
|
||||
if(c.type === undefined) {
|
||||
const invalidMsgType = `Source config ${index + 1} (${name}) in config.json does not have a "type" property! "type": "[sourceType]" must be one of ${sourceTypes.join(' | ')}`;
|
||||
this.emitter.emit('error', new Error(invalidMsgType));
|
||||
this.logger.error(invalidMsgType);
|
||||
continue;
|
||||
}
|
||||
if(!isSourceType(c.type.toLocaleLowerCase())) {
|
||||
const invalidMsgType = `Source config ${index + 1} (${name}) in config.json has an invalid source type of '${c.type}'. Must be one of ${sourceTypes.join(' | ')}`;
|
||||
const invalidMsgType = `Source config ${index + 1} (${name}) in config.json has an invalid source "type" of "${c.type}". Must be one of ${sourceTypes.join(' | ')}`;
|
||||
this.emitter.emit('error', new Error(invalidMsgType));
|
||||
this.logger.error(invalidMsgType);
|
||||
continue;
|
||||
|
||||
@@ -2,7 +2,7 @@ import dayjs, { Dayjs } from "dayjs";
|
||||
import EventEmitter from "events";
|
||||
import SpotifyWebApi from "spotify-web-api-node";
|
||||
import request from 'superagent';
|
||||
import { PlayObject, SCROBBLE_TS_SOC_END, SCROBBLE_TS_SOC_START, ScrobbleTsSOC } from "../../core/Atomic.js";
|
||||
import { PlayObject, SCROBBLE_TS_SOC_END, SCROBBLE_TS_SOC_START, ScrobbleTsSOC, SpotifyMeta } from "../../core/Atomic.js";
|
||||
import { combinePartsToString, truncateStringToLength } from "../../core/StringUtils.js";
|
||||
import { isNodeNetworkException } from "../common/errors/NodeErrors.js";
|
||||
import { hasUpstreamError, UpstreamError } from "../common/errors/UpstreamError.js";
|
||||
@@ -155,6 +155,7 @@ export default class SpotifySource extends MemoryPositionalSource {
|
||||
}
|
||||
|
||||
const {
|
||||
id: albumId,
|
||||
name: albumName,
|
||||
artists: albumArtists = [],
|
||||
images = []
|
||||
@@ -183,7 +184,15 @@ export default class SpotifySource extends MemoryPositionalSource {
|
||||
track: name,
|
||||
duration: duration_ms / 1000,
|
||||
playDate: played_at,
|
||||
playDateCompleted
|
||||
playDateCompleted,
|
||||
meta: {
|
||||
spotify: {
|
||||
track: id,
|
||||
artist: artists.map(x => x.id),
|
||||
albumArtist: actualAlbumArtists.map(x => x.id),
|
||||
album: albumId
|
||||
}
|
||||
}
|
||||
},
|
||||
meta: {
|
||||
deviceId: deviceId ?? `${NO_DEVICE}-${NO_USER}`,
|
||||
|
||||
@@ -74,6 +74,13 @@ export interface BrainzMeta {
|
||||
releaseGroup?: string
|
||||
}
|
||||
|
||||
export interface SpotifyMeta {
|
||||
artist?: string[]
|
||||
albumArtist?: string[]
|
||||
album?: string
|
||||
track?: string
|
||||
}
|
||||
|
||||
export interface TrackData {
|
||||
artists?: string[]
|
||||
albumArtists?: string[]
|
||||
@@ -86,6 +93,7 @@ export interface TrackData {
|
||||
|
||||
meta?: {
|
||||
brainz?: BrainzMeta
|
||||
spotify?: SpotifyMeta
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user