Skip to content
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

fix: Allow bot to post tweets with images generated by the imageGenerationPlugin #1040

Merged
merged 3 commits into from
Dec 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/client-twitter/src/interactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,8 @@ export class TwitterInteractionClient {
await this.runtime.processActions(
message,
responseMessages,
state
state,
callback
odilitime marked this conversation as resolved.
Show resolved Hide resolved
);

const responseInfo = `Context:\n\n${context}\n\nSelected Post: ${tweet.id} - ${tweet.username}: ${tweet.text}\nAgent's Output:\n${response.text}`;
Expand Down
49 changes: 48 additions & 1 deletion packages/client-twitter/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import { stringToUuid } from "@ai16z/eliza";
import { ClientBase } from "./base";
import { elizaLogger } from "@ai16z/eliza";
import { DEFAULT_MAX_TWEET_LENGTH } from "./environment";
import { Media } from "@ai16z/eliza";
import fs from "fs";
import path from "path";

export const wait = (minTime: number = 1000, maxTime: number = 3000) => {
const waitTime =
Expand Down Expand Up @@ -162,6 +165,16 @@ export async function buildConversationThread(
return thread;
}

export function getMediaType(attachment: Media) {
if (attachment.contentType?.startsWith("video")) {
return "video";
} else if (attachment.contentType?.startsWith("image")) {
return "image";
} else {
throw new Error(`Unsupported media type`);
}
}

export async function sendTweet(
client: ClientBase,
content: Content,
Expand All @@ -178,11 +191,45 @@ export async function sendTweet(
let previousTweetId = inReplyTo;

for (const chunk of tweetChunks) {
let mediaData: { data: Buffer; mediaType: string }[] | undefined;

if (content.attachments && content.attachments.length > 0) {
mediaData = await Promise.all(
content.attachments.map(async (attachment: Media) => {
if (/^(http|https):\/\//.test(attachment.url)) {
// Handle HTTP URLs
const response = await fetch(attachment.url);
if (!response.ok) {
throw new Error(
`Failed to fetch file: ${attachment.url}`
);
}
const mediaBuffer = Buffer.from(
await response.arrayBuffer()
);
const mediaType = getMediaType(attachment);
return { data: mediaBuffer, mediaType };
} else if (fs.existsSync(attachment.url)) {
// Handle local file paths
const mediaBuffer = await fs.promises.readFile(
path.resolve(attachment.url)
);
const mediaType = getMediaType(attachment);
return { data: mediaBuffer, mediaType };
} else {
throw new Error(
`File not found: ${attachment.url}. Make sure the path is correct.`
);
}
})
);
}
const result = await client.requestQueue.add(
async () =>
await client.twitterClient.sendTweet(
chunk.trim(),
previousTweetId
previousTweetId,
mediaData
)
);
const body = await result.json();
Expand Down
11 changes: 9 additions & 2 deletions packages/core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,9 @@ export type Media = {

/** Text content */
text: string;

/** Content type */
contentType?: string;
};

/**
Expand Down Expand Up @@ -1128,12 +1131,16 @@ export interface IPdfService extends Service {
}

export interface IAwsS3Service extends Service {
uploadFile(imagePath: string, useSignedUrl: boolean, expiresIn: number ): Promise<{
uploadFile(
imagePath: string,
useSignedUrl: boolean,
expiresIn: number
): Promise<{
success: boolean;
url?: string;
error?: string;
}>;
generateSignedUrl(fileName: string, expiresIn: number): Promise<string>
generateSignedUrl(fileName: string, expiresIn: number): Promise<string>;
}

export type SearchResult = {
Expand Down
1 change: 1 addition & 0 deletions packages/plugin-image-generation/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ const imageGeneration: Action = {
source: "imageGeneration",
description: "...", //caption.title,
text: "...", //caption.description,
contentType: "image",
},
],
},
Expand Down
Loading