def __init__(self, dbMethod, dbIp, dbPort, dbUser, dbPassword, dbName, tempPath, unknownPath, timezone, hash): self.dbIp = dbIp self.dbPort = dbPort self.dbUser = dbUser self.dbPassword = dbPassword self.dbName = dbName self.tempPath = tempPath self.unknownPath = unknownPath self.timezone = timezone self.uniqueHash = hash self.dbMethod = dbMethod #new www service self.www_hash = 'www_hash' self.dbWrapper = DbWrapper(self.dbMethod, self.dbIp, self.dbPort, self.dbUser, self.dbPassword, self.dbName, self.timezone, self.uniqueHash) if not os.path.exists(self.tempPath): log.info('Temp directory created') os.makedirs(self.tempPath) if not os.path.exists(self.unknownPath): log.info('Unknow directory created') os.makedirs(self.unknownPath) if not os.path.exists(self.www_hash): log.info('www_hash directory created') os.makedirs(self.www_hash)
from db.dbWrapper import DbWrapper from walkerArgs import parseArgs import os, glob from shutil import copyfile args = parseArgs() dbWrapper = DbWrapper(str(args.db_method), str(args.dbip), args.dbport, args.dbusername, args.dbpassword, args.dbname, args.timezone) def main(): print '' print 'If you want to insert a Gymhash to your Database, just take the File from Unknown Folder starting with *gym_crop* ' print 'and copy the last part of the Filename.' print '' print 'f.e. 1_gym_crop_55.747355_99.163981_1536177248.96_45b5939252c695a9.jpg - the Hash is 45b5939252c695a9 ' print '' print 'Additionally you need the gym_id or fort_id (rm or monocle)' print '' hash = raw_input("Enter Hash Value from Filename: ") gym = raw_input("Enter Gym / Fort ID: ") print '' if hash and gym: if dbWrapper.insertHash(hash, 'gym', gym, '999'): print 'Hash added - the Gym should now be recognized.' for file in glob.glob("www_hash/unkgym_*" + str(hash) + ".jpg"):
def main_thread(): global nextRaidQueue global lastPogoRestart global telnMore global pogoWindowManager global sleep global runWarningThreadEvent global windowLock global screenWrapper global lastScreenshotTaken global lastScreenHash global lastScreenHashCount log.info("main: Starting TelnetGeo Client") telnGeo = TelnetGeo(str(args.tel_ip), args.tel_port, str(args.tel_password), args.tel_timeout_command, args.tel_timeout_socket) log.info("main: Starting dbWrapper") dbWrapper = DbWrapper(str(args.db_method), str(args.dbip), args.dbport, args.dbusername, args.dbpassword, args.dbname, args.timezone) updateRaidQueue(dbWrapper) lastRaidQueueUpdate = time.time() if lastPogoRestart is None: lastPogoRestart = time.time() route = getJsonRoute(args.file, args.gym_distance, args.max_count_gym_sum_up_around_gym, args.route_file) log.info("main: Route to be taken: %s, amount of coords: %s" % (str(route), str(len(route)))) log.info("main: Max_distance before teleporting: %s" % args.max_distance) log.info("main: Checking if screen is on and pogo is running") if not sleep: if args.no_initial_restart is False: turnScreenOnAndStartPogo() else: startPogo() log.info('Starting speedweatherWarning Thread....') w = Thread(target=checkSpeedWeatherWarningThread, name='speedWeatherCheck') w.daemon = True w.start() emptycount = 0 locationCount = 0 while True: log.info("main: Next round") curLat = 0.0 curLng = 0.0 i = 0 # index in route failcount = 0 lastRoundEggHatch = False # loop over gyms: # walk to next gym # get to raidscreen # take screenshot # check time to restart pogo # process the entire route, prioritize hatched eggs in every second round (if anything has hatched) while i < len(route): while sleep: time.sleep(1) curTime = time.time() # update the raid queue every 5mins... if (curTime - lastRaidQueueUpdate) >= (5 * 60): updateRaidQueue(dbWrapper) lastRaidQueueUpdate = curTime windowLock.acquire() # Restart pogo every now and then... if args.restart_pogo > 0: # log.debug("main: Current time - lastPogoRestart: %s" % str(curTime - lastPogoRestart)) # if curTime - lastPogoRestart >= (args.restart_pogo * 60): locationCount += 1 if locationCount > args.restart_pogo: log.error("scanned " + str(args.restart_pogo) + " locations, restarting pogo") restartPogo() locationCount = 0 windowLock.release() # let's check for speed and weather warnings while we're walking/teleporting... runWarningThreadEvent.set() lastLat = curLat lastLng = curLng egghatchLocation = False log.debug( "main: Checking for raidqueue priority. Current time: %s, Current queue: %s" % (str(time.time()), str(nextRaidQueue))) # determine whether we move to the next gym or to the top of our priority queue if not lastRoundEggHatch and len( nextRaidQueue) > 0 and nextRaidQueue[0][0] < time.time(): # the topmost item in the queue lays in the past... log.info( 'main: An egg has hatched, get there asap. Location: %s' % str(nextRaidQueue[0])) egghatchLocation = True nextStop = heapq.heappop(nextRaidQueue)[ 1] # gets the location tuple curLat = nextStop.latitude curLng = nextStop.longitude time.sleep(1) lastRoundEggHatch = True else: # continue as usual log.info('main: Moving on with gym at %s' % route[i]) curLat = route[i]['lat'] curLng = route[i]['lng'] # remove whitespaces that might be on either side... i += 1 lastRoundEggHatch = False # store current position in file posfile = open(args.position_file + '.position', "w") posfile.write(str(curLat) + ", " + str(curLng)) posfile.close() log.debug("main: next stop: %s, %s" % (str(curLat), str(curLng))) log.debug( 'main: LastLat: %s, LastLng: %s, CurLat: %s, CurLng: %s' % (lastLat, lastLng, curLat, curLng)) # get the distance from our current position (last) to the next gym (cur) distance = getDistanceOfTwoPointsInMeters(float(lastLat), float(lastLng), float(curLat), float(curLng)) log.info('main: Moving %s meters to the next position' % distance) delayUsed = 0 if (args.speed == 0 or (args.max_distance and 0 < args.max_distance < distance) or (lastLat == 0.0 and lastLng == 0.0)): log.info("main: Teleporting...") telnGeo.setLocation(curLat, curLng, 0) delayUsed = args.post_teleport_delay # Test for cooldown / teleported distance if args.cool_down_sleep: if distance > 2500: delayUsed = 30 elif distance > 5000: delayUsed = 45 elif distance > 10000: delayUsed = 60 log.info("Need more sleep after Teleport: %s seconds!" % str(delayUsed)) if 0 < args.walk_after_teleport_distance < distance: toWalk = getDistanceOfTwoPointsInMeters( float(curLat), float(curLng), float(curLat) + 0.0001, float(curLng) + 0.0001) log.error("Walking a bit: %s" % str(toWalk)) time.sleep(0.3) telnGeo.walkFromTo(curLat, curLng, curLat + 0.0001, curLng + 0.0001, 11) log.debug("Walking back") time.sleep(0.3) telnGeo.walkFromTo(curLat + 0.0001, curLng + 0.0001, curLat, curLng, 11) log.debug("Done walking") else: log.info("main: Walking...") telnGeo.walkFromTo(lastLat, lastLng, curLat, curLng, args.speed) delayUsed = args.post_walk_delay log.info("Sleeping %s" % str(delayUsed)) time.sleep(delayUsed) # ok, we should be at the next gym, check for errors and stuff # TODO: improve errorhandling by checking results and trying again and again # not using continue to always take a new screenshot... log.debug("main: Acquiring lock") while sleep or not runWarningThreadEvent.isSet(): time.sleep(0.1) windowLock.acquire() log.debug("main: Lock acquired") if not takeScreenshot(): windowLock.release() continue if args.last_scanned: log.info('main: Set new scannedlocation in Database') dbWrapper.setScannedLocation(str(curLat), str(curLng), str(curTime)) log.info( "main: Checking raidcount and copying raidscreen if raids present" ) countOfRaids = pogoWindowManager.readRaidCircles( os.path.join(args.temp_path, 'screenshot.png'), 123) if countOfRaids == -1: # reopen raidtab and take screenshot... log.warning( "main: Count present but no raid shown, reopening raidTab") reopenRaidTab() # tabOutAndInPogo() if not takeScreenshot(): windowLock.release() continue countOfRaids = pogoWindowManager.readRaidCircles( os.path.join(args.temp_path, 'screenshot.png'), 123) # elif countOfRaids == 0: # emptycount += 1 # if emptycount > 30: # emptycount = 0 # log.error("Had 30 empty scans, restarting pogo") # restartPogo() # not an elif since we may have gotten a new screenshot.. #detectin weather if args.weather: weather = checkWeather( os.path.join(args.temp_path, 'screenshot.png')) if weather[0]: log.debug('Submit Weather') dbWrapper.updateInsertWeather(curLat, curLng, weather[1], curTime) else: log.error('Weather could not detected') if countOfRaids > 0: log.debug( "main: New und old Screenshoot are different - starting OCR" ) log.debug("main: countOfRaids: %s" % str(countOfRaids)) curTime = time.time() copyFileName = args.raidscreen_path + '/raidscreen_' + str( curTime) + "_" + str(curLat) + "_" + str( curLng) + "_" + str(countOfRaids) + '.png' log.debug('Copying file: ' + copyFileName) copyfile(os.path.join(args.temp_path, 'screenshot.png'), copyFileName) os.remove(os.path.join(args.temp_path, 'screenshot.png')) log.debug("main: Releasing lock") windowLock.release()
class Scanner: def __init__(self, dbMethod, dbIp, dbPort, dbUser, dbPassword, dbName, tempPath, unknownPath, timezone, hash): self.dbIp = dbIp self.dbPort = dbPort self.dbUser = dbUser self.dbPassword = dbPassword self.dbName = dbName self.tempPath = tempPath self.unknownPath = unknownPath self.timezone = timezone self.uniqueHash = hash self.dbMethod = dbMethod #new www service self.www_hash = 'www_hash' self.dbWrapper = DbWrapper(self.dbMethod, self.dbIp, self.dbPort, self.dbUser, self.dbPassword, self.dbName, self.timezone, self.uniqueHash) if not os.path.exists(self.tempPath): log.info('Temp directory created') os.makedirs(self.tempPath) if not os.path.exists(self.unknownPath): log.info('Unknow directory created') os.makedirs(self.unknownPath) if not os.path.exists(self.www_hash): log.info('www_hash directory created') os.makedirs(self.www_hash) def detectRaidTime(self, raidpic, hash, raidNo, radius): zero = datetime.datetime.now() unixnow = time.mktime(zero.timetuple()) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'detectRaidTime: Reading Raidtimer') height, width, channel = raidpic.shape raidtimer = raidpic[int(round(radius*2*0.03)+(2*radius)+(radius*2*0.265)):int(round(radius*2*0.03)+(2*radius)+(radius*2*0.43)), 0:width] raidtimer = cv2.resize(raidtimer, (0,0), fx=2, fy=2, interpolation=cv2.INTER_CUBIC) emptyRaidTempPath = os.path.join(self.tempPath, str(raidNo) + str(hash) + '_emptyraid.png') cv2.imwrite(emptyRaidTempPath, raidtimer) rt = Image.open(emptyRaidTempPath) gray = rt.convert('L') bw = gray.point(lambda x: 0 if x<200 else 255, '1') raidtimer = pytesseract.image_to_string(bw, config='--psm 6 --oem 3').replace(' ', '').replace('~','').replace('o','0').replace('O','0').replace('-','').replace('.',':').replace('U','0') #cleanup os.remove(emptyRaidTempPath) raidFound = len(raidtimer) > 0 if raidFound: if ':' in raidtimer: log.info('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'detectRaidTime: found raidtimer %s' % raidtimer) hatchTime = self.getHatchTime(raidtimer, raidNo) if hatchTime: log.info('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'detectRaidTime: Hatchtime %s' % str(hatchTime)) if hatchTime > unixnow + (60 * 60 * 2) or hatchTime < unixnow: log.info('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'detectRaidTime: Hatchtime not logical') return (raidFound, False, False, False) #raidstart = getHatchTime(self, raidtimer) - self.timezone * (self.timezone*60*60) raidstart = hatchTime #- (self.timezone * 60 * 60) raidend = hatchTime + (int(args.raid_time) * 60) #- (self.timezone * 60 * 60) #raidend = getHatchTime(self, raidtimer) + int(45*60) - (self.timezone*60*60) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'detectRaidTime: Start: ' + str(raidstart) + ' End: ' + str(raidend)) return (raidFound, True, raidstart, raidend) else: return (raidFound, True, False, False) else: return (raidFound, False, '0', '0') else: return (raidFound, False, False, False) def detectRaidEndtimer(self, raidpic, hash, raidNo, radius): zero = datetime.datetime.now() unixnow = time.mktime(zero.timetuple()) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'detectRaidEndtimer: Reading Raidtimer') height, width, channel = raidpic.shape raidtimer = raidpic[int(round(radius*2*0.03)+(2*radius)+(radius*2*0.10)):int(round(radius*2*0.03)+(2*radius)+(radius*2*0.23)), 0:width] raidtimer = cv2.resize(raidtimer, (0,0), fx=3, fy=3, interpolation=cv2.INTER_CUBIC) emptyRaidTempPath = os.path.join(self.tempPath, str(raidNo) + str(hash) + '_endraid.png') cv2.imwrite(emptyRaidTempPath, raidtimer) rt = Image.open(emptyRaidTempPath) gray = rt.convert('L') bw = gray.point(lambda x: 0 if x<200 else 255, '1') raidtimer = pytesseract.image_to_string(bw, config='--psm 6 --c tessedit_char_whitelist=01234567890:').replace(' ', '').replace('~','').replace('o','0').replace('O','0').replace('"','').replace('-','').replace('.',':').replace('B','8').replace('A','4').replace('—','').replace('_','').replace("'","").replace('U','0') log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'detectRaidEndtimer: Raid-End-Text: ' + str(raidtimer)) os.remove(emptyRaidTempPath) raidEndFound = len(raidtimer) > 0 if raidEndFound: if raidtimer.count(':') < 2 : if len(raidtimer) == 7: raidtimer = '0:' + str(raidtimer[2:4]) + ':' + str(raidtimer[5:7]) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'detectRaidEndtimer: Try to repair Endtime: %s' % str(raidtimer)) if ':' in raidtimer: now = datetime.datetime.now() log.info('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'detectRaidEndtimer: found raidendtimer %s' % raidtimer) endTime = self.getEndTime(raidtimer, raidNo) if endTime: log.info('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'detectRaidEndtimer: Endtime %s' % str(endTime)) if endTime > unixnow + (int(args.raid_time) * 60): log.info('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'detectRaidEndtimer: Endtime not logical') return (raidEndFound, False, False) #raidstart = getHatchTime(self, raidtimer) - self.timezone * (self.timezone*60*60) raidend = endTime #- (self.timezone * 60 * 60) #raidend = getHatchTime(self, raidtimer) + int(45*60) - (self.timezone*60*60) return (raidEndFound, True, raidend) else: return (raidEndFound, False, False) else: log.info('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'detectRaidEndtimer: no raidendtimer detected') return (raidEndFound, False, '0') else: return (raidEndFound, False, False) def detectRaidBoss(self, raidpic, lvl, hash, raidNo): foundmon = None monID = None log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'Extracting Raidboss') picName = os.path.join(self.tempPath, str(hash) + '_raidboss' + str(raidNo) +'.jpg') #self.genCannyMonPic(raidpic, picName) cv2.imwrite(picName,raidpic) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'detectRaidBoss: Scanning Raidboss') monHash = None log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'detectRaidBoss: Monhash: ' + str(monHash)) if monHash is None: for file in glob.glob("mon_img/_mon_*_" + str(lvl) + ".png"): log.debug("Comparing to %s" % str(file)) find_mon = mt_mon.mon_image_matching(file, picName, raidNo, hash) if foundmon is None or find_mon > foundmon[0]: foundmon = find_mon, file if foundmon and foundmon[0]>0.01: monSplit = foundmon[1].split('_') monID = monSplit[3] #we found the mon that's most likely to be the one that's in the crop log.info('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'detectRaidBoss: Found mon in mon_img: ' + str(monID)) else: os.remove(picName) return monHash, picName if monID: #self.imageHash(picName, monID, False, 'mon-' + str(lvl), raidNo) os.remove(picName) return monID, picName log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'No Mon found!') os.remove(picName) return False, picName def detectLevel(self, raidpic, hash, raidNo, radius): foundlvl = None lvl = None log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'Scanning Level') height, width, channel = raidpic.shape raidlevel = raidpic[int(round(radius*2*0.03)+(2*radius)+(radius*2*0.43)):int(round(radius*2*0.03)+(2*radius)+(radius*2*0.68)), 0:width] raidlevel = cv2.resize(raidlevel, (0,0), fx=0.5, fy=0.5) imgray = cv2.cvtColor(raidlevel, cv2.COLOR_BGR2GRAY) imgray = cv2.GaussianBlur(imgray, (9, 9), 2) ret, thresh = cv2.threshold(imgray, 220, 255,0) (_, contours, _) = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) lvl = len(contours)-1 if lvl >=1 and lvl <=5: log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'detectLevel: found level %s' % str(lvl)) return lvl log.info('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'detectLevel: could not find level') return None def checkDummy(self,raidpic, x1, x2, y1, y2, hash, raidNo, radius): foundgym = None log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'checkDummy: Check for dummy Gym Image') template = ("mon_img/dummy_nearby.jpg") find_gym = mt.fort_image_matching(raidpic, template, True, 0.9, raidNo, hash, True, radius, x1, x2, y1, y2) if find_gym >= 0.9: return True return False def detectGym(self, raidpic, hash, raidNo, captureLat, captureLng, radius, monId = None): foundgym = None gymId = None x1=0.30 x2=0.62 y1=0.62 y2=1.23 foundMonCrops = False log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'detectGym: Scanning Gym') #if gymHash is none, we haven't seen the gym yet, otherwise, gymHash == gymId we are looking for if monId: log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'detectGym: Got Mon-ID for Gym-Detection %s' % monId) with open('monsspec.json') as f: data = json.load(f) if str(monId) in data: foundMonCrops = True crop = data[str(monId)]["Crop"] log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'detectGym: Found other Crops for Mon %s' % monId) log.debug(str(crop)) x1 = crop['X1'] x2 = crop['X2'] y1 = crop['Y1'] y2 = crop['Y2'] log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'detectGym: Cropsizes: x1:%s, x2:%s, y1:%s, y2:%s' % (str(x1), str(x2), str(y1), str(y2))) gymHashvalue = self.getImageHash(raidpic, True, raidNo, 'gym', x1, x2, y1, y2, radius) gymHash = self.imageHashExists(raidpic, True, 'gym', raidNo, x1, x2, y1, y2, radius) if gymHash is None: if self.checkDummy(raidpic, x1, x2, y1, y2, hash, raidNo, radius): log.info('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'detectGym: Found dummy gym pic') self.unknownfound(raidpic, 'unkgym', False, raidNo, hash, False, gymHashvalue, captureLat, captureLng) return 'dummy' log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'detectGym: No Gym-Hash: found - searching') log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'detectGym: Searching closest gyms') closestGymIds = self.dbWrapper.getNearGyms(captureLat, captureLng, hash, raidNo, str(args.gym_scan_distance)) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'detectGym: Detecting Gym') for closegym in closestGymIds: for file in glob.glob("gym_img/_" + str(closegym[0]) + "_.jpg"): find_gym = mt.fort_image_matching(raidpic, file, True, float(args.gym_detection_value), raidNo, hash, checkX=True, radius=radius, x1=x1, x2=x2, y1=y1, y2=y2) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'detectGym: Compare Gym-ID - ' + str(closegym[0]) + ' - Match: ' + str(find_gym)) if foundgym is None or find_gym > foundgym[0]: foundgym = find_gym, file if foundgym and foundgym[0]>=float(args.gym_detection_value): #okay, we very likely found our gym gymSplit = foundgym[1].split('_') gymId = gymSplit[2] else: self.imageHash(raidpic, gymHash, True, 'gym', raidNo, x1, x2, y1, y2, radius) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'detectGym: Detected Gym-ID: ' + str(gymHash)) return gymHash if gymId: log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'detectGym: Detected Gym - Gym-ID: '+ str(gymId)) gymHash = self.imageHash(raidpic, gymId, True, 'gym', raidNo, x1=x1, x2=x2, y1=y1, y2=y2, radius=radius) self.unknownfound(raidpic, 'gym', False, raidNo, hash, False, gymHashvalue, '0', '0') return gymId else: #we could not find the gym... self.unknownfound(raidpic, 'unkgym', False, raidNo, hash, False, gymHashvalue, captureLat, captureLng) return None def unknownfound(self, raidpic, type, zoom, raidNo, hash, captureTime, imageHash=0, lat=0, lng=0): if captureTime: text = datetime.datetime.fromtimestamp(float(captureTime)) text = "Scanned: " + str(text.strftime("%Y-%m-%d %H:%M")) self.addTextToCrop(raidpic, text, True) raidpic = cv2.imread(raidpic) if imageHash: existFile = os.path.join(self.www_hash, str(type) + "_*_" + str(imageHash) +".jpg") if not glob.glob(existFile): cv2.imwrite(os.path.join(self.www_hash, str(type) + "_" + str(lat) + "_" + str(lng) + "_" + str(imageHash) +".jpg"), raidpic) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'saveforweb: Write hash file for www: ' + str(type) + "_" + str(lat) + "_" + str(lng) + "_" + str(imageHash) +".jpg") else: log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'saveforweb: Hash file for www already exists: ' + str(type) + "_" + str(lat) + "_" + str(lng) + "_" + str(imageHash) +".jpg") else: cv2.imwrite(os.path.join(self.unknownPath, str(raidNo) + "_" + str(type) + "_" + str(lat) + "_" + str(lng) + "_" + str(time.time()) + "_" + str(imageHash) +".jpg"), raidpic) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'unknownfound: Write unknown file: ' + str(type) + "_" + str(lat) + "_" + str(lng) + "_" + str(time.time()) +".jpg") return True def addTextToCrop(self, picture, text, grayscale=False): from PIL import Image, ImageFont, ImageDraw img = Image.open(picture) draw = ImageDraw.Draw(img) font = ImageFont.truetype('font/arial.ttf', 10) x,y = 0,0 w, h = font.getsize(text) draw.rectangle((x, y, x + img.size[0] , y + h + 1), fill='black') if grayscale: draw.text((x, y),text,(255),font=font) else: draw.text((x, y), text, (255,255,255), font=font) img.save(picture) def successfound(self, raidpic, type, gymId, raidNo, lvl, captureTime, mon=0): if not args.save_success: log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'successfound: Saving submit raidpics is disable') return text = datetime.datetime.fromtimestamp(float(captureTime)) text = "Scanned: " + str(text.strftime("%Y-%m-%d %H:%M")) self.addTextToCrop(raidpic, text) if not os.path.exists(args.successsave_path): log.info('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'successfound: Save directory created') os.makedirs(args.successsave_path) with open('gym_info.json') as f: data = json.load(f) gymname = 'unknown' latitude = '00' longitude = '00' if str(gymId) in data: gymname = data[str(gymId)]["name"].replace('/', '-').replace('\\','/') latitude = data[str(gymId)]["latitude"] longitude = data[str(gymId)]["longitude"] curTime = time.time() saveFileName = str(type) + "_" + str(curTime) + "__LVL_" + str(lvl) + "__MON_" + str(mon) + "__LAT_"+ str(latitude) + "__LNG_" + str(longitude) + "__" + str(gymname) + "__" + str(gymId) + ".jpg" log.info('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'successfound: Filename: ' + str(saveFileName)) copyfile(raidpic, os.path.join(args.successsave_path, str(saveFileName))) log.info('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'successfound: Raidcrop successfully saved') def decodeHashJson(self, hashJson, raidNo): data = json.loads(hashJson) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'Decoding Raid Hash Json') raidGym = data['gym'] raidLvl = data["lvl"] raidMon = data["mon"] return raidGym, raidLvl, raidMon def encodeHashJson(self, gym, lvl, mon, raidNo): log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'Encoding Raid Hash Json') hashJson = json.dumps({'gym': gym, 'lvl': lvl, 'mon': mon, 'lvl': lvl}, separators=(',',':')) return hashJson def cropImage(self, image, raidNo, radius): gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY) gray=cv2.GaussianBlur(gray, (7, 7), 2) output = image.copy() height, width, channel = output.shape output = output[0:height*2/3,0:width] image_cols, image_rows, _ = image.shape circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, 20, param1=50,param2=30, minRadius=radius, maxRadius=radius) if circles is not None: circles = np.round(circles[0, :]).astype("int") for (x, y, r) in circles: log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'cropImage: Detect crop coordinates x: ' + str(x) +' y: ' + str(y) +' with radius: ' + str(r)) new_crop = output[y-r:y+r, x-r:x+r] return new_crop return False def start_detect(self, filenameOfCrop, hash, raidNo, captureTime, captureLat, captureLng, orgFileName, radius): log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: Starting detection of crop') log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: Original Filename: ' + str(orgFileName)) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: Original Lat: ' + str(captureLat)) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: Original Lng: ' + str(captureLng)) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: Capture Time: ' + str(captureTime)) if not os.path.isfile(filenameOfCrop): log.error('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: File does not exist: %s'% str(filenameOfCrop)) return monfound = False eggfound = False log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: Starting analysis of ID %s' % str(hash)) img = cv2.imread(filenameOfCrop,3) raidhash = self.cropImage(img, raidNo, radius) raidhashPic = os.path.join(self.tempPath, str(hash) + "_raidhash" + str(raidNo) +".jpg") cv2.imwrite(raidhashPic, raidhash) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: Generating Raidhash') genRaidHash = self.getImageHash(raidhashPic, False, raidNo, 'raid') #get (raidstart, raidend, raidtimer) as (timestamp, timestamp, human-readable hatch) raidtimer = self.detectRaidTime(img, hash, raidNo, radius) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: Got raidtime %s' % (str(raidtimer))) #first item in tuple stands for raid present in crop or not if (not raidtimer[0]): #there is no raid, stop analysis of crop, abandon ship os.remove(filenameOfCrop) os.remove(raidhashPic) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: Crop does not show a raid, stopping analysis') return False #second item is true for egg present, False for mon present eggfound = raidtimer[1] raidstart = raidtimer[2] #will be 0 if eggfound = False. We report a mon anyway raidend = raidtimer[3] #will be 0 if eggfound = False. We report a mon anyway if (not raidstart or not raidend): #there is no raid, stop analysis of crop, abandon ship os.remove(filenameOfCrop) os.remove(raidhashPic) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: Crop does not show a valid time, stopping analysis') return False log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: Creating Hash overall') raidHash = self.imageHashExists(raidhashPic, False, 'raid', raidNo) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: detectRaidHash: ' + str(raidHash)) raidlevel = self.detectLevel(img, hash, raidNo, radius) #we need the raid level to make the possible set of mons smaller log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: Determined raidlevel to be %s' % (str(raidlevel))) if raidHash: raidHash_ = self.decodeHashJson(raidHash, raidNo) gym = raidHash_[0] lvl = raidHash_[1] mon = raidHash_[2] if lvl == raidlevel and raidlevel is not None: if not mon: lvl = self.detectLevel(img, hash, raidNo, radius) #redetect level log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: Determined raidlevel to be %s' % (str(lvl))) if lvl is None: log.error('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: Could not determine raidlevel. Filename of Crop: %s' % (filenameOfCrop)) os.remove(filenameOfCrop) os.remove(raidhashPic) return True log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: Found Raidhash with an egg - fast submit') log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: Found egg level %s starting at %s and ending at %s. GymID: %s' % (lvl, raidstart, raidend, gym)) self.dbWrapper.submitRaid(str(gym), None, lvl, raidstart, raidend, 'EGG', raidNo, captureTime) else: raidend = self.detectRaidEndtimer(img, hash, raidNo, radius) if raidend[1]: log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: Found Raidhash with an mon and endtime - fast submit') log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: Submitting mon. ID: %s, gymId: %s' % (str(mon), str(gym))) self.dbWrapper.submitRaid(str(gym), mon, lvl, None, raidend[2], 'MON', raidNo, captureTime, True) else: log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: Found Raidhash with an mon - fast submit') log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: Submitting mon. ID: %s, gymId: %s' % (str(mon), str(gym))) self.dbWrapper.submitRaid(str(gym), mon, lvl, None, None, 'MON', raidNo, captureTime) self.imageHash(raidhashPic, raidHash, False, 'raid', raidNo) os.remove(filenameOfCrop) os.remove(raidhashPic) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: Finished') return True else: log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: detected Level not Hash Level') if raidlevel is None: log.error('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: Could not determine raidlevel. Filename of Crop: %s' % (filenameOfCrop)) os.remove(filenameOfCrop) os.remove(raidhashPic) return True if eggfound: log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: Found the crop to contain an egg') eggId = eggIdsByLevel[int(raidlevel) - 1] if not eggfound: log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: Found the crop to contain a raidboss, lets see what boss it is') monFound = self.detectRaidBoss(img, raidlevel, hash, raidNo) if not monFound[0]: #we could not determine the mon... let's move the crop to unknown and stop analysing log.warning('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: Could not determine mon in crop, aborting and moving crop to unknown') monUnkPic = os.path.join(self.tempPath, str(hash) + "_unkmon" + str(raidNo) +".jpg") cv2.imwrite(monUnkPic, img) self.unknownfound(monUnkPic, 'mon', False, raidNo, hash, captureTime, False, captureLat, captureLng) log.warning('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: could not determine mon, aborting analysis') os.remove(raidhashPic) os.remove(monUnkPic) os.remove(filenameOfCrop) return True log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: Scanning Gym') gymId = self.detectGym(raidhashPic, hash, raidNo, captureLat, captureLng, radius, monFound[0]) else: #let's get the gym we're likely scanning the image of gymId = self.detectGym(raidhashPic, hash, raidNo, captureLat, captureLng, radius) #gymId is either None for Gym not found or contains the gymId as String if gymId == 'dummy': log.warning('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: determine dummy pic, aborting analysis') return True if gymId is None: #gym unknown... log.warning('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: Could not determine gym, aborting analysis') os.remove(filenameOfCrop) os.remove(raidhashPic) log.debug("start_detect[crop %s]: finished" % str(raidNo)) return True #return true since a raid is present, we just couldn't find the correct gym if eggfound: log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: Found egg level %s starting at %s and ending at %s. GymID: %s' % (raidlevel, raidstart, raidend, gymId)) submitStatus = self.dbWrapper.submitRaid(str(gymId), None, raidlevel, raidstart, raidend, 'EGG', raidNo, captureTime) if submitStatus: self.successfound(filenameOfCrop, 'EGG', gymId, raidNo, raidlevel, captureTime) raidHashJson = self.encodeHashJson(gymId, raidlevel, False, raidNo) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: Adding Raidhash to Database: ' + str(raidHashJson)) self.imageHash(raidhashPic, raidHashJson, False, 'raid', raidNo) else: log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: Checking for Endtime') if not self.dbWrapper.readRaidEndtime(str(gymId), raidNo): log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: No existing Egg found') raidend = self.detectRaidEndtimer(img, hash, raidNo, radius) if raidend[1]: log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: Submitting mon without egg. ID: %s, gymId: %s' % (str(monFound[0]), str(gymId))) submitStatus = self.dbWrapper.submitRaid(str(gymId), monFound[0], raidlevel, None, raidend[2], 'MON', raidNo, captureTime, True) else: log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: Submitting mon without raidend. ID: %s, gymId: %s' % (str(monFound[0]), str(gymId))) submitStatus = self.dbWrapper.submitRaid(str(gymId), monFound[0], raidlevel, None, None, 'MON', raidNo, captureTime) else: log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: Submitting mon with previously reported endtime. ID: %s, gymId: %s' % (str(monFound[0]), str(gymId))) submitStatus = self.dbWrapper.submitRaid(str(gymId), monFound[0], raidlevel, None, None, 'MON', raidNo, captureTime) if submitStatus: self.successfound(filenameOfCrop, 'MON', gymId, raidNo, raidlevel, captureTime, str(monFound[0])) raidHashJson = self.encodeHashJson(gymId, raidlevel, monFound[0], raidNo) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: Adding Raidhash to Database: ' + str(raidHashJson)) self.imageHash(raidhashPic, raidHashJson, False, 'raid', raidNo) self.unknownfound(raidhashPic, 'raid', False, raidNo, hash, False, genRaidHash, '0', '0') os.remove(raidhashPic) os.remove(filenameOfCrop) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'start_detect: Finished') return True def dhash(self, image, raidNo, hash_size = 8): # Grayscale and shrink the image in one step. h = str(imagehash.dhash(image)) return h image = image.convert('L').resize( (hash_size + 1, hash_size), Image.ANTIALIAS, ) pixels = list(image.getdata()) # Compare adjacent pixels. difference = [] for row in xrange(hash_size): for col in xrange(hash_size): pixel_left = image.getpixel((col, row)) pixel_right = image.getpixel((col + 1, row)) difference.append(pixel_left > pixel_right) # Convert the binary array to a hexadecimal string. decimal_value = 0 hex_string = [] for index, value in enumerate(difference): if value: decimal_value += 2**(index % 8) if (index % 8) == 7: hex_string.append(hex(decimal_value)[2:].rjust(2, '0')) decimal_value = 0 hashValue = ''.join(hex_string) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'ImageHash: Generated Image Hash: ' + str(hashValue)) return hashValue def imageHashExists(self, image, zoom, type, raidNo, x1=0.30, x2=0.62, y1=0.62, y2=1.23, radius=0, hashSize=8): image2 = cv2.imread(image,3) image2 = cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY) if zoom: x1 = int(round(radius*2*0.03)+(radius*x1)) x2 = int(round(radius*2*0.03)+(radius*x2)) y1 = int(round(radius*2*0.03)+(radius*y1)) y2 = int(round(radius*2*0.03)+(radius*y2)) crop = image2[int(y1):int(y2),int(x1):int(x2)] else: crop = image2 tempHash = os.path.join(self.tempPath, str(time.time()) + "_" + str(raidNo) + "temphash_check.jpg") cv2.imwrite(tempHash, crop) hashPic = Image.open(tempHash) imageHash = self.dhash(hashPic, raidNo) os.remove(tempHash) if type == 'raid': distance = 4 else: distance = 4 existHash = self.dbWrapper.checkForHash(str(imageHash), str(type), raidNo, distance) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'imageHashExists: Hash found: %s' % existHash[1]) return existHash[1] def imageHash(self, image, id, zoom, type, raidNo, x1=0.30, x2=0.62, y1=0.62, y2=1.23, radius=0, hashSize=8): image2 = cv2.imread(image,3) image2 = cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY) if zoom: x1 = int(round(radius*2*0.03)+(radius*x1)) x2 = int(round(radius*2*0.03)+(radius*x2)) y1 = int(round(radius*2*0.03)+(radius*y1)) y2 = int(round(radius*2*0.03)+(radius*y2)) crop = image2[int(y1):int(y2),int(x1):int(x2)] else: crop = image2 tempHash = os.path.join(self.tempPath, str(time.time()) + "_" + str(raidNo) + "temphash_new.jpg") cv2.imwrite(tempHash, crop) hashPic = Image.open(tempHash) imageHash = self.dhash(hashPic, raidNo) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'imageHash: ' + str(imageHash)) os.remove(tempHash) if type == 'raid': distance = 4 else: distance = 4 existHash = self.dbWrapper.checkForHash(str(imageHash), str(type), raidNo, distance) if existHash[0]: log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'imageHash: Hash already in Database: ' + str(existHash[2]) ) self.dbWrapper.insertHash(str(existHash[2]), str(type), str(id), raidNo) return str(existHash[2]) else: log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'imageHash: Adding Hash to Database: '+ str(imageHash)) self.dbWrapper.insertHash(str(imageHash), str(type), str(id), raidNo) return str(imageHash) def getImageHash(self, image, zoom, raidNo, type, x1=0.30, x2=0.62, y1=0.62, y2=1.23, radius=0, hashSize=8): image2 = cv2.imread(image,3) image2 = cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY) if zoom: x1 = int(round(radius*2*0.03)+(radius*x1)) x2 = int(round(radius*2*0.03)+(radius*x2)) y1 = int(round(radius*2*0.03)+(radius*y1)) y2 = int(round(radius*2*0.03)+(radius*y2)) crop = image2[int(y1):int(y2),int(x1):int(x2)] else: crop = image2 tempHash = os.path.join(self.tempPath, str(time.time()) + "_" + str(raidNo) + "temphash_new.jpg") cv2.imwrite(tempHash, crop) hashPic = Image.open(tempHash) imageHash = self.dhash(hashPic, raidNo) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'getImageHash: ' + str(imageHash)) os.remove(tempHash) if type == 'raid': distance = 4 else: distance = 4 existHash = self.dbWrapper.checkForHash(str(imageHash), str(type), raidNo, distance) if existHash[0]: log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'getImageHash: Hash already in Database: ' + str(existHash[2]) ) return str(existHash[2]) else: log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'getImageHash: Hash not in Database: '+ str(imageHash)) return str(imageHash) def checkHourMin(self, hour_min): hour_min[0] = unicode(hour_min[0].replace('O','0').replace('o','0').replace('A','4')) hour_min[1] = unicode(hour_min[1].replace('O','0').replace('o','0').replace('A','4')) if (hour_min[0]).isnumeric()==True and (hour_min[1]).isnumeric()==True: return True, hour_min else: return False, hour_min def checkHourMinSec(self, hour_min_sec): hour_min_sec[0] = unicode(hour_min_sec[0].replace('O','0').replace('o','0').replace('A','4')) hour_min_sec[1] = unicode(hour_min_sec[1].replace('O','0').replace('o','0').replace('A','4')) hour_min_sec[2] = unicode(hour_min_sec[2].replace('O','0').replace('o','0').replace('A','4')) if (hour_min_sec[0]).isnumeric()==True and (hour_min_sec[1]).isnumeric()==True and (hour_min_sec[2]).isnumeric()==True: return True, hour_min_sec else: return False, hour_min_sec # returns UTC timestamp def getHatchTime(self,data, raidNo): zero = datetime.datetime.now().replace(hour=0,minute=0,second=0,microsecond=0) unix_zero = time.mktime(zero.timetuple()) hour_min_divider = data.find(':') if hour_min_divider is None or hour_min_divider == -1: return False #TODO: think about only one big fat regex noone wants to read lateron am_found = re.search(r'[a|A]\w+', data) pm_found = re.search(r'[p|P]\w+', data) hour_min = re.search(r'([\d]{1,2}:[\d]{1,2})', data) if hour_min is None: log.fatal('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ]' + 'getHatchTime: Could not locate a HH:MM') return False else: hour_min = hour_min.group(1).split(':') ret, hour_min = self.checkHourMin(hour_min) if not ret: return False if am_found: log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'getHatchTime: Found AM') return int(unix_zero)+int(hour_min[0])*3600+int(hour_min[1])*60 elif pm_found: log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'getHatchTime: Found PM') if hour_min[0] == '12': return int(unix_zero)+int(hour_min[0])*3600+int(hour_min[1])*60 else: return int(unix_zero)+(int(hour_min[0])+12)*3600+int(hour_min[1])*60 else: log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'getHatchTime: Found EU Time') return int(unix_zero)+int(hour_min[0])*3600+int(hour_min[1])*60 def getEndTime(self, data, raidNo): zero = datetime.datetime.now() unix_zero = time.mktime(zero.timetuple()) hour_min_divider = data.find(':') log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'getHatchTime: :Count: ' + str(data.count(':'))) if data.count(':') < 2 : log.error('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) +') ] ' + 'getHatchTime: Detect wrong Endtimer of Raid') return False if hour_min_divider != -1: data = data.replace('~','').replace('-','').replace(' ','') hour_min = data.split(':') ret, hour_min = self.checkHourMinSec(hour_min) if ret: return int(unix_zero)+int(hour_min[0])*3600+int(hour_min[1])*60+int(hour_min[2]) else: return False else: return False
def copyMons(pogoasset): monList = [] log.info('Processing Pokemon Matching....') with open('raidmons.json') as f: data = json.load(f) monImgPath = os.getcwd() + '/mon_img/' filePath = os.path.dirname(monImgPath) if not os.path.exists(filePath): log.info('mon_img directory created') os.makedirs(filePath) assetPath = pogoasset if not os.path.exists(assetPath): log.error('PogoAssets not found') exit(0) for file in glob.glob(monImgPath + "*mon*.png"): os.remove(file) for mons in data: for mon in mons['DexID']: lvl = mons['Level'] if str(mon).find("_") > -1: mon_split = str(mon).split("_") mon = mon_split[0] frmadd = mon_split[1] else: frmadd = "00" mon = '{:03d}'.format(int(mon)) monList.append(mon) monFile = monImgPath + '_mon_' + str(mon) + '_' + str( lvl) + '.png' if not os.path.isfile(monFile): monFileAsset = assetPath + '/pokemon_icons/pokemon_icon_' + str( mon) + '_' + frmadd + '.png' if not os.path.isfile(monFileAsset): log.error('File ' + str(monFileAsset) + ' not found') exit(0) copyfile(monFileAsset, monFile) image = Image.open(monFile) image.convert("RGBA") canvas = Image.new( 'RGBA', image.size, (255, 255, 255, 255)) # Empty canvas colour (r,g,b,a) canvas.paste( image, mask=image ) # Paste the image onto the canvas, using it's alpha channel as mask canvas.save(monFile, format="PNG") monAsset = cv2.imread(monFile, 3) height, width, channels = monAsset.shape monAsset = cv2.inRange(monAsset, np.array([240, 240, 240]), np.array([255, 255, 255])) cv2.imwrite(monFile, monAsset) crop = cv2.imread(monFile, 3) crop = crop[0:int(height), 0:int((width / 10) * 10)] kernel = np.ones((1, 1), np.uint8) crop = cv2.erode(crop, kernel, iterations=1) cv2.imwrite(monFile, crop) _monList = myList = ','.join(map(str, monList)) dbWrapper = DbWrapper(str(args.db_method), str(args.dbip), args.dbport, args.dbusername, args.dbpassword, args.dbname, args.timezone) dbWrapper.deleteHashTable(_monList, 'mon')
def main_thread(): global nextRaidQueue global lastPogoRestart global telnMore global pogoWindowManager global sleep global runWarningThreadEvent global windowLock global screenWrapper global lastScreenshotTaken log.info("main: Starting TelnetGeo Client") telnGeo = TelnetGeo(str(args.tel_ip), args.tel_port, str(args.tel_password), args.tel_timeout_command, args.tel_timeout_socket) log.info("main: Starting dbWrapper") dbWrapper = DbWrapper(str(args.db_method), str(args.dbip), args.dbport, args.dbusername, args.dbpassword, args.dbname, args.timezone) updateRaidQueue(dbWrapper) lastRaidQueueUpdate = time.time() if lastPogoRestart is None: lastPogoRestart = time.time() route = getJsonRoute(args.file, args.gym_distance, args.max_count_gym_sum_up_around_gym) log.info("main: Route to be taken: %s, amount of coords: %s" % (str(route), str(len(route)))) log.info("main: Max_distance before teleporting: %s" % args.max_distance) log.info("main: Checking if screen is on and pogo is running") if not sleep: turnScreenOnAndStartPogo() emptycount = 0 locationCount = 0 while True: log.info("main: Next round") curLat = 0.0 curLng = 0.0 i = 0 # index in route failcount = 0 lastRoundEggHatch = False # loop over gyms: # walk to next gym # get to raidscreen # take screenshot # check time to restart pogo # process the entire route, prioritize hatched eggs in every second round (if anything has hatched) while i < len(route): while sleep: time.sleep(1) curTime = time.time() # update the raid queue every 5mins... if (curTime - lastRaidQueueUpdate) >= (5 * 60): updateRaidQueue(dbWrapper) lastRaidQueueUpdate = curTime # Restart pogo every now and then... if args.restart_pogo > 0: #log.debug("main: Current time - lastPogoRestart: %s" % str(curTime - lastPogoRestart)) # if curTime - lastPogoRestart >= (args.restart_pogo * 60): locationCount += 1 if locationCount > args.restart_pogo: log.error("scanned " + str(args.restart_pogo) + " locations, restarting pogo") restartPogo() locationCount = 0 # let's check for speed and weather warnings while we're walking/teleporting... runWarningThreadEvent.set() lastLat = curLat lastLng = curLng egghatchLocation = False log.debug( "main: Checking for raidqueue priority. Current time: %s, Current queue: %s" % (str(time.time()), str(nextRaidQueue))) # determine whether we move to the next gym or to the top of our priority queue if not lastRoundEggHatch and len( nextRaidQueue) > 0 and nextRaidQueue[0][0] < time.time(): # the topmost item in the queue lays in the past... log.info( 'main: An egg has hatched, get there asap. Location: %s' % str(nextRaidQueue[0])) egghatchLocation = True nextStop = heapq.heappop(nextRaidQueue)[ 1] # gets the location tuple curLat = nextStop.latitude curLng = nextStop.longitude time.sleep(1) lastRoundEggHatch = True else: # continue as usual log.info('main: Moving on with gym at %s' % route[i]) curLat = route[i]['lat'] curLng = route[i]['lng'] # remove whitespaces that might be on either side... i += 1 lastRoundEggHatch = False log.debug("main: next stop: %s, %s" % (str(curLat), str(curLng))) log.debug( 'main: LastLat: %s, LastLng: %s, CurLat: %s, CurLng: %s' % (lastLat, lastLng, curLat, curLng)) # get the distance from our current position (last) to the next gym (cur) distance = getDistanceOfTwoPointsInMeters(float(lastLat), float(lastLng), float(curLat), float(curLng)) log.info('main: Moving %s meters to the next position' % distance) delayUsed = 0 if (args.speed == 0 or (args.max_distance and args.max_distance > 0 and distance > args.max_distance) or (lastLat == 0.0 and lastLng == 0.0)): log.info("main: Teleporting...") telnGeo.setLocation(curLat, curLng, 0) delayUsed = args.post_teleport_delay else: log.info("main: Walking...") telnGeo.walkFromTo(lastLat, lastLng, curLat, curLng, args.speed) delayUsed = args.post_walk_delay time.sleep(delayUsed) # ok, we should be at the next gym, check for errors and stuff # TODO: improve errorhandling by checking results and trying again and again # not using continue to always take a new screenshot... log.debug("main: Clearing event, acquiring lock") runWarningThreadEvent.clear() windowLock.acquire() log.debug("main: Lock acquired") log.debug("main: Checking if pogo is running...") if not telnMore.isPogoTopmost(): log.warning("main: Starting Pogo") startPogo(False) windowLock.release() continue while not getToRaidscreen(12): if failcount > 5: log.fatal( "main: failed to find raidscreen way too often. Exiting" ) sys.exit(1) failcount += 1 log.error( "main: Failed to find the raidscreen multiple times in a row. Stopping pogo and taking a " "break of 5 minutes") stopPogo() time.sleep(300) startPogo(False) failcount = 0 # well... we are on the raidtab, but we want to reopen it every now and then, so screw it reopenedRaidTab = False # if not egghatchLocation and math.fmod(i, 30) == 0: # log.warning("main: Closing and opening raidtab every 30 locations scanned... Doing so") # reopenRaidTab() # tabOutAndInPogo() # screenWrapper.getScreenshot('screenshot.png') # reopenedRaidTab = True if args.last_scanned: log.info('main: Set new scannedlocation in Database') dbWrapper.setScannedLocation(str(curLat), str(curLng), str(curTime)) log.info( "main: Checking raidcount and copying raidscreen if raids present" ) countOfRaids = pogoWindowManager.readRaidCircles( 'screenshot.png', 123) if countOfRaids == -1 and not reopenedRaidTab: # reopen raidtab and take screenshot... log.warning( "main: Count present but no raid shown, reopening raidTab") reopenRaidTab() tabOutAndInPogo() screenWrapper.getScreenshot('screenshot.png') countOfRaids = pogoWindowManager.readRaidCircles( 'screenshot.png', 123) # elif countOfRaids == 0: # emptycount += 1 # if emptycount > 30: # emptycount = 0 # log.error("Had 30 empty scans, restarting pogo") # restartPogo() log.debug("main: countOfRaids: %s" % str(countOfRaids)) if countOfRaids > 0: curTime = time.time() copyfile( 'screenshot.png', args.raidscreen_path + '/raidscreen_' + str(curTime) + "_" + str(curLat) + "_" + str(curLng) + "_" + str(countOfRaids) + '.png') log.debug("main: Releasing lock") windowLock.release()
def copyMons(pogoasset): monList = [] log.info('Processing Pokemon Matching....') with open('raidmons.json') as f: data = json.load(f) monImgPath = os.getcwd() + '/mon_img/' filePath = os.path.dirname(monImgPath) if not os.path.exists(filePath): log.info('mon_img directory created') os.makedirs(filePath) assetPath = pogoasset if not os.path.exists(assetPath): log.error('PogoAssets not found') exit(0) for file in glob.glob(monImgPath + "*mon*.png"): os.remove(file) for mons in data: for mon in mons['DexID']: lvl = mons['Level'] if str(mon).find("_") > -1: mon_split = str(mon).split("_") mon = mon_split[0] frmadd = mon_split[1] else: frmadd = "00" mon = '{:03d}'.format(int(mon)) monList.append(mon) monFile = monImgPath + '_mon_' + str(mon) + '_' + str( lvl) + '.png' if not os.path.isfile(monFile): monFileAsset = assetPath + '/pokemon_icons/pokemon_icon_' + str( mon) + '_' + frmadd + '.png' if not os.path.isfile(monFileAsset): log.error('File ' + str(monFileAsset) + ' not found') exit(0) copyfile(monFileAsset, monFile) image = Image.open(monFile) image.convert("RGBA") canvas = Image.new( 'RGBA', image.size, (255, 255, 255, 255)) # Empty canvas colour (r,g,b,a) canvas.paste( image, mask=image ) # Paste the image onto the canvas, using it's alpha channel as mask canvas.save(monFile, format="PNG") monAsset = cv2.imread(monFile, 3) height, width, channels = monAsset.shape monAsset = cv2.inRange(monAsset, np.array([240, 240, 240]), np.array([255, 255, 255])) cv2.imwrite(monFile, monAsset) crop = cv2.imread(monFile, 3) crop = crop[0:int(height), 0:int((width / 10) * 10)] kernel = np.ones((2, 2), np.uint8) crop = cv2.erode(crop, kernel, iterations=1) kernel = np.ones((3, 3), np.uint8) crop = cv2.morphologyEx(crop, cv2.MORPH_CLOSE, kernel) #gray = cv2.cvtColor(crop,cv2.COLOR_BGR2GRAY) #_,thresh = cv2.threshold(gray,1,255,cv2.THRESH_BINARY_INV) #contours = cv2.findContours(thresh,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) #cnt = contours[0] #x,y,w,h = cv2.boundingRect(cnt) #crop = crop[y-1:y+h+1,x-1:x+w+1] cv2.imwrite(monFile, crop) _monList = myList = '|'.join(map(str, monList)) dbWrapper = DbWrapper(str(args.db_method), str(args.dbip), args.dbport, args.dbusername, args.dbpassword, args.dbname, args.timezone) dbWrapper.clearHashGyms(_monList)
class Scanner: def __init__(self, dbMethod, dbIp, dbPort, dbUser, dbPassword, dbName, tempPath, unknownPath, timezone, hash): self.dbIp = dbIp self.dbPort = dbPort self.dbUser = dbUser self.dbPassword = dbPassword self.dbName = dbName self.tempPath = tempPath self.unknownPath = unknownPath self.timezone = timezone self.uniqueHash = hash self.dbMethod = dbMethod self.dbWrapper = DbWrapper(self.dbMethod, self.dbIp, self.dbPort, self.dbUser, self.dbPassword, self.dbName, self.timezone, self.uniqueHash) if not os.path.exists(self.tempPath): log.info('Temp directory created') os.makedirs(self.tempPath) if not os.path.exists(self.unknownPath): log.info('Unknow directory created') os.makedirs(self.unknownPath) def detectRaidTime(self, raidpic, hash, raidNo): log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'detectRaidTime: Reading Raidtimer') raidtimer = raidpic[200:230, 30:150] raidtimer = cv2.resize(raidtimer, (0, 0), fx=2, fy=2, interpolation=cv2.INTER_CUBIC) emptyRaidTempPath = os.path.join( self.tempPath, str(raidNo) + str(hash) + '_emptyraid.png') cv2.imwrite(emptyRaidTempPath, raidtimer) rt = Image.open(emptyRaidTempPath) gray = rt.convert('L') bw = gray.point(lambda x: 0 if x < 200 else 255, '1') raidtimer = pytesseract.image_to_string( bw, config='--psm 6 --oem 3').replace(' ', '').replace( '~', '').replace('o', '0').replace('O', '0').replace('-', '').replace('.', ':') #log.debug(re.match(r'\d\d:\d\d[am|pm]*', raidtimer)) #cleanup os.remove(emptyRaidTempPath) raidFound = len(raidtimer) > 0 if raidFound: if ':' in raidtimer: log.info('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'detectRaidTime: found raidtimer %s' % raidtimer) hatchTime = self.getHatchTime(raidtimer, hash) if hatchTime: log.info('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'detectRaidTime: Hatchtime %s' % str(hatchTime)) #raidstart = getHatchTime(self, raidtimer) - self.timezone * (self.timezone*60*60) raidstart = hatchTime #- (self.timezone * 60 * 60) raidend = hatchTime + 45 * 60 #- (self.timezone * 60 * 60) #raidend = getHatchTime(self, raidtimer) + int(45*60) - (self.timezone*60*60) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'detectRaidTime: Start: ' + str(raidstart) + ' End: ' + str(raidend)) return (raidFound, True, raidstart, raidend) else: return (raidFound, True, False, False) else: return (raidFound, False, '0', '0') else: return (raidFound, False, False, False) def detectRaidEndtimer(self, raidpic, hash, raidNo): log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'detectRaidEndtimer: Reading Raidtimer') raidtimer = raidpic[178:200, 45:130] raidtimer = cv2.resize(raidtimer, (0, 0), fx=2, fy=2, interpolation=cv2.INTER_CUBIC) emptyRaidTempPath = os.path.join( self.tempPath, str(raidNo) + str(hash) + '_endraid.png') cv2.imwrite(emptyRaidTempPath, raidtimer) rt = Image.open(emptyRaidTempPath) gray = rt.convert('L') bw = gray.point(lambda x: 0 if x < 200 else 255, '1') raidtimer = pytesseract.image_to_string( bw, config='--psm 6 --oem 3').replace(' ', '').replace( '~', '').replace('o', '0').replace('O', '0').replace( '-', '').replace('.', ':').replace('B', '8').replace( 'A', '4').replace('—', '') log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'detectRaidEndtimer: Raid-End-Text: ' + str(raidtimer)) os.remove(emptyRaidTempPath) raidEndFound = len(raidtimer) > 0 if raidEndFound: if ':' in raidtimer: now = datetime.datetime.now() log.info('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'detectRaidEndtimer: found raidendtimer %s' % raidtimer) endTime = self.getEndTime(raidtimer, hash) if endTime: log.info('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'detectRaidEndtimer: Endtime %s' % str(endTime)) #raidstart = getHatchTime(self, raidtimer) - self.timezone * (self.timezone*60*60) raidend = endTime #- (self.timezone * 60 * 60) #raidend = getHatchTime(self, raidtimer) + int(45*60) - (self.timezone*60*60) return (raidEndFound, True, raidend) else: return (raidEndFound, False, False) else: log.info('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'detectRaidEndtimer: no raidendtimer detected') return (raidEndFound, False, '0') else: return (raidEndFound, False, False) def detectRaidBoss(self, raidpic, lvl, hash, raidNo): foundmon = None monID = None log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'Extracting Raidboss') lower = np.array([80, 60, 30], dtype="uint8") upper = np.array([110, 90, 70], dtype="uint8") kernel = np.ones((3, 3), np.uint8) kernel2 = np.ones((6, 6), np.uint8) raidMonZoom = cv2.resize(raidpic, (0, 0), fx=2, fy=2) mask = cv2.inRange(raidMonZoom, lower, upper) output = cv2.bitwise_and(raidMonZoom, raidMonZoom, mask=mask) monAsset = cv2.inRange(output, np.array([0, 0, 0]), np.array([15, 15, 15])) monAsset = cv2.morphologyEx(monAsset, cv2.MORPH_CLOSE, kernel) monAsset = cv2.morphologyEx(monAsset, cv2.MORPH_OPEN, kernel2) picName = os.path.join(self.tempPath, str(hash) + '_raidboss' + str(raidNo) + '.jpg') cv2.imwrite(picName, monAsset) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'detectRaidBoss: Scanning Raidboss') monHash = self.imageHashExists( os.path.join(self.tempPath, str(hash) + '_raidboss' + str(raidNo) + '.jpg'), False, 'mon-' + str(lvl), raidNo) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'detectRaidBoss: Monhash: ' + str(monHash)) if monHash is None: for file in glob.glob("mon_img/_mon_*_" + str(lvl) + ".png"): find_mon = mt.fort_image_matching(file, picName, False, 0.60, raidNo, hash) if foundmon is None or find_mon > foundmon[0]: foundmon = find_mon, file if foundmon and foundmon[0] > 0.60: monSplit = foundmon[1].split('_') monID = monSplit[3] #we found the mon that's most likely to be the one that's in the crop log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'detectRaidBoss: Found mon in mon_img: ' + str(monID)) else: os.remove(picName) return monHash, monAsset if monID: self.imageHash(picName, monID, False, 'mon-' + str(lvl), raidNo) os.remove(picName) return monID, monAsset log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'No Mon found!') os.remove(picName) return False, monAsset def detectLevel(self, raidpic, hash, raidNo): foundlvl = None lvl = None lvlTypes = [ 'mon_img/_raidlevel_5_.jpg', 'mon_img/_raidlevel_4_.jpg', 'mon_img/_raidlevel_3_.jpg', 'mon_img/_raidlevel_2_.jpg', 'mon_img/_raidlevel_1_.jpg' ] raidlevel = raidpic[230:260, 0:170] #raidlevel = cv2.resize(raidlevel, (0,0), fx=2, fy=2) cv2.imwrite( os.path.join(self.tempPath, str(hash) + '_raidlevel' + str(raidNo) + '.jpg'), raidlevel) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'Scanning Level') for file in lvlTypes: find_lvl = mt.fort_image_matching( file, os.path.join(self.tempPath, str(hash) + '_raidlevel' + str(raidNo) + '.jpg'), False, 0.7, raidNo, hash) if foundlvl is None or find_lvl > foundlvl[0]: foundlvl = find_lvl, file if not foundlvl is None: lvlSplit = foundlvl[1].split('_') lvl = lvlSplit[3] os.remove( os.path.join(self.tempPath, str(hash) + '_raidlevel' + str(raidNo) + '.jpg')) if lvl: log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'detectLevel: found level %s' % str(lvl)) return lvl else: log.info('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'detectLevel: could not find level') return None def checkDummy(self, raidpic, x1, x2, y1, y2, hash, raidNo): log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'checkDummy: Check for dummy Gym Image') img = cv2.imread(raidpic, 3) template = cv2.imread("mon_img/dummy_nearby.jpg", 3) crop = img[int(y1):int(y2), int(x1):int(x2)] result = cv2.matchTemplate(crop, template, cv2.TM_CCOEFF_NORMED) (_, maxVal, minLoc, maxLoc) = cv2.minMaxLoc(result) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'checkDummy: Match: ' + str(maxVal)) if maxVal >= 0.90: return True return False def detectGym(self, raidpic, hash, raidNo, captureLat, captureLng, monId=None): foundgym = None gymId = None x1 = 25 x2 = 50 y1 = 50 y2 = 80 foundMonCrops = False log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'detectGym: Scanning Gym') #if gymHash is none, we haven't seen the gym yet, otherwise, gymHash == gymId we are looking for if monId: log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'detectGym: Got Mon-ID for Gym-Detection %s' % monId) with open('monsspec.json') as f: data = json.load(f) if str(monId) in data: foundMonCrops = True crop = data[str(monId)]["Crop"] log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'detectGym: Found other Crops for Mon %s' % monId) log.debug(str(crop)) x1 = crop['X1'] x2 = crop['X2'] y1 = crop['Y1'] y2 = crop['Y2'] log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'detectGym: Cropsizes: x1:%s, x2:%s, y1:%s, y2:%s' % (str(x1), str(x2), str(y1), str(y2))) if self.checkDummy(raidpic, x1, x2, y1, y2, hash, raidNo): log.info('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'detectGym: Found dummy gym pic') return None gymHash = self.imageHashExists(raidpic, True, 'gym', raidNo, x1, x2, y1, y2) if gymHash is None: log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'detectGym: No Gym-Hash: found - searching') log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'detectGym: Searching closest gyms') closestGymIds = self.dbWrapper.getNearGyms(captureLat, captureLng, hash, raidNo) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'detectGym: Detecting Gym') for closegym in closestGymIds: for file in glob.glob("gym_img/_" + str(closegym[0]) + "_.jpg"): find_gym = mt.fort_image_matching( raidpic, file, True, float(args.gym_detection_value), raidNo, hash, x1, x2, y1, y2) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'detectGym: Compare Gym-ID - ' + str(closegym[0]) + ' - Match: ' + str(find_gym)) if foundgym is None or find_gym > foundgym[0]: foundgym = find_gym, file if foundgym and foundgym[0] >= float( args.gym_detection_value): #okay, we very likely found our gym gymSplit = foundgym[1].split('_') gymId = gymSplit[2] else: self.imageHash(raidpic, gymId, True, 'gym', raidNo, x1, x2, y1, y2) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'detectGym: Detected Gym-ID: ' + str(gymHash)) return gymHash if gymId: log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'detectGym: Found Gym - Gym-ID: ' + str(gymId)) if foundMonCrops: log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'detectGym: Dont hash Gym with spec. Mon Crops') else: self.imageHash(raidpic, gymId, True, 'gym', raidNo, x1, x2, y1, y2) return gymId else: #we could not find the gym... return None def unknownfound(self, raidpic, type, zoom, raidNo, hash, captureTime, imageHash=0, lat=0, lng=0): if captureTime: text = datetime.datetime.fromtimestamp(float(captureTime)) text = "Scanned: " + str(text.strftime("%Y-%m-%d %H:%M")) self.addTextToCrop(raidpic, text) raidpic = cv2.imread(raidpic) cv2.imwrite( os.path.join( self.unknownPath, str(type) + "_" + str(lat) + "_" + str(lng) + "_" + str(time.time()) + "_" + str(imageHash) + ".jpg"), raidpic) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'unknownfound: Write unknown file: ' + str(type) + "_" + str(lat) + "_" + str(lng) + "_" + str(time.time()) + ".jpg") return True def addTextToCrop(self, picture, text): from PIL import Image, ImageFont, ImageDraw img = Image.open(picture) draw = ImageDraw.Draw(img) font = ImageFont.truetype('font/arial.ttf', 10) x, y = 0, 0 w, h = font.getsize(text) draw.rectangle((x, y, x + img.size[0], y + h + 1), fill='black') draw.text((x, y), text, (255, 255, 255), font=font) img.save(picture) def successfound(self, raidpic, type, gymId, raidNo, lvl, captureTime, mon=0): if not args.save_success: log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'successfound: Saving submit raidpics is disable') return text = datetime.datetime.fromtimestamp(float(captureTime)) text = "Scanned: " + str(text.strftime("%Y-%m-%d %H:%M")) self.addTextToCrop(raidpic, text) if not os.path.exists(args.successsave_path): log.info('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'successfound: Save directory created') os.makedirs(args.successsave_path) with open('gym_info.json') as f: data = json.load(f) gymname = 'unknown' latitude = '00' longitude = '00' if str(gymId) in data: gymname = data[str(gymId)]["name"].replace('/', '-').replace('\\', '/') latitude = data[str(gymId)]["latitude"] longitude = data[str(gymId)]["longitude"] curTime = time.time() saveFileName = str(type) + "_" + str(curTime) + "__LVL_" + str( lvl) + "__MON_" + str(mon) + "__LAT_" + str( latitude) + "__LNG_" + str(longitude) + "__" + str( gymname) + "__" + str(gymId) + ".jpg" log.info('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'successfound: Filename: ' + str(saveFileName)) copyfile(raidpic, os.path.join(args.successsave_path, str(saveFileName))) log.info('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'successfound: Raidcrop successfully saved') def decodeHashJson(self, hashJson, raidNo): data = json.loads(hashJson) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'Decoding Raid Hash Json') raidGym = data['gym'] raidLvl = data["lvl"] raidMon = data["mon"] return raidGym, raidLvl, raidMon def encodeHashJson(self, gym, lvl, mon, raidNo): log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'Encoding Raid Hash Json') hashJson = json.dumps({ 'gym': gym, 'lvl': lvl, 'mon': mon, 'lvl': lvl }, separators=(',', ':')) return hashJson def cropImage(self, image, raidNo): gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) output = image.copy() image_cols, image_rows, _ = image.shape circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 2, image_cols, param1=100, param2=15, minRadius=71, maxRadius=71) if circles is not None: circles = np.round(circles[0, :]).astype("int") for (x, y, r) in circles: log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'cropImage: Detect crop coordinates x: ' + str(x) + ' y: ' + str(y) + ' with radius: ' + str(r)) new_crop = output[y - r - 1:y + r + 1, x - r - 1:x + r + 1] return new_crop return False def resize(image, width=None, height=None, inter=cv2.INTER_AREA): dim = None (h, w) = image.shape[:2] if width is None and height is None: return image if width is None: r = height / float(h) dim = (int(w * r), height) else: r = width / float(w) dim = (width, int(h * r)) resized = cv2.resize(image, dim, interpolation=inter) return resized def start_detect(self, filenameOfCrop, hash, raidNo, captureTime, captureLat, captureLng, orgFileName): log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'start_detect: Starting detection of crop') log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'start_detect: Original Filename: ' + str(orgFileName)) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'start_detect: Original Lat: ' + str(captureLat)) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'start_detect: Original Lng: ' + str(captureLng)) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'start_detect: Capture Time: ' + str(captureTime)) if not os.path.isfile(filenameOfCrop): log.error('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'start_detect: File does not exist: %s' % str(filenameOfCrop)) return monfound = False eggfound = False log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'start_detect: Starting analysis of ID %s' % str(hash)) img_temp = Image.open(filenameOfCrop) hpercent = (270 / float(img_temp.size[1])) wsize = int((float(img_temp.size[0]) * float(hpercent))) img_temp = img_temp.resize((wsize, 270), Image.ANTIALIAS) img_temp.save(filenameOfCrop) img = cv2.imread(filenameOfCrop) raidhash = img[0:175, 0:170] raidhash = self.cropImage(raidhash, raidNo) raidhashPic = os.path.join( self.tempPath, str(hash) + "_raidhash" + str(raidNo) + ".jpg") cv2.imwrite(raidhashPic, raidhash) #get (raidstart, raidend, raidtimer) as (timestamp, timestamp, human-readable hatch) raidtimer = self.detectRaidTime(img, hash, raidNo) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'start_detect: Got raidtime %s' % (str(raidtimer))) #first item in tuple stands for raid present in crop or not if (not raidtimer[0]): #there is no raid, stop analysis of crop, abandon ship os.remove(filenameOfCrop) os.remove(raidhashPic) log.debug( '[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'start_detect: Crop does not show a raid, stopping analysis') return False #second item is true for egg present, False for mon present eggfound = raidtimer[1] raidstart = raidtimer[ 2] #will be 0 if eggfound = False. We report a mon anyway raidend = raidtimer[ 3] #will be 0 if eggfound = False. We report a mon anyway if (not raidstart or not raidend): #there is no raid, stop analysis of crop, abandon ship os.remove(filenameOfCrop) os.remove(raidhashPic) log.debug( '[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'start_detect: Crop does not show a valid time, stopping analysis' ) return False log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'start_detect: Creating Hash overall') #raidHash = self.imageHashExists(raidhashPic, False, 'raid', raidNo) raidHash = False log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'start_detect: detectRaidHash: ' + str(raidHash)) if raidHash: raidHash = self.decodeHashJson(raidHash, raidNo) gym = raidHash[0] lvl = raidHash[1] mon = raidHash[2] #if lvl != raidlevel: # log.debug('Scanned Raidlevel is different to hash - taking scanned level') # lvl = raidlevel if not mon: log.debug( '[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'start_detect: Found Raidhash with an egg - fast submit') log.debug( '[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'start_detect: Found egg level %s starting at %s and ending at %s. GymID: %s' % (lvl, raidstart, raidend, gym)) self.dbWrapper.submitRaid(str(gym), None, lvl, raidstart, raidend, 'EGG', raidNo, captureTime) else: log.debug( '[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'start_detect: Found Raidhash with an mon - fast submit') log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'start_detect: Submitting mon. ID: %s, gymId: %s' % (str(mon), str(gym))) self.dbWrapper.submitRaid(str(gym), mon, lvl, None, None, 'MON', raidNo, captureTime) os.remove(filenameOfCrop) os.remove(raidhashPic) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'start_detect: Finished') return True raidlevel = self.detectLevel( img, hash, raidNo ) #we need the raid level to make the possible set of mons smaller log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'start_detect: Determined raidlevel to be %s' % (str(raidlevel))) if raidlevel is None: log.error( '[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'start_detect: Could not determine raidlevel. Filename of Crop: %s' % (filenameOfCrop)) os.remove(filenameOfCrop) os.remove(raidhashPic) return True if eggfound: log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'start_detect: Found the crop to contain an egg') eggId = eggIdsByLevel[int(raidlevel) - 1] if not eggfound: log.debug( '[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'start_detect: Found the crop to contain a raidboss, lets see what boss it is' ) monFound = self.detectRaidBoss(img, raidlevel, hash, raidNo) if not monFound[0]: #we could not determine the mon... let's move the crop to unknown and stop analysing log.warning( '[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'start_detect: Could not determine mon in crop, aborting and moving crop to unknown' ) self.unknownfound(filenameOfCrop, 'mon', False, raidNo, hash, captureTime, False, captureLat, captureLng) log.warning( '[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'start_detect: could not determine mon, aborting analysis') os.remove(raidhashPic) os.remove(filenameOfCrop) return True log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'start_detect: Scanning Gym') gymId = self.detectGym(raidhashPic, hash, raidNo, captureLat, captureLng, monFound[0]) else: #let's get the gym we're likely scanning the image of gymId = self.detectGym(raidhashPic, hash, raidNo, captureLat, captureLng) #gymId is either None for Gym not found or contains the gymId as String if gymId is None: #gym unknown... log.warning( '[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'start_detect: Could not determine gym, aborting analysis') gymhash = self.getImageHash(raidhashPic, True, raidNo, x1=25, x2=50, y1=50, y2=80) self.unknownfound(filenameOfCrop, 'gym', False, raidNo, hash, captureTime, False, captureLat, captureLng) self.unknownfound(raidhashPic, 'gym_crop', False, raidNo, hash, False, gymhash, captureLat, captureLng) os.remove(filenameOfCrop) os.remove(raidhashPic) log.debug("start_detect[crop %s]: finished" % str(raidNo)) return True #return true since a raid is present, we just couldn't find the correct gym if eggfound: log.debug( '[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'start_detect: Found egg level %s starting at %s and ending at %s. GymID: %s' % (raidlevel, raidstart, raidend, gymId)) submitStatus = self.dbWrapper.submitRaid(str(gymId), None, raidlevel, raidstart, raidend, 'EGG', raidNo, captureTime) if submitStatus: self.successfound(filenameOfCrop, 'EGG', gymId, raidNo, raidlevel, captureTime) raidHashJson = self.encodeHashJson(gymId, raidlevel, False, raidNo) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'start_detect: Adding Raidhash to Database') #self.imageHash(raidhashPic, raidHashJson, False, 'raid', raidNo) else: log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'start_detect: Checking for Endtime') if not self.dbWrapper.readRaidEndtime(str(gymId), raidNo): log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'start_detect: No existing Egg found') raidend = self.detectRaidEndtimer(img, hash, raidNo) if raidend[1]: log.debug( '[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'start_detect: Submitting mon without egg. ID: %s, gymId: %s' % (str(monFound[0]), str(gymId))) submitStatus = self.dbWrapper.submitRaid( str(gymId), monFound[0], raidlevel, None, raidend[2], 'MON', raidNo, captureTime, True) else: log.debug( '[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'start_detect: Submitting mon without raidend. ID: %s, gymId: %s' % (str(monFound[0]), str(gymId))) submitStatus = self.dbWrapper.submitRaid( str(gymId), monFound[0], raidlevel, None, None, 'MON', raidNo, captureTime) else: log.debug( '[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'start_detect: Submitting mon with previously reported endtime. ID: %s, gymId: %s' % (str(monFound[0]), str(gymId))) submitStatus = self.dbWrapper.submitRaid( str(gymId), monFound[0], raidlevel, None, None, 'MON', raidNo, captureTime) if submitStatus: self.successfound(filenameOfCrop, 'MON', gymId, raidNo, raidlevel, captureTime, str(monFound[0])) raidHashJson = self.encodeHashJson(gymId, raidlevel, monFound[0], raidNo) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'start_detect: Adding Raidhash to Database') #self.imageHash(raidhashPic, raidHashJson, False, 'raid', raidNo) os.remove(raidhashPic) os.remove(filenameOfCrop) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'start_detect: Finished') return True def dhash(self, image, raidNo, hash_size=8): # Grayscale and shrink the image in one step. image = image.convert('L').resize( (hash_size + 1, hash_size), Image.ANTIALIAS, ) pixels = list(image.getdata()) # Compare adjacent pixels. difference = [] for row in xrange(hash_size): for col in xrange(hash_size): pixel_left = image.getpixel((col, row)) pixel_right = image.getpixel((col + 1, row)) difference.append(pixel_left > pixel_right) # Convert the binary array to a hexadecimal string. decimal_value = 0 hex_string = [] for index, value in enumerate(difference): if value: decimal_value += 2**(index % 8) if (index % 8) == 7: hex_string.append(hex(decimal_value)[2:].rjust(2, '0')) decimal_value = 0 hashValue = ''.join(hex_string) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'ImageHash: Generated Image Hash: ' + str(hashValue)) return hashValue def imageHashExists(self, image, zoom, type, raidNo, x1=25, x2=50, y1=50, y2=80, hashSize=8): image2 = cv2.imread(image, 3) image2 = cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY) if zoom: crop = image2[int(y1):int(y2), int(x1):int(x2)] else: crop = image2 tempHash = os.path.join( self.tempPath, str(time.time()) + "_" + str(raidNo) + "temphash_check.jpg") cv2.imwrite(tempHash, crop) hashPic = Image.open(tempHash) imageHash = self.dhash(hashPic, raidNo) os.remove(tempHash) existHash = self.dbWrapper.checkForHash(str(imageHash), str(type), raidNo) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'imageHashExists: Hash found: %s' % existHash[1]) return existHash[1] def imageHash(self, image, id, zoom, type, raidNo, x1=25, x2=50, y1=50, y2=80, hashSize=8): image2 = cv2.imread(image, 3) image2 = cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY) if zoom: crop = image2[int(y1):int(y2), int(x1):int(x2)] else: crop = image2 tempHash = os.path.join( self.tempPath, str(time.time()) + "_" + str(raidNo) + "temphash_new.jpg") cv2.imwrite(tempHash, crop) hashPic = Image.open(tempHash) imageHash = self.dhash(hashPic, raidNo) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'imageHash: ' + str(imageHash)) os.remove(tempHash) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'imageHash: Adding Hash to Database') self.dbWrapper.insertHash(str(imageHash), str(type), str(id), raidNo) def getImageHash(self, image, zoom, raidNo, x1=25, x2=50, y1=50, y2=80, hashSize=8): image2 = cv2.imread(image, 3) image2 = cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY) if zoom: crop = image2[int(y1):int(y2), int(x1):int(x2)] else: crop = image2 tempHash = os.path.join( self.tempPath, str(time.time()) + "_" + str(raidNo) + "temphash_new.jpg") cv2.imwrite(tempHash, crop) hashPic = Image.open(tempHash) imageHash = self.dhash(hashPic, raidNo) log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'imageHash: ' + str(imageHash)) os.remove(tempHash) return imageHash def checkHourMin(self, hour_min): hour_min[0] = unicode(hour_min[0].replace('O', '0').replace( 'o', '0').replace('A', '4')) hour_min[1] = unicode(hour_min[1].replace('O', '0').replace( 'o', '0').replace('A', '4')) if (hour_min[0]).isnumeric() == True and ( hour_min[1]).isnumeric() == True: return True, hour_min else: return False, hour_min def checkHourMinSec(self, hour_min_sec): hour_min_sec[0] = unicode(hour_min_sec[0].replace('O', '0').replace( 'o', '0').replace('A', '4')) hour_min_sec[1] = unicode(hour_min_sec[1].replace('O', '0').replace( 'o', '0').replace('A', '4')) hour_min_sec[2] = unicode(hour_min_sec[2].replace('O', '0').replace( 'o', '0').replace('A', '4')) if (hour_min_sec[0]).isnumeric() == True and ( hour_min_sec[1]).isnumeric() == True and ( hour_min_sec[2]).isnumeric() == True: return True, hour_min_sec else: return False, hour_min_sec # returns UTC timestamp def getHatchTime(self, data, raidNo): zero = datetime.datetime.now().replace(hour=0, minute=0, second=0, microsecond=0) unix_zero = time.mktime(zero.timetuple()) hour_min_divider = data.find(':') if hour_min_divider is None or hour_min_divider == -1: return False #TODO: think about only one big fat regex noone wants to read lateron am_found = re.search(r'[a|A]\w+', data) pm_found = re.search(r'[p|P]\w+', data) hour_min = re.search(r'([\d]{1,2}:[\d]{1,2})', data) if hour_min is None: log.fatal('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ]' + 'getHatchTime: Could not locate a HH:MM') return False else: hour_min = hour_min.group(1).split(':') ret, hour_min = self.checkHourMin(hour_min) if not ret: return False if am_found: log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'getHatchTime: Found AM') return int(unix_zero) + int(hour_min[0]) * 3600 + int( hour_min[1]) * 60 elif pm_found: log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'getHatchTime: Found PM') if hour_min[0] == '12': return int(unix_zero) + int(hour_min[0]) * 3600 + int( hour_min[1]) * 60 else: return int(unix_zero) + (int(hour_min[0]) + 12) * 3600 + int( hour_min[1]) * 60 else: log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'getHatchTime: Found EU Time') return int(unix_zero) + int(hour_min[0]) * 3600 + int( hour_min[1]) * 60 def getEndTime(self, data, raidNo): zero = datetime.datetime.now() unix_zero = time.mktime(zero.timetuple()) hour_min_divider = data.find(':') log.debug('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'getHatchTime: :Count: ' + str(data.count(':'))) if data.count(':') < 2: log.error('[Crop: ' + str(raidNo) + ' (' + str(self.uniqueHash) + ') ] ' + 'getHatchTime: Detect wrong Endtimer of Raid') return False if hour_min_divider != -1: data = data.replace('~', '').replace('-', '').replace(' ', '') hour_min = data.split(':') ret, hour_min = self.checkHourMinSec(hour_min) if ret: return int(unix_zero) + int(hour_min[0]) * 3600 + int( hour_min[1]) * 60 + int(hour_min[2]) else: return False else: return False