├── AmazonAlert.py ├── DailyScan.py └── README.md /AmazonAlert.py: -------------------------------------------------------------------------------- 1 | # ----- Plotting Configuration ------------------------------------------------- 2 | 3 | import matplotlib 4 | matplotlib.use('Agg') 5 | import matplotlib.pyplot as plt 6 | from matplotlib.ticker import FuncFormatter 7 | from matplotlib.dates import DateFormatter 8 | import numpy as np 9 | import datetime as dt 10 | 11 | def plotDatePrice(productID, productTitle, data): 12 | 13 | # Data setup 14 | x, y = [], [] 15 | for datapoint in data: 16 | date = datapoint.split('|')[0] 17 | price = float(datapoint.split('|')[1]) 18 | x.append(dt.datetime.strptime(date, '%Y-%m-%d')) 19 | y.append(price) 20 | x = matplotlib.dates.date2num(x) 21 | x_np, y_np = np.array(x), np.array(y) 22 | 23 | # Plot setup 24 | ax = plt.figure(figsize=(6, 3)).add_subplot(111) 25 | ax.spines['top'].set_visible(False) 26 | ax.spines['right'].set_visible(False) 27 | ax.get_xaxis().tick_bottom() 28 | ax.get_yaxis().tick_left() 29 | ax.plot(x_np, y_np, color='lightblue', lw=2) 30 | ax.margins(0.05) 31 | ax.yaxis.set_major_formatter(FuncFormatter(lambda x, pos: ('$%i' % (x)))) 32 | ax.xaxis.set_major_formatter(DateFormatter('%Y-%m-%d')) 33 | plt.yticks(fontsize=8) 34 | plt.ylim(ymin=min(y)*0.7, ymax=max(y)*1.3) 35 | plt.title('Recent Price History\n'+productTitle, weight ='light', fontsize=12, y=1.08) 36 | plt.xticks(rotation=40, fontsize=7) 37 | plt.tight_layout() 38 | plt.savefig(productID+'.png') 39 | return productID+'.png' 40 | 41 | # ----- Email Configuration ---------------------------------------------------- 42 | 43 | import smtplib 44 | from email.mime.multipart import MIMEMultipart 45 | from email.mime.text import MIMEText 46 | from email.mime.image import MIMEImage 47 | 48 | def sendEmail(product, graph, EMAIL_CREDENTIALS): 49 | 50 | # Gmail credentials 51 | self = EMAIL_CREDENTIALS[0] 52 | password = EMAIL_CREDENTIALS[1] 53 | fromAddr = EMAIL_CREDENTIALS[2] 54 | toAddr = EMAIL_CREDENTIALS[3] 55 | 56 | # Handle base 57 | msg = MIMEMultipart() 58 | msg['From'] = fromAddr 59 | msg['To'] = toAddr 60 | msg['Subject'] = "Price Alert: " + product 61 | msgText = MIMEText('


', 'html') 62 | msg.attach(msgText) 63 | 64 | # Embed image 65 | image = open(graph, 'rb') 66 | msgImage = MIMEImage(image.read()) 67 | msgImage.add_header('Content-ID', '') 68 | msg.attach(msgImage) 69 | image.close() 70 | 71 | # Send email 72 | server = smtplib.SMTP('smtp.gmail.com', 587) 73 | server.starttls() 74 | server.login(self, password) 75 | text = msg.as_string() 76 | server.sendmail(fromAddr, toAddr, text) 77 | server.quit() 78 | 79 | # ----- Amazon API ------------------------------------------------------------- 80 | 81 | from amazon.api import AmazonAPI 82 | import csv 83 | import time 84 | 85 | def readPrices(csvFile): 86 | priceData = {} 87 | targetData = {} 88 | with open(csvFile, 'rb') as infile: 89 | for line in infile: 90 | row = line.strip('\n\r').split(',') 91 | column = row[0].split('|') 92 | priceData[column[0]] = row[1:] 93 | targetData[column[0]] = column[1] 94 | infile.close() 95 | return priceData, targetData 96 | 97 | def updatePrices(newPriceData, oldPriceData): 98 | for pair in newPriceData: 99 | product = pair[0] 100 | price = pair[1] 101 | try: oldPriceData[product].append(price) 102 | except KeyError: 103 | print "Product %s was skipped." % (product) 104 | print "It has not been initalized with an alert price!" 105 | return oldPriceData 106 | 107 | def writePrices(newPriceData, targetData, csvFile): 108 | with open(csvFile, 'wb') as outfile: 109 | writer = csv.writer(outfile) 110 | for product in newPriceData: 111 | target = targetData[product] 112 | writer.writerow([product+'|'+target]+newPriceData[product]) 113 | outfile.close() 114 | 115 | def getPrice(productID, AWS_CREDENTIALS): 116 | amazon = AmazonAPI(AWS_CREDENTIALS[0], AWS_CREDENTIALS[1], AWS_CREDENTIALS[2]) 117 | result = amazon.lookup(ItemId=productID) 118 | return result.title, result.price_and_currency[0] 119 | 120 | def addProduct(productID, csvFile, alertWhen, alertType, AWS_CREDENTIALS): 121 | currentPrice = getPrice(productID, AWS_CREDENTIALS)[1] 122 | 123 | if alertType == "percentChange": 124 | delta = (float(alertWhen)/100)+1 125 | alertPrice = currentPrice*delta 126 | 127 | elif alertType == "desiredPrice": 128 | alertPrice = float(alertWhen) 129 | 130 | else: raise ValueError('Invalid alertType') 131 | 132 | with open(csvFile, 'a') as outfile: 133 | writer = csv.writer(outfile) 134 | writer.writerow([productID+'|'+str(alertPrice)]) 135 | outfile.close() 136 | 137 | def dailyScan(productIDs, csvFile, AWS_CREDENTIALS, EMAIL_CREDENTIALS): 138 | prices, targets = readPrices(csvFile) 139 | alerts = [] 140 | update = [] 141 | for productID in productIDs: 142 | title, price = getPrice(productID, AWS_CREDENTIALS) 143 | date = time.strftime("%Y-%m-%d") 144 | update.append((productID,date+'|'+str(price))) 145 | 146 | try: 147 | if price <= float(targets[productID]): 148 | alerts.append(productID) 149 | except KeyError: pass 150 | 151 | updatedPrices = updatePrices(update, prices) 152 | writePrices(updatedPrices, targets, csvFile) 153 | 154 | for alert in alerts: 155 | graph = plotDatePrice(alert, title, updatedPrices[alert]) 156 | sendEmail(title, graph, EMAIL_CREDENTIALS) 157 | -------------------------------------------------------------------------------- /DailyScan.py: -------------------------------------------------------------------------------- 1 | from AmazonAlert import addProduct, dailyScan 2 | 3 | # ----- Gmail Credentials ----------- 4 | 5 | EMAIL_SELF = 'youremail@gmail.com' 6 | EMAIL_PASSWORD = 'yourpassword' 7 | EMAIL_FROM = EMAIL_SELF 8 | EMAIL_TO = EMAIL_SELF 9 | EMAIL_CREDENTIALS = [EMAIL_SELF, EMAIL_PASSWORD, EMAIL_FROM, EMAIL_TO] 10 | 11 | # ----- Amazon Credentials ----------- 12 | 13 | AWS_ACCESS_KEY_ID = 'Your AWS Access Key ID' 14 | AWS_SECRET_ACCESS_KEY = 'Your AWS Secret Access Key' 15 | AWS_ASSOCIATE_TAG = 'Your AWS Associate Tag' 16 | AWS_CREDENTIALS = [AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_ASSOCIATE_TAG] 17 | 18 | def main(): 19 | csvFile = 'priceHistory.csv' 20 | products = ['B01GW3H3U8', 'B01DFKC2SO', 'B00DB9JV5W'] 21 | dailyScan(products, csvFile, AWS_CREDENTIALS, EMAIL_CREDENTIALS) 22 | 23 | if __name__ == '__main__': 24 | main() 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Deprecated 2 | 3 | This project is no longer maintained. --------------------------------------------------------------------------------