Automatic Contest Winning via Selenium

by Kyle Bradshaw

With some spare time on a recent weekend, my brain was begging for a project.

Taking the opportunity, I remembered something I had wished existed in my teen years, and now realized the tools were available to create.  Around 2010, I was addicted to Twitter, spending my time reading and responding to people I follow, and browsing tweets from certain search terms.

Along the way, I began to win contests - lots of them!  With prizes ranging from the usual t-shirts to my favorite: Japanese KitKat bars.

One contest type I was really good at was code redemption, where a user tweets out an Xbox Live code for a game or DLC pack.  I always had my redeem page open, ready to copy and paste.  But I knew there had to be a better way.

Now, in my primary work time, I use the Selenium WebDriver to automate certain tedious tasks in a workplace situation.  Usually, Selenium is used as a test suite for web dev projects, but it also works very well for our uses, because it does little1 to give itself away as being automated, unless the site has advanced protection in place2.

Having Python bindings just sweetens the deal for me.  With my knowledge of this tool in hand, I set to work.

At this point, a little recon is in order, so we'll bust open IDLE and take a look.

import selenium
from selenium.webdriver.common.keys import Keys
# This is so we can press the Enter key later.

driver = selenium.webdriver.Firefox()
driver.get("https://account.xbox.com/en-us/paymentandbilling/redeemcode/")

At this point, we're redirected to the login page.

Let's make sure we can log in programmatically.  Firefox makes this easy, right-click the "Email Address" box and choose "Inspect Element."  This jumps to the relevant source code to identify the object.

Already we can see that Microsoft is fighting back against us.  So let's type something into the email and password boxes, highlight the text, and try to Inspect Element again.

This gets us the IDs "i0116" and "i0118" for the email and password fields respectively.

So clear the boxes and let's try from IDLE:

em_box = driver.find_element_by_id("i0116")
em_box.click() # Just to be safe. Users usually don't start typing in a box before clicking it.
em_box.send_keys("gil_baits@hotmail.com")
pw_box = driver.find_element_by_id("i0118")
pw_box.click()
pw_box.send_keys("password")
pw_box.send_keys(Keys.RETURN)

With valid info, this logs us in successfully and redirects back to the "Redeem Code" page.  We're greeted with a shiny Redeem button.  Let's Inspect it and send it a click.

rdm_btn = driver.find_element_by_id("redeemCodeBtn")
rdm_btn.click()

This is the home stretch.

We can't quite as easily select the code box as we'd expect.  Attempting to do so will return an error saying the Element can't be found.

This is because Selenium treats web frames as separate web pages, and the frame we're looking for is nested rather deep.

driver.switch_to.frame("blenderIFrame")
driver.switch_to.frame("webBlendHost")
driver.switch_to.frame("appHost")
codebox = driver.find_element_by_id('tokenField')
codebox.send_keys("QQQQQ-QQQQQ-QQQQQ-QQQQQ-QQQQQ")
codebox.send_keys(Keys.RETURN)

Looking good!

Now let's parse a given text for valid Xbox codes.  We know that Xbox codes follow a given format: five sets of five alphanumeric characters.

We can check for this easily using Python's regular expressions module, re:

import re

xbox_exp = re.compile(".{5}-.{5}-.{5}-.{5}-.{5}")
# . is any character, {5} indicates five of the previous character
def x_check(text):
    results = xbox_exp.findall(text.capitalize())
    # Capitalize it for our convenience.
    codes = False
    if len(results) > 0:
        codes = []
        for x in results:
            codes.append(x)
    return codes

Now we just need some text to run through our function.

For this, the best source is likely Twitter, so using the available Twitter module, we can begin.  For this you'll need valid Twitter API and OAuth keys for your account3.

import twitter

auth = twitter.OAuth(token, token_secret, consumer_key, consumer_secret)
stream = twitter.TwitterStream(domain="userstream.twitter.com", auth=auth)
for tweet in stream.user():
    if "text" in tweet:
        x_check(tweet["text"])

Putting it all together into a complete automated process, we get CodeSnag.py, which I've taken the liberty of adding PlayStation support to and releasing4, making it ready for easy use and addition of new services.

Now just follow those giveaway accounts, and rake in the winnings.

Happy hunting!

1.)  As of writing, only Firefox gives any signal that it's being run by a WebDriver, by setting the webdriver attribute in the HTML of every page.

2.)  stackoverflow.com/a/33403473/955974

3.)  apps.twitter.com/app/new

4.)  bitbucket.org/Skylled/codesnag


CodeSnag does what it says. Snags codes tweeted out in public giveaways and tries to redeem them first.

It does this through sixohsix's Twitter module, and the Selenium Webdriver module.

The author(s) of this program are not responsible for any or all damage that may occur using this software, including accounts getting banned.

The use of the software may be against the Terms of Service for the PlayStation Network or the Xbox Live Marketplace.

Exe requirements:
Visual C++ Runtime
Firefox (preferably ESR)

Source code requirements:
Python 2.7
Firefox (preferably ESR)
Selenium Module
Twitter Module

Usage tutorial:
Create a new twitter account, and follow only accounts that will potentially tweet out codes.
With this new account, create a new Twitter app.
Get the Consumer Key and Consumer Secret codes for your app
Generate an Access Token for your account, and get the Token Key and Token Secret
Edit the config_example.cfg file, entering your Twitter App keys appropriately, and **optionally** filling in your Xbox Email and Password.
PlayStation has a short timeout period, so you MUST enter your Email and Password, if you intend to use it.
If you do not want to use either Xbox or PSN, set their value to False
Rename the file to config.cfg

*** If you do not fill in the Xbox email and password, you will have 30 seconds to log in after the window opens. ***

CodeSnag-1.3-py2exe-win32.zip  Snags codes tweeted out in public giveaways and tries to redeem them first.
Return to $2600 Index