-
Notifications
You must be signed in to change notification settings - Fork 29
Upload media data is available with Twitter-API-v2 #45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 1.x
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -585,7 +585,62 @@ export async function createCreateTweetRequest( | |||||||||||||||||||||||||||||||
| if (mediaData && mediaData.length > 0) { | ||||||||||||||||||||||||||||||||
| // Note: Twitter API v2 media upload requires separate endpoint | ||||||||||||||||||||||||||||||||
| // For now, we'll skip media upload as it requires additional implementation | ||||||||||||||||||||||||||||||||
| console.warn("Media upload not yet implemented for Twitter API v2"); | ||||||||||||||||||||||||||||||||
| // console.warn("Media upload not yet implemented for Twitter API v2"); | ||||||||||||||||||||||||||||||||
| tweetConfig.media = { | ||||||||||||||||||||||||||||||||
| media_ids:[""] | ||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||
| let media_ids: string[] = []; | ||||||||||||||||||||||||||||||||
| for(let i = 0; i < mediaData.length; i++){ | ||||||||||||||||||||||||||||||||
| const media = mediaData[i]; | ||||||||||||||||||||||||||||||||
| const v2 = v2client.v2; | ||||||||||||||||||||||||||||||||
| 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; | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
Comment on lines
+596
to
+620
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing import and fragile MIME type detection. The code references 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 |
||||||||||||||||||||||||||||||||
| const id = await v2.uploadMedia(media.data, {media_type: type}); | ||||||||||||||||||||||||||||||||
| media_ids.push(id); | ||||||||||||||||||||||||||||||||
| if(i === 3){ // max 4 media in a post | ||||||||||||||||||||||||||||||||
| break; | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
Comment on lines
+621
to
+625
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add error handling for media upload failures. The 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 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| 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; | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
Comment on lines
+628
to
+643
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 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
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| // Handle reply | ||||||||||||||||||||||||||||||||
|
|
@@ -607,6 +662,7 @@ export async function createCreateTweetRequest( | |||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| export async function createCreateNoteTweetRequest( | ||||||||||||||||||||||||||||||||
| text: string, | ||||||||||||||||||||||||||||||||
| auth: TwitterAuth, | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical: Invalid media_ids initialization will cause API errors.
Initializing
media_idswith 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:
Then, only add the
mediaproperty totweetConfigafter successfully collecting media IDs (move lines 589-591 after the media upload loop and make it conditional).🤖 Prompt for AI Agents