diff --git a/readme.md b/readme.md index 50c7921..b6db39f 100644 --- a/readme.md +++ b/readme.md @@ -2,18 +2,15 @@ [![JSR](https://jsr.io/badges/@codybrom/denim)](https://jsr.io/@codybrom/denim) [![JSR Score](https://jsr.io/badges/@codybrom/denim/score)](https://jsr.io/@codybrom/denim) -**Denim** is a Deno module that provides a simple interface for posting single Threads posts using text, images, or videos. +**Denim** is a TypeScript/Deno module designed to simplify the process of creating and managing posts on Threads. It provides an intuitive API for posting text, images, videos, and carousels, as well as retrieving posts and managing rate limits. ## Features -- Create and publish posts on Threads with an easy-use-API -- Supports text-only, image, video, and carousel posts -- Add alt text to image and video posts -- Attach links to text posts -- Geo-gate content to specific countries -- Control who can reply to posts -- Retrieve publishing rate limit information -- Ready to deploy as an edge function +- **Create and Publish Posts**: Easily create and publish text, image, video, and carousel posts. +- **Media Support**: Add alt text to images and videos, attach links to text posts, and control replies. +- **Monitor Rate Limits**: Retrieve publishing rate limit information. +- **Mock API**: Includes a mock API for testing purposes without hitting real endpoints. +- **Edge Function Ready**: Deployable as a serverless edge function for real-time posting. ## Installation @@ -29,7 +26,9 @@ This will add the latest version of Denim to your project's dependencies. ## Usage -To import straight from JSR: +### Importing + +To import Denim directly in your Deno project from JSR: ```typescript import { ThreadsPostRequest, createThreadsContainer, publishThreadsContainer } from 'jsr:@codybrom/denim'; @@ -37,6 +36,8 @@ import { ThreadsPostRequest, createThreadsContainer, publishThreadsContainer } f ### Basic Usage +Here's a basic example of creating and publishing a text post: + ```typescript import { createThreadsContainer, publishThreadsContainer, ThreadsPostRequest } from "jsr:@codybrom/denim"; @@ -44,9 +45,7 @@ const request: ThreadsPostRequest = { userId: "YOUR_USER_ID", accessToken: "YOUR_ACCESS_TOKEN", mediaType: "TEXT", - text: "Check out Denim on GitHub!", - linkAttachment: "https://github.com/codybrom/denim", - replyControl: "everyone", + text: "Hello, Threads!", }; // Create a container @@ -63,17 +62,9 @@ console.log(`Post published with ID: ${publishedId}`); ```typescript import { getPublishingLimit } from "jsr:@codybrom/denim"; -const userId = "YOUR_USER_ID"; -const accessToken = "YOUR_ACCESS_TOKEN"; - -try { - const rateLimit = await getPublishingLimit(userId, accessToken); - console.log("Current usage:", rateLimit.quota_usage); - console.log("Total quota:", rateLimit.config.quota_total); - console.log("Quota duration (seconds):", rateLimit.config.quota_duration); -} catch (error) { - console.error("Failed to retrieve rate limit information:", error); -} +const rateLimit = await getPublishingLimit("YOUR_USER_ID", "YOUR_ACCESS_TOKEN"); +console.log("Current usage:", rateLimit.quota_usage); +console.log("Total quota:", rateLimit.config.quota_total); ``` ### Posting Different Media Types @@ -114,19 +105,7 @@ const imageRequest: ThreadsPostRequest = { }; ``` -#### Video Post - -```typescript -const videoRequest: ThreadsPostRequest = { - userId: "YOUR_USER_ID", - accessToken: "YOUR_ACCESS_TOKEN", - mediaType: "VIDEO", - text: "Watch this video!", - videoUrl: "https://example.com/video.mp4", -}; -``` - -#### Video Post with Alt Text, Reply Control and Geo-gating* (requires special account permission) +#### Video Post with Alt Text and Reply Controls ```typescript const videoRequest: ThreadsPostRequest = { @@ -136,7 +115,6 @@ const videoRequest: ThreadsPostRequest = { text: "Watch this video!", videoUrl: "https://example.com/video.mp4", altText: "A tutorial on how to make a chocolate cake", - allowlistedCountryCodes: ["US", "GB"], replyControl: "mentioned_only", }; ``` @@ -145,14 +123,13 @@ const videoRequest: ThreadsPostRequest = { ```typescript import { createCarouselItem, createThreadsContainer, publishThreadsContainer, ThreadsPostRequest } from "jsr:@codybrom/denim"; - // First, create carousel items const item1Id = await createCarouselItem({ userId: "YOUR_USER_ID", accessToken: "YOUR_ACCESS_TOKEN", mediaType: "IMAGE", imageUrl: "https://example.com/image1.jpg", - altText: "First image in the carousel", + altText: "First image", }); const item2Id = await createCarouselItem({ @@ -160,40 +137,37 @@ const item2Id = await createCarouselItem({ accessToken: "YOUR_ACCESS_TOKEN", mediaType: "VIDEO", videoUrl: "https://example.com/video.mp4", - altText: "Video in the carousel", + altText: "A video", }); -// Then, create the carousel post +// Create and publish the carousel post const carouselRequest: ThreadsPostRequest = { userId: "YOUR_USER_ID", accessToken: "YOUR_ACCESS_TOKEN", mediaType: "CAROUSEL", - text: "Check out this carousel post!", + text: "Check out this carousel!", children: [item1Id, item2Id], - replyControl: "everyone", }; -const containerId = await createThreadsContainer(carouselRequest); -const publishedId = await publishThreadsContainer(carouselRequest.userId, carouselRequest.accessToken, containerId); - -console.log(`Carousel post published with ID: ${publishedId}`); +const carouselContainerId = await createThreadsContainer(carouselRequest); +const publishedContainerId = await publishThreadsContainer(carouselRequest.userId, carouselRequest.accessToken, carouselContainerId); ``` ## Deploying as an Edge Function -Denim can be easily deployed as an edge function. An example implementation is provided in `examples/edge-function.ts`. +Denim can be easily deployed as an edge function on serverless platforms that support Deno. An example implementation is available in `examples/edge-function.ts`. -To deploy: +### Deployment Steps -1. Copy the `examples/edge-function.ts` file to your project. -2. Deploy this file to your serverless platform that supports Deno. -3. Send POST requests to your function's URI with the appropriate JSON body. +1. Copy `examples/edge-function.ts` to your project. +2. Deploy the file to your serverless platform. +3. Send requests to your function's URI. ### Example cURL Commands ```bash # Post a text-only Thread -curl -X POST \ +curl -X POST /post \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_AUTH_KEY" \ -d '{ @@ -202,7 +176,6 @@ curl -X POST \ "mediaType": "TEXT", "text": "Hello from Denim!" }' - # Post an image Thread curl -X POST \ -H "Content-Type: application/json" \ @@ -232,11 +205,11 @@ Note: Replace with your actual authorization headers if your edge function requi ## Security Note -Ensure that your function is deployed with appropriate access controls and authentication mechanisms to protect sensitive data like access tokens. +Ensure your deployment uses proper access controls and authentication to protect sensitive data like access tokens. ## Testing -To run the tests: +Run the tests using: ```bash deno test mod_test.ts @@ -244,8 +217,8 @@ deno test mod_test.ts ## Contributing -Contributions are welcome! Please feel free to submit a Pull Request. +Contributions are welcome! Feel free to submit issues or pull requests. ## License -[MIT License](LICENSE) +This project is licensed under the [MIT License](LICENSE).