Node.js 和 Spotify API 集成无法创建播放列表

问题描述 投票:0回答:1
const express = require('express');
const axios = require('axios');
const querystring = require('querystring');
const router = express.Router();
require('dotenv').config();

const client_id = process.env.SPOTIFY_CLIENT_ID;
const client_secret = process.env.SPOTIFY_CLIENT_SECRET;
const userId = process.env.SPOTIFY_USER_ID;

let spotifyAccessToken = ''; // Dynamically set by app.js
let spotifyRefreshToken = ''; // Dynamically set by app.js

async function refreshAccessToken() {
    const authOptions = {
        url: 'https://accounts.spotify.com/api/token',
        form: {
            grant_type: 'refresh_token',
            refresh_token: spotifyRefreshToken
        },
        headers: {
            'Authorization': 'Basic ' + Buffer.from(client_id + ':' + client_secret).toString('base64')
        }
    };

    try {
        const response = await axios.post(authOptions.url, querystring.stringify(authOptions.form), {
            headers: authOptions.headers,
        });

        spotifyAccessToken = response.data.access_token;
        console.log('New Access Token:', spotifyAccessToken);
    } catch (error) {
        console.error('Error refreshing access token:', error);
    }
}

// Middleware to refresh the token if needed
router.use(async (req, res, next) => {
    if (!spotifyAccessToken) {
        await refreshAccessToken();
    }
    next();
});

// Function to convert Spotify track URLs to URIs
function convertUrlsToUris(urls) {
    return urls.map(url => {
        const match = url.match(/track\/([^?\/]+)$/);
        if (match) {
            return `spotify:track:${match[1]}`;
        }
        throw new Error(`Invalid URL format: ${url}`);
    });
}

router.post('/create-playlist', async (req, res) => {
    const { spotifyLinks, youtubeLink, videoTitle } = req.body;
    const playlistName = videoTitle;

    try {
        // Create a new playlist
        const createPlaylistResponse = await axios.post(
            `https://api.spotify.com/v1/users/${userId}/playlists`,
            {
                name: playlistName,
                description: 'Playlist created from YouTube video',
                public: false
            },
            {
                headers: {
                    'Authorization': `Bearer ${spotifyAccessToken}`,
                    'Content-Type': 'application/json'
                }
            }
        );

        const playlistId = createPlaylistResponse.data.id;
        console.log('Created Playlist ID:', playlistId);

        // Convert track URLs to URIs
        const trackUris = convertUrlsToUris(spotifyLinks);

        // Add tracks to the playlist
        if (trackUris && trackUris.length > 0) {
            const addTracksResponse = await axios.post(
                `https://api.spotify.com/v1/playlists/${playlistId}/tracks`,
                {
                    uris: trackUris
                },
                {
                    headers: {
                        'Authorization': `Bearer ${spotifyAccessToken}`,
                        'Content-Type': 'application/json'
                    }
                }
            );
            console.log('Tracks added to Playlist:', addTracksResponse.data);
        }

        res.json({ message: 'Playlist created successfully', playlistId });
    } catch (error) {
        console.error('Error creating playlist:', error.response ? error.response.data : error.message);
        res.status(500).json({ error: error.response ? error.response.data : 'Error creating playlist' });
    }
});

module.exports = router;

以上是我的spotify.js 代码。我正在尝试创建一个 Web 应用程序,它接受 YouTube 链接,然后识别视频中的歌曲并使用所有 Spotify 链接创建 Spotify 播放列表。目前,我能够获取列表中的所有 Spotify 链接,但是当我将所有这些信息发送到 spotify.js 时,我收到创建播放列表的错误。我尝试查看日志并使用聊天 gpt,但无法找出错误。这应该创建播放列表并向其中添加歌曲。我已经创建了一个函数来格式化链接,所以我认为这不应该是一个问题。我可以获得一些帮助来找出潜在的错误吗?以下是用于创建播放列表的 Spotify Web API 的链接:https://developer.spotify.com/documentation/web-api/reference/create-playlist

node.js curl axios spotify webapi
1个回答
0
投票

您可以使用

req.app.set
req.app.get
而不是将令牌值存储在全局范围内

此外,通过在

req.app
中存储值,可以使用
req.app.get

在任何控制器中访问
let spotifyAccessToken = ''; // Dynamically set by app.js ❌
let spotifyRefreshToken = ''; ❌

在中间件中

router.use(async (req, res, next) => {
    if(!req.app.get('spotifyAccessToken')){
        await refreshAccessToken(req);
    }
    next();
});

在控制器中

async function refreshAccessToken(req) {
    const authOptions = {
        url: 'https://accounts.spotify.com/api/token',
        form: {
            grant_type: 'refresh_token',
            refresh_token: spotifyRefreshToken
        },
        headers: {
            'Authorization': 'Basic ' + Buffer.from(client_id + ':' + client_secret).toString('base64')
        }
    };

    try {
        const response = await axios.post(authOptions.url, querystring.stringify(authOptions.form), {
            headers: authOptions.headers,
        });

        const spotifyAccessToken = response.data.access_token;

        req.app.set('spotifyAccessToken',spotifyAccessToken); // here is the magic ✅

        console.log('New Access Token:', spotifyAccessToken);
    } catch (error) {
        console.error('Error refreshing access token:', error);
    }
}

这个方法很高效,因为我们不能在commonjs中使用全局await。

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