import {z} from 'zod' export type AccountMapping = {platform: string, accountId?: string | undefined}; export type YouTubeOptions = {title: string, categoryId: string, madeForKids: boolean, privacyStatus?: ('public' | 'unlisted' | 'private') | undefined, tags?: Array | undefined, defaultLanguage?: string | undefined, containsSyntheticMedia?: boolean | undefined, embeddable?: boolean | undefined, publicStatsViewable?: boolean | undefined, license?: ('youtube' | 'creativeCommon') | undefined, thumbnailUrl?: string | undefined}; export type TikTokOptions = {privacyLevel: 'PUBLIC_TO_EVERYONE' | 'MUTUAL_FOLLOW_FRIENDS' | 'FOLLOWER_OF_CREATOR' | 'SELF_ONLY', disableComment: boolean, brandContentToggle: boolean, brandOrganicToggle: boolean, isAigc: boolean, postMode?: ('DIRECT_POST' | 'MEDIA_UPLOAD') | undefined, disableDuet?: boolean | undefined, disableStitch?: boolean | undefined, videoCoverTimestampMs?: number | undefined, autoAddMusic?: boolean | undefined, photoCoverIndex?: number | undefined, photoTitle?: string | undefined}; export type InstagramOptions = {shareToFeed?: boolean | undefined, coverUrl?: string | undefined, thumbOffsetMs?: number | undefined, audioName?: string | undefined, collaborators?: Array | undefined, locationId?: string | undefined, userTags?: (Array<{username: string, x?: number | undefined, y?: number | undefined}>) | undefined, altText?: string | undefined, isAiGenerated?: boolean | undefined, isTrialReel?: boolean | undefined, trialGraduationStrategy?: ('MANUAL' | 'SS_PERFORMANCE') | undefined}; export type ThreadsOptions = {replyControl?: ('everyone' | 'accounts_you_follow' | 'mentioned_only' | 'parent_post_author_only' | 'followers_only') | undefined, topic?: string | undefined, altText?: string | undefined, linkAttachment?: string | undefined, quotePostId?: string | undefined, locationId?: string | undefined, allowlistedCountryCodes?: Array | undefined, chainItems?: (Array<{text: string, mediaUrl?: string | undefined, mediaType?: ('image' | 'video') | undefined, altText?: string | undefined}>) | undefined}; export type BlueskyOptions = {langs?: Array | undefined}; export type MastodonOptions = {visibility?: ('public' | 'unlisted' | 'private' | 'direct') | undefined, spoilerText?: string | undefined, sensitive?: boolean | undefined, language?: string | undefined}; export type TelegramOptions = {disableNotification?: boolean | undefined, protectContent?: boolean | undefined}; export type DiscordOptions = {channelId?: string | undefined}; export type PinterestOptions = {boardId: string, boardName?: string | undefined, title?: string | undefined, link?: string | undefined, altText?: string | undefined, coverUrl?: string | undefined, thumbOffsetMs?: number | undefined}; export type PlatformOptions = {youtube?: YouTubeOptions | undefined, tiktok?: TikTokOptions | undefined, instagram?: InstagramOptions | undefined, threads?: ThreadsOptions | undefined, bluesky?: BlueskyOptions | undefined, mastodon?: MastodonOptions | undefined, telegram?: TelegramOptions | undefined, discord?: DiscordOptions | undefined, pinterest?: PinterestOptions | undefined} | {[key: string]: unknown}; export type CreatePostRequest = {title?: string | undefined, caption?: string | undefined, accountMappings: Array, platforms?: Array | undefined, accountId?: string | undefined, mediaUrls?: Array | undefined, mediaType?: ('image' | 'video') | undefined, postType?: ('post' | 'reel' | 'story') | undefined, hashtags?: Array | undefined, platformCaptions?: {[key: string]: string} | undefined, platformOptions?: PlatformOptions | undefined, status?: ('draft' | 'scheduled' | 'published') | undefined, scheduledAt?: string | undefined}; export type CreateApiPostsArgs = {body: CreatePostRequest}; export type CreateApiPostsOptions = {baseUrl?: string | undefined, ApiKey?: string | undefined, fetch?: typeof fetch | undefined}; export const createPostResult = z.object({postIds: z.array(z.string()).optional(), status: z.enum(["draft", "scheduled", "queued"]).optional(), dispatchDeferred: z.boolean().optional()}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * Create a draft, schedule, or publish now (controlled by status) * * POST /posts */ export const createApiPosts = async (args: CreateApiPostsArgs, options?: CreateApiPostsOptions) => { const {baseUrl = "https://api.posteahora.com/functions/v1/api", fetch: fetchFn = fetch, ApiKey} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('content-type', "application/json") headers.set('accept', "application/json") if (ApiKey !== undefined) headers.set('authorization', `Bearer ${ApiKey}`) const url = `${baseUrl.replace(/\/+$/, '')}/posts${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "POST", headers, body: JSON.stringify(args.body)}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(createPostResult, await res.json()) };