Files
simstudioai--sim/apps/sim/tools/tiktok/get_user.ts
T
wehub-resource-sync d25d482dc2
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
Publish CLI Package / publish-npm (push) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:20:55 +08:00

174 lines
5.0 KiB
TypeScript

import { tiktokGetUserApiDataSchema } from '@/tools/tiktok/api-schemas'
import type { TikTokGetUserParams, TikTokGetUserResponse } from '@/tools/tiktok/types'
import { readTikTokApiResponse, TIKTOK_USER_FIELDS } from '@/tools/tiktok/utils'
import type { ToolConfig } from '@/tools/types'
function emptyUserOutput(): TikTokGetUserResponse['output'] {
return {
openId: '',
unionId: null,
displayName: '',
bioDescription: null,
profileDeepLink: null,
isVerified: null,
username: null,
followerCount: null,
followingCount: null,
likesCount: null,
videoCount: null,
}
}
export const tiktokGetUserTool: ToolConfig<TikTokGetUserParams, TikTokGetUserResponse> = {
id: 'tiktok_get_user',
name: 'TikTok Get User',
description:
'Get the authenticated TikTok user profile information including display name, avatar, bio, follower count, and video statistics.',
version: '1.0.0',
oauth: {
required: true,
provider: 'tiktok',
requiredScopes: ['user.info.basic', 'user.info.profile', 'user.info.stats'],
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'TikTok OAuth access token',
},
fields: {
type: 'string',
required: false,
visibility: 'user-or-llm',
default: TIKTOK_USER_FIELDS,
description:
'Comma-separated list of fields to return. Available: open_id, union_id, avatar_url, avatar_large_url, display_name, bio_description, profile_deep_link, is_verified, username, follower_count, following_count, likes_count, video_count. Include avatar_url and avatar_large_url to receive the avatarFile output.',
},
},
request: {
url: (params: TikTokGetUserParams) => {
const fields = params.fields || TIKTOK_USER_FIELDS
return `https://open.tiktokapis.com/v2/user/info/?fields=${encodeURIComponent(fields)}`
},
method: 'GET',
headers: (params: TikTokGetUserParams) => ({
Authorization: `Bearer ${params.accessToken}`,
}),
},
transformResponse: async (response: Response): Promise<TikTokGetUserResponse> => {
const { data, error } = await readTikTokApiResponse(response, tiktokGetUserApiDataSchema)
if (error) {
return {
success: false,
output: emptyUserOutput(),
error: error.message || 'Failed to fetch user info',
}
}
const user = data?.user
if (!user) {
return {
success: false,
output: emptyUserOutput(),
error: 'No user data returned',
}
}
const avatarSourceUrl = user.avatar_large_url ?? user.avatar_url
const avatarFileName = `${user.username || user.open_id || 'tiktok-user'}-avatar.jpg`
return {
success: true,
output: {
openId: user.open_id ?? '',
unionId: user.union_id ?? null,
displayName: user.display_name ?? '',
bioDescription: user.bio_description ?? null,
profileDeepLink: user.profile_deep_link ?? null,
isVerified: user.is_verified ?? null,
username: user.username ?? null,
followerCount: user.follower_count ?? null,
followingCount: user.following_count ?? null,
likesCount: user.likes_count ?? null,
videoCount: user.video_count ?? null,
...(avatarSourceUrl && {
avatarFile: {
name: avatarFileName,
mimeType: 'image/jpeg',
url: avatarSourceUrl,
},
}),
},
}
},
outputs: {
openId: {
type: 'string',
description: 'Unique TikTok user ID for this application',
},
unionId: {
type: 'string',
description: 'Unique TikTok user ID across all apps from the same developer',
optional: true,
},
displayName: {
type: 'string',
description: 'User display name',
},
bioDescription: {
type: 'string',
description: 'User bio description',
optional: true,
},
profileDeepLink: {
type: 'string',
description: 'Deep link to user TikTok profile',
optional: true,
},
isVerified: {
type: 'boolean',
description: 'Whether the account is verified',
optional: true,
},
username: {
type: 'string',
description: 'TikTok username',
optional: true,
},
followerCount: {
type: 'number',
description: 'Number of followers',
optional: true,
},
followingCount: {
type: 'number',
description: 'Number of accounts the user follows',
optional: true,
},
likesCount: {
type: 'number',
description: 'Total likes received across all videos',
optional: true,
},
videoCount: {
type: 'number',
description: 'Total number of public videos',
optional: true,
},
avatarFile: {
type: 'file',
description:
'Downloadable copy of the profile avatar image (largest available variant), stored as a workflow file so it can be chained into file-consuming blocks (e.g. attached to an email).',
optional: true,
},
},
}