This commit is contained in:
2025-02-14 11:59:11 +02:00
parent e6b898ef09
commit 9ddf068049
73 changed files with 5767 additions and 126 deletions

80
lib/omniRecommendation.ts Normal file
View File

@@ -0,0 +1,80 @@
"use client";
import { getCookie } from "./roblox";
type RecommendationEntry = {
contentType: "Game"|string,
contentId: number,
contentStringId: string,
contentMetadata: {
Score: string
}
}
type RecommendationSort = {
topic: string,
topicId: number,
treatmentType: string,
recommendationList: RecommendationEntry[],
nextPageTokenForTopic: null,
numberOfRows: number,
topicLayoutData: any
}
export type ContentMetadata = {
totalUpVotes: number,
totalDownVotes: number,
universeId: number,
name: string,
rootPlaceId: number,
description: null,
playerCount: number,
primaryMediaAsset: any,
under9: boolean,
under13: boolean,
minimumAge: number,
ageRecommendationDisplayName: string,
friendVisits: any[],
friendVisitedString: string,
layoutDataBySort: any
}
export type OmniRecommendation = {
pageType: "Home" | string,
requestId: string,
sortsRefreshInterval: number,
contentMetadata: {
Game: {[id: string]: ContentMetadata},
CatalogAsset: any,
CatalogBundle: any,
RecommendedFriend: any,
GameCoPlay: any
},
nextPageToken: string,
isSessionExpired: boolean,
globalLayoutData: any,
isPartialFeed: boolean,
DebugInfoGroups: boolean,
sorts: RecommendationSort[]
}
export async function getOmniRecommendationsHome(): Promise<OmniRecommendation> {
const data = await fetch(`${document.baseURI}api/discovery/omni-recommendation`,{
method: "POST",
headers: {
Authorization: `${getCookie()}`
},
body: JSON.stringify({
pageType: "Home",
sessionId: crypto.randomUUID(),
supportedTreatmentTypes: ["SortlessGrid"],
authIntentData: null,
cpuCores: 4,
maxResolution: "1920x1080",
maxMemory: 8192
})
})
return await data.json() as OmniRecommendation
}
// https://apis.roblox.com/discovery-api/omni-recommendation

9
lib/roblox.ts Normal file
View File

@@ -0,0 +1,9 @@
"use client";
export function setCookie(cookie: string): void {
window.localStorage.roblosecurity = cookie;
}
export function getCookie() {
return window.localStorage.roblosecurity
}

52
lib/thumbnailLoader.ts Normal file
View File

@@ -0,0 +1,52 @@
"use client";
import { addGameThumbnail } from "@/hooks/use-lazy-load";
import { getCookie } from "./roblox";
export type AssetThumbnail = {
requestId: string,
errorCode: number,
errorMessage: string,
targetId: number,
state: "Completed" | string,
imageUrl: string,
version: string
}
export type ThumbnailRequest = {
type: "GameThumbnail",
targetId: number,
format: "webp",
size: string
}
export async function getThumbnails(b: ThumbnailRequest[]): Promise<AssetThumbnail[]> {
const data = await fetch(`${document.baseURI}api/thumbnails/batch`,{
method: "POST",
headers: {
Authorization: `${getCookie()}`
},
body: JSON.stringify(
b.map(a=>{
return {
requestId: `${a.targetId}::${a.type}:${a.size}:${a.format}:regular`,
type: a.type,
targetId: a.targetId,
token: "",
format: a.format,
size: a.size
}
})
)
})
return (await data.json() as any).data as AssetThumbnail[]
}
export async function loadThumbnails(b: ThumbnailRequest[]): Promise<void> {
const th = await getThumbnails(b);
th.forEach(a=>{
addGameThumbnail(a.targetId.toString(), a.imageUrl)
})
}
// https://apis.roblox.com/discovery-api/omni-recommendation

6
lib/utils.ts Normal file
View File

@@ -0,0 +1,6 @@
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}