ToneGuessr/server/services/youtubeService.js
2025-03-01 16:39:13 +01:00

112 lines
3.3 KiB
JavaScript

const { google } = require('googleapis');
const youtube = google.youtube('v3');
const YOUTUBE_API_KEY = process.env.YOUTUBE_API_KEY;
const PLAYLIST_ID = "PLmXxqSJJq-yXrCPGIT2gn8b34JjOrl4Xf";
const PLAYLISTS = {
seventies: 'PLmXxqSJJq-yXrCPGIT2gn8b34JjOrl4Xf',
eighties: 'PLmXxqSJJq-yUvMWKuZQAB_8yxnjZaOZUp',
nineties: 'PLmXxqSJJq-yUF3jbzjF_pa--kuBuMlyQQ'
};
const API_KEY = process.env.YOUTUBE_API_KEY;
const cachedSongsByPlaylist = {};
const CACHE_TTL = 3600000; // 1 hour
/**
* Fetches songs from YouTube playlist and returns them
*/
const fetchPlaylistSongs = async (playlistId = null) => {
if (!playlistId) {
console.warn("No playlist ID provided, using default");
playlistId = PLAYLISTS.seventies; // default fallback
}
const now = Date.now();
if (cachedSongsByPlaylist[playlistId] &&
cachedSongsByPlaylist[playlistId].songs.length > 0 &&
(now - cachedSongsByPlaylist[playlistId].timestamp) < CACHE_TTL) {
console.log(`Using cached songs for playlist ${playlistId}`);
return cachedSongsByPlaylist[playlistId].songs;
}
try {
console.log(`Fetching fresh songs from YouTube API for playlist ${playlistId}...`);
const playlistUrl = `https://www.googleapis.com/youtube/v3/playlistItems?part=snippet,contentDetails&maxResults=50&playlistId=${playlistId}&key=${YOUTUBE_API_KEY}`;
const response = await fetch(playlistUrl);
const data = await response.json();
if (data.error) {
console.error("YouTube API error:", data.error);
throw new Error(data.error.message);
}
if (!data.items || !data.items.length) {
throw new Error("No songs found in the playlist");
}
const songs = data.items.map((item, index) => ({
id: index + 1,
youtubeId: item.contentDetails.videoId,
title: item.snippet.title,
artist: item.snippet.videoOwnerChannelTitle || "Unknown Artist",
coverUrl: item.snippet.thumbnails.high?.url || item.snippet.thumbnails.default?.url,
playlistId: playlistId
}));
cachedSongsByPlaylist[playlistId] = {
songs,
timestamp: now
};
return songs;
} catch (error) {
console.error(`Error fetching YouTube playlist ${playlistId}:`, error);
return cachedSongsByPlaylist[playlistId]?.songs || getDefaultSongs();
}
};
const getAvailableSongIds = async (playlistId) => {
const songs = await fetchPlaylistSongs(playlistId);
return songs.map(song => song.id);
};
async function getPlaylistDetails() {
try {
const details = {};
for (const [genre, playlistId] of Object.entries(PLAYLISTS)) {
const response = await youtube.playlists.list({
key: API_KEY,
part: 'snippet,contentDetails',
id: playlistId
});
const playlist = response.data.items[0];
details[genre] = {
id: playlistId,
title: playlist.snippet.title,
description: playlist.snippet.description,
thumbnail: playlist.snippet.thumbnails.maxres || playlist.snippet.thumbnails.high,
songCount: playlist.contentDetails.itemCount,
votes: 0
};
}
return details;
} catch (error) {
console.error('Error fetching playlist details:', error);
throw error;
}
}
module.exports = {
fetchPlaylistSongs,
getAvailableSongIds,
PLAYLISTS,
getPlaylistDetails
};