// Import necessary modules
const { TwitterApi } = require('twitter-api-v2');
// Configure Twitter client with authentication
const client = new TwitterApi({
appKey: process.env.API_KEY,
appSecret: process.env.API_SECRET_KEY,
accessToken: process.env.ACCESS_TOKEN,
accessSecret: process.env.ACCESS_TOKEN_SECRET,
});
// Client with read and write permissions
const rwClient = client.readWrite;
// Stores the authenticated bot user id (set in verifyBot)
let botUserId = null;
// Function to check if the bot is working
async function verifyBot() {
try {
// Get authenticated user information (X API v2)
const me = await rwClient.v2.me();
botUserId = me.data.id;
console.log(`Bot successfully initialized! User: @${me.data.username}`);
return true;
} catch (error) {
console.error('Error verifying bot:', error);
return false;
}
}
// Function to post a tweet
async function postTweet(text) {
try {
const tweet = await rwClient.v2.tweet(text);
console.log(`Tweet posted successfully! ID: ${tweet.data.id}`);
return tweet;
} catch (error) {
console.error('Error posting tweet:', error);
throw error;
}
}
// Function to respond to mentions
async function respondToMentions() {
if (!botUserId) return;
try {
// Fetch recent mentions (X API v2)
const mentions = await rwClient.v2.userMentionTimeline(botUserId, {
max_results: 10,
});
for (const tweet of mentions.data?.data ?? []) {
// Check if it's a new mention (implement control logic)
if (tweet.text.includes('!ping')) {
// Reply to the mention
await rwClient.v2.reply(
'Pong! 🤖 X Bot working correctly!',
tweet.id
);
console.log(`Replied to mention (tweet ID: ${tweet.id})`);
}
}
} catch (error) {
console.error('Error processing mentions:', error);
}
}
// Function to search and interact with specific tweets
async function searchAndInteract(query) {
if (!botUserId) return;
try {
// Search recent tweets (X API v2)
const tweets = await rwClient.v2.search(query, {
max_results: 10,
});
for (const tweet of tweets.data?.data ?? []) {
// Like the tweet
await rwClient.v2.like(botUserId, tweet.id);
console.log(`Liked tweet ID: ${tweet.id}`);
// Wait a bit between actions to avoid rate limiting
await new Promise(resolve => setTimeout(resolve, 2000));
}
} catch (error) {
console.error('Error searching and interacting:', error);
}
}
// Main bot function
async function runBot() {
console.log('Starting X bot...');
// Check if the bot is configured correctly
const botOk = await verifyBot();
if (!botOk) {
console.error('Bot initialization failed');
return;
}
// Example: Post an initialization tweet
try {
await postTweet('🤖 X Bot initialized and running on Square Cloud!');
} catch (error) {
console.log('Initialization tweet failed, but bot continues running');
}
// Main bot loop
setInterval(async () => {
try {
// Check and respond to mentions every 5 minutes
await respondToMentions();
// Example: Search and interact with tweets about a specific topic
// await searchAndInteract('#SquareCloud');
} catch (error) {
console.error('Error in main loop:', error);
}
}, 5 * 60 * 1000); // 5 minutes
console.log('Bot running. Press Ctrl+C to stop.');
}
// Signal handling for graceful shutdown
process.on('SIGINT', () => {
console.log('\nShutting down X bot...');
process.exit(0);
});
process.on('SIGTERM', () => {
console.log('\nShutting down X bot...');
process.exit(0);
});
// Initialize the bot
runBot();