diff --git a/clients/LastfmScrobbler.js b/clients/LastfmScrobbler.js index b3b6baac..64ade333 100644 --- a/clients/LastfmScrobbler.js +++ b/clients/LastfmScrobbler.js @@ -3,7 +3,7 @@ import dayjs from 'dayjs'; import { buildTrackString, - playObjDataMatch, + playObjDataMatch, removeUndefinedKeys, setIntersection, sleep, sortByPlayDate, truncateStringToLength, @@ -259,13 +259,19 @@ export default class LastfmScrobbler extends AbstractScrobbleClient { try { const response = await this.api.callApi(client => client.trackScrobble( - { + // i don't know if its lastfm-node-client building the request params incorrectly + // or the last.fm api not handling the params correctly... + // + // ...but in either case if any of the below properties is undefined (possibly also null??) + // then last.fm responds with an IGNORED scrobble and error code 1 (totally unhelpful) + // so remove all undefined keys from the object before passing to the api client + removeUndefinedKeys({ artist: artists.join(', '), duration, track, album, timestamp: playDate.unix(), - })); + }))); const { scrobbles: { '@attr': { diff --git a/utils.js b/utils.js index 3c6a4683..e6179bb3 100644 --- a/utils.js +++ b/utils.js @@ -327,3 +327,25 @@ export const spreadDelay = (retries, multiplier) => { } return s; } + +export const removeUndefinedKeys = (obj) => { + let newObj = {}; + Object.keys(obj).forEach((key) => { + if(Array.isArray(obj[key])) { + newObj[key] = obj[key]; + } else if (obj[key] === Object(obj[key])) { + newObj[key] = removeUndefinedKeys(obj[key]); + } else if (obj[key] !== undefined) { + newObj[key] = obj[key]; + } + }); + if(Object.keys(newObj).length === 0) { + return undefined; + } + Object.keys(newObj).forEach(key => { + if(newObj[key] === undefined || (null !== newObj[key] && typeof newObj[key] === 'object' && Object.keys(newObj[key]).length === 0)) { + delete newObj[key] + } + }); + return newObj; +}