import { BasePlatform, type ActorConfig } from './base.js';
import type { UnifiedPost } from '../types.js';
export class TikTokPlatform extends BasePlatform {
readonly config: ActorConfig = {
actorId: 'clockworks/tiktok-scraper',
platform: 'tiktok',
defaultMaxResults: 30,
};
buildInput(params: Record<string, unknown>): Record<string, unknown> {
const input: Record<string, unknown> = {
resultsPerPage: params.max_results ?? this.config.defaultMaxResults,
};
if (params.profiles) {
input.profiles = params.profiles;
}
if (params.hashtags) {
input.hashtags = params.hashtags;
}
if (params.search) {
input.searchQueries = [params.search as string];
}
return input;
}
normalize(raw: Record<string, unknown>[]): UnifiedPost[] {
return raw.map(item => {
const text = this.safeString(item.text ?? item.desc ?? item.description ?? '');
const authorInfo = item.authorMeta as Record<string, unknown> | undefined;
return {
id: this.makeId(this.safeString(item.id ?? item.videoId ?? '')),
platform: 'tiktok' as const,
author: {
username: this.safeString(authorInfo?.name ?? item.author ?? ''),
displayName: this.safeString(authorInfo?.nickName ?? authorInfo?.nickname ?? ''),
followers: this.safeNumber(authorInfo?.fans ?? authorInfo?.followers),
verified: Boolean(authorInfo?.verified),
},
content: text,
url: this.safeString(item.webVideoUrl ?? item.url ?? ''),
timestamp: this.safeDate(item.createTimeISO ?? new Date((this.safeNumber(item.createTime)) * 1000)),
engagement: {
likes: this.safeNumber(item.diggCount ?? item.likes ?? (item.stats as any)?.diggCount),
comments: this.safeNumber(item.commentCount ?? item.comments ?? (item.stats as any)?.commentCount),
shares: this.safeNumber(item.shareCount ?? item.shares ?? (item.stats as any)?.shareCount),
views: this.safeNumber(item.playCount ?? item.views ?? (item.stats as any)?.playCount),
},
media: { type: 'video', urls: [this.safeString(item.videoUrl ?? item.url ?? '')].filter(Boolean) },
hashtags: this.extractHashtags(text),
metadata: {
musicName: (item.musicMeta as any)?.musicName,
duration: item.duration ?? item.videoLength,
isAd: item.isAd,
},
};
});
}
}