from seleniumwire import webdriver # Import from seleniumwire from seleniumwire.utils import decode from time import sleep from flask import Flask as f from flask import Response from dateutil import parser from datetime import datetime, timedelta, timezone import json import re import asyncio import logging import threading import os log = logging.getLogger('werkzeug') log.setLevel(logging.ERROR) log.disabled = True # Create a new instance of the Chrome driver valuestore = {} datestore = {} lastUpdate = datetime.now(timezone.utc) app = f("web") #app.logger.disabled = True h2 = timedelta(hours=2) def interceptor(request, response): # A response interceptor takes two args global lastUpdate if 'ws-travis.dus.com/socket.io/?EIO=3&transport=polling' in request.url : body = decode(response.body, response.headers.get('Content-Encoding', 'identity')) x = re.split("\d\d\d:\d\d\/dus,", body.decode("utf-8")) lastUpdate = datetime.now(timezone.utc) for i in [i for i in x if i]: try: j = json.loads(i) handleJson(j) except ValueError: if i.find("online-level") > 0: #print ("Fixed: ", i) j = json.loads(i[:i.rfind(']') + 1]) handleJson(j) #else: #print ("Err: ", i) # StackOverflow def killChildren(driver): print('Quitting session: ', driver.session_id) driver.quit() try: pid = True while pid: pid = os.waitpid(-1, os.WNOHANG) print("Reaped child: ", str(pid)) try: if pid[0] == 0: pid = False except: pass except ChildProcessError: pass def idIsRecent(id): return id in valuestore and datetime.now(timezone.utc) - parser.parse(datestore[id]) < timedelta(seconds=30) def handleJson(jsonObj): if isinstance(jsonObj, list): if 'online-level' in jsonObj: #typ = jsonObj[1]["LevelValues"][0]["Type"] value = jsonObj[1]["LevelValues"][0]["Values"][0] NmtId = jsonObj[1]["NmtId"] time = jsonObj[1]["Time"] valuestore[NmtId] = value datestore[NmtId] = time # Gibt den letzten bekannten Wert fuer die NMTID zurueck @app.route('/nmt/') def nmtid(id): if idIsRecent(id): return format( valuestore[id], '.1f') else: return "E_NA" # Entweder out of date oder nicht existent # Gibt eine Liste mit verfuegbaren ids zurueck @app.route('/ids') def ids(): l = filter(idIsRecent,list(valuestore.keys())) return ','.join(map(str,list(l))) def createDriver(): options = webdriver.ChromeOptions() options.add_argument('--headless') options.add_argument("--incognito") options.add_argument("--nogpu") options.add_argument("--disable-gpu") options.add_argument("--window-size=1280,1280") options.add_argument("--no-sandbox") options.add_argument("--enable-javascript") options.add_argument('--disable-dev-shm-usage') driver = webdriver.Chrome(options=options) driver.response_interceptor = interceptor return driver if __name__ == '__main__': # start flask server threading.Thread(target=lambda: app.run(host='0.0.0.0', port=80, debug=False, use_reloader=False)).start() # wait time to restart will be dynamically adapted, # if unexpected things happen in chrome or the real world restartWait = timedelta(hours=4) # setup webdriver d0 = createDriver() # start initial driver d0.get('https://dus-travis.dus.com/') lastaccess = datetime.now(timezone.utc) # loop and restart with restartWait Interval while True: sleep(30) if datetime.now(timezone.utc) > lastaccess + restartWait: d1 = createDriver() d1.get('https://dus-travis.dus.com/') print ("New Failover Driver started, waiting 10 seconds ...") sleep(10) killChildren(d0) del d0 print ("Original driver deleted") d0 = createDriver() d0.get('https://dus-travis.dus.com/') print ("Recreating original driver and waiting 10 seconds ...") sleep(10) killChildren(d1) del d1 print ("Failover Driver deleted") lastaccess = datetime.now(timezone.utc) l = filter(idIsRecent,list(valuestore.keys())) if len(list(l)) < 1 and lastUpdate < datetime.now(timezone.utc) - timedelta(seconds=90): restartWait = timedelta(minutes=3) print ("Something stupid happened, setting interval to 3m") else: if restartWait < timedelta(hours=1): restartWait = timedelta(hours=4) print ("Something stupid normalized, resetting interval to 4h")