Created
April 30, 2025 04:36
-
-
Save shouc/d3777f4d453db98194800fae8d190dcd to your computer and use it in GitHub Desktop.
trent monitor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { TwitterApi } from 'twitter-api-v2'; | |
import { Configuration, OpenAIApi } from 'openai'; | |
import yargs from 'yargs'; | |
import { hideBin } from 'yargs/helpers'; | |
import TelegramBot from 'node-telegram-bot-api'; | |
import * as dotenv from 'dotenv'; | |
dotenv.config(); | |
enum Victim { | |
FIREDANCER = 'Firedancer', | |
SOLAYER = 'Solayer', | |
ECLIPSE = 'Eclipse', | |
FOGO = 'Fogo', | |
} | |
interface TweetAnalysisResult { | |
victim: Victim | null; | |
confidence: number; | |
explanation: string; | |
} | |
class TwitterMonitor { | |
private twitterClient: TwitterApi; | |
private openaiClient: OpenAIApi; | |
private telegramBot: TelegramBot | null = null; | |
private telegramChatId: string | null = null; | |
constructor(twitterBearerToken: string, openaiApiKey: string, telegramToken?: string, telegramChatId?: string) { | |
this.twitterClient = new TwitterApi(twitterBearerToken); | |
const configuration = new Configuration({ | |
apiKey: openaiApiKey, | |
}); | |
this.openaiClient = new OpenAIApi(configuration); | |
if (telegramToken) { | |
this.telegramBot = new TelegramBot(telegramToken, { polling: false }); | |
this.telegramChatId = telegramChatId || null; | |
} | |
} | |
async monitorUser(username: string = "trentdotsol", limit: number = 10): Promise<void> { | |
try { | |
const user = await this.twitterClient.v2.userByUsername(username); | |
if (!user.data) { | |
throw new Error(`User ${username} not found`); | |
} | |
const userId = user.data.id; | |
const tweets = await this.twitterClient.v2.userTimeline(userId, { | |
max_results: limit, | |
exclude: ['retweets', 'replies'] | |
}); | |
for (const tweet of tweets.data.data) { | |
const analysis = await this.analyzeTweet(tweet.text); | |
const message = ` | |
Tweet: ${tweet.text} | |
Analysis: | |
${analysis.victim ? `Target: ${analysis.victim}` : 'No specific target identified'} | |
Confidence: ${analysis.confidence}% | |
Explanation: ${analysis.explanation} | |
`; | |
console.log(message); | |
if (this.telegramBot && this.telegramChatId) { | |
await this.telegramBot.sendMessage(this.telegramChatId, message); | |
} | |
} | |
} catch (error) { | |
console.error('Error monitoring Twitter:', error); | |
if (this.telegramBot && this.telegramChatId) { | |
await this.telegramBot.sendMessage(this.telegramChatId, `Error monitoring Twitter: ${error}`); | |
} | |
} | |
} | |
private async analyzeTweet(tweetText: string): Promise<TweetAnalysisResult> { | |
try { | |
const prompt = ` | |
Analyze the following tweet and picture and determine if it's targeting any of these projects: | |
- Firedancer | |
- Solayer | |
- Eclipse | |
- Fogo | |
Tweet: "${tweetText}" | |
If the tweet is targeting one of these, identify which one, provide a confidence score (0-100), | |
and explain your reasoning. If it's not targeting any of them, indicate that. | |
`; | |
const response = await this.openaiClient.createChatCompletion({ | |
model: "gpt-4o-mini", | |
messages: [ | |
{ role: "system", content: "You are an expert at analyzing tweets about project." }, | |
{ role: "user", content: prompt } | |
], | |
}); | |
const content = response.data.choices[0]?.message?.content || ''; | |
return this.parseGptResponse(content); | |
} catch (error) { | |
console.error('Error analyzing tweet with GPT:', error); | |
return { | |
victim: null, | |
confidence: 0, | |
explanation: 'Error analyzing tweet' | |
}; | |
} | |
} | |
private parseGptResponse(response: string): TweetAnalysisResult { | |
let victim: Victim | null = null; | |
let confidence = 0; | |
let explanation = ''; | |
// Look for mentions of each victim | |
for (const v of Object.values(Victim)) { | |
if (response.includes(v)) { | |
victim = v as Victim; | |
break; | |
} | |
} | |
// Extract confidence score if present | |
const confidenceMatch = response.match(/confidence[:\s]+(\d+)/i); | |
if (confidenceMatch && confidenceMatch[1]) { | |
confidence = parseInt(confidenceMatch[1], 10); | |
} | |
// Extract explanation | |
const explanationMatch = response.match(/reasoning[:\s]+(.*)/i); | |
if (explanationMatch && explanationMatch[1]) { | |
explanation = explanationMatch[1].trim(); | |
} else { | |
explanation = response; // Use full response if no specific explanation found | |
} | |
return { | |
victim, | |
confidence, | |
explanation | |
}; | |
} | |
} | |
async function main() { | |
const argv = await yargs(hideBin(process.argv)) | |
.option('username', { | |
alias: 'u', | |
description: 'Twitter username to monitor', | |
type: 'string', | |
default: 'trentdotsol' | |
}) | |
.option('limit', { | |
alias: 'l', | |
description: 'Number of tweets to analyze', | |
type: 'number', | |
default: 10 | |
}) | |
.help() | |
.alias('help', 'h') | |
.argv; | |
const twitterToken = process.env.TWITTER_BEARER_TOKEN; | |
const openaiToken = process.env.OPENAI_API_KEY; | |
const telegramToken = process.env.TELEGRAM_BOT_TOKEN; | |
const telegramChatId = process.env.TELEGRAM_CHAT_ID; | |
if (!twitterToken || !openaiToken) { | |
console.error('Missing required environment variables. Please set TWITTER_BEARER_TOKEN and OPENAI_API_KEY.'); | |
process.exit(1); | |
} | |
const monitor = new TwitterMonitor( | |
twitterToken, | |
openaiToken, | |
telegramToken, | |
telegramChatId | |
); | |
while (true) { | |
await monitor.monitorUser(argv.username, argv.limit); | |
await new Promise(resolve => setTimeout(resolve, 1000)); | |
} | |
} | |
main().catch(error => { | |
console.error('Error in main execution:', error); | |
process.exit(1); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment