Skip to content

Commit

Permalink
fix: update blackhawk provider for funcaptcha
Browse files Browse the repository at this point in the history
  • Loading branch information
stevenmirabito committed May 22, 2020
1 parent 961b8dc commit a7adca1
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 22 deletions.
35 changes: 13 additions & 22 deletions balance_check/providers/blackhawk.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import sys
import requests
from bs4 import BeautifulSoup
from balance_check import logger, config
from balance_check.utils.captcha import CaptchaSolver
from balance_check.utils.captcha import CaptchaSolver, extract_arkose_key
from balance_check.provider import BalanceCheckProvider
from balance_check.validators.credit_card import Issuer, CreditCardSchema

Expand All @@ -24,47 +23,40 @@ def scrape(self, fields):

resp = session.get(self.website_url)
if resp.status_code != 200:
logger.critical(
raise RuntimeError(
f"Failed to GET Blackhawk website (status code {resp.status_code})"
)
sys.exit(1)

page_html = BeautifulSoup(resp.content, features="html.parser")
transactions = page_html.find(id="CheckBalanceTransactions")
form = transactions.find("form")
if not form:
logger.critical("Unable to find balance check form")
sys.exit(1)
raise RuntimeError("Unable to find balance check form")

endpoint = "{}{}".format(self.website_url, form["action"])

token_field = transactions.find(
"input", attrs={"name": "__RequestVerificationToken"}
)
if not token_field:
logger.critical("Failed to retrieve verification token")
sys.exit(1)
raise RuntimeError("Failed to retrieve verification token")

fields["__RequestVerificationToken"] = token_field["value"]

recaptcha_field = transactions.find("div", class_="g-recaptcha")
if not recaptcha_field:
logger.critical("Unable to find reCAPTCHA")
sys.exit(1)
arkose_key = extract_arkose_key(resp.text)
if not arkose_key:
raise RuntimeError("Failed to extract Arkose Labs public key")

site_key = recaptcha_field["data-sitekey"]

logger.info("Solving reCAPTCHA (~30s)")
logger.info("Solving FunCaptcha (~30s)")

captcha_solver = CaptchaSolver(api_key=config.ANTI_CAPTCHA_KEY)
captcha = captcha_solver.solve_recaptcha(self.website_url, site_key)
captcha = captcha_solver.solve_funcaptcha(self.website_url, arkose_key)
if captcha["errorId"] != 0:
logger.critical(
"Unable to solve reCAPTCHA ({})".format(captcha["errorDescription"])
raise RuntimeError(
"Unable to solve FunCaptcha ({})".format(captcha["errorDescription"])
)
sys.exit(1)

fields["g-recaptcha-response"] = captcha["solution"]["gRecaptchaResponse"]
fields["captchaToken"] = captcha["solution"]["token"]

logger.info("Fetching card balance")

Expand All @@ -84,12 +76,11 @@ def scrape(self, fields):

form_resp = session.post(endpoint, data=fields)
if form_resp.status_code != 200:
logger.critical(
raise RuntimeError(
"Failed to retrieve card balance (status code {})".format(
form_resp.status_code
)
)
sys.exit(1)

balance_html = BeautifulSoup(form_resp.content, features="html.parser")

Expand Down
15 changes: 15 additions & 0 deletions balance_check/utils/captcha.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
import re
from python3_anticaptcha.ImageToTextTask import ImageToTextTask
from python3_anticaptcha.NoCaptchaTaskProxyless import NoCaptchaTaskProxyless
from python3_anticaptcha.FunCaptchaTaskProxyless import FunCaptchaTaskProxyless

ARKOSE_KEY_REGEX = r"arkoselabs\.com\/v2\/([A-Z0-9]{8}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{12})"


def extract_arkose_key(html):
match = re.search(ARKOSE_KEY_REGEX, html)
return match.group(1) if match else None


class CaptchaSolver:
def __init__(self, api_key):
self.image_task = ImageToTextTask(anticaptcha_key=api_key)
self.recaptcha_task = NoCaptchaTaskProxyless(anticaptcha_key=api_key)
self.funcaptcha_task = FunCaptchaTaskProxyless(anticaptcha_key=api_key)

def solve_image_url(self, image_link):
return self.image_task.captcha_handler(captcha_link=image_link)
Expand All @@ -17,3 +27,8 @@ def solve_recaptcha(self, page_url, site_key):
return self.recaptcha_task.captcha_handler(
websiteURL=page_url, websiteKey=site_key
)

def solve_funcaptcha(self, page_url, public_key):
return self.funcaptcha_task.captcha_handler(
websiteURL=page_url, websitePublicKey=public_key
)

0 comments on commit a7adca1

Please sign in to comment.