I co-created a website called 6tracker that notified people when an iPhone 6 was available for pick-up in an Apple Store near them (sound familiar?). It did pretty well overall, about 62,000 sign ups and 102,000 visitors (most of them in the first 3 weeks).

read more

Unfortunately, the guy who I was working with, Taylor Robinette, was less than ethical. I noticed some emails in the trash folder; users were donating to us and he was withdrawing the donations without telling me. I didn't care enough to confront him, it was only a couple hundred dollars, but it definitely revealed the kind of person he was (given I was the one who programmed the entire site and backend, and he marketed the thing on MacRumors forums and other sites until it got picked up).


#!/usr/bin/python
import os
import smtplib
import MySQLdb
import json
import time
import traceback
from pprint import pprint

def send_email(message, emails):
	
	username = "5strackersender1@gmail.com"
	password = "[redacted]"
	print "using: %s" % username
	try:
		server = smtplib.SMTP('smtp.gmail.com:587')
		server.ehlo()
		server.starttls()
		server.login(username,password)
		msg = "From: %s\r\nTo: \r\nSubject: Personal Pickup Checker\r\n\r\n%s" % (username,message)
		server.sendmail(username,emails,msg)
		server.quit()
	except:
		print "problem sending mail"
	
def search_users(zipCode,modelNumber):
	try:
		sconn = MySQLdb.connect(host = MySQL_host, user = MySQL_user, passwd = MySQL_passwd, db = MySQL_db)
		scur = sconn.cursor()
		scur.execute("SELECT * FROM personalPickupUsers WHERE zip LIKE '%{0}%' AND modelNumber LIKE '%{1}%' ".format(zipCode,modelNumber))
		records = scur.fetchall()
		scur.close()
		sconn.close()
		#returns the emails and phone numbers
		return [i[1] for i in records] + [i[2] for i in records]
	except:
		print "problem getting users"
		time.sleep(30)
		return []

def collectZips():
	try:
		sconn = MySQLdb.connect(host = MySQL_host, user = MySQL_user, passwd = MySQL_passwd, db = MySQL_db)
		scur = sconn.cursor()
		scur.execute("SELECT DISTINCT(zip) FROM personalPickupUsers")
		records = scur.fetchall()
		scur.close()
		sconn.close()
		#returns the zip codes that need to be checked
		return [i[0] for i in records] 
	except:
		print "problem getting zips"
		time.sleep(30)
		return []

def collectModelNumbers(zipCode):
	try:
		sconn = MySQLdb.connect(host = MySQL_host, user = MySQL_user, passwd = MySQL_passwd, db = MySQL_db)
		scur = sconn.cursor()
		scur.execute("SELECT DISTINCT(modelNumber) FROM personalPickupUsers WHERE zip = '{0}' ".format(zipCode))
		records = scur.fetchall()
		scur.close()
		sconn.close()
		#returns the model numbers that need to be checked for that zip code
		return [i[0] for i in records] 
	except: 
		print "problem getting model numbers"
		time.sleep(30)
		return []

previousModelsAndAvailabilities={}		
firstRun = True


MySQL_host = "23.229.204.97"
MySQL_user = "ppickup"
MySQL_passwd = "[redacted]"
MySQL_db = "Personal_Pickup"
try:
	conn = MySQLdb.connect(host = MySQL_host, user = MySQL_user, passwd = MySQL_passwd, db = MySQL_db, port=3306)
except:
	print "could not connect. Restart"


while True:

	zipCodes = collectZips()
	for zipCode in zipCodes:
		#time.sleep(1) #just not to overload their servers, but if a smarter approach is taken we can take this out.
		modelNumbers=collectModelNumbers(zipCode)
		for modelNumber in modelNumbers:
			os.system("./getsource.sh {0} {1}".format(zipCode,modelNumber))
			json_data=open('myAreaPage')
			try:
				data = json.load(json_data)
			except: 
				print "could not load data"
			
			for index in range(3): #made it three so it only does the three closest Apple Stores
				try:
					currentStoreName=data['body']['stores'][index]['storeName']
					availabilityOfCurrentDevice=data['body']['stores'][index]['partsAvailability'][modelNumber+'/A']['pickupSearchQuote']				
					if firstRun:
						previousModelsAndAvailabilities.update({(currentStoreName,modelNumber,zipCode):(availabilityOfCurrentDevice,"None")})
					else:
						#print previousModelsAndAvailabilities.get((currentStoreName,modelNumber))+" is a key we check"
						if previousModelsAndAvailabilities.get((currentStoreName,modelNumber,zipCode)) is None: #if this is something that someone just started tracking
							print "A new model was added!"
							#send_email("A new model was added!.","5strackersender@gmail.com")
							previousModelsAndAvailabilities.update({(currentStoreName,modelNumber,zipCode):(availabilityOfCurrentDevice,"None")})
						else:
							if availabilityOfCurrentDevice != previousModelsAndAvailabilities.get((currentStoreName,modelNumber,zipCode))[0]:
								#a change has been detected. Find appropriate users. 
								print data['body']['stores'][index]
								print index
								userList = search_users(zipCode,modelNumber)
								print userList
								if(availabilityOfCurrentDevice != previousModelsAndAvailabilities.get((currentStoreName,modelNumber,zipCode))[0] and availabilityOfCurrentDevice != previousModelsAndAvailabilities.get((currentStoreName,modelNumber,zipCode))[1]):
									send_email("{0} is now {1} at {2}.".format(modelNumber,availabilityOfCurrentDevice,currentStoreName),userList)
									#send_email("Email was just sent to a user.","5strackersender@gmail.com")
								pastAvailability = previousModelsAndAvailabilities.get((currentStoreName,modelNumber,zipCode))[1]
								previousModelsAndAvailabilities.update({(currentStoreName,modelNumber,zipCode):(availabilityOfCurrentDevice,pastAvailability)})
				except:
					print "something wrong, probably zip code"
						
	pprint(previousModelsAndAvailabilities)
	firstRun=False
	print "a cycle finished running"
	time.sleep(120)
	#except Exception as e:
	#	print str(e) 
	#	traceback.print_exc()
	#	send_email("There was an exception in the program. Waiting 5 minutes and trying again. ","5strackersender@gmail.com")
	#	time.sleep(300)