class AmazonProductProxy: def __init__(self, force_own_api=False): self.root = os.path.join(app.config['APP_ROOT'], "amws") self.profile = app.config['PROFILE'] aws_list_cred = self.get_aws_cred_from_file() if force_own_api: self.amazon = AmazonAPI(*aws_list_cred, Region='ES') else: if self.profile == BaseConfig.DEVELOPMENT_PROFILE: self.amazon = AmazonAPI(*aws_list_cred, Region='ES') else: self.amazon = ProductionAmazonAPI(*aws_list_cred, Region='ES') def search_products(self, query): product_res = self.extract_products( self.amazon.search(Keywords=query, SearchIndex='All', Availability="Available")) return product_res def search_by_asin(self, asin_list): return self.extract_products(self.amazon.lookup(ItemId=",".join(asin_list))) def create_cart(self, offer_id, quantity=1): item_dict = {'offer_id': offer_id, 'quantity': quantity} return self.amazon.cart_create(item_dict) def extract_products(self, products): product_res = [] try: for i, product in enumerate(products): # print "{0}. '{1}'".format(i, product.title) product_res.append(product) except Exception, e: return product_res return product_res
def createCart(products): pdict = {} for item in products: if item in pdict: pdict[item] = pdict[item] + 1 else: pdict[item] = 1 amazon = AmazonAPI(ACCESS_KEY, SECRET_KEY, ASSOC_ID) for index, key in enumerate(pdict.items()): product = amazon.lookup(ItemId=key[0]) item = {'offer_id': product.offer_id, 'quantity': key[1]} if index == 0: cart = amazon.cart_create(item) else: cart = amazon.cart_add(item, cart.cart_id, cart.hmac) return cart
def add_to_cart(request, cartItems): amazon = AmazonAPI('Access Key', 'Secret Key', 'gs2671-20') flag = True cartItems = eval(cartItems) for item in cartItems: if (flag): product = amazon.lookup(ItemId=item) amazon_cart = amazon.cart_create([{ 'offer_id': product.offer_id, 'quantity': 1 }]) flag = False else: product = amazon.lookup(ItemId=item) amazon.cart_add({ 'offer_id': product.offer_id, 'quantity': 1 }, amazon_cart.cart_id, amazon_cart.hmac) return HttpResponseRedirect(amazon_cart.purchase_url)
class TestAmazonCart(unittest.TestCase): def setUp(self): self.amazon = AmazonAPI( AMAZON_ACCESS_KEY, AMAZON_SECRET_KEY, AMAZON_ASSOC_TAG, CacheReader=cache_reader, CacheWriter=cache_writer, MaxQPS=0.5 ) def test_cart_clear_required_params(self): self.assertRaises(CartException, self.amazon.cart_clear, None, None) self.assertRaises(CartException, self.amazon.cart_clear, 'NotNone', None) self.assertRaises(CartException, self.amazon.cart_clear, None, 'NotNone') def build_cart_object(self): product = self.amazon.lookup(ItemId="B0016J8AOC") return self.amazon.cart_create( { 'offer_id': product._safe_get_element('Offers.Offer.OfferListing.OfferListingId'), 'quantity': 1 } ) def test_cart_create_single_item(self): cart = self.build_cart_object() assert_equals(len(cart), 1) def test_cart_create_multiple_item(self): product1 = self.amazon.lookup(ItemId="B0016J8AOC") product2 = self.amazon.lookup(ItemId="B007HCCNJU") asins = [product1.asin, product2.asin] cart = self.amazon.cart_create([ { 'offer_id': product1._safe_get_element('Offers.Offer.OfferListing.OfferListingId'), 'quantity': 1 }, { 'offer_id': product2._safe_get_element('Offers.Offer.OfferListing.OfferListingId'), 'quantity': 1 }, ]) assert_equals(len(cart), 2) for item in cart: assert_true(item.asin in asins) def test_cart_clear(self): cart = self.build_cart_object() new_cart = self.amazon.cart_clear(cart.cart_id, cart.hmac) assert_true(new_cart._safe_get_element('Cart.Request.IsValid')) def test_cart_clear_wrong_hmac(self): cart = self.build_cart_object() # never use urlencoded hmac, as library encodes as well. Just in case hmac = url_encoded_hmac we add some noise hmac = cart.url_encoded_hmac + '%3d' self.assertRaises(CartInfoMismatchException, self.amazon.cart_clear, cart.cart_id, hmac) def test_cart_attributes(self): cart = self.build_cart_object() for attribute in CART_ATTRIBUTES: getattr(cart, attribute) def test_cart_item_attributes(self): cart = self.build_cart_object() for item in cart: for attribute in CART_ITEM_ATTRIBUTES: getattr(item, attribute) def test_cart_get(self): # We need to flush the cache here so we will get a new cart that has not been used in test_cart_clear cache_clear() cart = self.build_cart_object() fetched_cart = self.amazon.cart_get(cart.cart_id, cart.hmac) assert_equals(fetched_cart.cart_id, cart.cart_id) assert_equals(len(fetched_cart), len(cart)) def test_cart_get_wrong_hmac(self): # We need to flush the cache here so we will get a new cart that has not been used in test_cart_clear cache_clear() cart = self.build_cart_object() self.assertRaises(CartInfoMismatchException, self.amazon.cart_get, cart.cart_id, cart.hmac + '%3d') def test_cart_add(self): cart = self.build_cart_object() product = self.amazon.lookup(ItemId="B007HCCNJU") item = { 'offer_id': product._safe_get_element('Offers.Offer.OfferListing.OfferListingId'), 'quantity': 1 } new_cart = self.amazon.cart_add(item, cart.cart_id, cart.hmac) assert_true(len(new_cart) > len(cart)) def test_cart_modify(self): cart = self.build_cart_object() cart_item_id = None for item in cart: cart_item_id = item.cart_item_id item = {'cart_item_id': cart_item_id, 'quantity': 3} new_cart = self.amazon.cart_modify(item, cart.cart_id, cart.hmac) assert_equals(new_cart[cart_item_id].quantity, '3') def test_cart_delete(self): cart = self.build_cart_object() cart_item_id = None for item in cart: cart_item_id = item.cart_item_id item = {'cart_item_id': cart_item_id, 'quantity': 0} new_cart = self.amazon.cart_modify(item, cart.cart_id, cart.hmac) self.assertRaises(KeyError, new_cart.__getitem__, cart_item_id)
class TestAmazonCart(unittest.TestCase): def setUp(self): self.amazon = AmazonAPI( _AMAZON_ACCESS_KEY, _AMAZON_SECRET_KEY, _AMAZON_ASSOC_TAG, CacheReader=cache_reader, CacheWriter=cache_writer, MaxQPS=0.5 ) def test_cart_clear_required_params(self): assert_raises(CartException, self.amazon.cart_clear, None, None) assert_raises(CartException, self.amazon.cart_clear, 'NotNone', None) assert_raises(CartException, self.amazon.cart_clear, None, 'NotNone') def build_cart_object(self): product = self.amazon.lookup(ItemId="B0016J8AOC") return self.amazon.cart_create( { 'offer_id': product.offer_id, 'quantity': 1 } ) def test_cart_create_single_item(self): cart = self.build_cart_object() assert_equals(len(cart), 1) def test_cart_create_multiple_item(self): product1 = self.amazon.lookup(ItemId="B0016J8AOC") product2 = self.amazon.lookup(ItemId=TEST_ASIN) asins = [product1.asin, product2.asin] cart = self.amazon.cart_create([ { 'offer_id': product1._safe_get_element( 'Offers.Offer.OfferListing.OfferListingId'), 'quantity': 1 }, { 'offer_id': product2._safe_get_element( 'Offers.Offer.OfferListing.OfferListingId'), 'quantity': 1 }, ]) assert_equals(len(cart), 2) for item in cart: assert_true(item.asin in asins) def test_cart_clear(self): cart = self.build_cart_object() new_cart = self.amazon.cart_clear(cart.cart_id, cart.hmac) assert_true(new_cart._safe_get_element('Cart.Request.IsValid')) def test_cart_clear_wrong_hmac(self): cart = self.build_cart_object() # never use urlencoded hmac, as library encodes as well. Just in case # hmac = url_encoded_hmac we add some noise hmac = cart.url_encoded_hmac + '%3d' assert_raises(CartInfoMismatchException, self.amazon.cart_clear, cart.cart_id, hmac) def test_cart_attributes(self): cart = self.build_cart_object() for attribute in CART_ATTRIBUTES: getattr(cart, attribute) def test_cart_item_attributes(self): cart = self.build_cart_object() for item in cart: for attribute in CART_ITEM_ATTRIBUTES: getattr(item, attribute) def test_cart_get(self): # We need to flush the cache here so we will get a new cart that has # not been used in test_cart_clear cache_clear() cart = self.build_cart_object() fetched_cart = self.amazon.cart_get(cart.cart_id, cart.hmac) assert_equals(fetched_cart.cart_id, cart.cart_id) assert_equals(len(fetched_cart), len(cart)) def test_cart_get_wrong_hmac(self): # We need to flush the cache here so we will get a new cart that has # not been used in test_cart_clear cache_clear() cart = self.build_cart_object() assert_raises(CartInfoMismatchException, self.amazon.cart_get, cart.cart_id, cart.hmac + '%3d') def test_cart_add(self): cart = self.build_cart_object() product = self.amazon.lookup(ItemId=TEST_ASIN) item = { 'offer_id': product._safe_get_element( 'Offers.Offer.OfferListing.OfferListingId'), 'quantity': 1 } new_cart = self.amazon.cart_add(item, cart.cart_id, cart.hmac) assert_true(len(new_cart) > len(cart)) def test_cart_modify(self): cart = self.build_cart_object() cart_item_id = None for item in cart: cart_item_id = item.cart_item_id item = {'cart_item_id': cart_item_id, 'quantity': 3} new_cart = self.amazon.cart_modify(item, cart.cart_id, cart.hmac) assert_equals(new_cart[cart_item_id].quantity, '3') def test_cart_delete(self): cart = self.build_cart_object() cart_item_id = None for item in cart: cart_item_id = item.cart_item_id item = {'cart_item_id': cart_item_id, 'quantity': 0} new_cart = self.amazon.cart_modify(item, cart.cart_id, cart.hmac) assert_raises(KeyError, new_cart.__getitem__, cart_item_id)
class AMZNMain: # Login information and opening statements def __init__(self): # Welcome the user print( "\n**************************************************************\n" + "Welcome to the Amazon-Discounts Command Line Interface (v1.0)!\n" + "Below are prompted instructions for your login information.\n" + "For the case that you might have made a mistake, please press\n" + "CTRL+C to start over. If anything breaks, please send a request\n" + "to: https://github.com/cristiangonzales/Amazon-Discounts/issues.\n" + "Thank you!\n" + "**************************************************************\n") # Prompt for information to log into the account key = input("Please enter your AWS key here: ") secret_key = input("Please enter your AWS secret key here: ") asso_tag = input("Please enter your AWS associate tag here: ") region = input("Please enter your region here (i.e. US, FR, CN, UK," + "IN, CA, DE, JP, IT): ") self.amazon = AmazonAPI(aws_key=str(key), aws_secret=str(secret_key), aws_associate_tag=str(asso_tag), region=str(region).upper()) # Initialize our cart to be pointing at nothing, at first self.cart = None # Ask for the discount rate, the output file, and the option discount = int( input("\nPlease enter the discount you would like to query for\n" + "(enter a whole number 1-99): ")) # Check to see if it is actually an integer between 0-99 if (not isinstance(discount, int)) or discount < 1 or discount > 99: raise Exception( "Sorry, you did not enter a number between 1 and 99!") # Prompt the user for an output text file to write to outputFile = open("../../amazon-discounts.log", 'w') errorLog = open("../../failed-proxies.log", 'w') # Optional argument as determined by the user optionArg = input( "Please enter a type of item you wish to search for!\n" + "If you do not have a particular type of item,\n" + "then enter a number so that we can search Goldbox\n" + "for you and look for discounts there. Also, if you\n" + "wish to search for a single item, you may enter the\n" + "keywords 'item lookup': ") # For this option argument, if it is not a keyword, then scrape Amazon's Goldbox page, # and if not, then search for that item through the API. Though, if a user inputs "item # lookup", then simply make a single list with that ASIN number appended. if optionArg.isdigit(): asinList = AMZNGoldboxFind().scrape_goldbox(int(optionArg)) elif optionArg.replace(" ", "").upper() == "ITEMLOOKUP": singleItem = str( input("\nPlease enter in the ASIN number of the item you\n" + "wish to look for here: ")) asinList = [] asinList.append(singleItem) else: asinList = self.item_search(optionArg, discount) # Cart count used in the final conditional. We will do a comparison. If the counter is 0, then we will # use the cart_create method to create the cart, and if not, then we will use the cart_add method # to add to the existing cart. cartCount = 0 # Iterate through the entire ASIN list to do the appropriate comparisons to see if that ASIN meets our # discount, and then we will write to the file for asin in asinList: # Here, we do an item lookup and get the title, current price, and offer url for this ASIN # In the case that the item is too low, then it will simply continue onto the next iteration # of the loop. try: titlePriceURLList = self.item_lookup(str(asin)) except: continue title = titlePriceURLList[0] currentPrice = titlePriceURLList[1] offerUrl = titlePriceURLList[2] # Interfacing with the CamelCamelCamel scraper, passing in the ASIN number and attempting to # get the average, lowest, and highest price for that ASIN number. Should it be the case that # the average price is none, then we will check for it and see if it is accordingly. camelPriceHistory = AMZNCamelScraper().AccessASIN(asin) averagePrice = camelPriceHistory.get_average_price() lowestPrice = camelPriceHistory.get_lowest_price() highestPrice = camelPriceHistory.get_highest_price() # Conditional here to see if the average price is NoneType. If it is, it did not connect so we # should move onto the next ASIN (continue to the next iteration) if averagePrice is None: errorLog.write("Proxy tunneling failed at " + str(camelPriceHistory.get_proxy())) continue # Now, we check the discount, sending the average price, the current price, and the user's discount if self.check_discount(discount, averagePrice, currentPrice): percentageOff = self.calculate_percentage_off( averagePrice, currentPrice) outputFile.write("Title: " + title + "\nAmazon price: " + str(currentPrice) + "\nCamelCamelCamel average price: " + str(averagePrice) + "\nCamelCamelCamel highest price: " + str(highestPrice) + "\nCamelCamelCamel lowest price: " + str(lowestPrice) + "\nPercentage off from average: " + str(percentageOff) + "\nURL: " + offerUrl + "\n\n") # Logic to add this item to our cart (if it is our first time adding to the cart, then create # the cart item, and if it isn't the first time, then we simply add to the existiing cart if cartCount == 0: self.cart_create(str(asin)) cartCount = cartCount + 1 else: self.cart_add(str(asin)) # Write the purchase URL to the logging file if cartCount != 0: outputFile.write("Click here to add all items to your cart: " + str(self.cart.purchase_url)) else: outputFile.write( "Sorry, we did not find any items to add to your cart!") # Once we are done, close the output file and error log, and say goodbye. errorLog.close() outputFile.close() print( "\nThank you for using the Amazon-Discounts CLI! Exiting now...\n") """ Item search in the case that the user requests a query. :param keywords: The keyword that the user requests in the case that they want to query Amazon, as a string. :param pctoff: The percent off that the user requests, as an integer. :return: A list of ASIN values, as strings """ def item_search(self, keywords, pctoff): try: result = self.amazon.search(SearchIndex='All', Keywords=keywords, MinPercentageOff=pctoff) asinList = [] for i, product in enumerate(result): asinList.append(product.asin) # logging.debug(product.asin) return asinList except Exception as e: raise AmazonException(str(e)) """ Item lookup for the specified ASIN number. :param ASIN: The ASIN number, as a string. :return amznList [title, price, URL] as an array. Title is a string, price as a float, and URL as a string """ def item_lookup(self, ASIN): try: # Initialize the Amazon list amznList = [] # Lookup the result based on ASIN result = self.amazon.lookup(ItemId=ASIN) # Append the appropriate values amznList.append(result.title) # logging.debug(result.title) amznList.append(float(result.formatted_price.replace('$', ''))) # logging.debug(result.formatted_price.replace('$', '')) amznList.append(result.offer_url) # logging.debug(result.offer_url) # Return the list to the caller return amznList except Exception as e: raise AmazonException(str(e)) """ Check to see if this is a discount, as wanted by the user. :return bool (dependent on if this is a discount that we want or not). """ def check_discount(self, discount, averagePrice, price): return (100 - (float(price) / float(averagePrice) * 100)) >= float(discount) """ calculate the percentage off the current Amazon price is from the average price. :return int """ def calculate_percentage_off(self, averagePrice, price): return int(100 - (float(price) / float(averagePrice) * 100)) """ Once we do all the appropriate comparisons, we will create the cart and add this item to the user's cart (this method is only used on the first ASIN). :param ASIN: The ASIN number of the discounted item :return void """ def cart_create(self, ASIN): try: product = self.amazon.lookup(ItemId=ASIN) item = {'offer_id': product.offer_id, 'quantity': 1} self.cart = self.amazon.cart_create(item) except Exception as e: raise AmazonException(str(e)) """ This method is instantiated if we have already created the cart, and we wish to add to it. :param ASIN: The ASIN number of the discounted item :return void """ def cart_add(self, ASIN): try: product = self.amazon.lookup(ItemId=ASIN) item = {'offer_id': product.offer_id, 'quantity': 1} self.amazon.cart_add(item, self.cart.cart_id, self.cart.hmac) except Exception as e: raise AmazonException(str(e))