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

Fix Spotify token/account joins and add guards

Join spotifyAccounts to spotifyTokens by userId (was using the wrong app
id), and add guard clauses that warn and return undefined when no tokens
or when token/app data are missing to avoid runtime errors.

Changed files
+12 -2
apps
api
src
xrpc
app
rocksky
+12 -2
apps/api/src/xrpc/app/rocksky/song/matchSong.ts
··· 141 .from(tables.spotifyTokens) 142 .leftJoin( 143 tables.spotifyApps, 144 - eq(tables.spotifyTokens.spotifyAppId, tables.spotifyApps.spotifyAppId), 145 ) 146 .leftJoin( 147 tables.spotifyAccounts, 148 - eq(tables.spotifyAccounts.spotifyAppId, tables.spotifyApps.id), 149 ) 150 .where(eq(tables.spotifyAccounts.isBetaUser, true)) 151 .limit(500) 152 .execute(); 153 154 const { spotify_tokens, spotify_apps } = 155 spotifyTokens[Math.floor(Math.random() * spotifyTokens.length)]; 156 157 const refreshToken = decrypt( 158 spotify_tokens.refreshToken,
··· 141 .from(tables.spotifyTokens) 142 .leftJoin( 143 tables.spotifyApps, 144 + eq(tables.spotifyApps.spotifyAppId, tables.spotifyTokens.spotifyAppId), 145 ) 146 .leftJoin( 147 tables.spotifyAccounts, 148 + eq(tables.spotifyAccounts.userId, tables.spotifyTokens.userId), 149 ) 150 .where(eq(tables.spotifyAccounts.isBetaUser, true)) 151 .limit(500) 152 .execute(); 153 154 + if (!spotifyTokens || spotifyTokens.length === 0) { 155 + console.warn("No Spotify tokens available for beta users"); 156 + return undefined; 157 + } 158 + 159 const { spotify_tokens, spotify_apps } = 160 spotifyTokens[Math.floor(Math.random() * spotifyTokens.length)]; 161 + 162 + if (!spotify_tokens || !spotify_apps) { 163 + console.warn("Invalid Spotify token or app data"); 164 + return undefined; 165 + } 166 167 const refreshToken = decrypt( 168 spotify_tokens.refreshToken,