File size: 2,927 Bytes
31d882e e04cf41 31d882e 987f2db 31d882e 987f2db 31d882e e04cf41 987f2db e04cf41 987f2db 9920173 987f2db 9920173 987f2db e04cf41 987f2db 9920173 987f2db 9920173 987f2db 9920173 987f2db 9920173 e04cf41 31d882e e04cf41 |
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 |
import Koa from "koa";
import bodyParser from "koa-bodyparser";
import compression from "koa-compress";
import morgan from "koa-morgan";
import Router from "koa-router";
import { inspect } from "util";
import "dotenv/config";
import { Client, auth } from "twitter-api-sdk";
const port = 7860;
const app = new Koa();
app.use(morgan("dev"));
app.use(compression());
app.use(bodyParser());
const { API_KEY, API_SECRET, BEARER_TOKEN, CLIENT_ID, CLIENT_SECRET, COOKIE } = process.env;
const router = new Router();
app.use(router.routes());
app.use(router.allowedMethods());
// Initialize auth client first
const authClient = new auth.OAuth2User({
client_id: CLIENT_ID as string,
client_secret: CLIENT_SECRET as string,
callback: "https://huggingface-projects-twitter-image-alt-bot.hf.space/callback",
scopes: ["tweet.read", "users.read", "offline.access"],
});
// Pass auth credentials to the library client
const twitterClient = new Client(authClient);
const BOT_NAME = "AltImageBot1";
const BOT_ID = "1612094318906417152";
function debug(stuff: any) {
console.log(inspect(stuff, { depth: 20 }));
}
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;
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();
}
async function lookupTweets() {
const data: TweetMentions = await ff(`users/${BOT_ID}/mentions`);
const lookups: TweetLookups = await ff(
`tweets?ids=${data.data
.map((t) => t.id)
.join(
","
)}&expansions=attachments.media_keys&media.fields=duration_ms,height,media_key,preview_image_url,public_metrics,type,url,width,alt_text`
);
const tweetWithImage = lookups.data.find((tweet) => tweet.attachments?.media_keys);
const imageUrl = lookups.includes.media.find(
(media) => media.media_key === tweetWithImage?.attachments!.media_keys[0]
)?.url!;
console.log("imageUrl", imageUrl);
const image = await (await fetch(imageUrl)).arrayBuffer();
console.log(image);
}
async function listen() {
try {
const promise = new Promise<void>((resolve, reject) => {
app.listen(port, "localhost", () => resolve());
app.once("error", (err) => reject(err));
});
await promise;
console.log("app started on port", port);
process.send?.("ready");
} catch (err) {
console.error(err);
}
}
listen();
process.on("unhandledRejection", async (err) => {
console.error("unhandled rejection", err);
});
lookupTweets();
|