@@ -14,18 +14,18 @@ import {
1414import {
1515 FormatPlayObjectOptions ,
1616 INITIALIZING ,
17- MalojaScrobbleData ,
18- MalojaScrobbleRequestData ,
19- MalojaScrobbleV2RequestData ,
20- MalojaScrobbleV3RequestData ,
21- MalojaV2ScrobbleData ,
22- MalojaV3ScrobbleData ,
2317 PlayObject ,
2418 TrackStringOptions
2519} from "../common/infrastructure/Atomic.js" ;
2620import { MalojaClientConfig } from "../common/infrastructure/config/client/maloja.js" ;
2721import { Notifiers } from "../notifier/Notifiers.js" ;
2822import { Logger } from '@foxxmd/winston' ;
23+ import {
24+ MalojaScrobbleData ,
25+ MalojaScrobbleRequestData ,
26+ MalojaScrobbleV2RequestData ,
27+ MalojaScrobbleV3RequestData , MalojaScrobbleV3ResponseData , MalojaV2ScrobbleData , MalojaV3ScrobbleData
28+ } from "../apis/maloja/interfaces" ;
2929
3030const feat = [ "ft." , "ft" , "feat." , "feat" , "featuring" , "Ft." , "Ft" , "Feat." , "Feat" , "Featuring" ] ;
3131
@@ -65,10 +65,7 @@ export default class MalojaScrobbler extends AbstractScrobbleClient {
6565 track : {
6666 artists : mArtists ,
6767 title : mTitle ,
68- album : {
69- name : mAlbum ,
70- artists : albumArtists
71- } = { } ,
68+ album : mAlbum ,
7269 // length of the track
7370 length : mLength ,
7471 } = { } ,
@@ -79,7 +76,14 @@ export default class MalojaScrobbler extends AbstractScrobbleClient {
7976 time = mTime ;
8077 title = mTitle ;
8178 duration = mLength ;
82- album = mAlbum ;
79+ if ( mAlbum !== null ) {
80+ const {
81+ albumtitle,
82+ name : mAlbumName ,
83+ artists : albumArtists
84+ } = mAlbum || { } ;
85+ album = albumtitle ?? mAlbumName ;
86+ }
8387 } else {
8488 // scrobble data structure for v2 and below
8589 const {
@@ -384,6 +388,8 @@ export default class MalojaScrobbler extends AbstractScrobbleClient {
384388 length : duration ,
385389 } ;
386390
391+ let responseBody : MalojaScrobbleV3ResponseData ;
392+
387393 try {
388394 // 3.0.3 has a BC for something (maybe seconds => length ?) -- see #42 in repo
389395 if ( this . serverVersion === undefined || compareVersions ( this . serverVersion , '3.0.2' ) > 0 ) {
@@ -398,53 +404,77 @@ export default class MalojaScrobbler extends AbstractScrobbleClient {
398404 . type ( 'json' )
399405 . send ( scrobbleData ) ) ;
400406
401- let scrobbleResponse = { } ;
407+ let scrobbleResponse : any | undefined = undefined ,
408+ scrobbledPlay : PlayObject ;
402409
403410 if ( this . serverVersion === undefined || compareVersions ( this . serverVersion , '3.0.0' ) >= 0 ) {
411+ responseBody = response . body ;
404412 const {
405- body : {
406- // @ts -expect-error TS(2525): Initializer provides no value for this binding ele... Remove this comment to see the full error message
407413 track,
408- } = { }
409- } = response ;
410- scrobbleResponse = {
411- time : playDate . unix ( ) ,
412- track : {
413- ...track ,
414- length : duration
415- } ,
416- }
417- if ( album !== undefined ) {
418- const {
419- album : malojaAlbum = { } ,
420- } = track ;
421- // @ts -expect-error TS(2339): Property 'track' does not exist on type '{}'.
422- scrobbleResponse . track . album = {
423- ...malojaAlbum ,
424- name : album
414+ status,
415+ warnings = [ ] ,
416+ } = responseBody ;
417+ if ( status === 'success' ) {
418+ if ( track !== undefined ) {
419+ scrobbleResponse = {
420+ time : playDate . unix ( ) ,
421+ track : {
422+ ...track ,
423+ length : duration
424+ } ,
425+ }
426+ if ( album !== undefined ) {
427+ const {
428+ album : malojaAlbum = { } ,
429+ } = track ;
430+ scrobbleResponse . track . album = {
431+ ...malojaAlbum ,
432+ name : album
433+ }
434+ }
425435 }
436+ if ( warnings . length > 0 ) {
437+ for ( const w of warnings ) {
438+ this . logger . warn ( `Maloja Warning: ${ w . desc } => ${ JSON . stringify ( w . value ) } ` )
439+ }
440+ }
441+ } else {
442+ throw new Error ( buildErrorString ( response ) ) ;
426443 }
427444 } else {
428- const { body : {
429- // @ts -expect-error TS(2525): Initializer provides no value for this binding ele... Remove this comment to see the full error message
430- track : {
431- time : mTime = playDate . unix ( ) ,
432- duration : mDuration = duration ,
433- album : mAlbum = album ,
434- ...rest
435- }
436- } = { } } = response ;
445+ const {
446+ body : {
447+ track : {
448+ time : mTime = playDate . unix ( ) ,
449+ duration : mDuration = duration ,
450+ album : mAlbum = album ,
451+ ...rest
452+ } = { }
453+ } = { }
454+ } = response ;
437455 scrobbleResponse = { ...rest , album : mAlbum , time : mTime , duration : mDuration } ;
438456 }
439- this . addScrobbledTrack ( playObj , this . formatPlayObj ( scrobbleResponse ) ) ;
440- if ( newFromSource ) {
441- this . logger . info ( `Scrobbled (New) => (${ source } ) ${ buildTrackString ( playObj ) } ` ) ;
457+ let warning = '' ;
458+ if ( scrobbleResponse === undefined ) {
459+ warning = `WARNING: Maloja did not return track data in scrobble response! Maybe it didn't scrobble correctly??` ;
460+ scrobbledPlay = playObj ;
461+ } else {
462+ scrobbledPlay = this . formatPlayObj ( scrobbleResponse )
463+ }
464+ this . addScrobbledTrack ( playObj , scrobbledPlay ) ;
465+ const scrobbleInfo = `Scrobbled (${ newFromSource ? 'New' : 'Backlog' } ) => (${ source } ) ${ buildTrackString ( playObj ) } ` ;
466+ if ( warning !== '' ) {
467+ this . logger . warn ( `${ scrobbleInfo } | ${ warning } ` ) ;
468+ this . logger . debug ( `Response: ${ this . logger . debug ( JSON . stringify ( response . body ) ) } ` ) ;
442469 } else {
443- this . logger . info ( `Scrobbled (Backlog) => ( ${ source } ) ${ buildTrackString ( playObj ) } ` ) ;
470+ this . logger . info ( scrobbleInfo ) ;
444471 }
445472 } catch ( e ) {
446473 await this . notifier . notify ( { title : `Client - ${ capitalize ( this . type ) } - ${ this . name } - Scrobble Error` , message : `Failed to scrobble => ${ buildTrackString ( playObj ) } | Error: ${ e . message } ` , priority : 'error' } ) ;
447474 this . logger . error ( `Scrobble Error (${ sType } )` , { playInfo : buildTrackString ( playObj ) , payload : scrobbleData } ) ;
475+ if ( responseBody !== undefined ) {
476+ this . logger . error ( 'Raw Response:' , responseBody ) ;
477+ }
448478 throw e ;
449479 } finally {
450480 this . logger . debug ( 'Raw Payload:' , scrobbleData ) ;
@@ -453,3 +483,30 @@ export default class MalojaScrobbler extends AbstractScrobbleClient {
453483 return true ;
454484 }
455485}
486+
487+ const buildErrorString = ( body : MalojaScrobbleV3ResponseData ) => {
488+ let valString : string | undefined = undefined ;
489+ const {
490+ status,
491+ error : {
492+ type,
493+ value,
494+ desc
495+ } = { }
496+ } = body ;
497+ if ( value !== undefined && value !== null ) {
498+ if ( typeof value === 'string' ) {
499+ valString = value ;
500+ } else if ( Array . isArray ( value ) ) {
501+ valString = value . map ( x => {
502+ if ( typeof x === 'string' ) {
503+ return x ;
504+ }
505+ return JSON . stringify ( x ) ;
506+ } ) . join ( ', ' ) ;
507+ } else {
508+ valString = JSON . stringify ( value ) ;
509+ }
510+ }
511+ return `Maloja API returned ${ status } of type ${ type } "${ desc } "${ valString !== undefined ? `: ${ valString } ` : '' } ` ;
512+ }
0 commit comments