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; }>; } 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 firstTweetId = data.data[0].id; const conversation: TweetLookups = await ff(`tweets?ids=${firstTweetId}&tweet.fields=conversation_id`); const conversation_id = conversation.data[0].conversation_id; const tweets = await ff( `tweets/search/recent?query=conversation_id:${conversation_id}&tweet.fields=in_reply_to_user_id,author_id,created_at,conversation_id&expansions=in_reply_to_user_id` ); debug(tweets); } async function listen() { try { const promise = new Promise((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();