fix: TikTok API endpoints and privacy level handling

- Fix publish endpoint: /post/video/init/ → /post/publish/video/init/
- Replace broken /video/list/ with /post/publish/creator_info/query/
- Auto-select valid privacy level from creator options (sandbox fix)
- Update tools, manifest, REST routes for creator_info
This commit is contained in:
Garfield
2026-05-12 00:53:55 -04:00
parent 30232e3ef8
commit 7796de12bf
4 changed files with 60 additions and 68 deletions

View File

@@ -82,43 +82,34 @@ export async function getUserProfile(
};
}
export async function getUserVideos(
args: { max_count?: number; account?: string },
export async function getCreatorInfo(
args: { account?: string },
customer?: Customer
): Promise<Array<{
id: string;
title?: string;
video_description?: string;
duration: number;
cover_image_url?: string;
share_url?: string;
view_count: number;
like_count: number;
comment_count: number;
share_count: number;
create_time: number;
}>> {
): Promise<{
creator_username: string;
creator_nickname: string;
creator_avatar_url?: string;
privacy_level_options: string[];
max_video_post_duration_sec: number;
comment_disabled: boolean;
duet_disabled: boolean;
stitch_disabled: boolean;
}> {
const accessToken = await resolveToken(args, customer);
const fields = 'id,title,video_description,duration,cover_image_url,share_url,view_count,like_count,comment_count,share_count,create_time';
const data = await tiktokRequest('/video/list/', accessToken, 'POST', {
max_count: Math.min(args.max_count ?? 10, 20),
fields: fields.split(','),
});
const data = await tiktokRequest('/post/publish/creator_info/query/', accessToken, 'POST', {});
const c = data;
return (data.videos ?? []).map((v: Record<string, unknown>) => ({
id: String(v.id ?? ''),
title: v.title as string | undefined,
video_description: v.video_description as string | undefined,
duration: Number(v.duration ?? 0),
cover_image_url: v.cover_image_url as string | undefined,
share_url: v.share_url as string | undefined,
view_count: Number(v.view_count ?? 0),
like_count: Number(v.like_count ?? 0),
comment_count: Number(v.comment_count ?? 0),
share_count: Number(v.share_count ?? 0),
create_time: Number(v.create_time ?? 0),
}));
return {
creator_username: c.creator_username ?? '',
creator_nickname: c.creator_nickname ?? '',
creator_avatar_url: c.creator_avatar_url,
privacy_level_options: c.privacy_level_options ?? [],
max_video_post_duration_sec: c.max_video_post_duration_sec ?? 0,
comment_disabled: c.comment_disabled ?? false,
duet_disabled: c.duet_disabled ?? false,
stitch_disabled: c.stitch_disabled ?? false,
};
}
export async function createVideo(
@@ -129,15 +120,21 @@ export async function createVideo(
const auditArgs = { title: args.title };
const accessToken = await resolveToken(args, customer);
// Step 1: initialise upload
const init = await tiktokRequest('/post/video/init/', accessToken, 'POST', {
// Step 1: query creator info to get valid privacy levels (sandbox may not support PUBLIC_TO_EVERYONE)
const creatorInfo = await getCreatorInfo(args, customer);
const privacyLevel = creatorInfo.privacy_level_options.includes('PUBLIC_TO_EVERYONE')
? 'PUBLIC_TO_EVERYONE'
: creatorInfo.privacy_level_options[0] ?? 'SELF_ONLY';
// Step 2: initialise upload
const init = await tiktokRequest('/post/publish/video/init/', accessToken, 'POST', {
post_info: {
title: args.title ?? '',
description: args.description ?? '',
disable_duet: false,
disable_comment: false,
disable_stitch: false,
privacy_level: 'PUBLIC_TO_EVERYONE',
privacy_level: privacyLevel,
},
source_info: {
source: 'PULL_FROM_URL',