diff --git a/backend/src/service/music_platform/wycloud/index.js b/backend/src/service/music_platform/wycloud/index.js index 9b03c5d..02f5f5f 100644 --- a/backend/src/service/music_platform/wycloud/index.js +++ b/backend/src/service/music_platform/wycloud/index.js @@ -8,6 +8,7 @@ const fs = require('fs'); const path = require('path'); const {requestApi} = require('./transport'); const { buildSongUrl } = require('../tunehub'); +const configManager = require('../config_manager'); async function uploadSong(uid, filePath) { const response = await safeRequest(uid, cloud, { @@ -201,48 +202,70 @@ async function getSongsFromPlaylist(uid, source, playlistId) { songsMap[song.id] = song; }); - // 使用 check_music API 检查歌曲是否可播放 - // 注意:由于需要批量检查,这里优化为分批处理 - const checkSongsPlayable = async (songIds) => { - const batchSize = 50; // 每批检查50首 - const results = {}; + // 检查是否启用精确检查(默认禁用,因为批量检查可能导致网络问题) + const globalConfig = await configManager.getGlobalConfig(); + const enableAccurateCheck = globalConfig?.enableAccurateCheck === true; - for (let i = 0; i < songIds.length; i += batchSize) { - const batch = songIds.slice(i, i + batchSize); - const batchPromises = batch.map(async (songId) => { - try { - const response = await safeRequest(uid, check_music, { id: songId, br: 999000 }, false); - if (response && response.success === true) { - return { id: songId, playable: true }; - } else { - return { id: songId, playable: false }; + let playableResults = {}; + if (enableAccurateCheck) { + // 使用 check_music API 检查歌曲是否可播放 + // 注意:由于需要批量检查,这里优化为分批处理 + const checkSongsPlayable = async (songIds) => { + const batchSize = 20; // 每批检查20首(降低并发压力) + const results = {}; + let successCount = 0; + let failureCount = 0; + + for (let i = 0; i < songIds.length; i += batchSize) { + const batch = songIds.slice(i, i + batchSize); + const batchPromises = batch.map(async (songId) => { + try { + const response = await safeRequest(uid, check_music, { + id: songId, + br: 999000 + }, false); + + if (response && response.success === true) { + successCount++; + return { id: songId, playable: true }; + } else if (response && response.success === false) { + successCount++; + return { id: songId, playable: false }; + } else { + failureCount++; + return { id: songId, playable: null }; // API调用失败,回退到 privileges 判断 + } + } catch (error) { + failureCount++; + logger.warn(`check music failed for ${songId}: ${error.message}`); + // 如果检查失败,回退到基于 privileges 字段的判断 + return { id: songId, playable: null }; // null 表示未知,需要回退判断 } - } catch (error) { - logger.warn(`check music failed for ${songId}: ${error.message}`); - // 如果检查失败,回退到基于 privileges 字段的判断 - return { id: songId, playable: null }; // null 表示未知,需要回退判断 + }); + + const batchResults = await Promise.all(batchPromises); + batchResults.forEach(result => { + results[result.id] = result.playable; + }); + + // 添加延迟,避免请求过快 + if (i + batchSize < songIds.length) { + await new Promise(resolve => setTimeout(resolve, 300)); // 增加延迟到300ms } - }); - - const batchResults = await Promise.all(batchPromises); - batchResults.forEach(result => { - results[result.id] = result.playable; - }); - - // 添加延迟,避免请求过快 - if (i + batchSize < songIds.length) { - await new Promise(resolve => setTimeout(resolve, 100)); } - } - return results; - }; + logger.info(`[checkSongsPlayable] Success: ${successCount}, Failed: ${failureCount}`); + return results; + }; - // 检查所有歌曲的可播放性 - const songIds = songsResponse.songs.map(song => song.id); - logger.info(`[getSongsFromPlaylist] Checking playable status for ${songIds.length} songs...`); - const playableResults = await checkSongsPlayable(songIds); - logger.info(`[getSongsFromPlaylist] Checked ${Object.keys(playableResults).length} songs`); + // 检查所有歌曲的可播放性 + const songIds = songsResponse.songs.map(song => song.id); + logger.info(`[getSongsFromPlaylist] Checking playable status for ${songIds.length} songs...`); + playableResults = await checkSongsPlayable(songIds); + logger.info(`[getSongsFromPlaylist] Checked ${Object.keys(playableResults).length} songs`); + } else { + logger.info(`[getSongsFromPlaylist] Accurate check disabled, using privileges-based judgment`); + } const isBlockedSong = (song, songInfo, playable) => { // the song has been added to cloud if the pc field is present