diff --git a/libraries/nestjs-libraries/src/chat/tools/integration.schedule.post.ts b/libraries/nestjs-libraries/src/chat/tools/integration.schedule.post.ts index 19433a7fae..fdc9df735b 100644 --- a/libraries/nestjs-libraries/src/chat/tools/integration.schedule.post.ts +++ b/libraries/nestjs-libraries/src/chat/tools/integration.schedule.post.ts @@ -16,6 +16,38 @@ import { const validUrlExtension = new ValidUrlExtension(); const validUrlPath = new ValidUrlPath(); +// Settings the agent tends to guess when the schema gives it no guidance — +// fill them explicitly so an omitted key never lands on a surprising value +// (e.g. TikTok UPLOAD sends the post to the user's app inbox instead of +// publishing it). +export const PROVIDER_SETTINGS_DEFAULTS: Record> = + { + tiktok: { content_posting_method: 'DIRECT_POST' }, + }; + +export const buildSettings = ( + providerIdentifier: string, + settings: { key: string; value: any }[], + base: AllProvidersSettings +): AllProvidersSettings => { + const merged = settings.reduce( + (acc: AllProvidersSettings, s: { key: string; value: any }) => ({ + ...acc, + [s.key]: s.value, + }), + base + ); + + const defaults = PROVIDER_SETTINGS_DEFAULTS[providerIdentifier] || {}; + for (const [key, value] of Object.entries(defaults)) { + if ((merged as any)[key] === undefined || (merged as any)[key] === '') { + (merged as any)[key] = value; + } + } + + return merged; +}; + // Same URL validation as MediaDto (valid.url.path) - each attachment must // point to an allowed upload domain and a supported file extension. const attachmentUrl = z @@ -147,11 +179,9 @@ If the tools return errors, you would need to rerun it with the right parameters // Same server-side validation as the dashboard / public API // (settings DTO + media checkValidity + empty / too-long content). - const settings = platform.settings.reduce( - (acc: AllProvidersSettings, s: { key: string; value: any }) => ({ - ...acc, - [s.key]: s.value, - }), + const settings = buildSettings( + integrations[platform.integrationId]?.providerIdentifier || '', + platform.settings, {} as AllProvidersSettings ); @@ -216,11 +246,9 @@ If the tools return errors, you would need to rerun it with the right parameters { integration, group: makeId(10), - settings: post.settings.reduce( - (acc: AllProvidersSettings, s: { key: string; value: any }) => ({ - ...acc, - [s.key]: s.value, - }), + settings: buildSettings( + integration.providerIdentifier, + post.settings, { __type: integration.providerIdentifier, } as AllProvidersSettings diff --git a/libraries/nestjs-libraries/src/dtos/posts/providers-settings/tiktok.dto.ts b/libraries/nestjs-libraries/src/dtos/posts/providers-settings/tiktok.dto.ts index 8417315f86..d36ccffe93 100644 --- a/libraries/nestjs-libraries/src/dtos/posts/providers-settings/tiktok.dto.ts +++ b/libraries/nestjs-libraries/src/dtos/posts/providers-settings/tiktok.dto.ts @@ -1,6 +1,7 @@ import { IsBoolean, ValidateIf, IsIn, IsString, MaxLength, IsOptional } from 'class-validator'; +import { JSONSchema } from 'class-validator-jsonschema'; export class TikTokDto { @ValidateIf((p) => p.title) @@ -44,5 +45,12 @@ export class TikTokDto { @IsIn(['DIRECT_POST', 'UPLOAD']) @IsString() + @JSONSchema({ + description: + 'Required. Use "DIRECT_POST" to actually publish the post to TikTok. ' + + '"UPLOAD" does NOT publish: it only sends the media to the user\'s TikTok app inbox, ' + + 'where they must manually finish and publish it within 24 hours or it is discarded. ' + + 'Only use "UPLOAD" when the user explicitly asks to review or edit the post inside the TikTok app before publishing.', + }) content_posting_method: 'DIRECT_POST' | 'UPLOAD'; } diff --git a/libraries/nestjs-libraries/src/integrations/social/tiktok.provider.ts b/libraries/nestjs-libraries/src/integrations/social/tiktok.provider.ts index 87be989289..89a2bbf259 100644 --- a/libraries/nestjs-libraries/src/integrations/social/tiktok.provider.ts +++ b/libraries/nestjs-libraries/src/integrations/social/tiktok.provider.ts @@ -19,7 +19,9 @@ import { Integration } from '@prisma/client'; import { Rules } from '@gitroom/nestjs-libraries/chat/rules.description.decorator'; @Rules( - 'TikTok can have one video or one picture or multiple pictures, it cannot be without an attachment' + 'TikTok can have one video or one picture or multiple pictures, it cannot be without an attachment. ' + + 'For the "content_posting_method" setting always use "DIRECT_POST" unless the user explicitly asks to review or edit the post inside the TikTok app before publishing. ' + + '"UPLOAD" does NOT publish the post: it only sends it to the user\'s TikTok app inbox, where they must manually complete it within 24 hours or it is discarded.' ) export class TiktokProvider extends SocialAbstract implements SocialProvider { identifier = 'tiktok';