import {z} from 'zod' 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 UpdatePostRequest = {title?: string | undefined, caption?: string | undefined, hashtags?: Array | undefined, mediaUrls?: Array | undefined, mediaType?: ('image' | 'video') | undefined, postType?: ('post' | 'reel' | 'story') | undefined, platforms?: Array | undefined, connectedAccountId?: string | undefined, platformOptions?: PlatformOptions | undefined, status?: ('draft' | 'scheduled') | undefined, scheduledAt?: string | undefined}; export type PatchApiPostsIdArgs = {body: UpdatePostRequest}; export type PatchApiPostsIdOptions = {baseUrl?: string | undefined, ApiKey?: string | undefined, fetch?: typeof fetch | undefined}; export const platformResult = z.object({platform: z.string(), success: z.boolean(), error: z.string().optional(), remote_post_id: z.string().optional(), remote_publish_id: z.string().optional(), remote_permalink: z.string().optional()}); export const post = z.object({id: z.string().optional(), title: z.string().nullable().optional(), caption: z.string().nullable().optional(), platforms: z.array(z.string()).optional(), status: z.enum(["draft", "scheduled", "queued", "published", "partial_published", "failed"]).optional(), scheduled_at: z.string().nullable().optional(), published_at: z.string().nullable().optional(), media_urls: z.array(z.string()).optional(), media_type: z.enum(["image", "video", "null"]).nullable().optional(), connected_account_id: z.string().nullable().optional(), platform_results: z.array(platformResult).optional(), created_at: z.string().optional()}); export const patchApiPostsIdResponse = z.object({post: post.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 }; /** * Edit a draft or scheduled post (only sent fields are touched) * * PATCH /posts/{id} */ export const patchApiPostsId = async (args: PatchApiPostsIdArgs, options?: PatchApiPostsIdOptions) => { 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/${encodeURIComponent(String(args.id))}${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "PATCH", 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(patchApiPostsIdResponse, await res.json()) };