Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
"use server" | |
import { developerMode } from "@/app/config" | |
import { WhoAmIUser, whoAmI } from "@/lib/huggingface/hub/src" | |
import { MediaRating } from "@/types/general" | |
import { redis } from "./redis"; | |
export async function getStatsForMedias(mediaIds: string[]): Promise<Record<string, { numberOfViews: number; numberOfLikes: number; numberOfDislikes: number}>> { | |
if (!Array.isArray(mediaIds)) { | |
return {} | |
} | |
try { | |
const stats: Record<string, { numberOfViews: number; numberOfLikes: number; numberOfDislikes: number; }> = {} | |
const listOfRedisIDs: string[] = [] | |
for (const mediaId of mediaIds) { | |
listOfRedisIDs.push(`videos:${mediaId}:stats:views`) | |
listOfRedisIDs.push(`videos:${mediaId}:stats:likes`) | |
listOfRedisIDs.push(`videos:${mediaId}:stats:dislikes`) | |
stats[mediaId] = { | |
numberOfViews: 0, | |
numberOfLikes: 0, | |
numberOfDislikes: 0, | |
} | |
} | |
const listOfRedisValues = await redis.mget<number[]>(...listOfRedisIDs) | |
let v = 0 | |
for (let i = 0; i < listOfRedisValues.length; i += 3) { | |
stats[mediaIds[v++]] = { | |
numberOfViews: listOfRedisValues[i] || 0, | |
numberOfLikes: listOfRedisValues[i + 1] || 0, | |
numberOfDislikes: listOfRedisValues[i + 2] || 0 | |
} | |
} | |
return stats | |
} catch (err) { | |
return {} | |
} | |
} | |
export async function countNewMediaView(mediaId: string): Promise<number> { | |
if (developerMode) { | |
const stats = await getStatsForMedias([mediaId]) | |
return stats[mediaId].numberOfViews | |
} | |
try { | |
const result = await redis.incr(`videos:${mediaId}:stats:views`) | |
return result | |
} catch (err) { | |
return 0 | |
} | |
} | |
export async function getMediaRating(mediaId: string, apiKey?: string): Promise<MediaRating> { | |
let numberOfLikes = 0 | |
let numberOfDislikes = 0 | |
let isLikedByUser = false | |
let isDislikedByUser = false | |
try { | |
// update video likes counter | |
numberOfLikes = (await redis.get<number>(`videos:${mediaId}:stats:likes`)) || 0 | |
numberOfDislikes = (await redis.get<number>(`videos:${mediaId}:stats:dislikes`)) || 0 | |
} catch (err) { | |
} | |
// optional: determine if the user liked or disliked the content | |
if (apiKey) { | |
try { | |
const credentials = { accessToken: apiKey } | |
const user = await whoAmI({ credentials }) as unknown as WhoAmIUser | |
const isLiked = await redis.get<boolean>(`users:${user.id}:activity:videos:${mediaId}:liked`) | |
if (isLiked !== null) { | |
isLikedByUser = !!isLiked | |
isDislikedByUser = !isLiked | |
} | |
} catch (err) { | |
console.error("failed to get user like status") | |
} | |
} | |
return { | |
isLikedByUser, | |
isDislikedByUser, | |
numberOfLikes, | |
numberOfDislikes, | |
} | |
} | |
export async function rateMedia(mediaId: string, liked: boolean, apiKey: string): Promise<MediaRating> { | |
// note: we want the like to throw an exception if it failed | |
let numberOfLikes = 0 | |
let numberOfDislikes = 0 | |
let isLikedByUser = false | |
let isDislikedByUser = false | |
const credentials = { accessToken: apiKey } | |
const user = await whoAmI({ credentials }) as unknown as WhoAmIUser | |
const hasLiked = await redis.get<boolean>(`users:${user.id}:activity:videos:${mediaId}:liked`) | |
const hasAlreadyRatedTheSame = hasLiked !== null && liked === hasLiked | |
if (hasAlreadyRatedTheSame) { | |
return { | |
numberOfLikes: await redis.get(`videos:${mediaId}:stats:likes`) || 0, | |
numberOfDislikes: await redis.get(`videos:${mediaId}:stats:dislikes`) || 0, | |
isLikedByUser: liked, | |
isDislikedByUser: !liked | |
} | |
} | |
const hasAlreadyRatedAndDifferently = hasLiked !== null && liked !== hasLiked | |
await redis.set(`users:${user.id}:activity:videos:${mediaId}:liked`, liked) | |
isLikedByUser = liked | |
isDislikedByUser = !liked | |
// if user has already rated the content, and it's different from the desired value, | |
// then we need to undo the rating | |
try { | |
if (liked) { | |
// update video likes counter | |
numberOfLikes = await redis.incr(`videos:${mediaId}:stats:likes`) | |
if (hasAlreadyRatedAndDifferently) { | |
numberOfDislikes = await redis.decr(`videos:${mediaId}:stats:dislikes`) | |
} | |
} else { | |
numberOfDislikes = await redis.incr(`videos:${mediaId}:stats:dislikes`) | |
if (hasAlreadyRatedAndDifferently) { | |
numberOfLikes = await redis.decr(`videos:${mediaId}:stats:likes`) | |
} | |
} | |
} catch (err) { | |
} finally { | |
return { | |
numberOfLikes, | |
numberOfDislikes, | |
isLikedByUser, | |
isDislikedByUser, | |
} | |
} | |
} | |