Skip to content

Latest commit

 

History

History
274 lines (188 loc) · 8.3 KB

reply_bot.rst

File metadata and controls

274 lines (188 loc) · 8.3 KB

Submission Stream Reply Bot

Most redditors have seen bots in action on the site. Reddit bots can perform a number of tasks including providing useful information, e.g., an Imperial to Metric units bot; convenience, e.g., a link corrector bot; or analytical information, e.g., redditor analyzer bot for writing complexity.

PRAW provides a simple way to build your own bot using the python programming language. As a result, it is little surprise that a majority of bots on Reddit are powered by PRAW.

This tutorial will show you how to build a bot that monitors a particular subreddit, /r/AskReddit, for new submissions containing simple questions and replies with an appropriate link to lmgtfy (Let Me Google This For You).

There are three key components we will address to perform this task:

  1. Monitor new submissions.
  2. Analyze the title of each submission to see if it contains a simple question.
  3. Reply with an appropriate lmgtfy link.

LMGTFY Bot

Our goal is to point users in the right direction when they ask a simple question that is unlikely to be upvoted or answered by other users.

An example of such questions are:

  1. "What is the capital of Canada?"
  2. "How many feet are in a yard?"

Once we identify these questions, our bot will reply to the submission with an appropriate lmgtfy link. For the example questions those links are:

  1. http://lmgtfy.com/?q=What+is+the+capital+of+Canada%3F
  2. http://lmgtfy.com/?q=How+many+feet+are+in+a+yard%3F

Step 1: Getting Started

Let's start by setting up a basic PRAW instance:

import praw

r = praw.Reddit(user_agent='Let me Google that for you Bot',
                client_id='CLIENT_ID', client_secret="CLIENT_SCRET",
                username='USERNAME', password='PASSWORD')

As usual, you will need an Oauth client_id and client_secret key for your bot (See Oauth set-up instructions here).

Additionally, you'll need to supply the credentials of your bot's account in the form of the "username" and "password" variables passed to the main Reddit instance.

Step 2: Monitoring New Submissions and Obtaining their Titles

To get the submissions to a subreddit, we simply need to call the subreddit method of our "r" object, like so:

subreddit= r.subreddit('askreddit').new(limit=100)

The limit here is 100 by default (so you could remove it), but you could change it if desired.

This code creates a lazy-loaded subreddit object.

Next, we'll need to extract the submission ids for each submission in the subreddit.

Here's how:

ids=[]
for submission in subreddit:
    ids.append(submission.id)

Once we have the ids, we can create a submission object for each submission, and extract/store the titles.

for id_number in ids:
    submission = r.submission(id=id_number)
    title = submission.title.lower()

Step 3: Analyzing the Titles

Now that we have the titles of the submissions in the "new" feed of /r/AskReddit, it's time to see if they contain a simple question in them.

This might mean that they contain strings like:

  • "what is"
  • "who is"
  • "what are"

And so on...You could get a lot for complicated, even considering title length. However, for the sake of this example, these 3 phrases will be enough.

Create an array that contains these strings.

questions  = ['what is', 'who is', 'what are']

Then, let's revisit our for-loop from above and check to see if the titles contain any of these:

for id_number in ids:
    submission = r.submission(id=id_number)
    title = submission.title.lower()
    for question_type in questions:
        if question_type in title:
            #make the reply

Step 4: Automatically Replying to the Submission

We're almost there, the last part is to make a reply request to the Reddit API. Thankfully, it's really simple with PRAW.

But first, we'll need to figure out what link to send people to in our comments.

By analyzing the lmgtfy links from earlier, the main things we need to do is change spaces to "+", and question marks to "%3F" (http://lmgtfy.com/?q=What+is+the+capital+of+Canada%3F).

Here's a very simple function to do so:

def fixurl(phrase):
    removespaces = phrase.replace(" ", "+")
    removequestions = removespaces.replace("?", "%3F")
    return removequestions

Then, we can format the text that we want to include in our reply (according to Reddit formatting guidelines), and make the reply:

for id_number in ids:
    submission = r.submission(id=id_number)
    title = submission.title.lower()
    for question_type in questions:
        if question_type in title:
            # make the reply
            correct_url = fixurl(title)
            reply_text="[Here's a link that might help](http://lmgtfy.com/?q=%s)" % (correct_url)
            # send the actual reply request
            submission.reply(reply_text)

If all went well, your post should have been made. Keep in mind that if your bot account is brand new, you'll be limited in how many posts you can make until you build up some karma. You may also have to manually answer Captchas at the start.

Step 5: Tying it all together

The main thing that we're missing is a way to run the bot continuously, and to not do the same work twice.

In order to do that, we'll place all the main code inside a 'while' loop.

As for the second part, when your 'subreddit' object returns the information about the AskReddit submissions, they are returned in order, just like you would see if you visited /r/AskReddit/new yourself.

So in order to prevent our bot from checking the same submissions twice, we only need to record the most recent submission ID, and check it when the while loop is executed next.

while True:
    ids=[]
    if ids:
        latest_id=ids[0]
    else:
        latest_id=''

This checks to make sure that the code has been run before ("if ids"), and then assigns the most recent submission ID (newest submitted) to the variable "latest_id".

Finally, one more loop before the main code is executed will prevent any duplicate work:

# remove any already examined submissions
if latest_id in ids:
    position = ids.index(latest_id)
    ids=ids[0:position]

This checks to see if we've already checked any submissions in our newly created list of ids before, and cleaves off those old submissions if we have.

Completed Code

The final code will show you how all these pieces fit together.

import time

import praw

r = praw.Reddit(user_agent='Let me Google that for you Bot',
                client_id='CLIENT_ID', client_secret="CLIENT_SCRET",
                username='USERNAME', password='PASSWORD')

questions = ['what is', 'who is', 'what are']


def fixurl(phrase):
    removespaces = phrase.replace(" ", "+")
    removequestions = removespaces.replace("?", "%3F")
    return removequestions


while True:
    ids = []

    # Check if we've already done some of the work
    if ids:
        latest_id = ids[0]
    else:
        latest_id = ''

    subreddit = r.subreddit('askreddit').new(limit=6)

    for x in subreddit:
        ids.append(x.id)

    # Remove any already examined submissions
    if latest_id in ids:
        position = ids.index(latest_id)
        ids = ids[0:position]

    # Identify title strings that match conditions
    for id_number in ids:
        submission = r.submission(id=id_number)
        title = submission.title.lower()
        for question_type in questions:
            if question_type in title:
                # make the reply
                correct_url = fixurl(title)
                reply_text = "[Here's a link that might help]\(http://lmgtfy.com/?q=%s)" % (correct_url)
                # send the actual reply request
                submission.reply(reply_text)