When is my Cake Day?

November 20, 2015

kek

Reddit gives all the user info in a handy JSON at this URL: https://www.reddit.com/user/<username here>/about.json

example: https://www.reddit.com/user/spez/about.json

The created_utc field in data is the date of user's registration aka Cake Day in unix epoch format (in UTC) and we can easily convert that to readable format:

>>> import time
>>> time.strftime("%D", time.gmtime(1118030400))
'06/06/05'

Using Python Requests, we can turn this into a handy function:

import time
import requests

def get_my_cake_day(username):
    url = "https://www.reddit.com/user/{}/about.json".format(username)
    r = requests.get(url)
    created_at = r.json()['data']['created_utc']
    return time.strftime("%D", time.gmtime(created_at))

Though above function will work, but soon it will start throwing HTTP 429 error i.e Too Many Requests. Thing is, Reddit doesn't really like when someone tries to fetch the data like this. The requests are made directly on Reddit servers without using the API. Now if you have want to find cake day of hundreds of users, you cannot use this method.

Solution? Use Reddit's API. In Python, we will use praw and prawoauth2. praw is a Python wrapper for Reddit's API and prawoauth2 helps dealing with OAuth2.

Let's start by installing praw:

pip install praw

Now we can convert the get_my_cake_day to praw version and get the user details like this:

import time
import praw

reddit_client = praw.Reddit(user_agent='my amazing cake day bot')

def get_my_cake_day(username):
    redditor = reddit_client.get_redditor(username)
    return time.strftime("%D", time.gmtime(redditor.created_utc))

Above code pretty much self explanatory. What if the user doesn't exist or shadowbanned? In such cases, praw throws an exception: praw.errors.NotFound. Lets modify get_my_cake_day to catch this:

def get_my_cake_day(username):
    try:
        redditor = reddit_client.get_redditor(username)
        return time.strftime("%D", time.gmtime(redditor.created_utc))
    except praw.errors.NotFound:
        return 'User does not exist or shadowbanned'

This is better compared to earlier version and we will stop getting rate limit errors often. Also, praw will handle such cases and makes requests again to fetch the data. But what if we want to increase the limit?

The above requests are not authenticated, meaning Reddit does not recognise your app. However, if we register this app in Reddit and let Reddit know, then requests limits will increase. So to authenticate our app over Oauth2, we will use prawoauth2. Lets install it first:

pip install prawoauth2

Follow the simple steps here to register your app on Reddit. Once done, you will get app_token and app_secret. Then you need to get access_token and refresh_token. You could use this handy onetime.py script. For detailed instructions check the documentation of prawoauth2. You should never make app_token, app_secret, access_token and refresh_token public and never commit them to version control. Keep them always secret.

Here is the complete script using prawoauth2:

import time
import praw

from secret import (app_key, app_secret, access_token, refresh_token,
                    user_agent, scopes)

reddit_client = praw.Reddit(user_agent='my amazing cakeday bot')
oauth_helper = PrawOAuth2Mini(reddit_client, app_key=app_key,
                              app_secret=app_secret,
                              access_token=access_token,
                              refresh_token=refresh_token, scopes=scopes)


def get_my_cake_day(username):
    try:
        redditor = reddit_client.get_redditor(username)
        return time.strftime("%D", time.gmtime(redditor.created_utc))
    except praw.errors.NotFound:
        return 'User does not exists or shadowbanned'

Again, pretty much self explanatory. If your tokens are correct and once PrawOAuth2Mini is initialized properly, there will be no issues with the app and you will have twice as many requests as compared to unauthenticated version.

Want to see above app in action? Check this - kekday. The app is open source and released under MIT License.