diff --git a/src/play.ts b/src/play.ts index 641ddd1..bff3d05 100644 --- a/src/play.ts +++ b/src/play.ts @@ -45,31 +45,43 @@ const playMusic: tool<{ spotifyUri = `spotify:${type}:${id}`; } - await handleSpotifyRequest(async (spotifyApi) => { - const device = deviceId || ''; - - if (!spotifyUri) { - await spotifyApi.player.startResumePlayback(device); - return; - } - - if (type === 'track') { - await spotifyApi.player.startResumePlayback(device, undefined, [ - spotifyUri, - ]); - } else { - await spotifyApi.player.startResumePlayback(device, spotifyUri); - } - }); + try { + await handleSpotifyRequest(async (spotifyApi) => { + const device = deviceId || ''; + + if (!spotifyUri) { + await spotifyApi.player.startResumePlayback(device); + return; + } + + if (type === 'track') { + await spotifyApi.player.startResumePlayback(device, undefined, [ + spotifyUri, + ]); + } else { + await spotifyApi.player.startResumePlayback(device, spotifyUri); + } + }); - return { - content: [ - { - type: 'text', - text: `Started playing ${type || 'music'} ${id ? `(ID: ${id})` : ''}`, - }, - ], - }; + return { + content: [ + { + type: 'text', + text: `Started playing ${type || 'music'} ${id ? `(ID: ${id})` : ''}`, + }, + ], + }; + } catch (error) { + return { + content: [ + { + type: 'text', + text: `Error starting playback: ${error instanceof Error ? error.message : String(error)}`, + isError: true, + }, + ], + }; + } }, }; @@ -182,24 +194,48 @@ const createPlaylist: tool<{ handler: async (args, _extra: SpotifyHandlerExtra) => { const { name, description, public: isPublic = false } = args; - const result = await handleSpotifyRequest(async (spotifyApi) => { - const me = await spotifyApi.currentUser.profile(); - - return await spotifyApi.playlists.createPlaylist(me.id, { - name, - description, - public: isPublic, + try { + const result = await handleSpotifyRequest(async (spotifyApi) => { + const me = await spotifyApi.currentUser.profile(); + + return await spotifyApi.playlists.createPlaylist(me.id, { + name, + description, + public: isPublic, + }); }); - }); - return { - content: [ - { - type: 'text', - text: `Successfully created playlist "${name}"\nPlaylist ID: ${result.id}\nPlaylist URL: ${result.external_urls.spotify}`, - }, - ], - }; + if (!result?.id) { + return { + content: [ + { + type: 'text', + text: `Error: Playlist creation failed — Spotify API returned no data. The operation may not have succeeded.`, + isError: true, + }, + ], + }; + } + + return { + content: [ + { + type: 'text', + text: `Successfully created playlist "${name}"\nPlaylist ID: ${result.id}\nPlaylist URL: ${result.external_urls.spotify}`, + }, + ], + }; + } catch (error) { + return { + content: [ + { + type: 'text', + text: `Error creating playlist: ${error instanceof Error ? error.message : String(error)}`, + isError: true, + }, + ], + }; + } }, }; @@ -236,14 +272,29 @@ const addTracksToPlaylist: tool<{ try { const trackUris = trackIds.map((id) => `spotify:track:${id}`); + let addSucceeded = true; await handleSpotifyRequest(async (spotifyApi) => { await spotifyApi.playlists.addItemsToPlaylist( playlistId, trackUris, position, ); + }).catch(() => { + addSucceeded = false; }); + if (!addSucceeded) { + return { + content: [ + { + type: 'text', + text: `Warning: Tracks may not have been added — Spotify API returned no confirmation. Verify the playlist manually.`, + isError: true, + }, + ], + }; + } + return { content: [ { diff --git a/src/utils.ts b/src/utils.ts index 65c405a..faa6905 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -355,16 +355,21 @@ export async function handleSpotifyRequest( const spotifyApi = await createSpotifyApi(); return await action(spotifyApi); } catch (error) { - // Skip JSON parsing errors as these are actually successful operations - const errorMessage = error instanceof Error ? error.message : String(error); + const errorMessage = + error instanceof Error ? error.message : String(error); + // JSON parse errors typically occur on successful 204 No Content responses + // from void operations (play, pause, skip, etc.). The operation succeeded, + // but the SDK fails to parse the empty response body. if ( errorMessage.includes('Unexpected token') || errorMessage.includes('Unexpected non-whitespace character') || errorMessage.includes('Exponent part is missing a number in JSON') ) { + console.warn( + `[Spotify] JSON parse error on response (void operation likely succeeded): ${errorMessage}`, + ); return undefined as T; } - // Rethrow other errors throw error; } }