|
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()); |
|
|
|
|
|
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"], |
|
}); |
|
|
|
|
|
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<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(); |
|
|