@@ -14,18 +14,18 @@ import {
14
14
import {
15
15
FormatPlayObjectOptions ,
16
16
INITIALIZING ,
17
- MalojaScrobbleData ,
18
- MalojaScrobbleRequestData ,
19
- MalojaScrobbleV2RequestData ,
20
- MalojaScrobbleV3RequestData ,
21
- MalojaV2ScrobbleData ,
22
- MalojaV3ScrobbleData ,
23
17
PlayObject ,
24
18
TrackStringOptions
25
19
} from "../common/infrastructure/Atomic.js" ;
26
20
import { MalojaClientConfig } from "../common/infrastructure/config/client/maloja.js" ;
27
21
import { Notifiers } from "../notifier/Notifiers.js" ;
28
22
import { Logger } from '@foxxmd/winston' ;
23
+ import {
24
+ MalojaScrobbleData ,
25
+ MalojaScrobbleRequestData ,
26
+ MalojaScrobbleV2RequestData ,
27
+ MalojaScrobbleV3RequestData , MalojaScrobbleV3ResponseData , MalojaV2ScrobbleData , MalojaV3ScrobbleData
28
+ } from "../apis/maloja/interfaces" ;
29
29
30
30
const feat = [ "ft." , "ft" , "feat." , "feat" , "featuring" , "Ft." , "Ft" , "Feat." , "Feat" , "Featuring" ] ;
31
31
@@ -65,10 +65,7 @@ export default class MalojaScrobbler extends AbstractScrobbleClient {
65
65
track : {
66
66
artists : mArtists ,
67
67
title : mTitle ,
68
- album : {
69
- name : mAlbum ,
70
- artists : albumArtists
71
- } = { } ,
68
+ album : mAlbum ,
72
69
// length of the track
73
70
length : mLength ,
74
71
} = { } ,
@@ -79,7 +76,14 @@ export default class MalojaScrobbler extends AbstractScrobbleClient {
79
76
time = mTime ;
80
77
title = mTitle ;
81
78
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
+ }
83
87
} else {
84
88
// scrobble data structure for v2 and below
85
89
const {
@@ -384,6 +388,8 @@ export default class MalojaScrobbler extends AbstractScrobbleClient {
384
388
length : duration ,
385
389
} ;
386
390
391
+ let responseBody : MalojaScrobbleV3ResponseData ;
392
+
387
393
try {
388
394
// 3.0.3 has a BC for something (maybe seconds => length ?) -- see #42 in repo
389
395
if ( this . serverVersion === undefined || compareVersions ( this . serverVersion , '3.0.2' ) > 0 ) {
@@ -398,53 +404,77 @@ export default class MalojaScrobbler extends AbstractScrobbleClient {
398
404
. type ( 'json' )
399
405
. send ( scrobbleData ) ) ;
400
406
401
- let scrobbleResponse = { } ;
407
+ let scrobbleResponse : any | undefined = undefined ,
408
+ scrobbledPlay : PlayObject ;
402
409
403
410
if ( this . serverVersion === undefined || compareVersions ( this . serverVersion , '3.0.0' ) >= 0 ) {
411
+ responseBody = response . body ;
404
412
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
407
413
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
+ }
425
435
}
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 ) ) ;
426
443
}
427
444
} 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 ;
437
455
scrobbleResponse = { ...rest , album : mAlbum , time : mTime , duration : mDuration } ;
438
456
}
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 ) ) } ` ) ;
442
469
} else {
443
- this . logger . info ( `Scrobbled (Backlog) => ( ${ source } ) ${ buildTrackString ( playObj ) } ` ) ;
470
+ this . logger . info ( scrobbleInfo ) ;
444
471
}
445
472
} catch ( e ) {
446
473
await this . notifier . notify ( { title : `Client - ${ capitalize ( this . type ) } - ${ this . name } - Scrobble Error` , message : `Failed to scrobble => ${ buildTrackString ( playObj ) } | Error: ${ e . message } ` , priority : 'error' } ) ;
447
474
this . logger . error ( `Scrobble Error (${ sType } )` , { playInfo : buildTrackString ( playObj ) , payload : scrobbleData } ) ;
475
+ if ( responseBody !== undefined ) {
476
+ this . logger . error ( 'Raw Response:' , responseBody ) ;
477
+ }
448
478
throw e ;
449
479
} finally {
450
480
this . logger . debug ( 'Raw Payload:' , scrobbleData ) ;
@@ -453,3 +483,30 @@ export default class MalojaScrobbler extends AbstractScrobbleClient {
453
483
return true ;
454
484
}
455
485
}
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