Welcome to another tutorial of mine! Be sure to check the previous ones here. In this one, I’m going to cover a script that upvotes every new submission and comment from a given subreddit. Please, don’t try to run it in reverse and downvote all the things. Please…
I assume that you have Python installed on your system. The tutorial targets Windows 10 with Powershell.
Registering the application
In order to use PRAW, we need to register our script first. Here’s how the form looks like:
When you hit create app
, you will have access to your app settings. With red I have marked variables that we will need later on.
Side note: it’s good to create a new user just for the script.
Setting up the virtual environment
Before you start coding, create a working directory for the script:
mkdir reddit-upvoter
cd mkdir
Now you can create the Python virtual environment in venv
directory:
python -m venv venv
Activate it:
.\venv\Scripts\activate.ps1
We are going to need PRAW installed. Do it with the command:
pip install praw
All set!
Preparing the battlefield
Create a file for the script (upvoter.py
) and the one for settings (settings.ini
):
New-Item upvoter.py
New-Item settings.ini
Open the upvoter.py
file in your favourite text editor. First we add some imports:
|
|
- A package needed to create
ConfigParser
object. - An object that will handle our settings file.
- The Python Reddit API Wrapper.
The script is going to be really simple, but it’s still a good idea to put our code in a class:
class Upvoter:
pass
Configuration
Let’s add configuration now so we don’t have to refactor our code later on:
|
|
2.
settings
is a path to settings file. It defaults to settings.ini
.
3.
Create a config object. We are passing an os.environ
reference because we are going to interpolate our system’s environmental variables.
4.
Read a config from a path passed as an argument.
As for settings file, paste this. We are going to define the variables in a moment:
|
|
1.
Put our settings in [reddit]
group. We will reference it using dictionary syntax: config['reddit']
.
2-3.
Fields from registering the application step. Here we interpolate the variables, meaning that the actual values can be found in system’s environmental variables. We externalize them for security purposes. This way we can easily commit our settings file to git and not worry that we expose our sensitive data.
4-5
Your redditor’s username and password.
6.
A string that identifies the app.
7.
Subreddit that the script will listen to.
Now we can actually declare our variables. Hit Windows
+ R
and execute this. I really hate how Windows can make simple tasks hard, but hey! It runs games…
rundll32.exe sysdm.cpl,EditEnvironmentVariables
Declare the variables as shown below:
Get the API object
We are going to create an authorized PRAW instance. The code should be self explanatory. Since we defined environmental variables earlier, all you have to do is to paste the following snippet:
|
|
Having fun with REPL
We will create the rest of the script experimentally, step by step, using Python’s REPL. Invoke the following command in Powershell:
python
You should get the following output, meaning you’ve activated the interpreter:
Python 3.7.0 (v3.7.0:1bf9cc5093, Jun 27 2018, 04:59:51) [MSC v.1914 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>
First we need to import our script:
from upvoter import Upvoter
Then we obtain our API instance:
api = Upvoter().api
Since we are experimenting now, create a thread on r/test for testing purposes and add a few comments. I’m going to use this thread from now on. Obtain the submission object with the following code:
submission = api.submission(url='https://www.reddit.com/r/test/comments/f9tz8c/upvoter_test/')
Having that, we can perform various actions. We are going focus on manipulating karma now. The following line will downvote our post:
submission.downvote()
When you navigate to the thread page in your browser, you should see that it has been downvoted. Now let’s do the opposite:
submission.upvote()
Now we are going to do the same with comments. Obtain them first:
comments = submission.comments
First we are going to downvote them using a simple for loop:
for comment in comments:
comment.downvote()
Then we upvote them:
for comment in comments:
comment.upvote()
Now do the same, but using a comments stream:
for comment in self.api.subreddit('test').stream.comments():
comment.upvote()
Using stream, new comments are fetched as they are posted. Now that we have it, we can put it all together in text editor.
Upvote all the things
Add the folowing method to our Upvoter
class:
|
|
3.
Get a comment from stream.
4.
Get a submission object.
5-6.
Upvote.
7.
Print that we have just processed the comment.
The last thing we have to do is to run our script:
if __name__ == '__main__':
upvoter = Upvoter()
upvoter.upvote()
We should end up with this code:
import os
from configparser import ConfigParser
from praw import Reddit
class Upvoter:
def upvote(self):
for comment in self.api.subreddit(self.config['reddit']['subreddit']).stream.comments():
submission = comment.submission
submission.upvote()
comment.upvote()
print('Processed comment {} in thread {}.'.format(comment.id, submission.url))
def __init__(self, settings='settings.ini'):
self.config = ConfigParser(os.environ)
self.config.read(settings)
self.api = Reddit(client_id=self.config['reddit']['client_id'],
client_secret=self.config['reddit']['client_secret'],
user_agent=self.config['reddit']['user_agent'],
username=self.config['reddit']['username'],
password=self.config['reddit']['password'])
if __name__ == '__main__':
upvoter = Upvoter()
upvoter.upvote()
And that’s it! I hope that you’ve found the tutorial useful. I’d ask you for an upvote, but I don’t implement it on my blog.