diff --git a/deno.json b/deno.json index 06b0734..6dde5f4 100644 --- a/deno.json +++ b/deno.json @@ -1,6 +1,6 @@ { "name": "@codybrom/denim", - "version": "1.3.0", + "version": "1.3.1", "description": "A Deno function for posting to Threads.", "entry": "./mod.ts", "exports": { diff --git a/mod.ts b/mod.ts index b95132a..7c2b340 100644 --- a/mod.ts +++ b/mod.ts @@ -70,7 +70,6 @@ export async function createThreadsContainer( // 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( @@ -80,16 +79,29 @@ export async function createThreadsContainer( } // Handle media type specific parameters - if (request.mediaType === "VIDEO") { - const videoItemId = await createVideoItemContainer(request); - body.set("media_type", "CAROUSEL"); - body.append("children", videoItemId); - } 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(",")); + switch (request.mediaType) { + case "VIDEO": + if (!request.videoUrl) + throw new Error("videoUrl is required for VIDEO media type"); + body.append("video_url", request.videoUrl); + if (request.altText) body.append("alt_text", request.altText); + break; + case "IMAGE": + if (!request.imageUrl) + throw new Error("imageUrl is required for IMAGE media type"); + body.append("image_url", request.imageUrl); + if (request.altText) body.append("alt_text", request.altText); + break; + case "TEXT": + if (request.linkAttachment) + body.append("link_attachment", request.linkAttachment); + break; + case "CAROUSEL": + if (!request.children || request.children.length < 2) { + throw new Error("CAROUSEL media type requires at least 2 children"); + } + body.append("children", request.children.join(",")); + break; } console.log(`Sending request to: ${url}`); @@ -149,9 +161,6 @@ function validateRequest(request: ThreadsPostRequest): void { if (request.mediaType !== "IMAGE" && request.imageUrl) { throw new Error("imageUrl can only be used with IMAGE media type"); } - if (request.mediaType !== "VIDEO" && request.videoUrl) { - throw new Error("videoUrl can only be used with VIDEO media type"); - } if (request.mediaType !== "TEXT" && request.linkAttachment) { throw new Error("linkAttachment can only be used with TEXT media type"); } @@ -166,49 +175,6 @@ function validateRequest(request: ThreadsPostRequest): void { } } -/** - * Creates a video item container for Threads. - * @param request - The ThreadsPostRequest object containing video post details - * @returns A Promise that resolves to the video item container ID - * @throws Will throw an error if the API request fails - */ -async function createVideoItemContainer( - request: ThreadsPostRequest -): Promise { - const url = `${THREADS_API_BASE_URL}/${request.userId}/threads`; - const body = new URLSearchParams({ - access_token: request.accessToken, - is_carousel_item: "true", - media_type: "VIDEO", - video_url: request.videoUrl!, - ...(request.altText && { alt_text: request.altText }), - }); - - 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 video item container: ${response.statusText}. Details: ${responseText}` - ); - } - - try { - const data = JSON.parse(responseText); - return data.id; - } catch (error) { - console.error(`Failed to parse response JSON: ${error}`); - throw new Error(`Invalid response from Threads API: ${responseText}`); - } -} - /** * Creates a carousel item for a Threads carousel post. * diff --git a/package.json b/package.json index e5d0984..8470fb6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@codybrom/denim", - "version": "1.3.0", + "version": "1.3.1", "description": "Typescript/Deno module to simplify posting to Threads with text, images, or videos", "main": "mod.ts", "directories": { diff --git a/readme.md b/readme.md index eac78d6..50c7921 100644 --- a/readme.md +++ b/readme.md @@ -32,13 +32,13 @@ This will add the latest version of Denim to your project's dependencies. To import straight from JSR: ```typescript -import { ThreadsPostRequest, createThreadsContainer, publishThreadsContainer } from 'jsr:@codybrom/denim@^1.3.0'; +import { ThreadsPostRequest, createThreadsContainer, publishThreadsContainer } from 'jsr:@codybrom/denim'; ``` ### Basic Usage ```typescript -import { createThreadsContainer, publishThreadsContainer, ThreadsPostRequest } from "jsr:@codybrom/denim@^1.3.0"; +import { createThreadsContainer, publishThreadsContainer, ThreadsPostRequest } from "jsr:@codybrom/denim"; const request: ThreadsPostRequest = { userId: "YOUR_USER_ID", @@ -61,7 +61,7 @@ console.log(`Post published with ID: ${publishedId}`); #### Retrieving Publishing Rate Limit ```typescript -import { getPublishingLimit } from "jsr:@codybrom/denim@^1.3.0"; +import { getPublishingLimit } from "jsr:@codybrom/denim"; const userId = "YOUR_USER_ID"; const accessToken = "YOUR_ACCESS_TOKEN"; @@ -144,7 +144,7 @@ const videoRequest: ThreadsPostRequest = { #### Carousel Post ```typescript -import { createCarouselItem, createThreadsContainer, publishThreadsContainer, ThreadsPostRequest } from "jsr:@codybrom/denim@^1.0.4"; +import { createCarouselItem, createThreadsContainer, publishThreadsContainer, ThreadsPostRequest } from "jsr:@codybrom/denim"; // First, create carousel items const item1Id = await createCarouselItem({