117 lines
3.4 KiB
JavaScript
117 lines
3.4 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;
|
|
|
|
let cachedSongs = null;
|
|
let lastFetchTime = 0;
|
|
const CACHE_TTL = 3600000; // 1 hour
|
|
|
|
/**
|
|
* Fetches songs from YouTube playlist and returns them
|
|
*/
|
|
const fetchPlaylistSongs = async () => {
|
|
const now = Date.now();
|
|
if (cachedSongs && cachedSongs.length > 0 && (now - lastFetchTime) < CACHE_TTL) {
|
|
console.log("Returning cached YouTube songs:", cachedSongs.length);
|
|
return cachedSongs;
|
|
}
|
|
|
|
try {
|
|
console.log("Fetching songs from YouTube API...");
|
|
const playlistUrl = `https://www.googleapis.com/youtube/v3/playlistItems?part=snippet,contentDetails&maxResults=50&playlistId=${PLAYLIST_ID}&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) {
|
|
console.error("No items found in YouTube playlist");
|
|
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 ||
|
|
"https://place-hold.it/500x500/333/fff?text=No%20Thumbnail",
|
|
}));
|
|
|
|
cachedSongs = songs;
|
|
lastFetchTime = now;
|
|
console.log("Fetched and cached YouTube songs:", songs.length);
|
|
|
|
return songs;
|
|
} catch (error) {
|
|
console.error("Error fetching YouTube playlist:", error);
|
|
|
|
if (cachedSongs && cachedSongs.length > 0) {
|
|
console.log("Using last cached songs due to API error");
|
|
return cachedSongs;
|
|
}
|
|
|
|
return [{
|
|
id: 1,
|
|
title: "Could not load songs",
|
|
artist: "API Error",
|
|
coverUrl: "https://place-hold.it/500x500/f00/fff?text=Error",
|
|
youtubeId: "dQw4w9WgXcQ"
|
|
}];
|
|
}
|
|
};
|
|
|
|
const getAvailableSongIds = async () => {
|
|
const songs = await fetchPlaylistSongs();
|
|
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
|
|
};
|