From 459236863e1727c68c65125fa75ec527f3c5fbcb Mon Sep 17 00:00:00 2001 From: echohack Date: Mon, 24 Feb 2020 14:42:57 -0800 Subject: [PATCH] Added attention to get information about accounts that may need attention and updated README. Added chromedriver to .gitignore. --- .gitignore | 1 + README.md | 9 +++++---- mintapi/api.py | 39 ++++++++++++++++++++++++++++++++++++--- 3 files changed, 42 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index f0a24baa..2d99c72a 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ build dist env +chromedriver __pycache__ *.pyc *.egg-info diff --git a/README.md b/README.md index 6718a339..21bd1183 100644 --- a/README.md +++ b/README.md @@ -110,13 +110,13 @@ Run it as a sub-process from your favorite language; `pip install mintapi` creat [--budgets | --budget_hist] [--net-worth] [--extended-accounts] [--transactions] [--extended-transactions] [--credit-score] [--credit-report] [--start-date [START_DATE]] [--include-investment] [--skip-duplicates] [--show-pending] - [--filename FILENAME] [--keyring] [--headless] + [--filename FILENAME] [--keyring] [--headless] [--attention] [--mfa-method {sms,email}] - [email] [password] + email password positional arguments: - email The e-mail address for your Mint.com account - password The password for your Mint.com account + email The e-mail address for your Mint.com account (required) + password The password for your Mint.com account (required) optional arguments: -h, --help show this help message and exit @@ -160,6 +160,7 @@ Run it as a sub-process from your favorite language; `pip install mintapi` creat --no_wait_for_sync Do not wait for accounts to sync --wait_for_sync_timeout Number of seconds to wait for sync (default is 300) + --attention. Get notice if there are any accounts that need attention >>> mintapi --keyring email@example.com [ diff --git a/mintapi/api.py b/mintapi/api.py index 96bb6cfa..32d5da34 100644 --- a/mintapi/api.py +++ b/mintapi/api.py @@ -173,12 +173,15 @@ def get_email_code(imap_account, imap_password, imap_server, imap_folder, debug= 'win64': 'win32' } +status_message = None + def get_web_driver(email, password, headless=False, mfa_method=None, mfa_input_callback=None, wait_for_sync=True, wait_for_sync_timeout=5 * 60, session_path=None, imap_account=None, imap_password=None, imap_server=None, imap_folder="INBOX"): + global status_message if headless and mfa_method is None: warnings.warn("Using headless mode without specifying an MFA method" "is unlikely to lead to a successful login. Defaulting --mfa-method=sms") @@ -296,11 +299,14 @@ def get_web_driver(email, password, headless=False, mfa_method=None, lambda x: "Account refresh complete" in status_message.get_attribute('innerHTML') ) except (TimeoutException, StaleElementReferenceException): - warnings.warn("Mint sync apparently incomplete after timeout. " - "Data retrieved may not be current.") + status_message = "Mint sync apparently incomplete after timeout. Data retrieved may not be current." + warnings.warn(status_message) else: driver.find_element_by_id("transaction") + if status_message is not None: + status_message = status_message.text + return driver @@ -350,6 +356,7 @@ class Mint(object): request_id = 42 # magic number? random number? token = None driver = None + status_message = None def __init__(self, email=None, password=None, mfa_method=None, mfa_input_callback=None, headless=False, session_path=None, @@ -455,6 +462,7 @@ def login_and_get_token(self, email, password, mfa_method=None, imap_folder=imap_folder, wait_for_sync=wait_for_sync, wait_for_sync_timeout=wait_for_sync_timeout) + self.status_message = status_message self.token = self.get_token() def get_token(self): @@ -467,6 +475,18 @@ def get_request_id_str(self): self.request_id += 1 return str(req_id) + def get_attention(self): + attention = None + # noinspection PyBroadException + try: + if "complete" in self.status_message: + attention = self.status_message.split(".")[1].strip() + else: + attention = self.status_message + except Exception: + pass + return attention + def get_bills(self): return self.get( '{}/bps/v2/payer/bills'.format(MINT_ROOT_URL), @@ -1164,6 +1184,10 @@ def main(): type=int, default=5 * 60, help=('Number of seconds to wait for sync. Default is 5 minutes')) + cmdline.add_argument( + '--attention', + action='store_true', + help='Display accounts that need attention (None if none).') options = cmdline.parse_args() @@ -1204,7 +1228,7 @@ def main(): if not any([options.accounts, options.budgets, options.transactions, options.extended_transactions, options.net_worth, options.credit_score, - options.credit_report]): + options.credit_report, options.attention]): options.accounts = True if options.session_path == 'None': @@ -1297,6 +1321,15 @@ def main(): else: raise ValueError('file type must be json for non-transaction data') + if options.attention: + attention_msg = mint.get_attention() + if attention_msg is None or attention_msg == "": + attention_msg = "no messages" + if options.filename is None: + print(attention_msg) + else: + with open(options.filename, 'w+') as f: + f.write(attention_msg) if __name__ == '__main__': main()