diff --git a/README.md b/README.md index 1ca6b05..2eddbfa 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ Automation tool for checking the balance of gift cards issued by various provide - [GameStop](https://www.gamestop.com/giftcards/) - `gamestop` CAPTCHA - [Best Buy](https://www.bestbuy.com/gift-card-balance) - `bestbuy` - [Home Depot](https://www.homedepot.com/mycheckout/giftcard) - `homedepot` CAPTCHA +- [Starbucks](https://www.starbucks.com/card) - `starbucks` Providers marked with CAPTCHA will require an [Anti-CAPTCHA](https://anti-captcha.com) API key. diff --git a/balance_check/providers/__init__.py b/balance_check/providers/__init__.py index 309bcc0..21c7034 100644 --- a/balance_check/providers/__init__.py +++ b/balance_check/providers/__init__.py @@ -9,4 +9,5 @@ "onevanilla", "prepaidgiftbalance", "spafinder", + "starbucks", ] diff --git a/balance_check/providers/starbucks.py b/balance_check/providers/starbucks.py new file mode 100644 index 0000000..3715dc5 --- /dev/null +++ b/balance_check/providers/starbucks.py @@ -0,0 +1,51 @@ +import asyncio +import pyppeteer +from balance_check import logger +from balance_check.provider import BalanceCheckProvider +from balance_check.validators.gift_card import Merchant, GiftCardSchema + + +class Starbucks(BalanceCheckProvider): + def __init__(self): + super().__init__() + + self.website_url = "https://www.starbucks.com/card" + self.schema = GiftCardSchema(Merchant.Starbucks) + + async def scrape(self, fields): + browser = await pyppeteer.launch( + handleSIGINT=False, handleSIGTERM=False, handleSIGHUP=False + ) + page = await browser.newPage() + + logger.info("Fetching balance check page") + await page.goto(self.website_url) + + logger.info("Filling balance check form") + await page.type("#Card_Number", fields["card_number"]) + await page.type("#Card_Pin", fields["pin"]) + + logger.info("Requesting balance") + await page.click("#CheckBalance button") + await page.waitForSelector(".fetch_balance_value", {"timeout": 10000}) + + avail_balance = await page.querySelectorEval( + ".fetch_balance_value", "(node => node.innerText)" + ) + + logger.info("Success! Card balance: {}".format(avail_balance)) + + return {"available_balance": avail_balance} + + def check_balance(self, **kwargs): + if self.validate(kwargs): + logger.info("Checking balance for card: {}".format(kwargs["card_number"])) + + loop = asyncio.new_event_loop() + asyncio.set_event_loop(loop) + + return loop.run_until_complete( + self.scrape( + {"card_number": kwargs["card_number"], "pin": kwargs["pin"],} + ) + ) diff --git a/requirements.txt b/requirements.txt index 6669cb4..7795227 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,4 +9,5 @@ requests tqdm lxml selenium +pyppeteer chromedriver-binary