From eb523089faec0d5ad153bff7e70ae7ad47160116 Mon Sep 17 00:00:00 2001 From: Steven Mirabito Date: Sun, 17 Nov 2019 00:09:33 -0800 Subject: [PATCH] Update provider discovery to fix binaries --- README.md | 2 +- balance-check.spec | 8 ++- balance_check/__init__.py | 12 +++- balance_check/__main__.py | 42 +++++++------- balance_check/provider.py | 31 ++++++++++ balance_check/providers/__init__.py | 57 ++++--------------- balance_check/providers/bestbuy.py | 2 +- balance_check/providers/blackhawk.py | 2 +- balance_check/providers/gamestop.py | 2 +- balance_check/providers/guitarcenter.py | 2 +- balance_check/providers/happy.py | 2 +- balance_check/providers/homedepot.py | 2 +- balance_check/providers/nike.py | 2 +- balance_check/providers/onevanilla.py | 2 +- balance_check/providers/prepaidgiftbalance.py | 2 +- balance_check/providers/spafinder.py | 2 +- 16 files changed, 91 insertions(+), 81 deletions(-) create mode 100644 balance_check/provider.py diff --git a/README.md b/README.md index f3f01ec..1ca6b05 100644 --- a/README.md +++ b/README.md @@ -117,7 +117,7 @@ Please fork this repository, push to your fork, and open a pull request to contr ### Adding a Provider -Providers must implement a uniquely-named subclass of `BalanceCheckProvider` in the `balance_check.providers` module. If your provider has been successfully registered, it will appear in the usage message as a supported provider. +Providers must implement a uniquely-named subclass of `BalanceCheckProvider` in the `balance_check.providers` module. You must then add it to the `__all__` list in `balance_check.providers.__init__`. If your provider has been successfully registered, it will appear in the usage message as a supported provider. Your provider must implement `check_balance(self, **kwargs)` which will accept a keyword argument for each column in the input spreadsheet. You may optionally define a [Cerberus schema](http://docs.python-cerberus.org/en/stable/validation-rules.html) on `self.schema` and invoke `self.validate` with any fields you would like to validate. This is recommended to ensure your provider will not send requests with bad card data. A built-in schema generator for prepaid cards is provided in `balance_check.validators.credit_card` and convenience functions for solving CAPTCHAs are provided on `balance_check.captcha_solver`. diff --git a/balance-check.spec b/balance-check.spec index bc854a3..f4b7540 100644 --- a/balance-check.spec +++ b/balance-check.spec @@ -1,12 +1,16 @@ # -*- mode: python -*- +from PyInstaller.utils.hooks import collect_submodules + block_cipher = None -a = Analysis(['balance_check/cli.py'], +a = Analysis(['balance_check/__main__.py'], pathex=['balance_check'], binaries=None, datas=None, - hiddenimports=None, + hiddenimports=( + collect_submodules('balance_check.providers') + ), hookspath=None, runtime_hooks=None, excludes=None, diff --git a/balance_check/__init__.py b/balance_check/__init__.py index 8b46468..f250471 100644 --- a/balance_check/__init__.py +++ b/balance_check/__init__.py @@ -1,7 +1,13 @@ import colorlog -from balance_check import config -from balance_check.utils.logging import configure_logger +from typing import Mapping from balance_check.version import __version__ logger = colorlog.getLogger() -configure_logger(logger) + +from balance_check.provider import BalanceCheckProvider +from balance_check.providers import * + +# Instantiate each provider module and populate the available providers +providers: Mapping[str, BalanceCheckProvider] = { + cls.__name__.lower(): cls() for cls in BalanceCheckProvider.__subclasses__() +} diff --git a/balance_check/__main__.py b/balance_check/__main__.py index 16eb42a..11e57e5 100644 --- a/balance_check/__main__.py +++ b/balance_check/__main__.py @@ -4,38 +4,40 @@ from concurrent.futures import ThreadPoolExecutor, as_completed from argparse import ArgumentParser, RawTextHelpFormatter from tqdm import tqdm -from balance_check import __version__, logger, config -from balance_check.providers import providers +from balance_check import __version__, logger, config, providers +from balance_check.utils.logging import configure_logger def main(): + configure_logger(logger) + providers_help = "\n".join([" - {}".format(p_name) for p_name in providers.keys()]) parser = ArgumentParser( formatter_class=RawTextHelpFormatter, description=f"""Check gift card balances for a variety of providers. - Supported providers: - {providers_help} +Supported providers: +{providers_help} - Requires an Anti-CAPTCHA API key for providers with CAPTCHAs. - Get one here: https://anti-captcha.com - Configure your key by setting the ANTI_CAPTCHA_KEY environment variable. +Requires an Anti-CAPTCHA API key for providers with CAPTCHAs. +Get one here: https://anti-captcha.com +Configure your key by setting the ANTI_CAPTCHA_KEY environment variable. - Your INPUT_CSV should be formatted as follows: - - A header row is required - - Each column should contain a parameter required by - the specified provider +Your INPUT_CSV should be formatted as follows: +- A header row is required +- Each column should contain a parameter required by +the specified provider - Example (for the 'blackhawk' provider): - ------------------------------------------------- - | card_number | exp_month | exp_year | cvv | - |------------------|-----------|----------|-----| - | 4111111111111111 | 12 | 24 | 999 | - ------------------------------------------------- +Example (for the 'blackhawk' provider): +------------------------------------------------- +| card_number | exp_month | exp_year | cvv | +|------------------|-----------|----------|-----| +| 4111111111111111 | 12 | 24 | 999 | +------------------------------------------------- - If you find this tool useful, consider buying a coffee for the author: - https://stevenmirabito.com/kudos""", +If you find this tool useful, consider buying a coffee for the author: +https://stevenmirabito.com/kudos""", ) parser.add_argument( @@ -95,7 +97,7 @@ def main(): if provider_allows_chunks: _chunk.append(card_data) if ( - i + 1 + i + 1 ) % provider.max_simultaneous: # If end of chunk, send to schedule... # Schedule balance check future = executor.submit(provider.check_balance, _chunk) diff --git a/balance_check/provider.py b/balance_check/provider.py new file mode 100644 index 0000000..d48f0f2 --- /dev/null +++ b/balance_check/provider.py @@ -0,0 +1,31 @@ +from cerberus import Validator +from balance_check import logger + + +class BalanceCheckProvider: + def __init__(self): + self.schema = None + + def validate(self, args): + if self.schema: + validator = Validator(self.schema) + if not validator.validate(args): + msg = "Invalid card data provided:\n" + + for field, errors in validator.errors.items(): + msg += "- {}:".format(field) + + if len(errors) == 1: + msg += " {}\n".format(errors[0]) + elif len(errors) > 1: + msg += "\n" + for error in errors: + msg += " - {}\n".format(error) + + logger.error(msg) + return False + + return True + + def check_balance(self, **kwargs): + raise NotImplementedError("Implement in subclass") diff --git a/balance_check/providers/__init__.py b/balance_check/providers/__init__.py index fc1f50c..309bcc0 100644 --- a/balance_check/providers/__init__.py +++ b/balance_check/providers/__init__.py @@ -1,45 +1,12 @@ -import os -from pkgutil import iter_modules -from importlib import import_module -from typing import Mapping -from cerberus import Validator -from balance_check import logger - - -class BalanceCheckProvider: - def __init__(self): - self.schema = None - - def validate(self, args): - if self.schema: - validator = Validator(self.schema) - if not validator.validate(args): - msg = "Invalid card data provided:\n" - - for field, errors in validator.errors.items(): - msg += "- {}:".format(field) - - if len(errors) == 1: - msg += " {}\n".format(errors[0]) - elif len(errors) > 1: - msg += "\n" - for error in errors: - msg += " - {}\n".format(error) - - logger.error(msg) - return False - - return True - - def check_balance(self, **kwargs): - raise NotImplementedError("Implement in subclass") - - -# Import all provider modules -for _, name, _ in iter_modules([os.path.dirname(__file__)]): - import_module("." + name, __package__) - -# Instantiate each provider module and populate the available providers -providers: Mapping[str, BalanceCheckProvider] = { - cls.__name__.lower(): cls() for cls in BalanceCheckProvider.__subclasses__() -} +__all__ = [ + "bestbuy", + "blackhawk", + "gamestop", + "guitarcenter", + "happy", + "homedepot", + "nike", + "onevanilla", + "prepaidgiftbalance", + "spafinder", +] diff --git a/balance_check/providers/bestbuy.py b/balance_check/providers/bestbuy.py index ead7f69..937c698 100644 --- a/balance_check/providers/bestbuy.py +++ b/balance_check/providers/bestbuy.py @@ -1,7 +1,7 @@ import requests import time from balance_check import logger, config -from balance_check.providers import BalanceCheckProvider +from balance_check.provider import BalanceCheckProvider from balance_check.validators.gift_card import Merchant, GiftCardSchema diff --git a/balance_check/providers/blackhawk.py b/balance_check/providers/blackhawk.py index a293b89..6291278 100644 --- a/balance_check/providers/blackhawk.py +++ b/balance_check/providers/blackhawk.py @@ -3,7 +3,7 @@ from bs4 import BeautifulSoup from balance_check import logger, config from balance_check.utils.captcha import CaptchaSolver -from balance_check.providers import BalanceCheckProvider +from balance_check.provider import BalanceCheckProvider from balance_check.validators.credit_card import Issuer, CreditCardSchema diff --git a/balance_check/providers/gamestop.py b/balance_check/providers/gamestop.py index d4bd656..bc7bb2a 100644 --- a/balance_check/providers/gamestop.py +++ b/balance_check/providers/gamestop.py @@ -6,7 +6,7 @@ from balance_check import logger, config from balance_check.utils import deep_get from balance_check.utils.captcha import CaptchaSolver -from balance_check.providers import BalanceCheckProvider +from balance_check.provider import BalanceCheckProvider from balance_check.validators.gift_card import Merchant, GiftCardSchema HEADERS = { diff --git a/balance_check/providers/guitarcenter.py b/balance_check/providers/guitarcenter.py index c9fee36..e579b5d 100644 --- a/balance_check/providers/guitarcenter.py +++ b/balance_check/providers/guitarcenter.py @@ -1,7 +1,7 @@ import requests import lxml.html from balance_check import logger, config -from balance_check.providers import BalanceCheckProvider +from balance_check.provider import BalanceCheckProvider from balance_check.validators.gift_card import Merchant, GiftCardSchema diff --git a/balance_check/providers/happy.py b/balance_check/providers/happy.py index 957917f..3621aef 100644 --- a/balance_check/providers/happy.py +++ b/balance_check/providers/happy.py @@ -3,7 +3,7 @@ from bs4 import BeautifulSoup from balance_check import logger, config from balance_check.utils.captcha import CaptchaSolver -from balance_check.providers import BalanceCheckProvider +from balance_check.provider import BalanceCheckProvider from balance_check.validators.credit_card import Issuer, CreditCardSchema diff --git a/balance_check/providers/homedepot.py b/balance_check/providers/homedepot.py index 3c56bca..8cc761f 100644 --- a/balance_check/providers/homedepot.py +++ b/balance_check/providers/homedepot.py @@ -3,7 +3,7 @@ from balance_check import logger, config from balance_check.utils import deep_get from balance_check.utils.captcha import CaptchaSolver -from balance_check.providers import BalanceCheckProvider +from balance_check.provider import BalanceCheckProvider from balance_check.validators.gift_card import Merchant, GiftCardSchema HEADERS = { diff --git a/balance_check/providers/nike.py b/balance_check/providers/nike.py index 065ec2e..0bcec36 100644 --- a/balance_check/providers/nike.py +++ b/balance_check/providers/nike.py @@ -1,6 +1,6 @@ import requests from balance_check import logger -from balance_check.providers import BalanceCheckProvider +from balance_check.provider import BalanceCheckProvider from balance_check.validators.gift_card import Merchant, GiftCardSchema diff --git a/balance_check/providers/onevanilla.py b/balance_check/providers/onevanilla.py index d72f2d1..178807d 100644 --- a/balance_check/providers/onevanilla.py +++ b/balance_check/providers/onevanilla.py @@ -7,7 +7,7 @@ from selenium.common.exceptions import TimeoutException from selenium.common.exceptions import NoSuchElementException from balance_check import logger -from balance_check.providers import BalanceCheckProvider +from balance_check.provider import BalanceCheckProvider from balance_check.validators.credit_card import Issuer, CreditCardSchema diff --git a/balance_check/providers/prepaidgiftbalance.py b/balance_check/providers/prepaidgiftbalance.py index e74ad83..4d9f857 100644 --- a/balance_check/providers/prepaidgiftbalance.py +++ b/balance_check/providers/prepaidgiftbalance.py @@ -9,7 +9,7 @@ from balance_check import logger, config from balance_check.utils.captcha import CaptchaSolver from balance_check.utils.browser import get_image_b64_by_id -from balance_check.providers import BalanceCheckProvider +from balance_check.provider import BalanceCheckProvider from balance_check.validators.credit_card import Issuer, CreditCardSchema diff --git a/balance_check/providers/spafinder.py b/balance_check/providers/spafinder.py index d848a35..33d2c04 100644 --- a/balance_check/providers/spafinder.py +++ b/balance_check/providers/spafinder.py @@ -3,7 +3,7 @@ from bs4 import BeautifulSoup from balance_check import logger, config from balance_check.utils.captcha import CaptchaSolver -from balance_check.providers import BalanceCheckProvider +from balance_check.provider import BalanceCheckProvider from balance_check.validators.credit_card import Issuer, CreditCardSchema