def main(): config = open_config() parser = argparse.ArgumentParser( description='Adding a tracking number manually') parser.add_argument( '-a', '--auto', action="store_true", help='Allows input of fields through the script invocation args') parser.add_argument('-t', '--tracking', help='Tracking number in question') parser.add_argument('-o', '--order', help='Order number to associate this tracking with') parser.add_argument('-g', '--group', help='Buying group for this tracking') args, _ = parser.parse_known_args() if args.auto: run_auto(config, args) return action = get_required_from_options( "Enter 'a' to add a tracking number to an existing cluster, " "'n' for a new tracking, or 'd' to delete a tracking", ["a", "n", "d"]) if action == "a": run_add(config) elif action == "n": run_new(config) elif action == "d": run_delete(config)
def main(): parser = argparse.ArgumentParser(description='Reconciliation script') parser.add_argument("--groups", nargs="*") args, _ = parser.parse_known_args() config = open_config() print("Reconciling ...") reconcile_new(config, args)
def main(): parser = argparse.ArgumentParser(description='Reconciliation script') parser.add_argument("--groups", nargs="*") parser.add_argument("--print-unknowns", "-u", action="store_true", help="print unknown trackings found in BG portals") args, _ = parser.parse_known_args() config = open_config() print("Reconciling ...") reconcile_new(config, args)
def get_order_ids_to_orders(args): mail = email_auth.email_authentication() mail.select('"[Gmail]/All Mail"') email_ids = get_email_ids(mail, args) config = open_config() email_to_orders = EmailToOrders(config) result = {} for email_id in tqdm(email_ids, desc="Fetching orders", unit="email"): for order in email_to_orders.get_orders(mail, email_id): result[order.order_id] = order return result
def main(): parser = argparse.ArgumentParser(description='Reconciliation script') parser.add_argument("--groups", nargs="*") parser.add_argument("--print-unknowns", "-u", action="store_true", help="print unknown trackings found in BG portals") parser.add_argument( '-f', '--full', action='store_true', help= 'Run a full reconciliation, not stopping once we see trackings we\'ve already seen in the sites' ) args, _ = parser.parse_known_args() config = open_config() print("Reconciling ...") reconcile_new(config, args)
def main(): parser = argparse.ArgumentParser( description="Ouptut a set of orders for which we don't have shipments") parser.add_argument("--days") args, _ = parser.parse_known_args() order_ids_to_orders = get_order_ids_to_orders(args) config = open_config() sheet_id = config['reconciliation']['baseSpreadsheetId'] orders_from_sheet = get_orders_from_sheet(sheet_id) for previous_order in orders_from_sheet: if previous_order.manually_verified and previous_order.order_id in order_ids_to_orders: order_ids_to_orders[previous_order.order_id].manually_verified = True orders_list = list(order_ids_to_orders.values()) orders_list = filter_orders(orders_list, config) orders_list.sort(key=cmp_to_key(compare)) objects_to_sheet = ObjectsToSheet() objects_to_sheet.upload_to_sheet(orders_list, sheet_id, 'Non-Shipped Orders')
# email_auth.py # # Combine standard login with option of OAuth2.0 # import base64 import smtplib from imaplib import IMAP4_SSL from googleapiclient.discovery import build from httplib2 import Http from oauth2client import file, client, tools from lib.config import open_config CONFIG = open_config() EMAIL_CONFIG = CONFIG['email'] GMAIL_URL = "https://mail.google.com/" IMAPURL = "imap.gmail.com" SMTPURL = "smtp.gmail.com" SMTPPORT = "587" USERNAME = EMAIL_CONFIG["username"] def email_authentication() -> IMAP4_SSL: mail = IMAP4_SSL(IMAPURL) if "password" in EMAIL_CONFIG and EMAIL_CONFIG["password"]: mail.login(EMAIL_CONFIG['username'], EMAIL_CONFIG['password']) else: creds = get_oauth_credentials() client_credentials = creds.get_access_token().access_token
def main(): parser = argparse.ArgumentParser(description='Get tracking #s script') parser.add_argument("--seen", action="store_true") parser.add_argument("--days") args, _ = parser.parse_known_args() driver_creator = DriverCreator() config = open_config() email_config = config['email'] email_sender = EmailSender(email_config) print("Retrieving Amazon tracking numbers from email ...") amazon_tracking_retriever = AmazonTrackingRetriever( config, args, driver_creator) try: trackings = amazon_tracking_retriever.get_trackings() except: send_error_email(email_sender, "Error retrieving Amazon emails") raise print("Retrieving Best Buy tracking numbers from email ...") bestbuy_tracking_retriever = BestBuyTrackingRetriever( config, args, driver_creator) try: trackings.update(bestbuy_tracking_retriever.get_trackings()) except: send_error_email(email_sender, "Error retrieving Best Buy emails") raise try: tracking_output = TrackingOutput(config) existing_tracking_nos = set([ t.tracking_number for t in tracking_output.get_existing_trackings() ]) new_tracking_nos = set( trackings.keys()).difference(existing_tracking_nos) print(f"Found {len(new_tracking_nos)} new tracking numbers " f"(out of {len(trackings)} total) from emails.") new_trackings = [trackings[n] for n in new_tracking_nos] # We only need to process new tracking numbers if there are any; # otherwise skip straight to processing existing locally stored data. if new_trackings: try: email_sender.send_email(new_trackings) except Exception as e: # When running --seen, we're often processing a very large number of emails that can # take a long time, and the Tracking Numbers email isn't too important to us (but the # upload to portals/Sheets definitely is). So don't fail after we've been running for # a long time just on account of a failed email. if args.seen: print( f"Email sending failed with error: {str(e)}\n{util.get_traceback_lines()}" ) print("New trackings are:\n" + "\n".join([str(nt) for nt in new_trackings])) print( "Continuing to portal/Sheet upload because email sending is non-essential." ) else: raise e print("Uploading all tracking numbers...") group_site_manager = GroupSiteManager(config, driver_creator) try: group_site_manager.upload(trackings.values()) except: send_error_email(email_sender, "Error uploading tracking numbers") if args.seen: print("Error uploading tracking numbers; skipping.") else: raise reconcilable_trackings = [t for t in new_trackings if t.reconcile] # Also only add new trackings to the sheet print("Adding results to Google Sheets") tracking_uploader = TrackingUploader(config) try: tracking_uploader.upload_trackings(reconcilable_trackings) except: send_error_email(email_sender, "Error uploading to Google Sheets") if args.seen: print("Error uploading to Google Sheets; skipping.") else: raise print("Writing results to file") try: tracking_output.save_trackings(new_trackings) except: send_error_email(email_sender, "Error writing output file") raise print("Done") except: print("Exception thrown after looking at the emails.") if not args.seen: print("Marking all relevant emails as unread to reset.") amazon_tracking_retriever.back_out_of_all() bestbuy_tracking_retriever.back_out_of_all() if not args.seen: print("Marked all as unread.") raise
import argparse import csv import datetime import glob from typing import List, Optional, Callable, Dict, Tuple from lib.config import open_config from lib.driver_creator import DriverCreator from lib.email_sender import EmailSender from lib.group_site_manager import GroupSiteManager, clean_csv_tracking from lib.objects_to_sheet import ObjectsToSheet from lib.tracking import Tracking from lib.tracking_output import TrackingOutput from lib.tracking_uploader import TrackingUploader config = open_config() def get_group(address: str) -> Tuple[Optional[str], bool]: address = address.upper() for group in config['groups'].keys(): group_conf = config['groups'][group] reconcile = bool( group_conf['reconcile']) if 'reconcile' in group_conf else True group_keys = config['groups'][group]['keys'] if isinstance(group_keys, str): group_keys = [group_keys] for group_key in group_keys: if str(group_key).upper() in address: return group, reconcile if len(address) > 3: