[READ-ONLY] Mirror of https://github.com/flo-bit/youtube-party-dj. democratic youtube player, everyone can vote and add songs, uni project, made with uix
0

Configure Feed

Select the types of activity you want to include in your feed.

youtube-party-dj / backend / data.tsx
2.7 kB 86 lines
1import { Innertube } from "https://deno.land/x/youtubei@v10.0.0-deno/deno.ts"; 2import uniqBy from 'https://cdn.skypack.dev/lodash/uniqBy'; 3import shuffle from 'https://cdn.skypack.dev/lodash/shuffle'; 4import take from 'https://cdn.skypack.dev/lodash/take'; 5 6const youtube = await Innertube.create(); 7 8export async function search(q: string) { 9 try { 10 11 const result = await youtube.search(q, {type: 'video', sort_by: 'relevance'}) 12 13 // filter out videos without duration (live?), then get first 10 videos 14 // @ts-ignore - no type for duration 15 const videos = result.videos.filter((item) => item.duration?.seconds).slice(0, 10); 16 17 return videos.map(item => normalizeVideo(item)); 18 } catch (error) { 19 console.error(error); 20 return []; 21 } 22} 23 24const normalizeVideo = (video: any) => { 25 console.log(video); 26 return { 27 title: video.title.text ?? 'Untitled', 28 // @ts-ignore - no type for thumbnails 29 thumbnail: video.thumbnails?.[0].url, 30 // @ts-ignore - no type for id 31 id: video.id, 32 likes: new Set<string>(), 33 added: Date.now(), 34 // @ts-ignore - no type for duration 35 duration: video.duration?.text ?? '-', 36 } 37} 38 39async function getRelatedVideos(videoId: string) { 40 try { 41 const videoDetails = await youtube.getInfo(videoId); 42 const related = videoDetails.watch_next_feed.map(related => normalizeVideo(related)); 43 return related; 44 } catch (error) { 45 console.error("Error fetching related videos:", error); 46 throw error; 47 } 48} 49 50export async function getRecommendations(queue: { id: string }[], maxRecommendations = 5) { 51 let allRecommendations: string[] = []; 52 53 for (const video of queue) { 54 try { 55 const relatedVideos = await getRelatedVideos(video.id); 56 allRecommendations.push(...relatedVideos.slice(0, maxRecommendations)); 57 } catch (error) { 58 console.error(`Error processing video ID ${video.id}:`, error); 59 } 60 } 61 62 // filter out duplicates that are in queue 63 const newRecommendations = allRecommendations.filter((video) => !queue.some((item) => item.id === video.id)); 64 65 const uniqueRecommendations = uniqBy(newRecommendations, 'id'); 66 67 const shuffledRecommendations = shuffle(uniqueRecommendations); 68 69 const finalRecommendations = take(shuffledRecommendations, maxRecommendations); 70 71 console.log("FINDAL RECOMMENDATIONS", finalRecommendations); 72 return finalRecommendations; 73} 74 75export async function updateRecommendations(session: any, code: string) { 76 const recommendations = await getRecommendations(session.queue); 77 78 recommendations.forEach(() => { 79 session?.recommendedQueue.pop() 80 }) 81 recommendations.forEach((video) => { 82 session?.recommendedQueue.push(video) 83 }) 84 85 return session; 86}