def write_applog(self, applog_info, error, runtime): now = datetime.datetime.now() timestamp = now.strftime("%Y-%m-%d %H:%M:%S") applog = { "storeName": applog_info["storeName"], "area": applog_info["areaName"], "modelName": applog_info["modelName"], "fengId": applog_info["fengId"], "appleId": applog_info["appleId"], "error": error, "timestamp": timestamp, "sleepTime": configHelper.readConfig('submitTimeSleep'), "totalTime": runtime, } self.__dao.setApplog(applog)
def storeCheck(): starttime = time.time() # imp.reload(sys) # https://reserve.cdn-apple.com/HK/zh_HK/reserve/iPhone/availability.json # https://reserve.cdn-apple.com/HK/zh_HK/reserve/iPhone/stores.json availurl = "https://reserve.cdn-apple.com/CN/zh_CN/reserve/iPhone/availability.json" avail_json = requests.get(availurl).json() if len(avail_json) < 1: print(bcolors.FAIL + time.strftime('%d, %b %Y %H:%M:%S') + " - Data Unavailable.") return # Fetch all clientInfos from DB clients = d.getClientInfos() # 组织好数据结构 mainDict = initClients(clients) print(mainDict) modelSelectURL = "https://reserve-cn.apple.com/CN/zh_CN/reserve/iPhone?channel=1&rv=&path=&sourceID=&iPP=false&appleCare=&iUID=&iuToken=&carrier=" # 遍历数据结构 for areaId, areaDict in mainDict.items(): stores = d.getStoresByArea(areaId) # 对于每一个地区的所有店铺遍历 for item in stores: storeId = item[0] storeName = item[1] areaName = item[2] storeStr = bcolors.OKGREEN + storeName + ", " + areaName + ", " + storeId print(storeStr) hasAvailModel = False # 过滤出当前店铺所有有库存的产品 allModels = avail_json.get(storeId) for modelId in allModels: # 如果当前产品id在顾客选择的产品范围之内,并且有库存的话 # 如果是测试模式,则不过滤 if modelId in areaDict and allModels[modelId] == "ALL": hasAvailModel = True # Get model name from DB # Create a new thread to open URL in browser url = modelSelectURL + "&partNumber=" + modelId +\ "&store=" + storeId if not test: print(bcolors.OKGREEN + modelId + " - " + getModelName(modelId)) logger.info(modelId + " - " + getModelName(modelId) + " - " + storeStr) os.system('espeak "Congratulations!"') print(areaId + storeId + modelId) clientInfo = areaDict[modelId][0] print ("clientInfo --", clientInfo) IReserve = myutil.get_class(configHelper.readEngine()) ir = IReserve() errorList = ir.reserve(url, clientInfo, test) # errorList = requestTest2.doIt() # requestWithSelenium.doIt(url, clientInfo, test) # Create applog record error = "" for errItem in errorList: error += errItem runtime = str(round(time.time()-starttime, 2)) print('运行时间' + runtime) now = datetime.datetime.now() timestamp = now.strftime("%Y-%m-%d %H:%M:%S") applog = { "storeName": storeName, "area": areaName, "modelName": getModelName(modelId), "fengId": clientInfo["fengId"], "appleId": clientInfo["appleId"], "error": error, "timestamp": timestamp, "sleepTime": configHelper.readConfig( 'submitTimeSleep'), "totalTime": runtime, } d.setApplog(applog) time.sleep(60) return if not hasAvailModel: print(bcolors.FAIL + "Nothing Available\n") print(bcolors.OKBLUE + "Updated: " + time.strftime('%d, %b %Y %H:%M:%S') + "\n") return
def main(): # Avoid the 'too many open files' exception os.system('ulimit -n 10000') def signal_handler(signal, frame): print(' - Stop Monitoring') sys.exit(0) # Handle Ctrl+C in terminal signal.signal(signal.SIGINT, signal_handler) print('Apple Store Monitoring \n') # Calculate program execution time starttime = time.time() ctrl = ireserve_ctrl.IReserveCtrl() # Check stock and get available model info values = ctrl.storeCheck() # If stock is available if values: reserve_info, applog_info = values error = "" try: # Reservation ctrl.do_reserve(reserve_info["areaId"], reserve_info["storeId"], reserve_info["modelId"], reserve_info["clientInfo"], reserve_info["storeStr"]) except (errors.IReserveLoginError, errors.IReserveReserveError) as e: error = e.message os.system('espeak "login or reserve error"') traceback.print_exc() # TODO remove current client from maindict ctrl.inactiveClient(reserve_info["clientInfo"]["oid"]) except errors.IReserveLoginFastError as e: error = e.message os.system('espeak "login too fast"') traceback.print_exc() time.sleep(configHelper.readConfig("loginsleep")) except errors.IReserveSMSError as e: os.system('espeak "phone number error"') error = e.message raise e except errors.IReserveAvailError as e: os.system('espeak "availability error"') error = e.message traceback.print_exc() except errors.ISMSTimeoutError as e: os.system('espeak "SMS timeout"') traceback.print_exc() time.sleep(configHelper.readConfig("loginsleep")) else: os.system('espeak "successfully reserved"') error = "success" ctrl.inactiveClient(reserve_info["clientInfo"]["oid"]) finally: runtime = str(round(time.time() - starttime, 2)) print('运行时间' + runtime) ctrl.write_applog(applog_info, error, runtime) time.sleep(2)
def sms_update(clientInfo, lock): """ Support reservation in different city with same appleId. As long as within half an hour, the same rcode can be used.Though different processed would be created based on records with same appleId in table 'rcode' still the same 支持同一账号不同地区的预约。只要是同一账号验证码半小时内是通用的。 虽然会根据rcode表中的相同的appleId启动不同的进程,但效果是一样的。 """ print("inside sms_update") while True: # 判断当前客户是否是active的, 如果已经是无效客户则立即退出子进程 isActive = dao.getClientInfo(clientInfo["oid"])[9] if not isActive: return # 获得上一次更新rcode的时间, 计算出时间差 phoneNumber = configHelper.readPhoneNumber(False) rcodeResult = dao.getRCode(phoneNumber, clientInfo["appleId"]) if rcodeResult: last_time = datetime.datetime.strptime( rcodeResult[0][4], "%Y-%m-%d %H:%M:%S") time_diff = round((datetime.datetime.now() - last_time) .total_seconds() / 60, 2) else: time_diff = 999 # 如果时间差超过30分钟,则需要更新rcode if time_diff >= 30: # 获得有效库存信息,用来生成登录URL reserve_info = store_check(clientInfo["area"]) if reserve_info is None: print(u"当前区域 %s 已关闭预约" % clientInfo["area"]) return storeId = reserve_info["storeId"] modelId = reserve_info["modelId"] # Get initial request URL modelSelectURL = configHelper.readURL("modelSelectURL") url = modelSelectURL + "&partNumber=" + modelId +\ "&store=" + storeId print (u"客户信息 -- " + myutil.format_dict(clientInfo, tab=1)) # 获得当天已发短信数目和当天已成功预约数 cellPhoneInfo = dao.getCellphoneInfo(phoneNumber) todayCount = cellPhoneInfo[2] + 1 availCount = cellPhoneInfo[3] # There might be maximum limit for messages per day # if todayCount > 100: # os.system('espeak "already five messages"') # return ir = IReserveHTTP() rCode = None try: rCode = ir.get_avail_rcode(url, clientInfo, lock) except errors.IReserveLoginError as e: os.system('espeak "login or reserve error"') traceback.print_exc() ctrl = ireserve_ctrl.IReserveCtrl() ctrl.inactiveClient(clientInfo["oid"]) except errors.IReserveLoginFastError as e: os.system('espeak "login too fast"') traceback.print_exc() print("sleeping 10 minutes") time.sleep(10 * 60) except errors.IReserveSMSError as e: os.system('espeak "phone number error"') raise e except errors.ISMSTimeoutError as e: os.system('espeak "SMS timeout"') traceback.print_exc() time.sleep(configHelper.readConfig("loginsleep")) if rCode: curTime = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") dao.insertOrUpdateRCode( rCode, phoneNumber, clientInfo["appleId"], curTime) # 更新对应手机号的信息,其有效预约次数要减一 dao.updateCellphoneInfo(phoneNumber, todayCount, availCount) else: sleep_min = 30.00 - time_diff print(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")) process_name = multiprocessing.current_process().name print(" Process[%s] sms_update() sleeping %s minutes..." % (process_name, sleep_min)) time.sleep(sleep_min * 60)
import json import twitterHelper as twitter import doorHelper as door import configHelper # load the config config = configHelper.readConfig() # remove @ signs from the allowed users config def stripAtSigns(allowedUsers): ret = [] for user in allowedUsers: ret.append(user.replace("@", "")) return ret # remove any # signs from hashtags in config def stripConfigHashtags(hashtags): ret = {} for hashtag, value in hashtags.iteritems(): ret[hashtag] = value.replace("#", "") return ret # get numeric user ids given a list of usernames # user id is required for filter(follow="userid") def getUserIds(app, users): userIdList = [] for user in users: userIdList.append(app.getUserId(user))
def __stepTimeSlot(self, url, govid, govidType, quantity): print("------------- Step 4.1 Select TimeSlots ---------------"), '\n' timeSlotURL = url + "&ajaxSource=true&_eventId=context&dims=" print("request URL: " + timeSlotURL) self.__session.headers = self.__getJSONHeaders() r = self.__session.get(timeSlotURL) print('--------[timeslots JSON RESULT]---' + r.text + '-------', '\n') error_str = self.__json_errmsg(r.text, "errors") if len(error_str) > 0: raise errors.IReserveSMSError(error_str) reserveDict = json.loads(r.text) # Finde the right time # get current hour timeslots = reserveDict["timeslots"] curHour = datetime.datetime.now().hour selectedId = "" selectedTime = "" # for timeslot in timeslots: for i, option in enumerate(timeslots): text = option['formattedTime'] curId = option['timeSlotId'] # Format : 下午 1:30 - 下午 2:00 arr = text.split(" ") hour = int(arr[1].split(":")[0]) # format hour to 24 hours if arr[0] == u"下午" and hour < 12: hour += 12 nightMode = configHelper.readMode("nightMode") if nightMode and curHour < 18: if hour >= 20: selectedId = curId selectedTime = text break else: if hour >= curHour + 2: selectedId = curId selectedTime = text break if i == len(timeslots) - 1: selectedId = curId selectedTime = text print(selectedId) print(selectedTime), '\n' # print (timeslots) print("-------------- Step 4.2 Submit Reserve ---------------"), '\n' data = { "selectedStoreNumber": reserveDict['selectedStoreNumber'], # "selectedPartNumber": partNumber, "selectedContractType": "UNLOCKED", "selectedQuantity": quantity, "selectedTimeSlotId": selectedId, "lastName": reserveDict["lastName"], "firstName": reserveDict["firstName"], "email": reserveDict["email"], "selectedGovtIdType": govidType, "govtId": govid, "p_ie": reserveDict["p_ie"], "_flowExecutionKey": reserveDict["_flowExecutionKey"], "_eventId": "next", "submit": "", } self.__session.headers = myutil.getHTMLHeaders() print(data), '\n' print("request URL: " + url), '\n' sleeptime = configHelper.readConfig('submitTimeSleep') print("current sleep time is : " + str(sleeptime)) time.sleep(sleeptime) r = self.__session.post(url, data=data) r = self.__session.get(r.url) url = r.url + "&ajaxSource=true&_eventId=context&dims=" print("request URL: " + url), '\n' self.__session.headers = self.__getJSONHeaders() r = self.__session.get(url) print('--------[Sumit Error JSON RESULT]---' + r.text + '-----', '\n') error_str = self.__json_errmsg(r.text, "errors") if len(error_str) > 0: if error_str == "availabilityError": raise errors.IReserveAvailError(error_str) else: raise errors.IReserveReserveError(error_str)
def stepTimeSlot(url, govid, govidType): print (" ------------------ Step 4.1 Select TimeSlots --------------------"), '\n' timeSlotURL = url + "&ajaxSource=true&_eventId=context&dims=" print ("request URL: " + timeSlotURL) session.headers = { "Accept":"application/json, text/javascript, */*; q=0.01", "Accept-Encoding":"gzip, deflate, br", "Accept-Language":"zh-CN,zh;q=0.8,zh-TW;q=0.6,en;q=0.4", "Connection":"keep-alive", "Content-Type":"application/json", "X-Requested-With":"XMLHttpRequest", } r = session.get(timeSlotURL) exportHTTPInfo(session, r) print '--------[timeslots JSON RESULT]---' + r.text + '---------------', '\n' reserveDict = json.loads(r.text) # Finde the right time # get current hour timeslots = reserveDict["timeslots"] curHour = datetime.datetime.now().hour selectedId = "" selectedTime = "" # for timeslot in timeslots: for i, option in enumerate(timeslots): text = option['formattedTime'] curId = option['timeSlotId'] # Format : 下午 1:30 - 下午 2:00 arr = text.split(" ") hour = int(arr[1].split(":")[0]) # format hour to 24 hours if arr[0] == u"下午" and hour < 12: hour += 12; if nightMode and curHour < 18: if hour >= 20: selectedId = curId selectedTime = text break else: if hour >= curHour + 2: selectedId = curId selectedTime = text break if i == len(timeslots) - 1: selectedId = curId selectedTime = text print (selectedId) print (selectedTime), '\n' # print (timeslots) print ("-------------- Step 4.2 Submit Reserve -----------------------"), '\n' data = { "selectedStoreNumber":reserveDict['selectedStoreNumber'], "selectedPartNumber":partNumber, "selectedContractType":"UNLOCKED", "selectedQuantity":"2", "selectedTimeSlotId":selectedId, "lastName":reserveDict["lastName"], "firstName":reserveDict["firstName"], "email":reserveDict["email"], "selectedGovtIdType":govidType, "govtId":govid, "p_ie":reserveDict["p_ie"], "_flowExecutionKey":reserveDict["_flowExecutionKey"], "_eventId":"next", "submit":"", } headers = { "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "Accept-Encoding": "gzip, deflate, sdch, br", "Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.6,en;q=0.4", "Connection": "keep-alive", "Content-Type":"application/x-www-form-urlencoded", # "Host":"reserve-cn.apple.com", # "Referer":"https://reserve.cdn-apple.com/CN/zh_CN/reserve/iPhone/availability?channel=1", "Upgrade-Insecure-Requests":1, "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/52.0.2743.116 Chrome/52.0.2743.116 Safari/537.36" } print (data), '\n' session.headers = headers print ("request URL: " + url), '\n' sleeptime = configHelper.readConfig('submitTimeSleep') print ("current time sleep is : " + str(sleeptime)) time.sleep(sleeptime) r = session.post(url, data=data) r = session.get(r.url) url = r.url + "&ajaxSource=true&_eventId=context&dims=" print ("request URL: " + url ), '\n' session.headers = { "Accept":"application/json, text/javascript, */*; q=0.01", "Accept-Encoding":"gzip, deflate, br", "Accept-Language":"zh-CN,zh;q=0.8,zh-TW;q=0.6,en;q=0.4", "Connection":"keep-alive", "Content-Type":"application/json", # "Host":"signin.apple.com", # "Origin":"https://signin.apple.com", "X-Requested-With":"XMLHttpRequest", } r = session.get(url) print '--------[Sumit Error JSON RESULT]---' + r.text + '---------------', '\n' rcDict = json.loads(r.text) return rcDict.get("errors", "")