feat: implement TikTok OAuth flow and integrate profile data into home page

This commit is contained in:
2026-06-30 20:41:01 +07:00 Unverified
parent de3ee40fa4
commit 2e3983e38c
8 changed files with 494 additions and 31 deletions
+32 -10
View File
@@ -1,7 +1,9 @@
import { getYoutubeSubscriberCount } from "./youtube";
import { getRobloxFollowerCount } from "./roblox";
import { getDiscordMemberCount } from "./discord";
import { getTiktokFollowerCount } from "./tiktok";
import { getTiktokProfile, type TiktokProfile } from "./tiktok";
export type { TiktokProfile };
export interface FollowerCounts {
youtube: number | null;
@@ -16,38 +18,58 @@ export interface FollowerInfo {
}
const CACHE_KEY = "erika:follower_counts";
const CACHE_KEY_TIKTOK = "erika:tiktok_profile";
const CACHE_TTL = 3600; // 1 hour
export async function getFollowerCounts(): Promise<FollowerCounts> {
export interface FetchResult {
counts: FollowerCounts;
tiktokProfile: TiktokProfile;
}
export async function getFollowerCounts(): Promise<FetchResult> {
try {
const { getRedisClient } = await import("@/lib/redis");
const redis = await getRedisClient();
const cached = await redis.get(CACHE_KEY);
if (cached) {
return JSON.parse(cached);
const [cachedCounts, cachedProfile] = await Promise.all([
redis.get(CACHE_KEY),
redis.get(CACHE_KEY_TIKTOK),
]);
if (cachedCounts && cachedProfile) {
return {
counts: JSON.parse(cachedCounts),
tiktokProfile: JSON.parse(cachedProfile),
};
}
} catch {
// Redis unavailable, fall through to fetch
}
const [youtube, roblox, discord, tiktok] = await Promise.all([
const [youtube, roblox, discord, tiktokProfileResult] = await Promise.all([
getYoutubeSubscriberCount(),
getRobloxFollowerCount(),
getDiscordMemberCount(),
getTiktokFollowerCount(),
getTiktokProfile(),
]);
const counts: FollowerCounts = { youtube, roblox, discord, tiktok };
const counts: FollowerCounts = {
youtube,
roblox,
discord,
tiktok: tiktokProfileResult.followerCount,
};
try {
const { getRedisClient } = await import("@/lib/redis");
const redis = await getRedisClient();
await redis.set(CACHE_KEY, JSON.stringify(counts), { ex: CACHE_TTL });
await Promise.all([
redis.set(CACHE_KEY, JSON.stringify(counts), { ex: CACHE_TTL }),
redis.set(CACHE_KEY_TIKTOK, JSON.stringify(tiktokProfileResult), { ex: CACHE_TTL }),
]);
} catch {
// Redis unavailable, skip caching
}
return counts;
return { counts, tiktokProfile: tiktokProfileResult };
}
const followerLabels: Record<keyof FollowerCounts, string> = {