mirror of
https://github.com/FoxxMD/multi-scrobbler.git
synced 2026-09-03 05:10:00 +03:00
refactor(listenbrainz): Consolidate lz endpoint submit parsing into lz response parsing
Consolidtes logic for parsing lz listen data structure
This commit is contained in:
+72
-97
@@ -270,82 +270,27 @@ export class ListenbrainzApiClient extends AbstractApiClient {
|
||||
|
||||
export const listenPayloadToPlay = (payload: ListenPayload, nowPlaying: boolean = false): PlayObject => {
|
||||
|
||||
// const listened = payload.listened_at ?? dayjs().unix();
|
||||
// const listenedAt = typeof listened === 'number' ? dayjs.unix(listened) : dayjs(listened);
|
||||
|
||||
// const {
|
||||
// track_metadata: {
|
||||
// additional_info = {}
|
||||
// } = {},
|
||||
// } = payload;
|
||||
|
||||
// const play = ListenbrainzApiClient.listenResponseToPlay({
|
||||
// ...payload,
|
||||
// track_metadata: {
|
||||
// ...payload.track_metadata,
|
||||
// additional_info
|
||||
// },
|
||||
// listened_at: listenedAt.unix()
|
||||
// });
|
||||
|
||||
// play.meta.nowPlaying = nowPlaying;
|
||||
const listened = payload.listened_at ?? dayjs().unix();
|
||||
const listenedAt = typeof listened === 'number' ? dayjs.unix(listened) : dayjs(listened);
|
||||
|
||||
const {
|
||||
listened_at = dayjs().unix(),
|
||||
track_metadata: {
|
||||
artist_name,
|
||||
track_name,
|
||||
release_name,
|
||||
additional_info: {
|
||||
duration,
|
||||
duration_ms,
|
||||
track_mbid,
|
||||
artist_mbids,
|
||||
artist_names = [],
|
||||
release_mbid,
|
||||
release_group_mbid,
|
||||
release_artist_name,
|
||||
release_artist_names = []
|
||||
} = {}
|
||||
additional_info = {}
|
||||
} = {},
|
||||
} = payload;
|
||||
|
||||
let albumArtists: string[];
|
||||
if(release_artist_name !== undefined) {
|
||||
albumArtists = [release_artist_name];
|
||||
}
|
||||
if(release_artist_names.length > 0) {
|
||||
albumArtists = unique([...(albumArtists ?? []), ...release_artist_names])
|
||||
}
|
||||
const play = listenResponseToPlay({
|
||||
...payload,
|
||||
track_metadata: {
|
||||
...payload.track_metadata,
|
||||
additional_info,
|
||||
},
|
||||
listened_at: listenedAt.unix()
|
||||
});
|
||||
|
||||
let dur: number = duration;
|
||||
if(dur === undefined && duration_ms !== undefined) {
|
||||
dur = duration_ms/1000;
|
||||
}
|
||||
play.meta.nowPlaying = nowPlaying;
|
||||
|
||||
const oldPlay = {
|
||||
data: {
|
||||
playDate: typeof listened_at === 'number' ? dayjs.unix(listened_at) : dayjs(listened_at),
|
||||
track: track_name,
|
||||
artists: unique([artist_name, ...artist_names]),
|
||||
albumArtists,
|
||||
album: release_name,
|
||||
duration: dur,
|
||||
meta: {
|
||||
brainz: {
|
||||
artist: artist_mbids !== undefined ? artist_mbids : undefined,
|
||||
album: release_mbid,
|
||||
albumArtist: release_group_mbid,
|
||||
track: track_mbid
|
||||
}
|
||||
}
|
||||
},
|
||||
meta: {
|
||||
nowPlaying,
|
||||
}
|
||||
}
|
||||
|
||||
return oldPlay;
|
||||
return play;
|
||||
}
|
||||
|
||||
export const listenResponseToPlay = (listen: ListenResponse): PlayObject => {
|
||||
@@ -367,7 +312,7 @@ export const listenResponseToPlay = (listen: ListenResponse): PlayObject => {
|
||||
} = {}
|
||||
} = listen;
|
||||
|
||||
const naivePlay = listenResponseToNaivePlay(listen);
|
||||
const naivePlay = listenToNaivePlay(listen);
|
||||
|
||||
if(artistMappings.length === 0) {
|
||||
// if there are no artist mappings its likely MB doesn't have info on this track so just use our internally derived attempt
|
||||
@@ -616,7 +561,7 @@ export const listenResponseToPlay = (listen: ListenResponse): PlayObject => {
|
||||
/**
|
||||
* Try to parse true artists and track name without using MB information
|
||||
* */
|
||||
export const listenResponseToNaivePlay = (listen: ListenResponse): PlayObject => {
|
||||
export const listenToNaivePlay = (listen: ListenResponse): PlayObject => {
|
||||
const {
|
||||
listened_at,
|
||||
recording_msid,
|
||||
@@ -627,12 +572,18 @@ export const listenResponseToNaivePlay = (listen: ListenResponse): PlayObject =>
|
||||
additional_info: {
|
||||
recording_msid: aRecordingMsid,
|
||||
recording_mbid: aRecordingMbid,
|
||||
release_artist_name,
|
||||
release_artist_names = [],
|
||||
release_group_mbid,
|
||||
release_mbid,
|
||||
artist_mbids = [],
|
||||
duration: aDuration,
|
||||
duration_ms: aDurationMs,
|
||||
music_service_name,
|
||||
music_service,
|
||||
submission_client,
|
||||
submission_client_version
|
||||
submission_client_version,
|
||||
artist_names = [],
|
||||
} = {},
|
||||
mbid_mapping: {
|
||||
recording_mbid: mRecordingMbid
|
||||
@@ -649,24 +600,39 @@ export const listenResponseToNaivePlay = (listen: ListenResponse): PlayObject =>
|
||||
}
|
||||
|
||||
let normalTrackName = track_name;
|
||||
let artists: string[] = [artist_name];
|
||||
let artists: string[] = [];
|
||||
|
||||
// since we aren't using MB mappings we should be conservative and assume artist string with & are proper names (not joiner)
|
||||
const parsedArtists = parseCredits(artist_name, [',', '/', '\\']);
|
||||
if (parsedArtists !== undefined) {
|
||||
if (parsedArtists.primary !== undefined) {
|
||||
artists.push(parsedArtists.primary);
|
||||
if(artist_names.length > 0) {
|
||||
artists = artist_names;
|
||||
} else {
|
||||
artists = [artist_name];
|
||||
|
||||
// since we aren't using MB mappings we should be conservative and assume artist string with & are proper names (not joiner)
|
||||
const parsedArtists = parseCredits(artist_name, [',', '/', '\\']);
|
||||
if (parsedArtists !== undefined) {
|
||||
if (parsedArtists.primary !== undefined) {
|
||||
artists.push(parsedArtists.primary);
|
||||
}
|
||||
artists = artists.concat(parsedArtists.secondary);
|
||||
}
|
||||
artists = artists.concat(parsedArtists.secondary);
|
||||
// use all delimiters when trying to find artists in track name
|
||||
const parsedTrackArtists = parseCredits(track_name);
|
||||
if (parsedTrackArtists !== undefined) {
|
||||
// if we found "ft. something" in track string then we now have a "real" track name and more artists
|
||||
normalTrackName = parsedTrackArtists.primary;
|
||||
artists = artists.concat(parsedTrackArtists.secondary)
|
||||
}
|
||||
artists = uniqueNormalizedStrArr(artists);
|
||||
}
|
||||
// use all delimiters when trying to find artists in track name
|
||||
const parsedTrackArtists = parseCredits(track_name);
|
||||
if (parsedTrackArtists !== undefined) {
|
||||
// if we found "ft. something" in track string then we now have a "real" track name and more artists
|
||||
normalTrackName = parsedTrackArtists.primary;
|
||||
artists = artists.concat(parsedTrackArtists.secondary)
|
||||
|
||||
let albumArtists: string[];
|
||||
if(release_artist_name !== undefined) {
|
||||
albumArtists = [release_artist_name];
|
||||
}
|
||||
artists = uniqueNormalizedStrArr(artists);
|
||||
if(release_artist_names.length > 0) {
|
||||
albumArtists = unique([...(albumArtists ?? []), ...release_artist_names])
|
||||
}
|
||||
|
||||
|
||||
const play: PlayObject = {
|
||||
data: {
|
||||
@@ -674,24 +640,35 @@ export const listenResponseToNaivePlay = (listen: ListenResponse): PlayObject =>
|
||||
track: normalTrackName,
|
||||
artists: artists,
|
||||
album: release_name,
|
||||
duration: dur
|
||||
albumArtists,
|
||||
duration: dur,
|
||||
meta: {
|
||||
}
|
||||
},
|
||||
meta: {
|
||||
source: 'listenbrainz',
|
||||
source: submission_client ?? 'listenbrainz',
|
||||
playId,
|
||||
deviceId: combinePartsToString([music_service_name ?? music_service, submission_client, submission_client_version])
|
||||
}
|
||||
}
|
||||
|
||||
const brainzMeta: BrainzMeta = {};
|
||||
if(Object.keys(additional_info).length > 0) {
|
||||
brainzMeta.additionalInfo = additional_info;
|
||||
if(trackId !== undefined) {
|
||||
play.meta.trackid = trackId;
|
||||
}
|
||||
|
||||
// we shouldn't include more metdata here because we don't know if the MB mapped data is actually correct
|
||||
if(trackId !== undefined) {
|
||||
brainzMeta.track = trackId;
|
||||
play.meta.trackid = trackId;
|
||||
const brainzMeta: BrainzMeta = removeUndefinedKeys({
|
||||
album: release_mbid,
|
||||
releaseGroup: release_group_mbid,
|
||||
track: trackId
|
||||
}) ?? {};
|
||||
|
||||
if(Object.keys(additional_info).length > 0) {
|
||||
brainzMeta.additionalInfo = additional_info;
|
||||
|
||||
}
|
||||
if(artist_mbids.filter(x => x.trim() !== "").length > 0) {
|
||||
brainzMeta.artist = artist_mbids.filter(x => x.trim() !== "");
|
||||
brainzMeta.additionalInfo.artist_mbids = brainzMeta.artist;
|
||||
}
|
||||
|
||||
if(Object.keys(brainzMeta).length > 0) {
|
||||
@@ -809,6 +786,4 @@ export const musicServiceToCononical = (str: string): string | undefined => {
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const FEAT_REGEX = new RegExp(/(.+) feat\. (.+)/);
|
||||
}
|
||||
+3
-1
@@ -97,6 +97,8 @@ export interface AdditionalTrackInfo {
|
||||
spotify_artist_ids?: string[];
|
||||
artist_names?: string[];
|
||||
albumartist?: string;
|
||||
|
||||
tracknumber?: number
|
||||
}
|
||||
export interface Track {
|
||||
artist_name: string;
|
||||
@@ -139,7 +141,7 @@ export interface TrackPayload extends MinimumTrack {
|
||||
mbid_mapping?: MbidMapping
|
||||
}
|
||||
export interface ListenPayload {
|
||||
listened_at: Date | number;
|
||||
listened_at?: Date | number;
|
||||
track_metadata: TrackPayload;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import { PlayObject } from "../../../core/Atomic.js";
|
||||
import { UpstreamError } from "../../common/errors/UpstreamError.js";
|
||||
|
||||
import { ListenbrainzApiClient, playToListenPayload, listenResponseToPlay, listenPayloadToPlay } from "../../common/vendor/ListenbrainzApiClient.js";
|
||||
import { ListenResponse } from '../../common/vendor/listenbrainz/interfaces.js';
|
||||
import { ListenPayload, ListenResponse, SubmitPayload } from '../../common/vendor/listenbrainz/interfaces.js';
|
||||
import { ExpectedResults } from "../utils/interfaces.js";
|
||||
import { withRequestInterception } from "../utils/networking.js";
|
||||
import artistWithProperJoiner from './correctlyMapped/artistProperHasJoinerInName.json' with { type: "json" };
|
||||
@@ -194,4 +194,38 @@ describe('Listenbrainz Endpoint Behavior', function() {
|
||||
|
||||
});
|
||||
|
||||
it('Should use artist_names if provided, rather than parse artist from string', function () {
|
||||
|
||||
const playFromPayload = listenPayloadToPlay(submit);
|
||||
|
||||
expect(playFromPayload.data.artists).to.be.eql(submit.track_metadata.additional_info.artist_names);
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
const submit: ListenPayload = {
|
||||
track_metadata: {
|
||||
artist_name: "Télépopmusik feat. Mau",
|
||||
track_name: "15 Minutes",
|
||||
release_name: "Angel Milk",
|
||||
additional_info: {
|
||||
submission_client: "navidrome",
|
||||
submission_client_version: "0.58.5 (131c0c56)",
|
||||
tracknumber: 15,
|
||||
artist_names: [
|
||||
"Télépopmusik",
|
||||
"Mau",
|
||||
],
|
||||
artist_mbids: [
|
||||
"265f242e-cf4e-4fbe-a3fe-43112387172f",
|
||||
"",
|
||||
],
|
||||
recording_mbid: "69864bde-4958-484e-bbeb-f9d8f06eb932",
|
||||
release_mbid: "90e011e2-1a3b-483c-9684-355601689c0f",
|
||||
release_group_mbid: "d1456679-3901-30a6-929c-39d6d84f49a0",
|
||||
duration_ms: 939020,
|
||||
},
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user