Skip to content

Instantly share code, notes, and snippets.

@Earthnuker
Created October 6, 2019 00:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Earthnuker/a475e18d95c20e3149990ab8080a1781 to your computer and use it in GitHub Desktop.
Save Earthnuker/a475e18d95c20e3149990ab8080a1781 to your computer and use it in GitHub Desktop.
Automatically scrape and submit SHiFT codes for borderlands
import mechanicalsoup
from getpass import getpass
import requests as RQ
from bs4 import BeautifulSoup as BS
from concurrent.futures import ThreadPoolExecutor,as_completed
import time
import sys
import re
import json
from pprint import pformat
from tqdm import tqdm
import os
responses=[]
if os.path.isfile("responses.json"):
pass
def fetch_codes():
shift_codes=[]
shift_re=re.compile(r"[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}")
shift_urls=["http://orcz.com/Borderlands:_Golden_Key",
"http://orcz.com/Borderlands_2:_Golden_Key",
"http://orcz.com/Borderlands_Pre-Sequel:_Shift_Codes",
"http://orcz.com/Borderlands_3:_Shift_Codes",
]
for url in shift_urls:
soup=BS(RQ.get(url).text,'lxml').find_all('table',{'class':'wikitable'})
for table in soup:
for td in table.find_all('td'):
shift_codes+=shift_re.findall(td.text)
return sorted(set(shift_codes))
AUTH_HEADERS={
'Host': "api.2k.com",
'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0",
'Accept': "*/*",
'Accept-Language': "en-US,en;q=0.5",
'Accept-Encoding': "gzip, deflate, br",
'Access-Control-Request-Method': "POST",
'Access-Control-Request-Headers': "content-type",
'Referer': "https://borderlands.com/en-US/",
'Origin': "https://borderlands.com",
'Connection': "keep-alive",
'Pragma': "no-cache",
'Cache-Control': "no-cache",
'cache-control': "no-cache",
}
def cors_rq(method,url,*args,**kwargs):
opts=browser.request('OPTIONS',url,*args,headers=AUTH_HEADERS,**kwargs)
opts.raise_for_status()
resp=browser.request(method,url,*args,headers=AUTH_HEADERS,**kwargs)
return resp
def code_info(shift_code):
info_url='https://api.2k.com/borderlands/code/{}/info'.format(shift_code)
return cors_rq('GET',info_url).json()
def redeem(code):
redeem_url="https://api.2k.com/borderlands/code/{code}/redeem/{offer_service}".format(**code)
while True:
resp=cors_rq('POST',redeem_url)
info=resp.json()
if info.get('error',{}).get('code')!='RATE_LIMITED':
break
time.sleep(300)
if info.get('message')=='REDEMPTION_QUEUED':
job_id=info.get('job_id')
if job_id:
delay=info['max_wait_milliseconds']/1000
time.sleep(delay)
resp=cors_rq('GET','https://api.2k.com/borderlands/code/{0}/job/{1}'.format(code['code'],job_id))
return {'url':redeem_url,'code':code,'result':resp.text}
return info
browser=mechanicalsoup.StatefulBrowser(user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0')
browser.open("https://borderlands.com/en-US/")
email=input("E-Mail: ")
passwd=getpass()
resp=cors_rq('POST','https://api.2k.com/borderlands/users/authenticate',json={"username":email,"password":passwd})
AUTH_HEADERS['X-Session']=resp.headers['X-SESSION-SET']
account_info=resp.json()
acct_key=[]
for game in account_info['playedGames']:
for platform in game['platforms']:
acct_key.append((platform['service'],game['title']))
def can_redeem(code,acct_key):
if not code.get('is_active'):
return False
if (code['offer_service'],code['offer_title']) not in acct_key:
return False
return True
codes=[]
with ThreadPoolExecutor(32) as pool:
jobs=[]
for code in tqdm(fetch_codes(),ascii=True,desc="Submiting Jobs"):
jobs.append(pool.submit(code_info,code))
pbar=tqdm(as_completed(jobs),total=len(jobs),ascii=True,desc="Fetching infos")
for code_info in pbar:
code_info=code_info.result()
if not code_info:
continue
if not 'entitlement_offer_codes' in code_info:
continue
codes+=code_info['entitlement_offer_codes']
codes=list(filter(lambda c:can_redeem(c,acct_key),codes))
responses=[]
for code in codes:
resp=redeem(code)
responses.append(resp)
print(pformat(resp))
print("="*20)
json.dump(responses,open("responses.json","w"))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment