A decentralized music tracking and discovery platform built on AT Protocol 🎵
listenbrainz spotify atproto lastfm musicbrainz scrobbling

fix: ensure optional parameters are handled correctly in record functions

Changed files
+48 -48
apps
api
src
+48 -48
apps/api/src/nowplaying/nowplaying.service.ts
··· 26 26 27 27 export async function putArtistRecord( 28 28 track: Track, 29 - agent: Agent, 29 + agent: Agent 30 30 ): Promise<string | null> { 31 31 const rkey = TID.nextStr(); 32 32 const record: Artist.Record = { 33 33 $type: "app.rocksky.artist", 34 34 name: track.albumArtist, 35 35 createdAt: new Date().toISOString(), 36 - pictureUrl: track.artistPicture, 36 + pictureUrl: track.artistPicture || undefined, 37 37 tags: track.genres || [], 38 38 }; 39 39 ··· 62 62 63 63 export async function putAlbumRecord( 64 64 track: Track, 65 - agent: Agent, 65 + agent: Agent 66 66 ): Promise<string | null> { 67 67 const rkey = TID.nextStr(); 68 68 ··· 103 103 104 104 export async function putSongRecord( 105 105 track: Track, 106 - agent: Agent, 106 + agent: Agent 107 107 ): Promise<string | null> { 108 108 const rkey = TID.nextStr(); 109 109 ··· 158 158 159 159 async function putScrobbleRecord( 160 160 track: Track, 161 - agent: Agent, 161 + agent: Agent 162 162 ): Promise<string | null> { 163 163 const rkey = TID.nextStr(); 164 164 ··· 276 276 .where( 277 277 and( 278 278 eq(artistAlbums.albumId, scrobble.album.id), 279 - eq(artistAlbums.artistId, scrobble.artist.id), 280 - ), 279 + eq(artistAlbums.artistId, scrobble.artist.id) 280 + ) 281 281 ) 282 282 .limit(1) 283 283 .then((rows) => rows[0]), ··· 440 440 }, 441 441 }), 442 442 null, 443 - 2, 443 + 2 444 444 ); 445 445 446 446 ctx.nc.publish( 447 447 "rocksky.scrobble", 448 - Buffer.from(message.replaceAll("sha_256", "sha256")), 448 + Buffer.from(message.replaceAll("sha_256", "sha256")) 449 449 ); 450 450 451 451 const trackMessage = JSON.stringify( ··· 492 492 xata_createdat: artist_album.createdAt.toISOString(), 493 493 xata_updatedat: artist_album.updatedAt.toISOString(), 494 494 }, 495 - }), 495 + }) 496 496 ); 497 497 498 498 ctx.nc.publish( 499 499 "rocksky.track", 500 - Buffer.from(trackMessage.replaceAll("sha_256", "sha256")), 500 + Buffer.from(trackMessage.replaceAll("sha_256", "sha256")) 501 501 ); 502 502 } 503 503 ··· 505 505 ctx: Context, 506 506 track: Track, 507 507 agent: Agent, 508 - userDid: string, 508 + userDid: string 509 509 ): Promise<void> { 510 510 // check if scrobble already exists (user did + timestamp) 511 511 const scrobbleTime = dayjs.unix(track.timestamp || dayjs().unix()); ··· 524 524 eq(tracks.title, track.title), 525 525 eq(tracks.artist, track.artist), 526 526 gte(scrobbles.timestamp, scrobbleTime.subtract(5, "seconds").toDate()), 527 - lte(scrobbles.timestamp, scrobbleTime.add(5, "seconds").toDate()), 528 - ), 527 + lte(scrobbles.timestamp, scrobbleTime.add(5, "seconds").toDate()) 528 + ) 529 529 ) 530 530 .limit(1) 531 531 .then((rows) => rows[0]); ··· 533 533 if (existingScrobble) { 534 534 console.log( 535 535 `Scrobble already exists for ${chalk.cyan(track.title)} at ${chalk.cyan( 536 - scrobbleTime.format("YYYY-MM-DD HH:mm:ss"), 537 - )}`, 536 + scrobbleTime.format("YYYY-MM-DD HH:mm:ss") 537 + )}` 538 538 ); 539 539 return; 540 540 } ··· 547 547 tracks.sha256, 548 548 createHash("sha256") 549 549 .update( 550 - `${track.title} - ${track.artist} - ${track.album}`.toLowerCase(), 550 + `${track.title} - ${track.artist} - ${track.album}`.toLowerCase() 551 551 ) 552 - .digest("hex"), 553 - ), 552 + .digest("hex") 553 + ) 554 554 ) 555 555 .limit(1) 556 556 .then((rows) => rows[0]); ··· 564 564 albums.sha256, 565 565 createHash("sha256") 566 566 .update(`${track.album} - ${track.albumArtist}`.toLowerCase()) 567 - .digest("hex"), 568 - ), 567 + .digest("hex") 568 + ) 569 569 ) 570 570 .limit(1) 571 571 .then((rows) => rows[0]); ··· 586 586 artists.sha256, 587 587 createHash("sha256") 588 588 .update(track.albumArtist.toLowerCase()) 589 - .digest("hex"), 590 - ), 589 + .digest("hex") 590 + ) 591 591 ) 592 592 .limit(1) 593 593 .then((rows) => rows[0]); ··· 618 618 artist: track.artist.split(",").map((a) => ({ name: a.trim() })), 619 619 name: track.title, 620 620 album: track.album, 621 - }, 621 + } 622 622 ); 623 623 624 624 if (!mbTrack?.trackMBID) { ··· 647 647 albums.sha256, 648 648 createHash("sha256") 649 649 .update(`${track.album} - ${track.albumArtist}`.toLowerCase()) 650 - .digest("hex"), 651 - ), 650 + .digest("hex") 651 + ) 652 652 ) 653 653 .limit(1) 654 654 .then((rows) => rows[0]); ··· 664 664 tracks.sha256, 665 665 createHash("sha256") 666 666 .update( 667 - `${track.title} - ${track.artist} - ${track.album}`.toLowerCase(), 667 + `${track.title} - ${track.artist} - ${track.album}`.toLowerCase() 668 668 ) 669 - .digest("hex"), 670 - ), 669 + .digest("hex") 670 + ) 671 671 ) 672 672 .limit(1) 673 673 .then((rows) => rows[0]); ··· 681 681 682 682 if (existingTrack) { 683 683 console.log( 684 - `Song found: ${chalk.cyan(existingTrack.id)} - ${track.title}, after ${chalk.magenta(tries)} tries`, 684 + `Song found: ${chalk.cyan(existingTrack.id)} - ${track.title}, after ${chalk.magenta(tries)} tries` 685 685 ); 686 686 } 687 687 ··· 694 694 artists.sha256, 695 695 createHash("sha256") 696 696 .update(track.albumArtist.toLowerCase()) 697 - .digest("hex"), 697 + .digest("hex") 698 698 ), 699 699 eq( 700 700 artists.sha256, 701 - createHash("sha256").update(track.artist.toLowerCase()).digest("hex"), 702 - ), 703 - ), 701 + createHash("sha256").update(track.artist.toLowerCase()).digest("hex") 702 + ) 703 + ) 704 704 ) 705 705 .limit(1) 706 706 .then((rows) => rows[0]); ··· 715 715 .innerJoin(artists, eq(userArtists.artistId, artists.id)) 716 716 .innerJoin(users, eq(userArtists.userId, users.id)) 717 717 .where( 718 - and(eq(artists.id, existingArtist?.id || ""), eq(users.did, userDid)), 718 + and(eq(artists.id, existingArtist?.id || ""), eq(users.did, userDid)) 719 719 ) 720 720 .limit(1) 721 721 .then((rows) => rows[0]); ··· 750 750 tracks.sha256, 751 751 createHash("sha256") 752 752 .update( 753 - `${track.title} - ${track.artist} - ${track.album}`.toLowerCase(), 753 + `${track.title} - ${track.artist} - ${track.album}`.toLowerCase() 754 754 ) 755 - .digest("hex"), 756 - ), 755 + .digest("hex") 756 + ) 757 757 ) 758 758 .limit(1) 759 759 .then((rows) => rows[0]); 760 760 761 761 while (!existingTrack?.artistUri && !existingTrack?.albumUri && tries < 30) { 762 762 console.log( 763 - `Artist uri not ready, trying again: ${chalk.magenta(tries + 1)}`, 763 + `Artist uri not ready, trying again: ${chalk.magenta(tries + 1)}` 764 764 ); 765 765 existingTrack = await ctx.db 766 766 .select() ··· 770 770 tracks.sha256, 771 771 createHash("sha256") 772 772 .update( 773 - `${track.title} - ${track.artist} - ${track.album}`.toLowerCase(), 773 + `${track.title} - ${track.artist} - ${track.album}`.toLowerCase() 774 774 ) 775 - .digest("hex"), 776 - ), 775 + .digest("hex") 776 + ) 777 777 ) 778 778 .limit(1) 779 779 .then((rows) => rows[0]); ··· 788 788 artists.sha256, 789 789 createHash("sha256") 790 790 .update(track.albumArtist.toLowerCase()) 791 - .digest("hex"), 792 - ), 791 + .digest("hex") 792 + ) 793 793 ) 794 794 .limit(1) 795 795 .then((rows) => rows[0]); ··· 812 812 albums.sha256, 813 813 createHash("sha256") 814 814 .update(`${track.album} - ${track.albumArtist}`.toLowerCase()) 815 - .digest("hex"), 816 - ), 815 + .digest("hex") 816 + ) 817 817 ) 818 818 .limit(1) 819 819 .then((rows) => rows[0]); ··· 843 843 844 844 if (existingTrack?.artistUri) { 845 845 console.log( 846 - `Artist uri ready: ${chalk.cyan(existingTrack.id)} - ${track.title}, after ${chalk.magenta(tries)} tries`, 846 + `Artist uri ready: ${chalk.cyan(existingTrack.id)} - ${track.title}, after ${chalk.magenta(tries)} tries` 847 847 ); 848 848 } 849 849 ··· 854 854 await tealfm.publishPlayingNow( 855 855 agent, 856 856 mbTrack, 857 - Math.floor(track.duration / 1000), 857 + Math.floor(track.duration / 1000) 858 858 ); 859 859 } 860 860