Add screens and components for Song Battle game, including Home, Lobby, Voting, Results, and Song Submission screens; implement YouTube video embedding and styles
Some checks failed
Publish Docker image / Push Docker image to Docker Hub (push) Failing after 7m12s
Some checks failed
Publish Docker image / Push Docker image to Docker Hub (push) Failing after 7m12s
This commit is contained in:
129
server/youtube-api.js
Normal file
129
server/youtube-api.js
Normal file
@ -0,0 +1,129 @@
|
||||
const { google } = require('googleapis');
|
||||
const axios = require('axios');
|
||||
|
||||
// You would need to obtain a YouTube API key from Google Cloud Console
|
||||
// For now, we'll use a placeholder - you'll need to replace this with your actual API key
|
||||
const API_KEY = process.env.YOUTUBE_API_KEY || 'NO';
|
||||
|
||||
// Initialize the YouTube API client
|
||||
const youtube = google.youtube({
|
||||
version: 'v3',
|
||||
auth: API_KEY
|
||||
});
|
||||
|
||||
/**
|
||||
* Extract YouTube video ID from various formats of YouTube links
|
||||
* @param {string} url - YouTube URL in any format
|
||||
* @returns {string|null} YouTube video ID or null if invalid
|
||||
*/
|
||||
function extractVideoId(url) {
|
||||
if (!url) return null;
|
||||
|
||||
// Handle different YouTube URL formats
|
||||
const patterns = [
|
||||
/(?:https?:\/\/)?(?:www\.)?youtube\.com\/watch\?v=([^&]+)/,
|
||||
/(?:https?:\/\/)?(?:www\.)?youtube\.com\/embed\/([^/?]+)/,
|
||||
/(?:https?:\/\/)?(?:www\.)?youtu\.be\/([^/?]+)/
|
||||
];
|
||||
|
||||
for (const pattern of patterns) {
|
||||
const match = url.match(pattern);
|
||||
if (match && match[1]) {
|
||||
return match[1];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get video metadata from YouTube API
|
||||
* @param {string} videoId - YouTube video ID
|
||||
* @returns {Promise<Object>} Video metadata including title and channel
|
||||
*/
|
||||
async function getVideoMetadata(videoId) {
|
||||
try {
|
||||
// Try using the googleapis library first
|
||||
try {
|
||||
const response = await youtube.videos.list({
|
||||
part: 'snippet',
|
||||
id: videoId
|
||||
});
|
||||
|
||||
const video = response.data.items[0];
|
||||
|
||||
if (video && video.snippet) {
|
||||
return {
|
||||
title: video.snippet.title,
|
||||
artist: video.snippet.channelTitle,
|
||||
thumbnail: video.snippet.thumbnails.default.url
|
||||
};
|
||||
}
|
||||
} catch (googleApiError) {
|
||||
console.log('Google API error, falling back to alternative method:', googleApiError.message);
|
||||
// If googleapis fails (e.g., due to API key issues), fall back to a simplified approach
|
||||
const response = await axios.get(`https://www.youtube.com/oembed?url=https://www.youtube.com/watch?v=${videoId}&format=json`);
|
||||
|
||||
if (response.data) {
|
||||
const title = response.data.title || '';
|
||||
// Try to extract artist from title (common format is "Artist - Title")
|
||||
const parts = title.split(' - ');
|
||||
const artist = parts.length > 1 ? parts[0] : response.data.author_name;
|
||||
|
||||
return {
|
||||
title: parts.length > 1 ? parts.slice(1).join(' - ') : title,
|
||||
artist: artist,
|
||||
thumbnail: response.data.thumbnail_url
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// If all methods fail, return default values
|
||||
return {
|
||||
title: 'Unknown Title',
|
||||
artist: 'Unknown Artist',
|
||||
thumbnail: null
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error fetching video metadata:', error.message);
|
||||
return {
|
||||
title: 'Unknown Title',
|
||||
artist: 'Unknown Artist',
|
||||
thumbnail: null
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for songs on YouTube
|
||||
* @param {string} query - Search query for YouTube
|
||||
* @returns {Promise<Array>} List of search results
|
||||
*/
|
||||
async function searchYouTube(query) {
|
||||
try {
|
||||
const response = await youtube.search.list({
|
||||
part: 'snippet',
|
||||
q: query,
|
||||
type: 'video',
|
||||
maxResults: 5,
|
||||
videoCategoryId: '10' // Category ID for Music
|
||||
});
|
||||
|
||||
return response.data.items.map(item => ({
|
||||
id: item.id.videoId,
|
||||
title: item.snippet.title,
|
||||
artist: item.snippet.channelTitle,
|
||||
thumbnail: item.snippet.thumbnails.default.url,
|
||||
youtubeLink: `https://www.youtube.com/watch?v=${item.id.videoId}`
|
||||
}));
|
||||
} catch (error) {
|
||||
console.error('Error searching YouTube:', error.message);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
extractVideoId,
|
||||
getVideoMetadata,
|
||||
searchYouTube
|
||||
};
|
Reference in New Issue
Block a user