DEV Community

Cover image for Creating a Twitter bot in Python using Twitter APIv2 πŸš€πŸš€
Dhravya
Dhravya

Posted on

Creating a Twitter bot in Python using Twitter APIv2 πŸš€πŸš€

When I was migrating @poet_this twitter bot to use the Twitter API v2, I wasn't able to find any good tutorials that do it, atleast none that worked properly. After the bot's success, many people reached out to me asking how they can also create a twitter by themselves! I'm here to help :)

πŸ€” What we're building

Let's create a twitter bot that replies whenever someone mentions the bot. To keep this simple, we'll just reply with the same text but capitalized.

What we wanna do:
(original_uploader): This is a cool tweet
(commenter): @ bot (*mentions the bot)
(bot): THIS IS A COOL TWEET

At the end of this tutorial, I'll also include ways to add more cool features to this, and some ideas for your own cool twitter bot!

⚑ Getting started

First of all, you'll need a Twitter developer account. Sign up for one on Twitter Developer dashboard

Here's a step-by-step guide by Twitter

Alright, once we're done with that...

Let's create a new python project!

Setting up the project

I recommend working in a virtual environment. Create a new folder, and open the terminal and use this command

python -m venv env
Enter fullscreen mode Exit fullscreen mode
env/Scripts/activate // on windows
source env/bin/activate // on linux
Enter fullscreen mode Exit fullscreen mode

Finally we just need to install the dependencies,

pip install python-dotenv python-twitter-v2
Enter fullscreen mode Exit fullscreen mode

That is the only two dependencies we really need right now. python-dotenv to use environment variables, and python-twitter-v2 to interact with the twitter API!

πŸ” Authenticating with Twitter

To authenticate with the twitter API with the bot's twitter account, we'll need a few things...

  • Consumer key (From developer dashboard)
  • Consumer secret (From developer dashboard)
  • Access token
  • Access token secret

Technically you can also use a bearer token, but let's keep it simple for now.

To get access token and secret (for testing), you can create them in the dashboard here:

Access token and secret

Make sure that you have the Read and Write permissions, we need that for the bot.

(If you want to control another account, for example, a bot account, follow these steps to get the access token/secret for another account - https://developer.twitter.com/en/docs/authentication/oauth-1-0a/obtaining-user-access-tokens)

Once we have all these tokens, create a file, .env and fill it in, in this fashion -

CONSUMER_KEY=...
CONSUMER_SECRET=...
ACCESS_TOKEN=...
ACCESS_TOKEN_SECRET=...
Enter fullscreen mode Exit fullscreen mode

πŸ‘¨πŸ»β€πŸ’» Let's start with the code now!

Let's break the problem into little pieces...

We want to,

  • Authenticate with Twitter API
  • Listen for all mentions
  • Reply!

Cool, first, let's authenticate

import pytwitter
from os import environ as env
from dotenv import load_dotenv

load_dotenv() # Loads the .env file we created earlier

api = pytwitter.Api(
    consumer_key=env["CONSUMER_KEY"],
    consumer_secret=env["CONSUMER_SECRET"],
    access_token=env["OAUTH_TOKEN"],
    access_secret=env["OAUTH_TOKEN_SECRET"],
)
Enter fullscreen mode Exit fullscreen mode

You can check if the bot is properly authenticated by using some endpoint, for example,

print(api.get_user(username="Twitter"))
# Should print Response(data=User(id='783214', name='Twitter', username='Twitter'))
Enter fullscreen mode Exit fullscreen mode

Now let's listen for mentions.
There's one thing to keep in mind though - we don't want to reply to ALL mentions. This is because how Twitter works.

Let's say, I make a tweet and someone comments on it
@DhravyaShah: Hello world!
@SomeOtherRandomUser: Hi Dhravya!

But, instead of just being "Hi Dhravya", it looks like this-
@DhravyaShah: Hello world!
@SomeOtherRandomUser: @DhravyaShah Hi Dhravya!

Notice the difference? This can be a problem in a twitter bot, where it will reply even to the comments under the bot.
We'll fix this by checking if the text is ONLY mentioning the bot, and nothing else.

How? Just remove all the mentions and check for an empty string!


last_tweet_id = 0 # Just a variable to keep track of the last tweet we replied to.

if __name__ == "__main__":

    while True:
        try:
            mentions = api.get_mentions(
                user_id=str(BOT_ID), # get bot id from tweeterid.com
                return_json=True,
                since_id=str(last_tweet_id),
                tweet_fields=[
                    "conversation_id",
                    "entities"
                ]
            )


            if not isinstance(mentions, dict):
                continue
Enter fullscreen mode Exit fullscreen mode

Cool, now we get a constant stream of mentions, well not really. We get all the mentions after since_id.

These mentions actually contain a LOT of data. I wanna keep it short so I won't get into the details, but feel free to print() this once and look through all the fields provided!

Now let's check if there's any data and it has the includes too (includes has all the extra entities)


    if not "data" in mentions.keys():
        continue # There's no more tweets

    for tweet in mentions["data"]:
        text = tweet["text"]
        reply_to = tweet["id"]

        # If it's not a reply to another tweet
        if not (tweet["conversation_id"] == tweet["id"]):
            if str(tweet["in_reply_to_user_id"]) == str(BOT_ID):
                continue

            # Get the parent tweet
            tweet_ = api.get_tweet(return_json=True,tweet_id=tweet["referenced_tweets"][0]["id"])
            text = tweet_["text"]


        # If tweet is a reply, it's in the format "@user @user @bot"
        users = [
                  mention["username"] for mention in tweet["entities"]["mentions"]
        ]
        new_txt = tweet["text"]
        # Remove all mentions in the start
        for user in users:
            new_txt = new_txt.replace(f"@{user}", "")

        new_txt = new_txt.strip()
Enter fullscreen mode Exit fullscreen mode

If new_txt is "" (empty), that means it's a "direct mention" - just a "@bot" comment. If it's a direct mention, the bot has been explicitly called, which means we can respond.


if (new_txt == ""):
    api.create_tweet(text=text.upper(), reply_in_reply_to_tweet_id = reply_to

Enter fullscreen mode Exit fullscreen mode

And finally, let's close the loop and also update the last_tweet_id to the new, last_tweet_id


            if "meta" in mentions.keys():
                if "newest_id" in mentions["meta"].keys():
                    last_tweet_id = mentions["meta"]["newest_id"]

    time.sleep(10)
Enter fullscreen mode Exit fullscreen mode

That's basically it! Here's the full code in a Github gist

You can add more features to the bot my adding "Keywords", just like how @poet_this works on twitter - The comment "@poet_this blue 2" (blue 2 being the keyword) generates that particular style of image.

Finally...

This was just a quick rundown, but now...
Try making a bot yourself! It's a very fun and rewarding process, and you'll learn a lot through it.

Thanks for reading!
You can support me by sponsoring me on Github - https://github.com/sponsors/Dhravya
You can follow me on Twitter - https://twitter.com/dhravyashah

Top comments (28)

Collapse
 
andypiper profile image
Andy Piper

Nice post, thanks for sharing! It is a little different, but if you don’t currently need to upload media for your bot, I’d recommend using OAuth 2.0 for your user authentication (Twitter is moving away from OAuth 1.0A in general for the v2 APIs) - what you’ve got here will work fine, but if your bot in the future needs access to specific new scopes for new features, it will need to use OAuth 2.0.

Collapse
 
dhravya profile image
Dhravya

Ohh- I didn't know that

This tutorial has a bit of the code i wrote for the twitter bot, which does need to upload media, which is probably why I wrote that bit a couple months ago.

Thanks for the feedback! Really appreciate it.

Collapse
 
dhravya profile image
Dhravya

Hey Andy! sorry for reaching out to you like this - but I figured you're the best person to ask. I am aware that you don't work at twitter now, but the understanding of the API might help me.

So, twitter keeps banning the bot for unsolicited mentions. I'm using the same exact code for @poet_this, is there anything that you think im doing wrong?

Your help would be insanely useful πŸ™ Ive been struggling with this since almost a month now

Collapse
 
andypiper profile image
Andy Piper

Unfortunately I don’t know how the anti spam system is configured now so I can only suggest removing mentions from the bot. Otherwise you’ll have to ask Elon πŸ‘Ž

Collapse
 
devgancode profile image
Ganesh Patil

Great article @dhravya ✌

Collapse
 
dhravya profile image
Dhravya

Thank you!

Collapse
 
farandg profile image
Comment marked as low quality/non-constructive by the community. View Code of Conduct
GF

Seriously ? No part of the code works and it's "great" ? I'm starting to suspect this fraudster has friends helping him...

Collapse
 
dhravya profile image
Dhravya

code doesn't work? fraudster? lolll

and yes, I do have friends, because I'm not the type of person who would create a Dev account and try everything they can to hurt a random person.

if you don't like my blogs, don't read them! starting to think you're just jealous

Thread Thread
 
farandg profile image
Comment marked as low quality/non-constructive by the community. View Code of Conduct
GF

Devolving to grade-school comebacks now, are we ? You're as crap at that as you are at code. Did you get help from your little brother?
I expose you so I must be jealous, right ? Truth is just don't like little shits like you.

Thread Thread
 
dhravya profile image
Dhravya

the fact that I'm talking respectfully and you're not, just proves my point

Thread Thread
 
farandg profile image
GF

Your point being that you don't have one. Not the hardest thing to prove, mate...

Collapse
 
edson profile image
Edson Bittencourt

Hi @dhravya, great job. I think there's a mistake in environment vars. The tutorial says to create a file and declare ACCESS_TOKEN, but it's loading OAUTH_TOKEN in the code.

Collapse
 
dhravya profile image
Dhravya

Oops my bad! I'll edit that bit

Collapse
 
farandg profile image
GF

It's nearly four months later and you still haven't. Do you need help understanding your mistake ?

Thread Thread
 
dhravya profile image
Dhravya

you literally just created an account to insult me lmao get a life

Thread Thread
 
farandg profile image
Comment marked as low quality/non-constructive by the community. View Code of Conduct
GF

Yup! I thrive in putting little shits like you back in their place. Your disgracing the coder community

Thread Thread
 
dhravya profile image
Dhravya

ah yes the gatekeeper

Thread Thread
 
farandg profile image
GF

I wouldn't call myself that. I don't have your arrogance, you see...
I just spot frauds

Collapse
 
dhravya profile image
Dhravya

I'm planning to write more tutorials and content in the near future.

If you guys have any queries regarding this tutorial, feel free to ask here in the comments!

Collapse
 
farandg profile image
GF

My request: please don't

Collapse
 
edson profile image
Edson Bittencourt

Great

Collapse
 
aneeqakhan profile image
Aneeqa Khan

Great article @dhravya

Collapse
 
todaydate_ profile image
Today's Date

Hi Bro Can You Give me Your Poet this bot codes ??

Some comments may only be visible to logged-in visitors. Sign in to view all comments.