Spotify Web API:接收类型错误:回调不是函数

问题描述 投票:0回答:1

我正在创建一个使用 Spotify Web API 和 OpenAI API 的 node.js Web 应用程序。服务器端代码基本上接受用户的提示,使用 OpenAI 语言模型对其进行处理,然后从 Spotify 获取曲目并构建播放列表。该应用程序成功获取提示、处理并获取曲目(我可以在我的控制台中看到正在获取的曲目),但之后我收到 TypeError: callback is not a function。似乎错误是由 Spotify Web API 中的 http-manager.js 文件引发的。

我认为我什至没有在我的代码中引用回调,这可能是 Spotify 的 API 问题/我尝试与之交互的方式吗?

这是测试应用程序时我的控制台中的确切错误:

TypeError: callback is not a function
    at /rbd/pnpm-volume/bfe9bf90-d68c-4e41-8b2a-95cefb846cfe/node_modules/spotify-web-api-node/src/http-manager.js:71:16
    at Request.callback (/rbd/pnpm-volume/bfe9bf90-d68c-4e41-8b2a-95cefb846cfe/node_modules/spotify-web-api-node/node_modules/superagent/lib/node/index.js:905:3)
    at /rbd/pnpm-volume/bfe9bf90-d68c-4e41-8b2a-95cefb846cfe/node_modules/spotify-web-api-node/node_modules/superagent/lib/node/index.js:1127:20
    at IncomingMessage.<anonymous> (/rbd/pnpm-volume/bfe9bf90-d68c-4e41-8b2a-95cefb846cfe/node_modules/spotify-web-api-node/node_modules/superagent/lib/node/parsers/json.js:22:7)
    at Stream.emit (events.js:400:28)
    at Unzip.<anonymous> (/rbd/pnpm-volume/bfe9bf90-d68c-4e41-8b2a-95cefb846cfe/node_modules/spotify-web-api-node/node_modules/superagent/lib/node/unzip.js:53:12)
    at Unzip.emit (events.js:400:28)
    at endReadableNT (internal/streams/readable.js:1334:12)
    at processTicksAndRejections (internal/process/task_queues.js:82:21)

服务器端代码:

//variables and imports

//openai api config code....

//fastify configuration code....

// Spotify configuration
const SPOTIFY_CLIENT_ID = process.env.SPOTIFY_CLIENT_ID;
const SPOTIFY_CLIENT_SECRET = process.env.SPOTIFY_CLIENT_SECRET;
const SPOTIFY_REDIRECT_URI = process.env.SPOTIFY_REDIRECT_URI;
const SPOTIFY_AUTH_SCOPES =
  'user-read-private user-read-email playlist-modify-public playlist-modify-private';

const SpotifyWebApi = require('spotify-web-api-node');

const spotifyApi = new SpotifyWebApi({
  clientId: SPOTIFY_CLIENT_ID,
  clientSecret: SPOTIFY_CLIENT_SECRET,
  redirectUri: SPOTIFY_REDIRECT_URI,
});

//search and extract songs from Spotify code...


// Utility function to generate a random string
function generateRandomString(length) {
  const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  let text = "";

  for (let i = 0; i < length; i++) {
    text += possible.charAt(Math.floor(Math.random() * possible.length));
  }

  return text;
}

//search keyword refining code...

//create playlist and add tracks to it
async function createPlaylistAndAddTracks(userId, playlistName, tracks, accessToken) {
  spotifyApi.setAccessToken(accessToken);

  try {
    const playlist = await new Promise((resolve, reject) => {
      spotifyApi.createPlaylist(userId, playlistName, { public: true }, (err, data) => {
        if (err) reject(err);
        resolve(data);
      });
    });

    const playlistId = playlist.body.id;

    const trackUris = tracks.map((track) => track.uri);

    await new Promise((resolve, reject) => {
      spotifyApi.addTracksToPlaylist(playlistId, trackUris, (err, data) => {
        if (err) reject(err);
        resolve(data);
      });
    });

    return playlistId;
  } catch (error) {
    console.error("Error creating playlist and adding tracks:", error);
    throw error;
  }
}

// Routes
// "/" get route

// "/" post route

fastify.get('/login', (req, reply) => {
  const state = generateRandomString(16);
  reply.setCookie("spotify_auth_state", state, {
    path: "/",
    maxAge: 3600, // 1 hour
    httpOnly: true,
  });

  const authUrl =
    'https://accounts.spotify.com/authorize' +
    '?response_type=code' +
    '&client_id=' + encodeURIComponent(SPOTIFY_CLIENT_ID) +
    '&scope=' + encodeURIComponent(SPOTIFY_AUTH_SCOPES) +
    '&redirect_uri=' + encodeURIComponent(SPOTIFY_REDIRECT_URI) +
    '&state=' + state;
  reply.redirect(authUrl);
});

// "user" get route code...

//"jockey" route for processing prompts and interacting with Spotify API
fastify.get('/jockey', function (request, reply) {
  return reply.view('/src/pages/jockey.hbs');
});

//taking user input and generating keywords for use in SpotifyAPI
fastify.post("/jockey", async function (request, reply) {
  const prompt = request.body.prompt;
  const promptWithInstruction = `We have a user who wants to listen to music related to the theme: "${prompt}". Can you provide a comma-separated list of keywords or phrases that are relevant to this theme and could be used to search for music on Spotify?`;


  try {
    const result = await openai.createCompletion({
      model: "text-davinci-003",
      prompt: promptWithInstruction,
      max_tokens: 2048,
      temperature: 0.8,
    });

    const generatedText = result.data.choices[0].text.trim();
    const keywords = extractKeywords(generatedText);
    console.log("Generated Keywords:", keywords); //MILKSTEAK
    
    const tracks = await searchAndExtractTracks(keywords, request.cookies.access_token);
    console.log("Extracted tracks:", tracks);
    
    // Get the user's ID
    const userResponse = await spotifyApi.getMe();
    const userId = userResponse.body.id;


    // Create a new playlist and add the fetched tracks
    const playlistId = await createPlaylistAndAddTracks(userId, request.cookies.access_token, tracks);


    // Redirect to the /jockey page after processing the input
    return reply.redirect("/jockey");

  } catch (error) {
    console.error(error);
    return reply.code(500).send("Error generating response from OpenAI API");
  }
});



fastify.get('/callback', async (req, reply) => {
  const code = req.query.code;
  const state = req.query.state;
  const storedState = req.cookies.spotify_auth_state;

  if (state === null || state !== storedState) {
    reply.code(400).send('State mismatch');
  } else {
    reply.clearCookie("spotify_auth_state");

    const tokenUrl = 'https://accounts.spotify.com/api/token';

    try {
      const response = await request.post(tokenUrl, {
        form: {
          code: code,
          redirect_uri: SPOTIFY_REDIRECT_URI,
          grant_type: 'authorization_code',
        },
        headers: {
          Authorization:
            'Basic ' +
            Buffer.from(SPOTIFY_CLIENT_ID + ':' + SPOTIFY_CLIENT_SECRET).toString('base64'),
        },
        json: true,
      });

      // Save the access_token and refresh_token in cookies
      const accessToken = response.access_token;
      const refreshToken = response.refresh_token;

      reply.setCookie("access_token", accessToken, {
        path: "/",
        maxAge: 3600, // 1 hour
        httpOnly: true,
      });

      reply.setCookie("refresh_token", refreshToken, {
        path: "/",
        maxAge: 30 * 24 * 60 * 60, // 30 days
        httpOnly: true,
      });

      reply.redirect('/jockey');

    } catch (error) {
      reply.code(400).send('Error: ' + error.message);
    }
  }
});

// let user logout and clear cookies/session "/logout" route


//fastify.listen code...
javascript node.js callback spotify glitch-framework
1个回答
0
投票

尝试在没有

createPlaylist
参数的情况下调用
userId
。下面的解释。
在版本 5.0.0 的 changelog 中说

创建播放列表 (createPlaylist) 方法不再接受 userId 字符串作为其第一个参数。

该函数的新定义是

createPlaylist(name, options, callback)
并且您使用 userId 参数
createPlaylist(userId, playlistName, { public: true }, (err, data))
调用它,这意味着该函数将您的
userId
参数解释为
name
playlistName
options
,
{public: true}
作为回调,您的
(err,data)=>{}
回调当然会被忽略,因此当需要该回调时,它将尝试执行您的
{public: true}()
参数,认为它的回调当然会引发错误说明那
callback is not a function
因为
{public: true}
确实不是一个函数。

© www.soinside.com 2019 - 2024. All rights reserved.