├── 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.
--------------------------------------------------------------------------------