Skip to content

Conversation

@icecoins
Copy link

@icecoins icecoins commented Oct 23, 2025

Upload media data is available with Twitter-API-v2, please check and update, thanks!
I have tested this function in my project, it works well with .PNG files.

Summary by CodeRabbit

Release Notes

  • New Features
    • Implemented media upload for tweets. Users can now attach up to 4 media items (images, videos, GIFs) when creating tweets. The system automatically detects media types and formats them appropriately for seamless integration. Media files are now properly processed and attached to tweets during composition.

@coderabbitai
Copy link

coderabbitai bot commented Oct 23, 2025

Walkthrough

Replaces a no-op warning with functional media upload logic in createCreateTweetRequest. When mediaData is provided, the implementation uploads up to 4 media items via v2 media upload API, infers MIME types from mediaType values, collects returned media IDs, and populates tweetConfig.media.media_ids.

Changes

Cohort / File(s) Summary
Media Upload Implementation
src/client/tweets.ts
Implemented media upload flow that handles multiple media items (up to 4), infers MIME types (jpg→JPEG, png→PNG, mp4/mov→MP4/Mov, text/plain→Srt, gif→Gif) from mediaType, uploads via v2 media endpoint, collects media IDs, and attaches them to tweet payload using structuredClone

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant Tweet Client
    participant Media Upload API
    participant Tweet Payload

    User->>Tweet Client: createCreateTweetRequest(mediaData)
    
    rect rgb(200, 230, 255)
    Note over Tweet Client: Media Upload Flow
    loop For each media item (max 4)
        Tweet Client->>Tweet Client: Infer MIME type from mediaType
        Tweet Client->>Media Upload API: Upload media (POST /2/media/upload)
        Media Upload API-->>Tweet Client: Return media_id
    end
    end
    
    rect rgb(200, 255, 220)
    Note over Tweet Client: Attach to Tweet
    Tweet Client->>Tweet Client: Collect all media IDs
    Tweet Client->>Tweet Payload: Set tweetConfig.media.media_ids
    Tweet Payload-->>User: Tweet with attached media
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

The change introduces new media upload logic with MIME type inference and multiple item handling confined to one file, requiring careful review of type mapping logic and media collection flow, but remaining focused in scope.

Poem

🐰 A tweet takes flight with media so fine,
Four items up, their IDs align,
From jpg to mp4, we infer with care,
Uploads now working, through the air!
No more warnings—just media there! 📸

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The pull request title "Upload media data is available with Twitter-API-v2" is directly related to the main change in the changeset. The implemented changes involve adding media upload flow functionality for tweet creation when mediaData is provided, which aligns with what the title conveys. The title is concise, uses clear language, and a teammate scanning the repository history would understand that media upload capability is now available for Twitter API v2 operations. While the title could be slightly more action-oriented (e.g., "Implement media upload flow for Twitter API v2 tweets"), it still effectively communicates the primary change.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between d4d104c and 1b96a93.

📒 Files selected for processing (1)
  • src/client/tweets.ts (2 hunks)
🔇 Additional comments (1)
src/client/tweets.ts (1)

666-675: No changes needed; implementation and comment are accurate.

Twitter API v2 doesn't have a separate endpoint for long-form "Notes" posts, and long-form content is delivered through the regular Posts/Tweets flows. The function correctly delegates to createCreateTweetRequest without modification, and the accompanying comment accurately reflects the API's behavior.

Comment on lines +589 to +591
tweetConfig.media = {
media_ids:[""]
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Critical: Invalid media_ids initialization will cause API errors.

Initializing media_ids with an empty string [""] is incorrect. If no media items are successfully uploaded (e.g., all fail or mediaData becomes empty after filtering), the tweet request will include an invalid media ID, causing the Twitter API to reject the request.

Apply this diff to fix the initialization:

-      tweetConfig.media = {
-        media_ids:[""]
-      };
-      let media_ids: string[] = [];
+      const media_ids: string[] = [];

Then, only add the media property to tweetConfig after successfully collecting media IDs (move lines 589-591 after the media upload loop and make it conditional).

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/client/tweets.ts around lines 589-591, the code sets
tweetConfig.media.media_ids = [""], which injects an invalid empty-string media
ID and will cause Twitter API errors; remove that initialization and instead,
after the media upload loop, if you have at least one successful media ID (e.g.,
mediaIds.length > 0), set tweetConfig.media = { media_ids: mediaIds } so the
media property is only added when there are valid uploaded IDs; ensure mediaIds
is collected during the loop and only used here.

Comment on lines +596 to +620
let type: EUploadMimeType = EUploadMimeType.Jpeg;
switch(media.mediaType){
case "image":
case "jpg":
break;
case "png":
type = EUploadMimeType.Png;
break;
case "video":
case "mp4":
type = EUploadMimeType.Mp4;
break;
case "quicktime":
type = EUploadMimeType.Mov;
break;
case "text":
case "plain":
type = EUploadMimeType.Srt;
break;
case "gif":
type = EUploadMimeType.Gif;
break;
default:
break;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Missing import and fragile MIME type detection.

The code references EUploadMimeType but this enum is not imported from twitter-api-v2. Additionally, the mediaType string matching is fragile—unexpected values silently default to JPEG, which could cause upload failures for unsupported formats.

Apply this diff to add the import:

 import type {
   ApiV2Includes,
   MediaObjectV2,
   PlaceV2,
   PollV2,
   TTweetv2Expansion,
   TTweetv2MediaField,
   TTweetv2PlaceField,
   TTweetv2PollField,
   TTweetv2TweetField,
   TTweetv2UserField,
   TweetV2,
   UserV2,
 } from "twitter-api-v2";
+import { EUploadMimeType } from "twitter-api-v2";

Consider improving the type detection logic with better validation:

let type: EUploadMimeType;
const normalizedType = media.mediaType.toLowerCase();

if (normalizedType.includes('png')) {
  type = EUploadMimeType.Png;
} else if (normalizedType.includes('gif')) {
  type = EUploadMimeType.Gif;
} else if (normalizedType.includes('mp4') || normalizedType === 'video') {
  type = EUploadMimeType.Mp4;
} else if (normalizedType.includes('quicktime') || normalizedType.includes('mov')) {
  type = EUploadMimeType.Mov;
} else if (normalizedType.includes('srt') || normalizedType === 'text/plain') {
  type = EUploadMimeType.Srt;
} else if (normalizedType.includes('jpeg') || normalizedType.includes('jpg') || normalizedType === 'image') {
  type = EUploadMimeType.Jpeg;
} else {
  throw new Error(`Unsupported media type: ${media.mediaType}`);
}
🤖 Prompt for AI Agents
In src/client/tweets.ts around lines 596 to 620, the code uses EUploadMimeType
without importing it and the current switch on media.mediaType silently falls
back to JPEG for unexpected values; import EUploadMimeType from 'twitter-api-v2'
and replace the fragile switch with robust normalization and validation:
normalize media.mediaType to lowercase, perform inclusive checks (e.g., contains
'png', 'gif', 'mp4' or equals 'video', contains 'quicktime'/'mov', contains
'srt' or equals 'text/plain', contains 'jpeg'/'jpg' or equals 'image') to map to
the correct EUploadMimeType, and throw an explicit error for unsupported types
instead of defaulting to JPEG so invalid media is caught early.

Comment on lines +621 to +625
const id = await v2.uploadMedia(media.data, {media_type: type});
media_ids.push(id);
if(i === 3){ // max 4 media in a post
break;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add error handling for media upload failures.

The uploadMedia call can fail (network issues, invalid format, size limits, etc.), but there's no try-catch block to handle failures gracefully. A single upload failure will abort the entire tweet creation.

Consider wrapping the upload in a try-catch to handle individual failures:

-        const id = await v2.uploadMedia(media.data, {media_type: type});
-        media_ids.push(id);
-        if(i === 3){ // max 4 media in a post
-          break;
-        }
+        try {
+          const id = await v2.uploadMedia(media.data, { media_type: type });
+          media_ids.push(id);
+          if (media_ids.length === 4) { // max 4 media in a post
+            break;
+          }
+        } catch (error) {
+          console.error(`Failed to upload media ${i}:`, error);
+          // Optionally: continue to try other media items, or throw to fail the entire operation
+        }

Note: Also improved the loop termination to check media_ids.length instead of the iterator, which is clearer.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const id = await v2.uploadMedia(media.data, {media_type: type});
media_ids.push(id);
if(i === 3){ // max 4 media in a post
break;
}
try {
const id = await v2.uploadMedia(media.data, { media_type: type });
media_ids.push(id);
if (media_ids.length === 4) { // max 4 media in a post
break;
}
} catch (error) {
console.error(`Failed to upload media ${i}:`, error);
// Optionally: continue to try other media items, or throw to fail the entire operation
}
🤖 Prompt for AI Agents
In src/client/tweets.ts around lines 621 to 625, the call to v2.uploadMedia is
unprotected so a single upload failure will abort the entire tweet flow; wrap
the uploadMedia call in a try-catch, only push the returned id into media_ids on
success, log or record the specific error (with context: which media index and
type), skip the failed media and continue attempting the rest, and change the
loop termination to break when media_ids.length >= 4 to enforce the max-4 rule
instead of checking the iterator.

Comment on lines +628 to +643
switch (media_ids.length) {
case 1:
tweetConfig.media.media_ids = [structuredClone(media_ids[0])];
break;
case 2:
tweetConfig.media.media_ids = [structuredClone(media_ids[0]), structuredClone(media_ids[1])];
break;
case 3:
tweetConfig.media.media_ids = [structuredClone(media_ids[0]), structuredClone(media_ids[1]), structuredClone(media_ids[2])];
break;
case 4:
tweetConfig.media.media_ids = [structuredClone(media_ids[0]), structuredClone(media_ids[1]), structuredClone(media_ids[2]), structuredClone(media_ids[3])];
break;
default:
break;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Simplify media_ids assignment.

The switch statement is unnecessarily verbose and uses structuredClone on string primitives, which is redundant since strings are immutable. This entire block can be replaced with a simple array assignment.

Apply this diff to simplify:

-      switch (media_ids.length) {
-        case 1:
-          tweetConfig.media.media_ids = [structuredClone(media_ids[0])];
-          break;
-        case 2:
-          tweetConfig.media.media_ids = [structuredClone(media_ids[0]), structuredClone(media_ids[1])];
-          break;
-        case 3:
-          tweetConfig.media.media_ids = [structuredClone(media_ids[0]), structuredClone(media_ids[1]), structuredClone(media_ids[2])];
-          break;
-        case 4:
-          tweetConfig.media.media_ids = [structuredClone(media_ids[0]), structuredClone(media_ids[1]), structuredClone(media_ids[2]), structuredClone(media_ids[3])];
-          break;
-        default:
-          break;
-      }
+      if (media_ids.length > 0) {
+        tweetConfig.media = { media_ids };
+      }

This also ensures the media property is only added when there are actual media IDs to attach.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/client/tweets.ts around lines 628 to 643, the switch that assigns
tweetConfig.media.media_ids is verbose and redundantly uses structuredClone on
string primitives; replace it with a single conditional that only adds the media
property when media_ids has items and assigns a shallow copy of the array (e.g.,
tweetConfig.media = { media_ids: [...media_ids] } or equivalent), removing
structuredClone and the switch entirely so media is only present when there are
actual media IDs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant