返回 AiToEarn
platforms.interface.ts
根目录 / project / aitoearn-backend / apps / aitoearn-server / src / core / channels / platforms / platforms.interface.ts
1 import type { AccountType, Locale, WorkStatus } from '@yikart/common'
2 import type { PublishRecordLinkStatus } from '@yikart/mongodb'
3 import type { Request, Response } from 'express'
4 import type { z } from 'zod'
5 import type { PlatformErrorCategory } from './platforms.exception'
6 import type { PublishMediaAdaptationOption } from './publish-media-adaptation.schema'
7 import type { PublishValidationIssue } from './publish.schema'
8
9 export enum CompletionStrategy {
10 Sync = 'sync',
11 Polling = 'polling',
12 MediaFinalize = 'media_finalize',
13 Webhook = 'webhook',
14 UserHandoff = 'user_handoff',
15 }
16
17 export enum AuthType {
18 OAuth2 = 'oauth2',
19 Browser = 'browser',
20 Plugin = 'plugin',
21 QrCode = 'qrcode',
22 }
23
24 export enum AuthCallbackResponseType {
25 Page = 'page',
26 Json = 'json',
27 }
28
29 export enum EditorType {
30 None = 'none',
31 Text = 'text',
32 Html = 'html',
33 }
34
35 export enum PublishContentMode {
36 // TODO: 等前端重构
37 // Text = 'text',
38 // ImageText = 'image_text',
39 Text = 'article2',
40 ImageText = 'article',
41 Video = 'video',
42 }
43
44 // ── Auth ──
45
46 export interface GenerateAuthUrlInput {
47 userId?: string
48 state: string
49 deviceType?: 'mobile' | 'desktop' | 'tablet' | 'unknown'
50 extras?: Record<string, unknown>
51 }
52
53 export interface GenerateAuthUrlResult {
54 url: string
55 state: string
56 redirectUri: string
57 extras?: Record<string, unknown>
58 }
59
60 export interface AuthCallbackInput {
61 callbackUrl?: string
62 query?: AuthCallbackQuery
63 body?: AuthCallbackBody
64 session: AuthCallbackSession
65 }
66
67 export interface AuthCallbackQuery {
68 code?: string
69 state?: string
70 error?: string
71 error_description?: string
72 token?: string
73 nickname?: string
74 avatar?: string
75 }
76
77 export interface AuthCallbackBody extends AuthCallbackQuery {
78 tickets?: Record<string, string>
79 }
80
81 export interface AuthCallbackSession {
82 id: string
83 authExtras?: Record<string, unknown>
84 }
85
86 export interface CredentialResult {
87 accessToken?: string
88 refreshToken?: string
89 expiresAt?: Date
90 scope?: string
91 tokenType?: string
92 platformUid?: string
93 profile?: PlatformAccountProfile
94 selectableAccounts?: PlatformSelectableAccount[]
95 callbackResponseType?: AuthCallbackResponseType
96 raw?: unknown
97 }
98
99 export interface CredentialContext {
100 accessToken: string
101 refreshToken?: string
102 expiresAt?: Date
103 scope?: string
104 platformUid?: string
105 account?: string
106 }
107
108 export interface PlatformAccountProfile {
109 platformUid: string
110 account?: string
111 displayName: string
112 avatarUrl?: string
113 email?: string
114 fansCount?: number
115 followingCount?: number
116 raw?: unknown
117 }
118
119 export interface PlatformSelectableAccount {
120 platform: AccountType
121 platformUid: string
122 account?: string
123 displayName: string
124 avatarUrl?: string
125 parentPlatformUid?: string
126 fansCount?: number
127 followingCount?: number
128 credential?: PlatformAccountCredentialSnapshot
129 profile?: Record<string, unknown>
130 raw?: unknown
131 }
132
133 export interface PlatformAccountCredentialSnapshot {
134 accessToken: string
135 refreshToken?: string
136 expiresAt?: Date
137 scope?: string
138 }
139
140 export interface RefreshCredentialInput {
141 accessToken: string
142 refreshToken?: string
143 }
144
145 export interface RevokeCredentialInput {
146 accessToken: string
147 refreshToken?: string
148 platformUid?: string
149 }
150
151 export interface RefreshAccountAccessInput {
152 rootAccessToken: string
153 rootRefreshToken?: string
154 platformUid: string
155 }
156
157 export interface AuthProvider {
158 generateAuthUrl: (input: GenerateAuthUrlInput) => Promise<GenerateAuthUrlResult>
159 exchangeCode: (input: AuthCallbackInput) => Promise<CredentialResult>
160 refresh: (input: RefreshCredentialInput) => Promise<CredentialResult>
161 revoke?: (input: RevokeCredentialInput) => Promise<void>
162 getProfile: (input: CredentialContext) => Promise<PlatformAccountProfile>
163 listSelectableAccounts?: (input: CredentialContext) => Promise<PlatformSelectableAccount[]>
164 refreshAccountAccess?: (input: RefreshAccountAccessInput) => Promise<PlatformSelectableAccount>
165 }
166
167 // ── Publish ──
168
169 export interface TopicCapability {
170 supported: boolean
171 nativeField?: boolean
172 maxCount?: number
173 maxTotalLength?: number
174 }
175
176 export interface PlatformMediaRules {
177 imageFormats?: string[]
178 videoFormats?: string[]
179 maxImageSize?: number
180 maxVideoSize?: number
181 minVideoDuration?: number
182 maxVideoDuration?: number
183 minImageWidth?: number
184 minImageHeight?: number
185 maxImageWidth?: number
186 maxImageHeight?: number
187 aspectRatio?: { min?: number, max?: number }
188 }
189
190 export interface PublishMediaInput {
191 url: string
192 metadata?: PublishMediaMetadata
193 options?: PublishMediaOptions
194 }
195
196 export interface PublishCoverInput {
197 url: string
198 metadata?: PublishMediaMetadata
199 options?: PublishMediaOptions
200 }
201
202 export interface PublishContentInput {
203 title?: string
204 body?: string
205 media: PublishMediaInput[]
206 cover?: PublishCoverInput
207 }
208
209 export interface PublishValidateInput<TOption = Record<string, unknown>> {
210 platform: AccountType
211 accountId: string
212 content: PublishContentInput
213 option?: TOption
214 }
215
216 export interface PublishValidationResult {
217 valid: boolean
218 issues?: PublishValidationIssue[]
219 }
220
221 export interface PublishNormalizeInput<TOption = Record<string, unknown>> {
222 platform: AccountType
223 accountId: string
224 content: PublishContentInput
225 option?: TOption
226 }
227
228 export interface NormalizedPublishTask<TOption = Record<string, unknown>> {
229 content: PublishContentInput
230 option?: TOption
231 mediaJobs?: PublishMediaJob[]
232 }
233
234 export interface PublishMediaJob {
235 mediaId: string
236 type: PublishMediaType
237 url: string
238 metadata?: PublishMediaMetadata
239 }
240
241 export enum PublishMediaType {
242 Image = 'image',
243 Video = 'video',
244 }
245
246 export interface PublishMediaMetadata {
247 type?: PublishMediaType
248 durationSec?: number
249 width?: number
250 height?: number
251 codec?: string
252 format?: string
253 sizeBytes?: number
254 }
255
256 export interface PublishMediaOptions {
257 adaptation?: PublishMediaAdaptationOption
258 }
259
260 export interface PublishPublishInput<TOption = Record<string, unknown>> {
261 taskId: string
262 platform: AccountType
263 accountId: string
264 content: PublishContentInput
265 option?: TOption
266 publishAt?: Date
267 credential: CredentialContext
268 }
269
270 export interface PublishProviderResult<TDataOption = Record<string, unknown>> {
271 status: number
272 platformWorkId?: string
273 permalink?: string
274 shortLink?: string
275 errorMessage?: string
276 originalWorkLink?: string
277 workStatus?: WorkStatus
278 linkStatus?: PublishRecordLinkStatus
279 linkMeta?: Record<string, unknown>
280 userAction?: PublishUserAction
281 mediaJobs?: PublishMediaJob[]
282 dataOption?: TDataOption
283 }
284
285 export interface PublishUserAction {
286 schema?: string
287 shortLink?: string
288 expiresAt: Date
289 data?: Record<string, unknown>
290 }
291
292 export interface PublishFinalizeInput<TDataOption = Record<string, unknown>, TOption = Record<string, unknown>> {
293 taskId: string
294 platform: AccountType
295 platformWorkId: string
296 mediaJobs: PublishMediaJob[]
297 option?: TOption
298 dataOption?: TDataOption
299 credential: CredentialContext
300 }
301
302 export interface PublishVerifyInput<TDataOption = Record<string, unknown>, TOption = Record<string, unknown>> {
303 taskId: string
304 platform: AccountType
305 platformWorkId: string
306 option?: TOption
307 dataOption?: TDataOption
308 credential: CredentialContext
309 }
310
311 export interface PublishVerifyResult {
312 published: boolean
313 permalink?: string
314 platformWorkId?: string
315 linkStatus?: PublishRecordLinkStatus
316 linkMeta?: Record<string, unknown>
317 }
318
319 export interface PublishCancelInput {
320 taskId: string
321 platform: AccountType
322 platformWorkId: string
323 credential: CredentialContext
324 }
325
326 export interface PublishCancelResult {
327 canceled: boolean
328 }
329
330 export interface PublishUpdateInput<TOption = Record<string, unknown>> {
331 taskId: string
332 platform: AccountType
333 platformWorkId: string
334 content: PublishContentInput
335 option?: TOption
336 credential: CredentialContext
337 }
338
339 export interface PublishProvider<TOption = Record<string, unknown>, TDataOption = Record<string, unknown>> {
340 readonly platform: AccountType
341
342 validate: (input: PublishValidateInput<TOption>) => Promise<PublishValidationResult>
343 normalize: (input: PublishNormalizeInput<TOption>) => Promise<NormalizedPublishTask<TOption>>
344 publish: (input: PublishPublishInput<TOption>) => Promise<PublishProviderResult<TDataOption>>
345 resolveMediaRules?: (input: PublishValidateInput<TOption>) => PlatformMediaRules
346 finalize?: (input: PublishFinalizeInput<TDataOption, TOption>) => Promise<PublishProviderResult<TDataOption>>
347 verify?: (input: PublishVerifyInput<TDataOption, TOption>) => Promise<PublishVerifyResult>
348 cancel?: (input: PublishCancelInput) => Promise<PublishCancelResult>
349 update?: (input: PublishUpdateInput<TOption>) => Promise<PublishProviderResult<TDataOption>>
350 }
351
352 export enum PublishOptionValueType {
353 List = 'list',
354 Tree = 'tree',
355 }
356
357 export interface PublishOptionSource {
358 field: string
359 label: string
360 description?: string
361 valueType: PublishOptionValueType
362 requiresAccount: boolean
363 filterSchema?: z.ZodTypeAny
364 createSchema?: z.ZodTypeAny
365 }
366
367 export type PublishOptionFilterValue = string | number | boolean | Date | null | undefined
368 export type PublishOptionFilters = Record<string, PublishOptionFilterValue | PublishOptionFilterValue[]>
369 export type PublishOptionJsonSchemaView = z.core.JSONSchema.BaseSchema
370
371 export interface PublishOptionValuesInput {
372 userId: string
373 accountId: string
374 field: string
375 filters?: Record<string, unknown>
376 credential: CredentialContext
377 }
378
379 export interface PublishOptionValueItem {
380 value: string
381 label: string
382 description?: string
383 disabled?: boolean
384 children?: PublishOptionValueItem[]
385 extra?: Record<string, unknown>
386 }
387
388 export interface PublishOptionValuesResult {
389 field: string
390 valueType: PublishOptionValueType
391 items: PublishOptionValueItem[]
392 }
393
394 export interface PublishOptionCreateInput {
395 userId: string
396 accountId: string
397 field: string
398 data?: Record<string, unknown>
399 credential: CredentialContext
400 }
401
402 export interface PublishOptionCreateResult {
403 field: string
404 valueType: PublishOptionValueType
405 item: PublishOptionValueItem
406 }
407
408 export interface PublishOptionSourceProvider {
409 listSources: () => PublishOptionSource[]
410 getValues: (input: PublishOptionValuesInput) => Promise<PublishOptionValuesResult>
411 createValue?: (input: PublishOptionCreateInput) => Promise<PublishOptionCreateResult>
412 }
413
414 // ── Analytics ──
415
416 export interface ChannelSnapshotTime {
417 snapshotAt: Date
418 fetchedAt?: Date
419 periodStartAt?: Date
420 periodEndAt?: Date
421 }
422
423 export interface ChannelAccountProfileSnapshot {
424 displayName?: string
425 username?: string
426 avatarUrl?: string
427 accountType?: string
428 }
429
430 export interface ChannelAccountMetricsSnapshot {
431 fansCount?: number
432 followingCount?: number
433 workCount?: number
434 readCount?: number
435 viewCount?: number
436 impressionCount?: number
437 reachCount?: number
438 likeCount?: number
439 collectCount?: number
440 forwardCount?: number
441 commentCount?: number
442 clickCount?: number
443 engagementCount?: number
444 }
445
446 export interface ChannelWorkSnapshot {
447 id: string
448 url?: string
449 title?: string
450 description?: string
451 mediaType?: string
452 coverUrl?: string
453 publishedAt?: Date
454 status?: string
455 author?: string
456 }
457
458 export interface ChannelWorkMetricsSnapshot {
459 viewCount?: number
460 playCount?: number
461 impressionCount?: number
462 reachCount?: number
463 likeCount?: number
464 collectCount?: number
465 commentCount?: number
466 shareCount?: number
467 saveCount?: number
468 clickCount?: number
469 engagementCount?: number
470 watchTimeSeconds?: number
471 }
472
473 export interface ChannelAccountDataSnapshotPayload extends ChannelSnapshotTime {
474 platformUid?: string
475 profile?: ChannelAccountProfileSnapshot
476 metrics?: ChannelAccountMetricsSnapshot
477 extra?: Record<string, unknown>
478 rawResponse?: unknown
479 }
480
481 export interface ChannelWorkDataSnapshotPayload extends ChannelSnapshotTime {
482 platformWorkId?: string
483 work: ChannelWorkSnapshot
484 metrics?: ChannelWorkMetricsSnapshot
485 extra?: Record<string, unknown>
486 rawResponse?: unknown
487 }
488
489 export interface ChannelAccountAnalyticsResult {
490 snapshots: ChannelAccountDataSnapshotPayload[]
491 profile?: ChannelAccountProfileSnapshot
492 metrics?: ChannelAccountMetricsSnapshot
493 extra?: Record<string, unknown>
494 rawResponse?: unknown
495 }
496
497 export interface ChannelWorkAnalyticsResult {
498 snapshots: ChannelWorkDataSnapshotPayload[]
499 work?: ChannelWorkSnapshot
500 metrics?: ChannelWorkMetricsSnapshot
501 extra?: Record<string, unknown>
502 rawResponse?: unknown
503 }
504
505 export interface ChannelWorkDataResult<TExtra = Record<string, unknown>> {
506 snapshots: ChannelWorkDataSnapshotPayload[]
507 work?: ChannelWorkSnapshot
508 metrics?: ChannelWorkMetricsSnapshot
509 extra?: TExtra
510 rawResponse?: unknown
511 }
512
513 export enum ChannelPaginationMode {
514 Cursor = 'cursor',
515 Page = 'page',
516 None = 'none',
517 }
518
519 export enum ChannelPaginationDirection {
520 Next = 'next',
521 Previous = 'previous',
522 }
523
524 export interface ChannelPaginationInput {
525 cursor?: string
526 limit?: number
527 direction?: ChannelPaginationDirection
528 page?: number
529 pageSize?: number
530 }
531
532 export interface ChannelCursorPaginationResult {
533 mode: ChannelPaginationMode.Cursor
534 nextCursor?: string
535 previousCursor?: string
536 hasNext: boolean
537 hasPrevious: boolean
538 limit: number
539 }
540
541 export interface ChannelPagePaginationResult {
542 mode: ChannelPaginationMode.Page
543 page: number
544 pageSize: number
545 total?: number
546 hasNext: boolean
547 hasPrevious: boolean
548 }
549
550 export interface ChannelNonePaginationResult {
551 mode: ChannelPaginationMode.None
552 }
553
554 export type ChannelPaginationResult
555 = | ChannelCursorPaginationResult
556 | ChannelPagePaginationResult
557 | ChannelNonePaginationResult
558
559 export interface ChannelCursorPaginationMetadata {
560 mode: ChannelPaginationMode.Cursor
561 defaultLimit: number
562 maxLimit: number
563 supportsPrevious: boolean
564 }
565
566 export interface ChannelPagePaginationMetadata {
567 mode: ChannelPaginationMode.Page
568 defaultPageSize: number
569 maxPageSize: number
570 supportsTotal: boolean
571 }
572
573 export interface ChannelNonePaginationMetadata {
574 mode: ChannelPaginationMode.None
575 }
576
577 export type ChannelPaginationMetadata
578 = | ChannelCursorPaginationMetadata
579 | ChannelPagePaginationMetadata
580 | ChannelNonePaginationMetadata
581
582 export interface ChannelWorkListItem {
583 platformWorkId: string
584 contentMode: PublishContentMode
585 title?: string
586 description?: string
587 url?: string
588 coverUrl?: string
589 publishedAt?: Date
590 authorName?: string
591 authorPlatformUid?: string
592 status?: string
593 metrics?: ChannelWorkMetricsSnapshot
594 }
595
596 export interface ChannelWorkListResult {
597 items: ChannelWorkListItem[]
598 pagination: ChannelPaginationResult
599 }
600
601 export interface AnalyticsAccountInput {
602 accountId: string
603 platform: AccountType
604 credential: CredentialContext
605 since?: Date
606 until?: Date
607 }
608
609 export interface AnalyticsWorkInput {
610 accountId: string
611 platformWorkId: string
612 platform: AccountType
613 credential: CredentialContext
614 since?: Date
615 until?: Date
616 }
617
618 export interface AnalyticsProvider {
619 fetchAccountAnalytics: (input: AnalyticsAccountInput) => Promise<ChannelAccountAnalyticsResult>
620 fetchWorkAnalytics?: (input: AnalyticsWorkInput) => Promise<ChannelWorkAnalyticsResult>
621 }
622
623 // ── Engagement ──
624
625 export interface EngagementCommentInput {
626 accountId: string
627 platformWorkId: string
628 platform: AccountType
629 credential: CredentialContext
630 content: string
631 replyToId?: string
632 }
633
634 export interface EngagementLikeInput {
635 accountId: string
636 platformWorkId: string
637 platform: AccountType
638 credential: CredentialContext
639 }
640
641 export interface EngagementQuoteInput extends EngagementLikeInput {
642 content: string
643 }
644
645 export interface EngagementCommentActionInput {
646 accountId: string
647 commentId: string
648 platform: AccountType
649 credential: CredentialContext
650 }
651
652 export interface EngagementAccountActionInput {
653 accountId: string
654 targetPlatformUid: string
655 platform: AccountType
656 credential: CredentialContext
657 }
658
659 export enum ChannelEngagementActionType {
660 Comment = 'comment',
661 Reply = 'reply',
662 DeleteComment = 'delete_comment',
663 Like = 'like',
664 Unlike = 'unlike',
665 Repost = 'repost',
666 UndoRepost = 'undo_repost',
667 Quote = 'quote',
668 Bookmark = 'bookmark',
669 RemoveBookmark = 'remove_bookmark',
670 HideReply = 'hide_reply',
671 UnhideReply = 'unhide_reply',
672 Follow = 'follow',
673 Unfollow = 'unfollow',
674 }
675
676 export enum ChannelEngagementFunctionName {
677 DeleteComment = 'delete_comment',
678 Like = 'like',
679 Unlike = 'unlike',
680 Repost = 'repost',
681 UndoRepost = 'undo_repost',
682 Quote = 'quote',
683 Bookmark = 'bookmark',
684 RemoveBookmark = 'remove_bookmark',
685 HideReply = 'hide_reply',
686 UnhideReply = 'unhide_reply',
687 Follow = 'follow',
688 Unfollow = 'unfollow',
689 }
690
691 export enum ChannelEngagementTargetType {
692 Work = 'work',
693 Comment = 'comment',
694 Account = 'account',
695 }
696
697 export interface ChannelComment {
698 platformCommentId: string
699 platformWorkId?: string
700 parentCommentId?: string
701 authorName?: string
702 authorPlatformUid?: string
703 content: string
704 createdAt?: Date
705 likeCount?: number
706 replyCount?: number
707 }
708
709 export interface ChannelCommentListResult {
710 items: ChannelComment[]
711 pagination: ChannelPaginationResult
712 }
713
714 export interface ChannelEngagementActionResult {
715 actionType: ChannelEngagementActionType
716 targetType: ChannelEngagementTargetType
717 targetId: string
718 platformActionId?: string
719 success: boolean
720 createdAt?: Date
721 }
722
723 export interface EngagementProvider {
724 readonly commentPagination: ChannelPaginationMetadata
725 listComments?: (input: EngagementListInput) => Promise<ChannelCommentListResult>
726 createComment?: (input: EngagementCommentInput) => Promise<ChannelEngagementActionResult>
727 deleteComment?: (input: EngagementDeleteInput) => Promise<ChannelEngagementActionResult>
728 like?: (input: EngagementLikeInput) => Promise<ChannelEngagementActionResult>
729 unlike?: (input: EngagementLikeInput) => Promise<ChannelEngagementActionResult>
730 repost?: (input: EngagementLikeInput) => Promise<ChannelEngagementActionResult>
731 undoRepost?: (input: EngagementLikeInput) => Promise<ChannelEngagementActionResult>
732 quote?: (input: EngagementQuoteInput) => Promise<ChannelEngagementActionResult>
733 bookmark?: (input: EngagementLikeInput) => Promise<ChannelEngagementActionResult>
734 removeBookmark?: (input: EngagementLikeInput) => Promise<ChannelEngagementActionResult>
735 hideReply?: (input: EngagementCommentActionInput) => Promise<ChannelEngagementActionResult>
736 unhideReply?: (input: EngagementCommentActionInput) => Promise<ChannelEngagementActionResult>
737 follow?: (input: EngagementAccountActionInput) => Promise<ChannelEngagementActionResult>
738 unfollow?: (input: EngagementAccountActionInput) => Promise<ChannelEngagementActionResult>
739 }
740
741 export interface EngagementListInput {
742 accountId: string
743 platformWorkId: string
744 platform: AccountType
745 credential: CredentialContext
746 pagination: ChannelPaginationInput
747 }
748
749 export interface EngagementDeleteInput {
750 accountId: string
751 commentId: string
752 platform: AccountType
753 credential: CredentialContext
754 }
755
756 // ── Browse ──
757
758 export interface BrowseSearchInput {
759 accountId: string
760 platform: AccountType
761 credential: CredentialContext
762 query: string
763 cursor?: string
764 limit?: number
765 }
766
767 export interface BrowseDetailInput {
768 accountId: string
769 platformWorkId: string
770 platform: AccountType
771 credential: CredentialContext
772 }
773
774 export interface BrowseProvider {
775 search?: (input: BrowseSearchInput) => Promise<unknown>
776 getDetail?: (input: BrowseDetailInput) => Promise<unknown>
777 }
778
779 // ── Work ──
780
781 export interface WorkLinkInfoInput {
782 accountId?: string
783 platform: AccountType
784 credential?: CredentialContext
785 link: string
786 dataId?: string
787 }
788
789 export interface WorkDetailInput {
790 accountId: string
791 platformWorkId: string
792 platform: AccountType
793 credential: CredentialContext
794 }
795
796 export interface WorkOwnershipInput {
797 accountId: string
798 platformWorkId: string
799 platform: AccountType
800 credential: CredentialContext
801 }
802
803 export interface WorkListInput {
804 accountId: string
805 platform: AccountType
806 credential: CredentialContext
807 pagination: ChannelPaginationInput
808 }
809
810 export interface WorkProvider {
811 readonly listWorksPagination?: ChannelPaginationMetadata
812 requiresCredentialForLinkInfo?: boolean
813 listWorks?: (input: WorkListInput) => Promise<ChannelWorkListResult>
814 getLinkInfo?: (input: WorkLinkInfoInput) => Promise<ChannelWorkDataResult>
815 getDetail?: (input: WorkDetailInput) => Promise<ChannelWorkDataResult>
816 verifyOwnership?: (input: WorkOwnershipInput) => Promise<boolean>
817 }
818
819 // ── Webhook ──
820
821 export interface PlatformWebhookContext {
822 platform: AccountType
823 }
824
825 export interface PlatformWebhookHandler {
826 handle: (request: Request, response: Response, context: PlatformWebhookContext) => Promise<void>
827 }
828
829 export interface RawBodyRequest extends Request {
830 rawBody?: Buffer
831 }
832
833 // ── Metadata ──
834
835 export interface PlatformContentLimits {
836 modes: PublishContentMode[]
837 maxTitleLength?: number
838 maxBodyLength?: number
839 maxTotalTextLength?: number
840 maxMediaCount?: number
841 maxImages?: number
842 maxVideos?: number
843 }
844
845 export interface PlatformPublishPolicy {
846 completionStrategy: CompletionStrategy
847 scheduleByPlatform: boolean
848 updateSupported: boolean
849 }
850
851 export interface PlatformEmptyAccountHint {
852 title: Record<Locale, string>
853 description: Record<Locale, string>
854 action?: {
855 label: Record<Locale, string>
856 url: string
857 }
858 }
859
860 export enum ChannelWorkAnalyticsDataSource {
861 Official = 'official',
862 PostInsightCrawler = 'post_insight_crawler',
863 }
864
865 export interface PlatformWorkAnalyticsMetadata {
866 dataSources: ChannelWorkAnalyticsDataSource[]
867 }
868
869 export interface PlatformAnalyticsMetadata {
870 work?: PlatformWorkAnalyticsMetadata
871 }
872
873 export interface PlatformMetadata {
874 platform: AccountType
875 displayName: Record<Locale, string>
876 logoUrl: string
877 authType: AuthType
878 authInstructions?: Record<Locale, string>
879 emptyAccountHint?: PlatformEmptyAccountHint
880 editor: EditorType
881 contentLimits: PlatformContentLimits
882 mediaRules: PlatformMediaRules
883 topic: TopicCapability
884 publishPolicy?: PlatformPublishPolicy
885 optionSchema: z.ZodTypeAny
886 defaultOption?: Record<string, unknown>
887 analytics?: PlatformAnalyticsMetadata
888 }
889
890 export interface PlatformStaticMetadata extends Omit<PlatformMetadata, 'logoUrl'> {}
891
892 export interface PlatformAuthCapabilities {
893 supported: boolean
894 revoke: boolean
895 selectableAccounts: boolean
896 refreshAccountAccess: boolean
897 }
898
899 export interface PlatformPublishCapabilities {
900 supported: boolean
901 cancel: boolean
902 update: boolean
903 verify: boolean
904 finalize: boolean
905 scheduleByPlatform: boolean
906 optionSources: boolean
907 completionStrategy?: CompletionStrategy
908 }
909
910 export interface PlatformAnalyticsCapabilities {
911 account: boolean
912 work: boolean
913 }
914
915 export interface ChannelEngagementOperationParameters {
916 querySchema: PublishOptionJsonSchemaView
917 bodySchema?: PublishOptionJsonSchemaView
918 dataSchema?: PublishOptionJsonSchemaView
919 }
920
921 export interface PlatformEngagementCommentCapabilities {
922 list: {
923 supported: boolean
924 pagination: ChannelPaginationMetadata
925 parameters: ChannelEngagementOperationParameters
926 }
927 create: {
928 supported: boolean
929 parameters: ChannelEngagementOperationParameters
930 }
931 }
932
933 export interface PlatformEngagementFunctionCapabilities {
934 name: ChannelEngagementFunctionName
935 label: Record<Locale, string>
936 target: ChannelEngagementTargetType
937 parameters: Required<ChannelEngagementOperationParameters>
938 }
939
940 export interface PlatformEngagementCapabilities {
941 comments: PlatformEngagementCommentCapabilities
942 functions: PlatformEngagementFunctionCapabilities[]
943 }
944
945 export interface PlatformWorkCapabilities {
946 listWorks: boolean
947 listWorksPagination: ChannelPaginationMetadata
948 getLinkInfo: boolean
949 getDetail: boolean
950 verifyOwnership: boolean
951 }
952
953 export interface PlatformBrowseCapabilities {
954 search: boolean
955 getDetail: boolean
956 }
957
958 export interface PlatformWebhookCapabilities {
959 supported: boolean
960 }
961
962 export interface PlatformCapabilities {
963 auth: PlatformAuthCapabilities
964 publish: PlatformPublishCapabilities
965 analytics: PlatformAnalyticsCapabilities
966 engagement: PlatformEngagementCapabilities
967 work: PlatformWorkCapabilities
968 browse: PlatformBrowseCapabilities
969 webhook: PlatformWebhookCapabilities
970 }
971
972 export enum PlatformStatus {
973 Hidden = 'hidden',
974 Available = 'available',
975 Unavailable = 'unavailable',
976 ComingSoon = 'coming_soon',
977 }
978
979 export interface CachedPlatformMetadata extends Omit<PlatformMetadata, 'optionSchema'> {
980 status: PlatformStatus
981 capabilities: PlatformCapabilities
982 optionSchema: Record<string, unknown>
983 }
984
985 // ── Runtime Policy ──
986
987 export interface PlatformMediaPolicy {
988 imageConvertFormat?: string
989 maxImageWidth?: number
990 maxImageHeight?: number
991 imageQuality?: number
992 videoMaxDuration?: number
993 videoMaxBitrate?: number
994 generateCover?: boolean
995 }
996
997 export interface PlatformRetryPolicy {
998 maxRetries?: number
999 backoffMs?: number
1000 backoffMultiplier?: number
1001 }
1002
1003 export interface PlatformRuntimePolicy {
1004 concurrency?: number
1005 scheduleWindow?: number
1006 publishTimeout?: number
1007 userActionTimeout?: number
1008 finalizeTimeout?: number
1009 webhookTimeout?: number
1010 refreshWait?: number
1011 refreshBeforeExpiry?: number
1012 backgroundRefresh?: boolean
1013 media?: PlatformMediaPolicy
1014 retry?: PlatformRetryPolicy
1015 }
1016
1017 // ── Platform Integration ──
1018
1019 export interface PlatformIntegration<TOption = Record<string, unknown>, TDataOption = Record<string, unknown>> {
1020 readonly platform: AccountType
1021 readonly metadata: PlatformMetadata
1022 readonly status?: PlatformStatus
1023 readonly runtime: PlatformRuntimePolicy
1024 readonly auth?: AuthProvider
1025 readonly publish?: PublishProvider<TOption, TDataOption>
1026 readonly publishOptions?: PublishOptionSourceProvider
1027 readonly analytics?: AnalyticsProvider
1028 readonly engagement?: EngagementProvider
1029 readonly browse?: BrowseProvider
1030 readonly work?: WorkProvider
1031 readonly webhook?: PlatformWebhookHandler
1032 }
1033
1034 // ── Error ──
1035
1036 export interface PublishTaskError {
1037 category: PlatformErrorCategory
1038 code?: string
1039 message: string
1040 originalData?: unknown
1041 retryable: boolean
1042 occurredAt: Date
1043 }
1044
1044 lines TYPESCRIPT