Gemini Twitter Bot With Encore.ts
Talha Ahsan
Posted on September 26, 2024
Introduction: What is the Gemini Twitter Bot?
The Gemini Twitter Bot is an automated tool that posts tweets every hour using content generated by Google Gemini. It’s built with Encore.ts, allowing you to create and publish tweets without having to do it manually.
Why Use the Gemini Twitter Bot?
Automating your Twitter posts can save you a lot of time. If you want to keep your Twitter account active without constantly logging in to post, this bot is a great solution. Thanks to the dynamic content from Google Gemini, each tweet is unique and engaging. This bot is ideal for:
- Developers interested in Twitter automation projects.
- Content creators who want to simplify their social media posting.
- Anyone with basic coding skills looking to learn about automation.
Who Can Benefit from This Bot?
This bot is designed for developers, content creators, or anyone eager to explore automation in their Twitter activities. It’s especially useful for those wanting to combine automation with creative AI content generation.
Why Choose Encore.ts?
Encore.ts is an open-source framework that helps build backends using TypeScript in a type-safe manner. It has no NPM dependencies, making it lightweight and fast. Because it’s built on Rust, Encore.ts can be up to 9 times faster than other frameworks like Express.js.
Encore.ts also simplifies app deployment. You can self-host using Docker or use the Encore Cloud Platform for automated deployments. If you're looking for a solution that focuses on performance, scalability, and type safety, Encore.ts is the way to go.
Prerequisites: What You Need to Get Started
Before diving into the Gemini Twitter Bot, make sure you have the following:
-
Encore.ts: Install Encore by following the instructions for your operating system:
-
Mac: Run
brew install encoredev/tap/encore
-
Windows: Run
iwr https://encore.dev/install.ps1 | iex
-
Linux: Run
curl -L https://encore.dev/install.sh | bash
-
Mac: Run
-
Twitter Developer Account: Sign up and get your API keys at the Twitter Developer Portal.
- You will need a Twitter API Key, API Secret, Access Token, and Access Token Secret.
Google Gemini API Key: Create an account at Google Cloud Console to get your Gemini API key for tweet generation.
-
Dependencies: Install these libraries:
- twitter-api-v2: For interacting with the Twitter API.
- @google/generative-ai: For generating content with Google Gemini.
Make sure everything is set up before moving on!
Step-by-Step Guide: Building Your Gemini Twitter Bot
1. Install Encore.ts
If you’re new to Encore.ts, here’s how to get started:
- Visit Encore's website and click Get Started.
- Sign up or log in if you already have an account.
- Depending on your operating system, follow these steps to install Encore.ts:
-
For Mac: Run
brew install encoredev/tap/encore
-
For Windows: Run
iwr https://encore.dev/install.ps1 | iex
-
For Linux: Run
curl -L https://encore.dev/install.sh | bash
-
For Mac: Run
After installation, create your bot app with the command:
encore app create my-twitter-bot
Choose TypeScript as your language and select Empty App as the template.
2. Set Up Your Twitter and Gemini Credentials
Once your Encore app is created, securely store your credentials using Encore’s secret storage:
- Set your Twitter API credentials:
encore secret set TwitterAPIKey --type dev,local,pr,prod
encore secret set TwitterAPISecret --type dev,local,pr,prod
encore secret set TwitterAccessToken --type dev,local,pr,prod
encore secret set TwitterAccessSecret --type dev,local,pr,prod
- Set your Gemini API key:
encore secret set GeminiAPIKey --type dev,local,pr,prod
3. Run Your Bot Locally
Now that your app and credentials are set up, you can run your bot locally:
encore run
This command will build and start your app. You can view the bot's activity in real-time at http://localhost:4000.
WorkFlow of Bot
Setting Up the Service in Encore.ts
Encore.ts simplifies the process of defining services, whether you’re working with a single service or developing a microservices architecture.
Creating a Service
To create a service in Encore.ts, just add a file called encore.service.ts
to your project directory. Here’s a simple example from this project:
import { Service } from "encore.dev/service";
export default new Service("twitterService");
In this code, we define a service named twitterService
. Encore will automatically include everything in this directory and its subdirectories as part of the service. This means you don’t have to worry about configuring each file individually.
Choosing Between a Monolith and Microservices
You can start with one service and expand as your project grows. Here’s how you might approach this:
Single Service: In a simple setup, your
twitterService
could handle all Twitter-related tasks, such as posting tweets and managing scheduling.-
Microservices: As your application expands, you might want to break down
twitterService
into smaller, more focused services. For instance:- A tweetService that specifically handles posting tweets.
- A scheduleService that manages when posts should go live.
This flexible architecture allows you to scale your application without dealing with complicated infrastructure. You can add new services as needed, keeping your code organized and manageable.
For more details, check out the Encore documentation on services.
Integrating Twitter API and Google Gemini API
To connect your application with the Twitter API and Google Gemini API, you'll need to securely store your API keys and create the necessary clients in the same directory as your encore.service.ts
file.
1. Setting Up the Twitter API
First, import the TwitterApi
from the twitter-api-v2
package. Use Encore's secret management feature to access your Twitter API credentials securely:
import { TwitterApi } from "twitter-api-v2";
import { secret } from "encore.dev/config";
// Retrieve Twitter API keys from Encore's secret storage
const appKey = secret("TWITTER_API_KEY");
const appSecret = secret("TWITTER_API_SECRET");
const accessSecret = secret("TWITTER_ACCESS_SECRET");
const accessToken = secret("TWITTER_ACCESS_TOKEN");
// Create a Twitter API client
export const xRWClient = new TwitterApi({
appKey: appKey(),
appSecret: appSecret(),
accessSecret: accessSecret(),
accessToken: accessToken(),
});
// Create a Read and Write Client
export const xClient = xRWClient.readWrite;
In this code:
- You import the necessary packages and retrieve the Twitter API keys using Encore’s secure secret management.
- The
xRWClient
is created to interact with the Twitter API, whilexClient
is a read-write client for posting tweets and accessing user timelines.
2. Setting Up the Gemini API
Next, configure the Google Gemini API using the @google/generative-ai
package:
import { GoogleGenerativeAI } from "@google/generative-ai";
import { secret } from "encore.dev/config";
// Retrieve Gemini API key from Encore's secret storage
const googleApi = secret("GEMINI_API_KEY");
// Create a Google Generative AI client
export const googleGenAI = new GoogleGenerativeAI(googleApi());
In this snippet:
- You import the necessary packages and retrieve the Gemini API key securely.
- The
googleGenAI
client is created to generate content using Google Gemini.
Organizing Your Directory Structure
Make sure that both the Twitter API and Gemini API setup code are in the same directory as your encore.service.ts
file. This organization allows Encore to effectively recognize and manage your services.
By following these steps, you'll successfully integrate both the Twitter API and Google Gemini API, laying the groundwork for your Twitter bot's functionalities.
For more information, refer to Encore's documentation on secret management.
Business Logic for Tweet Generation and Posting
In this section, we’ll dive into how we can generate and post tweets using both the Twitter API and Google Gemini API. We’ll do this through a class called TwitterService
, which handles everything related to tweet generation and posting.
Setting Up the TwitterService Class
Here’s what our TwitterService
class looks like:
import { googleGenAI } from "../twitter/client/setup/gemini.client.setup"; // Importing Google Gemini AI client
import { xClient } from "./client/setup/twitter.client.setup"; // Importing Twitter API client
export class TwitterService {
// Method to generate a tweet using Google Gemini AI
private async generateTweet(): Promise<string> {
const prompt = "Generate a funny, sarcastic tweet about crypto or coding frustrations.";
try {
// Specify the model for tweet generation
const model = googleGenAI.getGenerativeModel({
model: "gemini-1.5-flash"
});
// Generate content based on the prompt
const response = await model.generateContent(prompt);
return response.response.text() ?? 'Another day of coding!'; // Fallback message
} catch (error: unknown) {
console.error('Error generating tweet:', error instanceof Error ? error.message : error);
return 'Another day of coding!'; // Fallback message on error
}
}
// Method to post a dynamically generated tweet
public async dynamicTweet(): Promise<boolean> {
const tweet = await this.generateTweet(); // Generate the tweet
// Validate the generated tweet
if (!tweet || typeof tweet !== 'string' || tweet.trim() === '') {
console.error('Generated tweet is invalid:', tweet);
return false;
}
try {
// Post the tweet using Twitter API
const tweetResponse = await xClient.v2.tweet(tweet);
console.log("Tweet Posted -> ", tweetResponse.data);
return true; // Indicate success
} catch (error: unknown) {
console.error('Error posting tweet:', error instanceof Error ? error.message : error);
return false; // Indicate failure
}
}
}
Understanding the Class Methods
-
generateTweet
Method:- This private method is where the magic happens for tweet generation. We start by crafting a prompt that asks for a funny or sarcastic tweet, specifically about crypto or coding frustrations.
- We use the Google Gemini AI to generate content. If everything goes smoothly, we get a tweet back. But if there’s an issue, we’ve got a fallback—"Another day of coding!"—to keep things light.
-
dynamicTweet
Method:- This public method is our main action point for posting tweets. First, it calls
generateTweet()
to get our tweet content. - We check if the generated tweet is valid (not empty or null). If something seems off, we log an error and return
false
. - If everything looks good, we use the Twitter API to post the tweet. If that works, great! If not, we log the error and return
false
to indicate failure.
- This public method is our main action point for posting tweets. First, it calls
Directory Structure
Make sure the TwitterService
class lives in the same directory as your encore.service.ts
file. This way, Encore can easily find and manage your service.
By keeping things organized like this, we not only maintain clarity in our codebase but also make it easier to manage and expand in the future.
Creating the Twitter Controller
Now, let’s dive into setting up the TwitterController
. This is where we’ll define the controller function that handles incoming requests for posting tweets. It will work closely with our TwitterService
to generate and post tweets seamlessly.
Setting Up the TwitterController
Here’s what the TwitterController
looks like:
import { TwitterService } from "../twitter/twitter.service"; // Importing TwitterService
export class TwitterController {
private twitterService: TwitterService;
constructor() {
this.twitterService = new TwitterService(); // Instantiate TwitterService
this.post = this.post.bind(this); // Bind the post method
}
// Controller method to handle posting a tweet
public async post(): Promise<{ message: string }> {
try {
// Call the dynamicTweet method to post the tweet
const response = await this.twitterService.dynamicTweet();
// Check if the tweet posting was successful
if (!response) {
return { message: 'Failed to post tweet.' }; // Failure message
}
return { message: "Tweet Posted Successfully" }; // Success message
} catch (error: unknown) {
// Log error and return failure message
console.error('Error posting tweet:', error instanceof Error ? error.message : error);
return { message: 'Failed to post tweet.' }; // Failure message
}
}
}
Breaking It Down
Class Definition: The
TwitterController
class is all about managing the logic for handling tweet requests. It’s like the middleman between incoming requests and our tweeting functionality.Constructor: Inside the constructor, we create an instance of
TwitterService
. This is our go-to for all things related to tweet generation and posting. We also bind thepost
method to the current context, ensuring that it always has the rightthis
reference when called.-
The
post
Method: This is where the magic happens. It’s an asynchronous method that’s ready to handle requests for posting a tweet. Here’s the flow:- It starts by calling
this.twitterService.dynamicTweet()
, which generates and posts the tweet. - If the tweet posting fails for any reason, we return a failure message.
- But if it’s successful, we send back a success message to let the caller know everything went smoothly.
- We also catch any errors that might pop up during this process, log them for debugging, and return a failure message as well.
- It starts by calling
Creating the API Endpoint for Posting Tweets
Now it’s time to set up the API endpoint that will let users post tweets effortlessly. We’ll take advantage of the api
utility from Encore to define this endpoint and connect it to our TwitterController
.
Implementing the API
Here’s how to do it:
import { api } from "encore.dev/api"; // Importing the API utility from Encore
import { TwitterController } from "../controller/twitter.controller"; // Importing TwitterController
const twitterController = new TwitterController(); // Instantiate TwitterController
// Define the API endpoint for posting tweets
export const postTweet = api({
method: 'POST', // Specify the HTTP method
path: '/api/post/x/tweet', // Define the endpoint path
expose: true, // Set to true to allow external access
}, twitterController.post); // Connect the endpoint to the post method in TwitterController
Breaking It Down
-
Imports:
- First, we import the
api
function fromencore.dev/api
. This utility is our key to defining the API endpoint. - Next, we bring in the
TwitterController
, which will handle the logic for posting tweets.
- First, we import the
-
Controller Instance:
- We create an instance of
TwitterController
, allowing us to connect the API endpoint to its methods seamlessly.
- We create an instance of
-
API Definition:
- The
postTweet
constant holds our API definition. - We call the
api
function with an object that specifies:-
Method: We set this to
POST
, indicating that this endpoint is designed to handle POST requests. -
Path: We define the endpoint as
/api/post/x/tweet
, which is where clients will hit to post a tweet. -
Expose: This is set to
true
, meaning that anyone can access this API. If you want to keep it under wraps, you can change this tofalse
for internal use only.
-
Method: We set this to
- The
Usage Considerations
-
Exposing the API:
- By setting
expose
totrue
, you’re making this endpoint accessible to anyone. If your goal is to restrict access (for example, if it’s just for a cron job), you should switch this tofalse
.
- By setting
-
Cron Job Integration:
- If you’re planning to call this API from a cron job or another internal process without needing external access, simply set
expose
tofalse
to limit access to that endpoint.
- If you’re planning to call this API from a cron job or another internal process without needing external access, simply set
Setting Up a Cron Job for Tweet Posting
Let’s dive into setting up a cron job that will automatically post tweets at your chosen intervals! We’ll use the CronJob
class from encore.dev/cron
to handle the scheduling.
Implementing the Cron Job
Here’s how you can set it up:
import { CronJob } from "encore.dev/cron"; // Importing the CronJob class
import { postTweet } from "../apis/twitter.api"; // Importing the postTweet API
// Create a new CronJob for posting tweets
const tweetCronJob = new CronJob("Post-Tweet", {
every: "1h", // Set to run every hour
endpoint: postTweet // Connect the cron job to the postTweet API
});
Breaking It Down
-
Imports:
- We start by importing the
CronJob
class fromencore.dev/cron
. This class makes it super easy to schedule tasks. - Next, we import the
postTweet
API, which we’ll call from the cron job to actually post those tweets.
- We start by importing the
-
Setting Up the Cron Job:
- We create a new instance of
CronJob
and give it the name "Post-Tweet" for easy identification. - The
every
option is set to"1h"
, meaning our job will run every hour. - We link the cron job to the
postTweet
API with theendpoint
property, so it knows what to execute when it’s time to post.
- We create a new instance of
-
Starting the Cron Job:
- You can optionally start the cron job right away using
tweetCronJob.start()
. Depending on how your application is structured, you may want to control when this starts.
- You can optionally start the cron job right away using
Important Considerations
-
Deployment Requirement:
- Localhost Limitation: Keep in mind that cron jobs won’t run on localhost. To see this in action, you’ll need to deploy your application to a server that supports cron jobs.
-
Time Interval:
-
Even Distribution: When you’re setting the interval for your cron job, make sure it divides evenly into 24 hours. Valid intervals include
1h
,30m
,15m
, or5m
. -
Invalid Interval: Be careful with intervals like
7h
—those don’t divide evenly into 24 and will cause issues.
-
Even Distribution: When you’re setting the interval for your cron job, make sure it divides evenly into 24 hours. Valid intervals include
Examples of Valid Time Intervals
-
Valid:
- Every hour:
"1h"
- Every 30 minutes:
"30m"
- Every 15 minutes:
"15m"
- Every 5 minutes:
"5m"
- Every hour:
-
Invalid:
- Every 7 hours:
"7h"
(this doesn’t divide evenly)
- Every 7 hours:
Deploying Your Twitter Bot with Encore
Ready to take your Twitter bot live? Let’s walk through the steps to deploy your bot using Encore. It’s easier than you might think!
Steps to Deploy
-
Add Your Changes to Git:
- First things first, let’s stage all your changes. Run this command in your terminal:
git add .
-
Commit Your Changes:
- Now it’s time to commit those changes with a message that reflects what you’ve done. Use:
git commit -m "your-commit"
- Just replace
"your-commit"
with a descriptive phrase that sums up your changes. This helps you keep track of your progress!
-
Push to Encore:
- Finally, let’s deploy your application! Use this command to push your code to Encore:
git push encore
What Happens Next?
- After you run the deployment command, Encore takes over and handles the build and deployment for you. How convenient is that?
- Keep an eye on your terminal, as it will show you the deployment progress. If anything goes wrong, Encore will provide error messages to guide you through troubleshooting.
- Once everything is deployed successfully, your Twitter bot will be live and ready to start posting tweets on the schedule you set with the cron job!
Wrapping It Up
And that’s a wrap! You’ve successfully created and deployed your Twitter bot with Encore. If you’re eager to learn more, check out these helpful tutorials:
Feel free to explore these resources to deepen your understanding and enhance your bot!
Check Out the Source Code
If you want to see the code in action or even fork it for your own projects, here’s the link to the GitHub source code
Follow Bot on Twitter
Follow Twitter Bot account here: Bot Twitter Account
Thanks for reading, and happy coding!
Posted on September 26, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.