File size: 3,498 Bytes
85078f5 31d882e 85078f5 31d882e 85078f5 31d882e 85078f5 e04cf41 85078f5 e04cf41 987f2db e04cf41 987f2db 2b4727d 9920173 987f2db 9920173 987f2db e04cf41 987f2db 85078f5 987f2db 85078f5 2b4727d 9920173 987f2db 85078f5 2b4727d 85078f5 2b4727d 85078f5 31d882e 85078f5 31d882e e04cf41 85078f5 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
import OAuth from "oauth";
import "dotenv/config";
import { setTimeout } from "timers/promises";
const { API_KEY, API_SECRET, BEARER_TOKEN, ACCESS_TOKEN, ACCESS_TOKEN_SECRET } = process.env;
function getAuthHeader(oauth: OAuth.OAuth, url: string) {
return oauth.authHeader(url, ACCESS_TOKEN as string, ACCESS_TOKEN_SECRET as string, "post");
}
const client = new OAuth.OAuth(
"https://api.twitter.com/oauth/request_token",
"https://api.twitter.com/oauth/access_token",
API_KEY as string,
API_SECRET as string,
"1.0A",
null,
"HMAC-SHA1"
);
const BOT_ID = "1612094318906417152";
interface TweetMentions {
data: Array<{ id: string; text: string }>;
meta: {
result_count: number;
newest_id: string;
oldest_id: string;
};
}
interface TweetLookups {
data: Array<{
id: string;
conversation_id: "string";
text: string;
created_at: string;
attachments?: { media_keys: string[] };
}>;
includes: { media: Array<{ media_key: string; url: string }> };
}
async function ff(url: string) {
const resp = await fetch(`https://api.twitter.com/2/${url}`, {
headers: { Authorization: `Bearer ${BEARER_TOKEN}` },
});
if (resp.status !== 200) {
throw new Error("invalid status: " + resp.status + "- " + (await resp.text()));
}
return await resp.json();
}
let lastMention = "";
async function lookupTweets() {
const data: TweetMentions = await ff(`users/${BOT_ID}/mentions`);
let lookups: TweetLookups = await ff(
`tweets?ids=${data.data.map((t) => t.id).join(",")}${
lastMention && `start_time=${new Date(new Date(lastMention).getTime() + 1).toJSON()}`
}&tweet.fields=created_at&expansions=attachments.media_keys&media.fields=duration_ms,height,media_key,preview_image_url,public_metrics,type,url,width,alt_text`
);
if (!lastMention) {
console.log("added mention", lookups.data[0].created_at);
lastMention = lookups.data[0].created_at;
return;
}
const tweets = lookups.data.filter((tweet) => tweet.attachments?.media_keys.length === 1);
console.log(lastMention);
for (const tweet of tweets) {
const imageUrl = lookups.includes.media.find((media) => media.media_key === tweet?.attachments!.media_keys[0])
?.url!;
console.log("imageUrl", imageUrl);
const imageResp = await fetch(imageUrl);
const contentType = imageResp.headers.get("Content-Type");
const image = await imageResp.arrayBuffer();
console.log(contentType, image);
const altText = await fetch("https://olivierdehaene-git-large-coco.hf.space/run/predict", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
data: [`data:${contentType};base64,${Buffer.from(image).toString("base64")}`],
}),
})
.then((r) => r.json())
.then((r) => r.data);
console.log(altText[0]);
const header = getAuthHeader(client, "https://api.twitter.com/2/tweets");
const r = await fetch("https://api.twitter.com/2/tweets", {
headers: {
Authorization: header,
"user-agent": "v3CreateTweetJS",
"content-type": "application/json",
accept: "application/json",
},
body: JSON.stringify({
text: altText[0],
reply: { in_reply_to_tweet_id: tweet!.id, conversation_id: tweet!.conversation_id },
}),
method: "post",
});
console.log("end", await r.text());
}
}
process.on("unhandledRejection", async (err) => {
console.error("unhandled rejection", err);
});
async function run() {
while (1) {
console.log("looking up");
await lookupTweets();
await setTimeout(5_000);
}
}
run();
|