mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-05-14 15:00:54 -05:00
80 lines
1.9 KiB
TypeScript
80 lines
1.9 KiB
TypeScript
import * as R from "remeda";
|
|
import { twitchFetch } from "./fetch";
|
|
import {
|
|
type RawVideo,
|
|
type UsersResponse,
|
|
usersSchema,
|
|
videosSchema,
|
|
} from "./schemas";
|
|
|
|
export async function getUsersByLogin(
|
|
logins: string[],
|
|
): Promise<UsersResponse["data"]> {
|
|
if (logins.length === 0) return [];
|
|
|
|
const results: UsersResponse["data"] = [];
|
|
|
|
for (const batch of R.chunk(logins, 100)) {
|
|
const params = batch.map((l) => `login=${encodeURIComponent(l)}`).join("&");
|
|
|
|
const res = await twitchFetch(
|
|
`https://api.twitch.tv/helix/users?${params}`,
|
|
);
|
|
|
|
const parsed = usersSchema.safeParse(await res.json());
|
|
if (!parsed.success) {
|
|
throw new Error(
|
|
`Twitch users schema validation failed: ${parsed.error.message}`,
|
|
);
|
|
}
|
|
|
|
results.push(...parsed.data.data);
|
|
}
|
|
|
|
return results;
|
|
}
|
|
|
|
export async function getArchiveVideos(userId: string): Promise<RawVideo[]> {
|
|
const results: RawVideo[] = [];
|
|
let cursor: string | undefined;
|
|
|
|
while (true) {
|
|
const url = new URL("https://api.twitch.tv/helix/videos");
|
|
url.searchParams.set("user_id", userId);
|
|
url.searchParams.set("type", "archive");
|
|
url.searchParams.set("first", "100");
|
|
if (cursor) {
|
|
url.searchParams.set("after", cursor);
|
|
}
|
|
|
|
const res = await twitchFetch(url.toString());
|
|
|
|
const parsed = videosSchema.safeParse(await res.json());
|
|
if (!parsed.success) {
|
|
throw new Error(
|
|
`Twitch videos schema validation failed: ${parsed.error.message}`,
|
|
);
|
|
}
|
|
|
|
results.push(...parsed.data.data);
|
|
|
|
if (!parsed.data.pagination.cursor) break;
|
|
cursor = parsed.data.pagination.cursor;
|
|
}
|
|
|
|
return results;
|
|
}
|
|
|
|
const DURATION_REGEX = /(?:(\d+)h)?(?:(\d+)m)?(?:(\d+)s)?/;
|
|
|
|
export function parseTwitchDuration(duration: string): number {
|
|
const match = DURATION_REGEX.exec(duration);
|
|
if (!match) return 0;
|
|
|
|
const hours = Number(match[1] ?? 0);
|
|
const minutes = Number(match[2] ?? 0);
|
|
const seconds = Number(match[3] ?? 0);
|
|
|
|
return hours * 3600 + minutes * 60 + seconds;
|
|
}
|