feat(同步): 改进网易云音乐到Navidrome的播放列表同步逻辑

添加获取Navidrome播放列表歌曲ID的功能
确保同步时检查并补全缺失歌曲,避免重复添加
使用Set去重处理歌曲ID列表
This commit is contained in:
史悦
2026-01-13 09:33:44 +08:00
parent 5561bf2400
commit b5b093e64b

View File

@@ -549,6 +549,18 @@ async function updateNavidromePlaylist(playlistId, songIdsToAdd) {
} }
} }
async function getNavidromePlaylistSongIds(playlistId) {
try {
const result = await callSubsonicAPI('getPlaylist', { id: playlistId });
const entries = result.playlist?.entry || result.playlist?.song || [];
const list = Array.isArray(entries) ? entries : [entries];
return list.map(e => e?.id).filter(Boolean);
} catch (error) {
console.error('Get playlist error:', error.message);
return null;
}
}
async function findNavidromePlaylistByName(name) { async function findNavidromePlaylistByName(name) {
try { try {
const result = await callSubsonicAPI('getPlaylists'); const result = await callSubsonicAPI('getPlaylists');
@@ -690,23 +702,38 @@ async function syncPlaylist(playlist, cachedInfo = null) {
} }
} }
console.log(`[Sync] Matched ${allNavidromeIds.length} songs (New: ${newSongIds.length}). PlaylistID: ${playlist.navidromePlaylistId}`); const uniqueAllNavidromeIds = Array.from(new Set(allNavidromeIds));
console.log(`[Sync] Matched ${uniqueAllNavidromeIds.length} songs (New: ${newSongIds.length}). PlaylistID: ${playlist.navidromePlaylistId}`);
if (playlist.navidromePlaylistId) { if (playlist.navidromePlaylistId) {
// Playlist exists (either linked just now or before) // Playlist exists (either linked just now or before)
// Just append new songs if any // Always check existing playlist content and补齐缺失歌曲
if (newSongIds.length > 0) { let missingIds = [];
console.log(`[Sync] Adding ${newSongIds.length} new songs to existing playlist ${playlist.navidromePlaylistId}`); if (uniqueAllNavidromeIds.length > 0) {
await updateNavidromePlaylist(playlist.navidromePlaylistId, newSongIds); const existingIds = await getNavidromePlaylistSongIds(playlist.navidromePlaylistId);
if (Array.isArray(existingIds)) {
const existingSet = new Set(existingIds.map(id => id?.toString()));
missingIds = uniqueAllNavidromeIds.filter(id => !existingSet.has(id?.toString()));
console.log(`[Sync] Existing playlist has ${existingIds.length} songs, missing ${missingIds.length}`);
} else {
// Fallback: if无法读取至少追加本次新匹配到的
missingIds = newSongIds;
}
}
if (missingIds.length > 0) {
console.log(`[Sync] Adding ${missingIds.length} missing songs to existing playlist ${playlist.navidromePlaylistId}`);
await updateNavidromePlaylist(playlist.navidromePlaylistId, missingIds);
} else { } else {
console.log(`[Sync] No new songs to add to playlist ${playlist.navidromePlaylistId}`); console.log(`[Sync] No missing songs to add to playlist ${playlist.navidromePlaylistId}`);
} }
} else { } else {
// Playlist does NOT exist // Playlist does NOT exist
// Create it with ALL matched songs (if any) // Create it with ALL matched songs (if any)
if (allNavidromeIds.length > 0) { if (uniqueAllNavidromeIds.length > 0) {
console.log(`[Sync] Creating new playlist '${playlist.name}' with ${allNavidromeIds.length} songs`); console.log(`[Sync] Creating new playlist '${playlist.name}' with ${uniqueAllNavidromeIds.length} songs`);
const navidromePlaylistId = await createNavidromePlaylist(playlist.name, allNavidromeIds); const navidromePlaylistId = await createNavidromePlaylist(playlist.name, uniqueAllNavidromeIds);
playlist.navidromePlaylistId = navidromePlaylistId; playlist.navidromePlaylistId = navidromePlaylistId;
} else { } else {
// Try creating empty playlist? Subsonic API usually requires songId. // Try creating empty playlist? Subsonic API usually requires songId.