UNPKG

@codybrom/denim

Version:

A Deno/TypeScript library for the Threads API

123 lines (112 loc) 3.95 kB
import { THREADS_API_BASE_URL } from "../constants.ts"; import type { ThreadsPostRequest } from "../types.ts"; import { getAPI } from "../utils/getAPI.ts"; import { validateRequest } from "../utils/validateRequest.ts"; /** * Creates a Threads media container. * * @param request - The ThreadsPostRequest object containing post details * @returns A Promise that resolves to the container ID * @throws Will throw an error if the API request fails * * @example * ```typescript * const request: ThreadsPostRequest = { * userId: "123456", * accessToken: "your_access_token", * mediaType: "VIDEO", * text: "Check out this video!", * videoUrl: "https://example.com/video.mp4", * altText: "A cool video" * }; * const containerId = await createThreadsContainer(request); * ``` */ export async function createThreadsContainer( request: ThreadsPostRequest, ): Promise<string> { const api = getAPI(); if (api) { return api.createThreadsContainer(request); } try { // Input validation await validateRequest(request); const url = `${THREADS_API_BASE_URL}/${request.userId}/threads`; const body = new URLSearchParams({ access_token: request.accessToken, media_type: request.mediaType, }); // Add common optional parameters if (request.text) body.append("text", request.text); if (request.altText) body.append("alt_text", request.altText); if (request.replyControl) { body.append("reply_control", request.replyControl); } if (request.allowlistedCountryCodes) { body.append( "allowlisted_country_codes", JSON.stringify(request.allowlistedCountryCodes), ); } // New optional parameters if (request.replyToId) body.append("reply_to_id", request.replyToId); if (request.quotePostId) { body.append("quote_post_id", request.quotePostId); } if (request.topicTag) body.append("topic_tag", request.topicTag); if (request.isGhostPost !== undefined) { body.append("is_ghost_post", String(request.isGhostPost)); } if (request.locationId) body.append("location_id", request.locationId); if (request.autoPublishText !== undefined) { body.append("auto_publish_text", String(request.autoPublishText)); } if (request.isSpoilerMedia !== undefined) { body.append("is_spoiler_media", String(request.isSpoilerMedia)); } // JSON-serialized parameters if (request.pollAttachment) { body.append("poll_attachment", JSON.stringify(request.pollAttachment)); } if (request.textEntities) { body.append("text_entities", JSON.stringify(request.textEntities)); } if (request.textAttachment) { body.append("text_attachment", JSON.stringify(request.textAttachment)); } if (request.gifAttachment) { body.append("gif_attachment", JSON.stringify(request.gifAttachment)); } // Handle media type specific parameters if (request.mediaType === "VIDEO" && request.videoUrl) { body.append("video_url", request.videoUrl); } else if (request.mediaType === "IMAGE" && request.imageUrl) { body.append("image_url", request.imageUrl); } else if (request.mediaType === "TEXT" && request.linkAttachment) { body.append("link_attachment", request.linkAttachment); } else if (request.mediaType === "CAROUSEL" && request.children) { body.append("children", request.children.join(",")); } const response = await fetch(url, { method: "POST", body: body, headers: { "Content-Type": "application/x-www-form-urlencoded" }, }); const responseText = await response.text(); if (!response.ok) { throw new Error( `Failed to create container (${response.status} ${response.statusText}): ${responseText}`, ); } const data = JSON.parse(responseText); return data.id; } catch (error) { // Rethrow the error if it's already an Error instance if (error instanceof Error) { throw error; } // Otherwise, wrap it in a new Error throw new Error(`Failed to create Threads container: ${String(error)}`); } }