feed.ts
1.5 kB · typescript · 57 lines
1export type Post = {2 name: string;3 seed: number;4 at: string;5 duration: number;6 frames: number;7 size: number;8 segments: number;9 canvas: number;10 story: string;11};1213/* URLS */1415const BASE = "/cdn/feed/p";1617const postName = (name: string) => /^[0-9a-f]{8}$/.test(String(name ?? ""));1819export const postVideo = (name: string) => `${BASE}/${name}/${name}.mp4`;2021export const postMaster = (name: string) => `${BASE}/${name}/${name}-1080.mp4`;2223export const postPoster = (name: string) => `${BASE}/${name}/${name}.webp`;2425export const postManifest = (name: string) => `${BASE}/${name}/${name}.json`;2627export const postRoute = (name: string) => `/feed/${name}/`;2829export const FEED_ROUTE = "/feed/";3031/* INDEX */3233export function posts(text: string): Post[] {34 let rows: unknown = null;35 try {36 rows = JSON.parse(text);37 } catch {38 return [];39 }40 if (!Array.isArray(rows)) return [];41 const out: Post[] = [];42 for (const one of rows as Record<string, unknown>[]) {43 if (!one || !postName(one.name as string)) continue;44 out.push({45 name: String(one.name),46 seed: Number(one.seed ?? 0),47 at: String(one.at ?? ""),48 duration: Number(one.duration ?? 0),49 frames: Number(one.frames ?? 0),50 size: Number(one.size ?? 0),51 segments: Number(one.segments ?? 0),52 canvas: Number(one.canvas ?? 0),53 story: String(one.story ?? ""),54 });55 }56 return out.sort((a, b) => (a.at < b.at ? 1 : a.at > b.at ? -1 : a.name < b.name ? 1 : -1));57}