def get_mint_handle(): mint_username = keyring.get_password("mintapi", "username") mint_password = keyring.get_password("mintapi", "password") mint = mintapi.Mint( mint_username, # Email used to log in to Mint mint_password, # Your password used to log in to mint # Optional parameters mfa_method='sms', # Can be 'sms' (default), 'email', or 'soft-token'. # if mintapi detects an MFA request, it will trigger the requested method # and prompt on the command line. headless=False, # Whether the chromedriver should work without opening a # visible window (useful for server-side deployments) mfa_input_callback=None, # A callback accepting a single argument (the prompt) # which returns the user-inputted 2FA code. By default # the default Python `input` function is used. session_path=None, # Directory that the Chrome persistent session will be written/read from. # To avoid the 2FA code being asked for multiple times, you can either set # this parameter or log in by hand in Chrome under the same user this runs # as. imap_account=None, # account name used to log in to your IMAP server imap_password=None, # account password used to log in to your IMAP server imap_server=None, # IMAP server host name imap_folder='INBOX', # IMAP folder that receives MFA email wait_for_sync=False, # do not wait for accounts to sync wait_for_sync_timeout=300, # number of seconds to wait for sync ) return mint
def run(arguments): mint = mintapi.Mint(getCredentials("mint")["email"], getCredentials("mint")["password"], mfa_method='sms', headless=False) mint.get_accounts() # Get extended account detail at the expense of speed - requires an # additional API call for each account print(mint.get_accounts(True)) # Get budget information print(mint.get_budgets()) # Get transactions print(mint.get_transactions()) # as pandas dataframe print( mint.get_transactions_csv(include_investment=False)) # as raw csv data print( mint.get_transactions_json(include_investment=False, skip_duplicates=False)) # Get net worth print(mint.get_net_worth())
def __init__(self, email, password): self.email = email # TODO: I should def hash this password b/c this is unsafe self.password = password # TODO: do i even need this _cached_spending. yeah right? self._cached_spending = None self._connection = mintapi.Mint(self.email, self.password)
def connect(credentials, scraper_args=None): import mintapi mint = mintapi.Mint() scraper_args = dict(scraper_args or {}) def try_login(scraper): scraper = MintTokenScraper(credentials=credentials, **scraper_args) scraper.login() mint.driver = scraper.driver mint.token = mint.get_token() with scrape_lib.temp_scraper(MintTokenScraper, credentials=credentials, **scraper_args) as scraper: okay = False try: try_login(scraper) okay = True except (TimeoutError, selenium.common.exceptions.TimeoutException): if not scraper_args.get('headless') and not scraper_args.get( 'login_timeout'): raise traceback.print_exc() if okay: yield mint return scraper_args['headless'] = True scraper_args['login_timeout'] = None logger.info('Retrying login interactively') with scrape_lib.temp_scraper(MintTokenScraper, credentials=credentials, **scraper_args) as scraper: try_login(scraper) yield mint
def code(doneBefore): if not doneBefore: mint = mintapi.Mint(pw.getUser(), pw.getPass()) #, ius_session, thx_guid) filehandler = open('accounts.pi', 'w') pickle.dump(mint.get_accounts(), filehandler) getAccounts()
def __init__(self, user, pwd): """Login to Mint and refresh account data""" print( "Connecting to Mint...\nIt may take a couple minutes to login and refresh all account data..." ) self.mint = mintapi.Mint(user, pwd) print("Connected\n")
def download_transactions(month, use_local=False): cur_year, cur_mon = [int(val) for val in month.split('-')] if not use_local: mint_log.trace(f'downloading transactions for {cur_mon}/{cur_year}') mint = mintapi.Mint(email, password, headless=True, mfa_method='sms') mint.initiate_account_refresh() df = mint.get_transactions() df.to_json('mint_data.json') else: mint_log.trace( f'using local file to get transactions for {cur_mon}/{cur_year}') df = pd.read_json('mint_data.json') df['hash'] = df.apply(hash_row, axis=1) df['spent'] = df.apply(lambda x: x.amount * { 'debit': 1, 'credit': -1 }[x.transaction_type], axis=1) cur_df = df[df.apply(lambda x: filter_by_month(x, cur_mon, cur_year), axis=1)].copy() cur_df['month'] = cur_mon cur_df = cur_df.apply(update_categories, axis=1) return cur_df
def update_pickle_from_mint(pickle_name): with open('no_checkin.txt') as f: user = f.readline().strip() psw = f.readline().strip() mint = mintapi.Mint(user, psw) df = mint.get_transactions() df.to_pickle(pickle_name)
def get_transactions(mint_username, mint_password): """ Grab transactions from mintapi and create transaction objects. BUT - don't load them into database. """ # NOTE - for demo use secrets file for authentication instead of keyring # mint_password = keyring.get_password("system", mint_username) mint = mintapi.Mint(mint_username, mint_password) user_transactions = mint.get_transactions() categories = {} transaction_obj_list = [] for i in range(len(user_transactions.index)): date = str(user_transactions["date"][i])[:10] date = datetime.datetime.strptime(date, "%Y-%m-%d") description = user_transactions["description"][i] category = user_transactions["category"][i] categories[str(category).strip()] = 0 amount = float(user_transactions["amount"][i]) transaction_obj = Transaction(transaction_id=i, date=date, description=description, category=category, amount=amount) transaction_obj_list.append(transaction_obj) categories_to_remove = set([ "paycheck", "bills & utilities", "business services", "transfer", "federal tax", "credit card payment", "nan", "financial", "income", "interest income", "pharmacy", "check", "atm fee", "doctor", "air travel", "hotel", "gas & fuel" ]) for category in categories.keys(): if category in categories_to_remove: del categories[category] for transaction_obj in transaction_obj_list: category = transaction_obj.category if category in categories.keys(): categories[category] += transaction_obj.amount categories_to_group = { "entertainment": ("amusement", "entertainment", "music", "sports"), "restaurants": ("restaurants", "food & dining", "fast food"), "shopping": ("clothing", "books", "electronics & software", "hair"), "taxi": ("taxi", "rental car & taxi") } for category in categories_to_group.keys(): for grouped_category in categories_to_group[category]: if grouped_category != category: categories[category] += categories[grouped_category] del categories[grouped_category] return categories
def __init__(self, username, password): self.mint = mintapi.Mint(username, password) #print("Refreshing mint accounts...") #self.mint.initiate_account_refresh() #self.refresh_accounts() #print("Accounts refreshed!") self.accounts = self.mint.get_accounts() mintapi.print_accounts(self.accounts)
def loadMintAPIs(filename): apis = {} creds_file = open(filename) for line in creds_file: creds = json.loads(line) print "Loading Mint API for: " + creds['email'] apis[creds['email']] = mintapi.Mint(creds['email'], creds['password']) return apis
def transactions(self, fromdate=None): time.sleep(self.__sync_delay) self.__sync_delay = 0 m = mintapi.Mint(self.__username, self.__password) time.sleep( 20 + 10 * random.random() ) # Give mint.com time to synchronise transactions with banks yield from self.__remap(m.get_transactions_json())
def main(): print("Creating mint api connection") mint = mintapi.Mint(**mintParams()) parse_and_write_transactions(mint.get_transactions_csv()) mintdf, sheetsdf = tempTransactions(), sheetsTransactions() #pp.pprint(mintdf) #pp.pprint(sheetsdf) insertNewData(mintdf, sheetsdf, len(sheetsdf) + 2) update_col_format(SPREADSHEET, SHEET)
def get_mint_driver() -> mintapi.Mint: mint = mintapi.Mint() mint.driver = mintapi.signIn._create_web_driver_at_mint_com( HEADLESS, SESSION_PATH, USE_CHROMEDRIVER_ON_PATH, ) yield mint mint.close()
def mintapi_instance(username, password): try: mint = mintapi.Mint(username, password) # mint.token = mintapi_token(username, password) return mint except Exception, e: if 'login' in str(e): raise InvalidCredentials(str(e)) else: raise
def main(): '''Main''' if CONFIG['mintuser'] and CONFIG['mintpassword']: mint = mintapi.Mint(CONFIG['mintuser'], CONFIG['mintpassword']) for bank in mint.get_accounts(): print( "Display Name: %(fiLoginDisplayName)s\n" "Account Name: %(accountName)s\n" "Bank Name: %(fiName)s\n" "Id: %(id)s\n" "Balance: %(value)s\n") % bank
def __init__(self): """ Connects to Mintapi and assigns variables for methods used more than once. """ self.config = config.load() self.mintapi = mintapi.Mint(self.config['mint']['user'], self.config['mint']['pass'], self.config['mint']['ius_session'], self.config['mint']['thx_guid']) self.mintapi.initiate_account_refresh() self.transactionsDF = self.transactionsDF() self.lastMonthDF = self.last_month_transactions()
def get_transactions(): """ Returns a pd.DataFrame of deduplicated transactions stored in your Mint account """ email = os.environ['EMAIL'] password = os.environ['PASSWORD'] mint = mintapi.Mint(email, password) mint.initiate_account_refresh() transactions = mint.get_transactions() transactions.drop_duplicates(['date', 'original_description', 'amount'], inplace=True) return transactions
def download_detailed_transactions(month, use_local=False, refresh_acct=True): cur_year, cur_mon = [int(val) for val in month.split('-')] start_date = f'{cur_mon}/01/{str(cur_year)[2:]}' print(start_date) if not use_local: mint_log.trace(f'downloading transactions for {cur_mon}/{cur_year}') mint = mintapi.Mint(email, password, headless=True, mfa_method='sms') if refresh_acct: mint_log.trace('Refreshing account') mint.initiate_account_refresh() df = mint.get_detailed_transactions(start_date=start_date, include_investment=False) df['transaction_type'] = df['isDebit'].map(lambda x: 'debit' if x else 'credit') df = df[[ 'odate', 'mmerchant', 'omerchant', 'amount', 'transaction_type', 'mcategory', 'account', 'labels', 'note' ]] df.columns = [ 'date', 'description', 'original_description', 'amount', 'transaction_type', 'category', 'account_name', 'labels', 'notes' ] mint_log.trace(f'Saving data to file at {mint_data_path}') df.to_json(mint_data_path) else: mint_log.trace( f'Ising local transactions for {cur_mon}/{cur_year} from file at {mint_data_path}' ) df = pd.read_json(mint_data_path) df['hash'] = df.apply(hash_row, axis=1) df['category'] = df['category'].map(lambda x: x.lower()) df['spent'] = df['amount'] cur_df = df[df.apply(lambda x: filter_by_month(x, cur_mon, cur_year), axis=1)].copy() cur_df['month'] = cur_mon cur_df = cur_df.apply(update_categories, axis=1) mint_log.info(f'DataFrame created with {len(df)} records.') return cur_df[[ 'date', 'description', 'original_description', 'amount', 'transaction_type', 'category', 'account_name', 'labels', 'notes', 'hash', 'spent', 'month', 'm_category' ]]
def get_netWorth(intent, session): card_title = "Net Worth" ius_session = '0D729971F8014D46AFAE78535BA5EE5F' thx_guid = 'ECA2581CD1B3B676' thx_guid = 'GA1.2.869397484.1508601630' mint = mintapi.Mint(pw.getUser(), pw.getPass(), ius_session, thx_guid) net_Worth = mint.get_net_worth() should_end_session = True speech_output = "Your net worth is " + str( net_Worth) + " Dollars . Have a great one big boi." # return build_response({}, build_speechlet_response( # card_title, speech_output, None, should_end_session)) print('hello') print(speech_output)
def _LogIntoMint(creds: Credentials, options: ScraperOptions, chromedriver_download_path: Text, cookies: List[Text]) -> mintapi.Mint: """Logs into mint and retrieves an active connection. Args: creds: The credentials for the account to log into. options: Options for how to connect. chromedriver_download_path: Location of chromedriver. cookies: Cookies to attach to the session, when provided. Returns: The mint connection object. """ if os.getenv('CHROME_SESSION_PATH'): session_path = os.getenv('CHROME_SESSION_PATH') else: session_path = os.path.join(os.getcwd(), '.mintapi', 'session') if os.getenv('MFA_TOKEN'): mfa_method = 'soft-token' mfa_token = os.getenv('MFA_TOKEN') else: mfa_method = 'text' mfa_token = None mint = mintapi.Mint( creds.email, creds.mintPassword, chromedriver_download_path=chromedriver_download_path, headless=not options.showBrowser, imap_account=creds.email, imap_folder='Inbox', imap_password=creds.emailPassword, imap_server=_GLOBAL_CONFIG.IMAP_SERVER, mfa_input_callback=None, mfa_method=mfa_method, mfa_token=mfa_token, session_path=session_path, wait_for_sync=_GLOBAL_CONFIG.WAIT_FOR_ACCOUNT_SYNC, ) time.sleep(5) # Load cookies if provided. These are cookies only for mint.com domain. [mint.driver.add_cookie(cookie) for cookie in cookies] return mint
def do_notifications(notifications): ''' Format all the notifications from get_notifications into subject and message ''' billstring = [] if not notifications: return False weektotal = 0 for bill in notifications: bill['duedate'] = stylish_date(bill['duedate']) weektotal += int(bill['amount']) billstring.append( "%(name)s, %(description)s, Due: $%(amount)s on %(duedate)s" % bill) billstring = '\n'.join(billstring) curtime = datetime.datetime.now() message = ("Upcoming Bills:\n%(billstring)s\n\n" "Total amount of bills due: $%(weektotal)s\n") % { 'billstring': billstring, 'weektotal': weektotal, } if CONFIG['mintuser'] and CONFIG['mintpassword']: mint = mintapi.Mint(CONFIG['mintuser'], CONFIG['mintpassword']) bankinfo = mint.get_accounts() avaliable_balance = 0 for bank in bankinfo: if int(bank['id']) == int(CONFIG['mintaccountid']): avaliable_balance = int(bank['value']) secondmessage = ( "Expected balance at end of week: $%(remaining_balance)s\n" "Current Balance: $%(avaliable_balance)s") % { 'remaining_balance': avaliable_balance - weektotal, 'avaliable_balance': avaliable_balance, } message = message + secondmessage subject = 'Bills for the upcoming week of %(month)s %(day)s' % { 'month': calendar.month_name[curtime.month], 'day': stylish_date(curtime.day), } send_email(subject, message)
def main(): print('Starting splitter') user = keyring.get_password(KEYRING_SERVICE, "user") password = '' # if credentials already saved in keyring... if user: password = keyring.get_password(KEYRING_SERVICE, "password") else: user, password = cli.save_credentials(KEYRING_SERVICE) print("Logging in...") try: mint = mintapi.Mint(email=user, password=password, mfa_method='sms', headless=True, session_path=path.abspath("./session"), wait_for_sync=False) except: print( "Failed to login to mint/open new chrome session. Ensure your current chrome session is closed" ) exit() print("Logged in!") splitter = mint_splitter.Splitter(mint) accounts = splitter.get_filtered_accounts() selected_accounts = cli.get_selected_accounts(accounts) splitter.split_transactions(selected_accounts, start_date=cli.get_start_date()) mint.close() sys.exit()
def _init_mint(self) -> mintapi.Mint: config = {} with open('config/mint.json') as f: config = json.load(f) self.__mint = mintapi.Mint( bitarray(config['u']).tobytes().decode('utf8'), bitarray(config['p']).tobytes().decode('utf8'), # Optional parameters mfa_method= 'sms', # Can be 'sms' (default), 'email', or 'soft-token'. # if mintapi detects an MFA request, it will trigger the requested method # and prompt on the command line. headless= True, # Whether the chromedriver should work without opening a # visible window (useful for server-side deployments) mfa_input_callback= None, # A callback accepting a single argument (the prompt) # which returns the user-inputted 2FA code. By default # the default Python `input` function is used. session_path= './session', # Directory that the Chrome persistent session will be written/read from. # To avoid the 2FA code being asked for multiple times, you can either set # this parameter or log in by hand in Chrome under the same user this runs # as. imap_account=None, # account name used to log in to your IMAP server imap_password= None, # account password used to log in to your IMAP server imap_server=None, # IMAP server host name imap_folder='INBOX', # IMAP folder that receives MFA email wait_for_sync=False, # do not wait for accounts to sync wait_for_sync_timeout=300, # number of seconds to wait for sync use_chromedriver_on_path= False, # True will use a system provided chromedriver binary that # is on the PATH (instead of downloading the latest version) ) return self.__mint
def get_mint_account(): u = urllib.unquote(request.args.get('u')) p = urllib.unquote(request.args.get('p')) mint = mintapi.Mint(u, p) all_accounts = mint.get_accounts() # Need to sanitize python dates to be able to # convert to JSON for account in all_accounts: if 'closeDateInDate' in account: account['closeDateInDate'] = int( time.mktime(account['closeDateInDate'].timetuple())) if 'lastUpdatedInDate' in account: account['lastUpdatedInDate'] = int( time.mktime(account['lastUpdatedInDate'].timetuple())) if 'addAccountDateInDate' in account: account['addAccountDateInDate'] = int( time.mktime(account['addAccountDateInDate'].timetuple())) if 'fiLastUpdatedInDate' in account: account['fiLastUpdatedInDate'] = int( time.mktime(account['fiLastUpdatedInDate'].timetuple())) return simplejson.dumps(all_accounts)
def test_get_transactions(self, mocked_get_transactions): mocked_get_transactions.return_value = transactions_example mint = mintapi.Mint() transactions_df = mint.get_transactions() assert (isinstance(transactions_df, pd.DataFrame))
import mintapi import datetime import pandas as pd mint = mintapi.Mint('username', 'password') ## Get transactions transaction=mint.get_transactions() # as pandas dataframe transaction.describe() transaction.head() debit_transaction = transaction[transaction['transaction_type'] == 'debit'] debit_transaction['Date'] =pd.to_datetime(debit_transaction['date']) debit_transaction['Month']=debit_transaction['Date'].dt.month debit_transaction['Year'] =debit_transaction['Date'].dt.year filter_list = ['bills & utilities','mobile phone','internet','utilities','television'] debit_transaction.loc[debit_transaction.category.isin(filter_list),'category']='Bills & utilities' filter_list = ['coffee shops', 'fast food', 'food & dining','restaurants'] debit_transaction.loc[debit_transaction.category.isin(filter_list),'category']='Eating Out' filter_list = ['charity','gifts & donations','kids activities' ] debit_transaction.loc[debit_transaction.category.isin(filter_list),'category']='Charity' filter_list = ['movies & dvds', 'hotel','air travel', 'travel', 'amusement', 'sports' , 'sporting goods','entertainment' ] debit_transaction.loc[debit_transaction.category.isin(filter_list),'category']='Travel & Amusement' filter_list = ['parking', 'rental car & taxi','auto & transport','public transportation','service & parts','auto insurance'] debit_transaction.loc[debit_transaction.category.isin(filter_list),'category']='Transport' filter_list = ['groceries','shopping','books','clothing','gift','home improvement','newspapers & magazines','electronics & software','office supplies'] debit_transaction.loc[debit_transaction.category.isin(filter_list),'category']='Groceries & shopping' filter_list = ['shipping','personal care','hair','home services','tuition'] debit_transaction.loc[debit_transaction.category.isin(filter_list),'category']='Business services' filter_list = ['doctor','pharmacy'] debit_transaction.loc[debit_transaction.category.isin(filter_list),'category']='Health'
# Run this file to force account data refresh import mintapi import config import time mint = mintapi.Mint(config.mint_email, config.mint_pass) mint.initiate_account_refresh()
currentMonth = int(t.month) if currentMonth == examinedMonth: budget = budget - float(stringAmount) if (thisDate.strftime("%Y-%m-%d") == str(t)): if k < limit: listToAppendTo.append(fullString) if (transactions[k]['category'] == 'income'): totalAmountEarnt = totalAmountEarnt + float(stringAmount) else: totalAmountBought = totalAmountBought + float(stringAmount) k += 1 else: budget = 985 mint = mintapi.Mint(email, password, ius_session, thx_guid) transactions = mint.get_transactions_json() for i in transactions: i = json.dumps(i) t = datetime.datetime.today() t = (t + datetime.timedelta(days=timeChange)).date() thisDate = dt.strptime(transactions[k]['date'], '%b %d').date() thisDate = thisDate.replace(year=datetime.datetime.today().year) stringDate = thisDate.strftime("%Y-%m-%d") stringCategory = unicodedata.normalize( 'NFKD', transactions[k]['mmerchant']).encode('ascii', 'ignore') stringAmount = unicodedata.normalize('NFKD', transactions[k]['amount']).encode( 'ascii', 'ignore')
def main(): args = parse_args() home = os.path.expanduser("~") default_session_path = os.path.join(home, '.mintapi', 'session') try: password = keyring.get_password('mintapi', args.username) except: print( "keyring couldn't get saved password, please manually enter the password" ) password = getpass.getpass("Mint password: "******"Saving the password to keyring") keyring.set_password('mintapi', args.username, password) # init Mint print("Logging into Mint") mint = mintapi.Mint( args.username, password, mfa_method='sms', headless=False, session_path= default_session_path, # saved session to avoid multiple MFA requests wait_for_sync=True, wait_for_sync_timeout=300, # number of seconds to wait for sync use_chromedriver_on_path= True, # Use chromedriver on PATH since Debian Chromium is behind the latest release ) # Get Transactions print("Obtaining transactions") df = get_transactions(mint) # Filter by date, if applicable if args.start_date: print(f"Filtering transactions that occured before {args.start_date}") df = df[df["date"] >= args.start_date].copy() if args.end_date: print(f"Fitering transactions that occured after {args.end_date}") df = df[df["date"] <= args.end_date].copy() # Capitalize first character in category df["category"] = df["category"].str.title() # Check unmapped categories unmapped = [] for category in pd.unique(df.category): if category not in MAPPING: unmapped.append(category) print(f"{category:>25s} is unmapped") print(f"Found a total of {len(unmapped)} unmapped categories") proceed = input( "Proceed with logging? (y/n/print) ") # TODO: make more user friendly if proceed == "print": for category in unmapped: sample_df = df.query(f"category == '{category}'")[[ "date", "description", "original_description", "category", "transaction_type" ]] sample_df = sample_df.sample(n=min(5, len(sample_df))) print(f"Category: {category:<25}") print(sample_df.to_markdown()) _ = input("Press ENTER for next category ") print("\n---\n") proceed = input("Proceed with logging? (y/n/CTRL-C) ") if proceed == "y": # Get logged transactions print( "Obtaining already logged transactions to avoid repeating transactions" ) start_date = df.date.min() end_date = df.date.max() transactions = get_moneylover_log(start_date, end_date, wallet=args.wallet) # Log transactions in Money Lover print("Start logging transactions into Money Lover") for _, row in df.iterrows(): log_transaction(row, args.wallet, transactions) else: print("Ending program")