Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
"use server" | |
import { VideoInfo } from "@/types" | |
import { getVideoIndex } from "./getVideoIndex" | |
const HARD_LIMIT = 100 | |
// this just return ALL videos on the platform | |
export async function getVideos({ | |
mandatoryTags = [], | |
niceToHaveTags = [], | |
sortBy = "date", | |
ignoreVideoIds = [], | |
maxVideos = HARD_LIMIT, | |
}: { | |
// the videos MUST include those tags | |
mandatoryTags?: string[] | |
// tags that we should try to use to filter the videos, | |
// but it isn't a hard limit - TODO: use some semantic search here? | |
niceToHaveTags?: string[] | |
sortBy?: "random" | "date" | |
// ignore some ids - this is used to not show the same videos again | |
// eg. videos already watched, or disliked etc | |
ignoreVideoIds?: string[] | |
maxVideos?: number | |
}): Promise<VideoInfo[]> { | |
// the index is gonna grow more and more, | |
// but in the future we will use some DB eg. Prisma or sqlite | |
const published = await getVideoIndex({ | |
status: "published", | |
renewCache: true | |
}) | |
let allPotentiallyValidVideos = Object.values(published) | |
if (ignoreVideoIds.length) { | |
allPotentiallyValidVideos = allPotentiallyValidVideos.filter(video => !ignoreVideoIds.includes(video.id)) | |
} | |
if (sortBy === "date") { | |
allPotentiallyValidVideos.sort(((a, b) => b.updatedAt.localeCompare(a.updatedAt))) | |
} else { | |
allPotentiallyValidVideos.sort(() => Math.random() - 0.5) | |
} | |
let videosMatchingFilters: VideoInfo[] = allPotentiallyValidVideos | |
// filter videos by mandatory tags, or else we return everything | |
const mandatoryTagsList = mandatoryTags.map(tag => tag.toLowerCase().trim()).filter(tag => tag) | |
if (mandatoryTagsList.length) { | |
videosMatchingFilters = allPotentiallyValidVideos.filter(video => | |
video.tags.some(tag => | |
mandatoryTagsList.includes(tag.toLowerCase().trim()) | |
) | |
) | |
} | |
// filter videos by mandatory tags, or else we return everything | |
const niceToHaveTagsList = niceToHaveTags.map(tag => tag.toLowerCase().trim()).filter(tag => tag) | |
if (niceToHaveTagsList.length) { | |
videosMatchingFilters = videosMatchingFilters.filter(video => | |
video.tags.some(tag => | |
mandatoryTagsList.includes(tag.toLowerCase().trim()) | |
) | |
) | |
// if we don't have enough videos | |
if (videosMatchingFilters.length < maxVideos) { | |
// count how many we need | |
const nbMissingVideos = maxVideos - videosMatchingFilters.length | |
// then we try to fill the gap with valid videos from other topics | |
const videosToUseAsFiller = allPotentiallyValidVideos | |
.filter(video => !videosMatchingFilters.some(v => v.id === video.id)) // of course we don't reuse the same | |
// .sort(() => Math.random() - 0.5) // randomize them | |
.slice(0, nbMissingVideos) // and only pick those we need | |
videosMatchingFilters = [ | |
...videosMatchingFilters, | |
...videosToUseAsFiller, | |
] | |
} | |
} | |
// we enforce the max limit of HARD_LIMIT (eg. 100) | |
return videosMatchingFilters.slice(0, Math.min(HARD_LIMIT, maxVideos)) | |
} |