DEV Community

Cover image for I Built a Twitter Bot So I Don't Have to Check Twitter Every 5 Minutes!
Suvin Nimnaka
Suvin Nimnaka

Posted on

I Built a Twitter Bot So I Don't Have to Check Twitter Every 5 Minutes!

Picture this. You've built an amazing product. You're proud of it. Your mom's proud of it. Even your cat seems impressed (though cats are notoriously hard to please). But here's the thing: people are talking about your product on Twitter (well, “X” now, but let’s be real, we’re all still calling it Twitter), and you have absolutely no idea what they're saying.

Sure, you could spend your entire day doom-scrolling through Twitter, searching for mentions of your product. But let's be honest. That's about as appealing as watching paint dry in slow motion. Plus, you've got actual work to do, like building more amazing features or figuring out why the coffee machine in the office keeps making that weird noise.

The solution? Build a bot that watches Twitter for you and sends updates directly to your team's Google Chat. It's like having a really dedicated intern who never sleeps, never complains, and never eats your lunch from the office fridge.

What We're Building

We're creating a Node.js service that:

  1. Monitors Twitter for tweets containing your product's hashtag.
  2. Forwards the juicy details to your Google Chat workspace.
  3. Runs once, exits, and repeats the same every 15 minutes.
  4. Does all this without you having to touch Twitter with a 10-foot pole.

Prerequisites (The boring, necessary stuff)

Before we dive into the fun part, make sure you have:

  • Node.js installed (version 14 or higher – we're not animals here)
  • A Twitter Developer Account
  • A Google Chat workspace (or the ability to create webhooks in one)
  • A Choreo Account. If you don't have one, sign up for free at https://console.choreo.dev/signup.

Step 1: Setting Up Your Twitter API Access

First things first. You need to get cozy with the Twitter API. Don't worry, it's not as scary as it sounds.

  1. Head over to developer.twitter.com.
  2. Create an app (call it something cool like "HashtagWatcher3000").
  3. Generate a Bearer Token.
  4. Keep that token safe.

Step 2: Google Chat Webhook Setup

Now let's set up the delivery mechanism – Google Chat webhooks.

  1. Go to your Google Chat space.
  2. Click on the space name → "Manage webhooks".
  3. Create a new webhook.
  4. Copy that URL and note it down somewhere.

Step 3: Project Setup (The Base)

Create a new directory and initialize your project:

mkdir twitter-hashtag-monitor
cd twitter-hashtag-monitor
npm init -y
Enter fullscreen mode Exit fullscreen mode

Install the dependencies we'll need:

npm install axios dotenv
Enter fullscreen mode Exit fullscreen mode

Why these packages?

  • axios: For making HTTP requests
  • dotenv: For managing environment variables (keeping secrets secret)

Step 4: Environment Configuration

Create a .env file to store your sensitive information:

TWITTER_BEARER_TOKEN=your_actual_bearer_token_here
GOOGLE_CHAT_WEBHOOK_URL=your_webhook_url_here
HASHTAG=#yourproducthashtag
Enter fullscreen mode Exit fullscreen mode

And create a .gitignore file just to make sure you don't accidentally commit your API keys.

node_modules
.env
Enter fullscreen mode Exit fullscreen mode

Important: Never, ever, EVER commit your .env file to version control. That's like leaving your house key under the doormat with a note saying "free stuff inside."

Step 5: The Main Event – Building the Bot

Now for the fun part! Create an index.js file.

require("dotenv").config();
const axios = require("axios");

// Configuration object (keeping configs organized)
const config = {
    bearerToken: process.env.TWITTER_BEARER_TOKEN,
    googleChatWebhookUrl: process.env.GOOGLE_CHAT_WEBHOOK_URL,
    hashtag: process.env.HASHTAG || "#choreoisawesome", // Default hashtag
    checkInterval: 15, // minutes to look back
    maxResults: 10,
    twitterServiceUrl: "https://api.twitter.com/2/tweets/search/recent",
};
Enter fullscreen mode Exit fullscreen mode

The Tweet Search Function

This function is the heart of our operation:

async function searchTweets() {
    try {
        const now = new Date();
        // Twitter needs a 10-second buffer, so we use 20 to be safe
        const endTime = new Date(now.getTime() - 20 * 1000);
        const timeAgo = new Date(endTime.getTime() - config.checkInterval * 60 * 1000);

        const params = {
            query: config.hashtag,
            start_time: timeAgo.toISOString(),
            end_time: endTime.toISOString(),
            max_results: config.maxResults,
            "tweet.fields": "created_at,author_id,public_metrics,text",
            "user.fields": "username,name",
        };

        const response = await axios.get(config.twitterServiceUrl, {
            headers: {
                Authorization: `Bearer ${config.bearerToken}`,
            },
            params,
        });

        return response.data.data || [];
    } catch (error) {
        console.error("Error searching tweets:", error.response?.data || error.message);
        return [];
    }
}
Enter fullscreen mode Exit fullscreen mode

What's happening here?

  • We create a time window (last 15 minutes, but ending 20 seconds ago)
  • We ask Twitter for tweets containing our hashtag in that timeframe
  • We request additional fields like metrics and user info (because context matters)
  • If something goes wrong, we gracefully return an empty array instead of crashing

To learn more about the search API, head over to the Search Recent Posts API on X API Documentation.

The Google Chat Messenger

This function takes our Tweet data and formats it nicely for Google Chat.

async function sendTweetsToService(tweets) {
    if (tweets.length === 0) {
        console.log("No tweets found in the last", config.checkInterval, "minutes");
        return;
    }

    try {
        const tweetToSend = tweets[0]; // We only send the first tweet for now
        console.log(`Found ${tweets.length} tweet(s), sending the first one to Google Chat`);

        // Format message for Google Chat
        const message = {
            text:
                `🐦 New Tweet Found!\n\n` +
                `*Hashtag:* ${config.hashtag}\n` +
                `*Author:* ${tweetToSend.username || tweetToSend.author_id}\n` +
                `*Created:* ${tweetToSend.created_at}\n\n` +
                `*Tweet:*\n${tweetToSend.text}\n\n` +
                `*Metrics:* ❤️ ${tweetToSend.public_metrics?.like_count || 0} | 🔁 ${
                    tweetToSend.public_metrics?.retweet_count || 0
                }`,
        };

        const response = await axios.post(config.googleChatWebhookUrl, message, {
            headers: {
                "Content-Type": "application/json",
            },
        });

        console.log("Successfully sent tweet to Google Chat");

        // Mission accomplished – time to exit
        console.log("Tweet sent successfully. Stopping the service...");
        process.exit(0);
    } catch (error) {
        console.error("Error sending tweet to Google Chat:", error.response?.data || error.message);
    }
}
Enter fullscreen mode Exit fullscreen mode

Pro Tip: Instead of just sending a text message to Google Chat, you can send nicely formatted cards. Check the Google Chat Cards Documentation for more information.

Tying It All Together

async function checkAndSendTweets() {
    console.log(`\n[${new Date().toISOString()}] Checking for tweets with hashtag: ${config.hashtag}`);

    const tweets = await searchTweets();
    await sendTweetsToService(tweets);
}

function startMonitoring() {
    console.log("Starting Twitter Hashtag Monitor");
    checkAndSendTweets(); // Run immediately
}

// Handle graceful shutdown (Ctrl+C)
process.on("SIGINT", () => {
    console.log("\nShutting down Twitter Hashtag Monitor...");
    process.exit(0);
});

// Start the service
startMonitoring();
Enter fullscreen mode Exit fullscreen mode

If you are too lazy to read the entire thing, here is the full source code: https://github.com/Suvink/fetch-tweets-from-hashtag

Step 6: Package.json Scripts

Add some convenient scripts to your package.json:

{
  "name": "twitter-hashtag-monitor",
  "version": "1.0.0",
  "description": "Service to monitor Twitter hashtags and forward tweets",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "dev": "node index.js"
  },
  "dependencies": {
    "axios": "^1.5.0",
    "dotenv": "^16.3.1"
  },
  "keywords": ["twitter", "api", "monitoring", "hashtag"],
  "author": "Tony Stark",
  "license": "MIT"
}
Enter fullscreen mode Exit fullscreen mode

Step 7: Testing Your Creation

Time to see if your digital creation comes to life.

npm start
Enter fullscreen mode Exit fullscreen mode

If everything is configured correctly, you should see:

  1. A log message indicating the bot is checking for tweets.
  2. Either a "no tweets found" message or a successful Google Chat notification.
  3. The process exits gracefully.

Important:
Twitter (X) API has very low rate limits (duh) for free accounts. You will only be able to search Tweets once every 15 minutes.

Step 8: Scheduling The Script on Choreo

Choreo is a fantastic platform for running scheduled tasks without the hassle of managing infrastructure. Here's how to deploy your task there.

Before following the below steps, make sure you commit your code to GitHub.

Step 8.1: Set Up Your Choreo Component

  1. Log into Choreo: Head over to console.choreo.dev and sign in with your account.
  2. Create a Component: Click on "Create Component" to start the magic.
  3. Choose Component Type: Select "Scheduled Task" as your component type.
  4. Link Your Repository: Connect your GitHub repository that contains the source code.
  5. Configure Build Settings:
    • Choose NodeJS as your Build Preset.
    • Select your preferred Node.js version.
  6. Click Create: Hit that create button and let Choreo work its magic

Choreo Component Creation

Step 8.2: Wait for the Build

Once your component is created, Choreo will start building your project:

  • Go to Build page from the left menu.
  • Watch the build process complete (grab another coffee while you wait).
  • Make sure the build status shows as successful.

Step 8.3: Configure and Deploy

Now comes the fun part. Deployment!

  1. From the left menu, click on "Deploy".
  2. Click the "Configure and Deploy" button.
  3. Environment Configurations:
    • In the pop-up drawer, click "Add Configuration"
    • Add your environment variables from your .env file:
      • TWITTER_BEARER_TOKEN: Your Twitter API bearer token
      • GOOGLE_CHAT_WEBHOOK_URL: Your Google Chat webhook URL
      • HASHTAG: Your product hashtag (e.g., #choreoisawesome)
  4. Click Next: Move to the scheduling configuration
  5. Set Schedule:
    • In the schedule drawer, set it to run every 15 minutes
    • This ensures the task is compatible with Twitter API rate limits :(

Scheduling a task in Choreo

  1. Hit (just press!) that deploy button and watch your task come to life!

Step 8.4: Monitoring the Execution

Want to see your bot in action?

  • Go to Execute from the left menu
  • Check the execution history to see when your bot runs
  • View execution logs to see if tweets are being found and sent
  • Monitor for any errors or issues

Task execution page on Choreo

Why Choreo is awesome for this:

  • No server management headaches
  • Built-in scheduling (no cron jobs needed)
  • Easy environment variable management
  • Execution history and logging out of the box
  • Scales automatically (though our bot is pretty lightweight)

Conclusion (The Part Where I Wrap This Up)

And there you have it! You've just built a Twitter monitoring bot that saves you from the endless scroll of social media doom. Your bot will dutifully watch Twitter for mentions of your product and deliver the good news (or constructive feedback) straight to your team's Google Chat.

No more FOMO about what people are saying about your product. No more manual searching through Twitter. No more wondering if that one customer actually liked your latest feature.

Just pure, automated, social media monitoring bliss.

Now go forth and monitor those hashtags! And maybe treat yourself to a cheesecake from Barista. You've earned it.


P.S. - If this helped you become the office hero, consider buying me a coffee or simply putting a reaction!

Buy Me A Coffee

Top comments (0)