Exemple #1
0
    def __init__(self, db_wrapper: DbWrapper, args,
                 mapping_manager: MappingManager, websocket, logger, app,
                 deviceUpdater):
        self._db: DbWrapper = db_wrapper
        self._args = args
        if self._args.madmin_time == "12":
            self._datetimeformat = '%Y-%m-%d %I:%M:%S %p'
        else:
            self._datetimeformat = '%Y-%m-%d %H:%M:%S'
        self._adb_connect = ADBConnect(self._args)
        self._device_updater = deviceUpdater
        self.research_trigger_queue = Queue()

        self._mapping_manager: MappingManager = mapping_manager

        self._ws_server = websocket
        self._ws_connected_phones: list = []
        self._logger = logger
        self._app = app
        self.add_route()

        self.trigger_thread = None
        self.trigger_thread = Thread(name='research_trigger',
                                     target=self.research_trigger)
        self.trigger_thread.daemon = True
        self.trigger_thread.start()
Exemple #2
0
    def __init__(self, db, args, logger, app):
        self._db = db
        self._args = args
        if self._args.madmin_time == "12":
            self._datetimeformat = '%Y-%m-%d %I:%M:%S %p'
        else:
            self._datetimeformat = '%Y-%m-%d %H:%M:%S'
        self._adb_connect = ADBConnect(self._args)
        self._ws_connected_phones: list = []
        self._logger = logger

        self._app = app
        self.add_route()
Exemple #3
0
    def __init__(self, db, args, mapping_parser, websocket, logger, app):
        self._db = db
        self._args = args
        if self._args.madmin_time == "12":
            self._datetimeformat = '%Y-%m-%d %I:%M:%S %p'
        else:
            self._datetimeformat = '%Y-%m-%d %H:%M:%S'
        self._adb_connect = ADBConnect(self._args)

        self._mapping_parser = mapping_parser
        self._device_mapping = self._mapping_parser.get_devicemappings()

        self._ws_server = websocket
        self._ws_connected_phones: list = []
        self._logger = logger
        self._app = app
        self.add_route()
Exemple #4
0
    def __init__(self, db_wrapper: DbWrapper, args,
                 mapping_manager: MappingManager, websocket, logger, app,
                 deviceUpdater):
        self._db: DbWrapper = db_wrapper
        self._args = args
        if self._args.madmin_time == "12":
            self._datetimeformat = '%Y-%m-%d %I:%M:%S %p'
        else:
            self._datetimeformat = '%Y-%m-%d %H:%M:%S'
        self._adb_connect = ADBConnect(self._args)
        self._device_updater = deviceUpdater

        self._mapping_manager: MappingManager = mapping_manager

        self._ws_server = websocket
        self._ws_connected_phones: list = []
        self._logger = logger
        self._app = app
        self.add_route()
Exemple #5
0
    def __init__(self, db, args, logger, app, mapping_manager: MappingManager, data_manager):
        self._db = db
        self._args = args
        if self._args.madmin_time == "12":
            self._datetimeformat = '%Y-%m-%d %I:%M:%S %p'
        else:
            self._datetimeformat = '%Y-%m-%d %H:%M:%S'
        self._adb_connect = ADBConnect(self._args)
        self._ws_connected_phones: list = []
        self._logger = logger
        self._data_manager = data_manager
        self._app = app
        self._app.config["TEMPLATES_AUTO_RELOAD"] = True
        cache.init_app(self._app)
        self._mapping_mananger = mapping_manager

        self.add_route()
Exemple #6
0
class control(object):
    def __init__(self, db_wrapper: DbWrapper, args,
                 mapping_manager: MappingManager, websocket, logger, app,
                 deviceUpdater):
        self._db: DbWrapper = db_wrapper
        self._args = args
        if self._args.madmin_time == "12":
            self._datetimeformat = '%Y-%m-%d %I:%M:%S %p'
        else:
            self._datetimeformat = '%Y-%m-%d %H:%M:%S'
        self._adb_connect = ADBConnect(self._args)
        self._device_updater = deviceUpdater

        self._mapping_manager: MappingManager = mapping_manager

        self._ws_server = websocket
        self._ws_connected_phones: list = []
        self._logger = logger
        self._app = app
        self.add_route()

    def add_route(self):
        routes = [
            ("/devicecontrol", self.get_phonescreens),
            ("/take_screenshot", self.take_screenshot),
            ("/click_screenshot", self.click_screenshot),
            ("/swipe_screenshot", self.swipe_screenshot),
            ("/quit_pogo", self.quit_pogo),
            ("/restart_phone", self.restart_phone),
            ("/clear_game_data", self.clear_game_data),
            ("/send_gps", self.send_gps),
            ("/send_text", self.send_text),
            ("/upload", self.upload),
            ("/send_command", self.send_command),
            ("/get_uploaded_files", self.get_uploaded_files),
            ("/uploaded_files", self.uploaded_files),
            ("/delete_file", self.delete_file),
            ("/install_file", self.install_file),
            ("/get_install_log", self.get_install_log),
            ("/delete_log_entry", self.delete_log_entry),
            ("/install_status", self.install_status),
            ("/install_file_all_devices", self.install_file_all_devices),
            ("/restart_job", self.restart_job),
            ("/delete_log", self.delete_log),
            ("/get_all_workers", self.get_all_workers),
            ("/job_for_worker", self.job_for_worker),
            ("/reload_jobs", self.reload_jobs),
        ]
        for route, view_func in routes:
            self._app.route(route, methods=['GET', 'POST'])(view_func)

    @auth_required
    @nocache
    @logger.catch()
    def get_phonescreens(self):
        if not os.path.exists(os.path.join(self._args.temp_path, "madmin")):
            os.makedirs(os.path.join(self._args.temp_path, "madmin"))

        screens_phone = []
        ws_connected_phones = []
        if self._ws_server is not None:
            phones = self._ws_server.get_reg_origins().copy()
        else:
            phones = []
        devicemappings = self._mapping_manager.get_all_devicemappings()

        # Sort devices by name.
        phones = sorted(phones)
        for phonename in phones:
            ws_connected_phones.append(phonename)
            add_text = ""
            adb_option = False
            adb = devicemappings.get(phonename, {}).get('adb', False)
            if adb is not None and self._adb_connect.check_adb_status(
                    adb) is not None:
                self._ws_connected_phones.append(adb)
                adb_option = True
                add_text = '<b>ADB</b>'
            else:
                self._ws_connected_phones.append(adb)

            filename = generate_device_screenshot_path(phonename,
                                                       devicemappings,
                                                       self._args)
            try:
                screenshot_ending: str = ".jpg"
                image_resize(filename,
                             os.path.join(self._args.temp_path, "madmin"),
                             width=250)
                screen = "screenshot/madmin/screenshot_" + str(
                    phonename) + screenshot_ending
                screens_phone.append(
                    generate_phones(phonename,
                                    add_text,
                                    adb_option,
                                    screen,
                                    filename,
                                    self._datetimeformat,
                                    dummy=False))
            except IOError:
                screen = "static/dummy.png"
                screens_phone.append(
                    generate_phones(phonename,
                                    add_text,
                                    adb_option,
                                    screen,
                                    filename,
                                    self._datetimeformat,
                                    dummy=True))
                try:
                    os.remove(filename)
                    self._logger.info(
                        "Screenshot {} was corrupted and has been deleted",
                        filename)
                except:
                    pass

        for phonename in self._adb_connect.return_adb_devices():
            if phonename.serial not in self._ws_connected_phones:
                devicemappings = self._mapping_manager.get_all_devicemappings()
                for pho in devicemappings:
                    if phonename.serial == devicemappings[pho].get(
                            'adb', False):
                        adb_option = True
                        add_text = '<b>ADB - no WS<img src="/static/warning.png" width="20px" ' \
                                   'alt="NO websocket connection!"></b>'
                        filename = generate_device_screenshot_path(
                            pho, devicemappings, self._args)
                        if os.path.isfile(filename):
                            image_resize(filename,
                                         os.path.join(self._args.temp_path,
                                                      "madmin"),
                                         width=250)
                            screenshot_ending: str = ".jpg"
                            screen = "screenshot/madmin/screenshot_" + str(
                                pho) + screenshot_ending
                            screens_phone.append(
                                generate_phones(pho,
                                                add_text,
                                                adb_option,
                                                screen,
                                                filename,
                                                self._datetimeformat,
                                                dummy=False))
                        else:
                            screen = "static/dummy.png"
                            screens_phone.append(
                                generate_phones(pho,
                                                add_text,
                                                adb_option,
                                                screen,
                                                filename,
                                                self._datetimeformat,
                                                dummy=True))

        return render_template('phonescreens.html',
                               editform=screens_phone,
                               header="Device control",
                               title="Device control")

    @auth_required
    def take_screenshot(self, origin=None, adb=False):
        origin = request.args.get('origin')
        useadb = request.args.get('adb', False)
        self._logger.info('MADmin: Making screenshot ({})', str(origin))

        devicemappings = self._mapping_manager.get_all_devicemappings()
        adb = devicemappings.get(origin, {}).get('adb', False)
        filename = generate_device_screenshot_path(origin, devicemappings,
                                                   self._args)

        if useadb == 'True' and self._adb_connect.make_screenshot(
                adb, origin, "jpg"):
            self._logger.info('MADMin: ADB screenshot successfully ({})',
                              str(origin))
        else:
            self.generate_screenshot(origin)

        creationdate = datetime.datetime.fromtimestamp(
            creation_date(filename)).strftime(self._datetimeformat)

        return creationdate

    def generate_screenshot(self, origin):
        devicemappings = self._mapping_manager.get_all_devicemappings()
        screenshot_type: ScreenshotType = ScreenshotType.JPEG
        if devicemappings.get(origin, {}).get("screenshot_type",
                                              "jpeg") == "png":
            screenshot_type = ScreenshotType.PNG

        screenshot_quality: int = devicemappings.get(origin, {}).get(
            "screenshot_quality", 80)

        temp_comm = self._ws_server.get_origin_communicator(origin)
        temp_comm.get_screenshot(
            generate_device_screenshot_path(origin, devicemappings,
                                            self._args), screenshot_quality,
            screenshot_type)

        filename = generate_device_screenshot_path(origin, devicemappings,
                                                   self._args)
        image_resize(filename,
                     os.path.join(self._args.temp_path, "madmin"),
                     width=250)

        return

    @auth_required
    def click_screenshot(self):
        origin = request.args.get('origin')
        click_x = request.args.get('clickx')
        click_y = request.args.get('clicky')
        useadb = request.args.get('adb')
        devicemappings = self._mapping_manager.get_all_devicemappings()

        filename = generate_device_screenshot_path(origin, devicemappings,
                                                   self._args)
        with Image.open(filename) as screenshot:
            width, height = screenshot.size

        real_click_x = int(width / float(click_x))
        real_click_y = int(height / float(click_y))
        adb = devicemappings.get(origin, {}).get('adb', False)

        if useadb == 'True' and self._adb_connect.make_screenclick(
                adb, origin, real_click_x, real_click_y):
            self._logger.info('MADMin: ADB screenclick successfully ({})',
                              str(origin))
        else:
            self._logger.info('MADMin WS Click x:{} y:{} ({})',
                              str(real_click_x), str(real_click_y),
                              str(origin))
            temp_comm = self._ws_server.get_origin_communicator(origin)
            temp_comm.click(int(real_click_x), int(real_click_y))

        time.sleep(2)
        return self.take_screenshot(origin, useadb)

    @auth_required
    def swipe_screenshot(self):
        origin = request.args.get('origin')
        click_x = request.args.get('clickx')
        click_y = request.args.get('clicky')
        click_xe = request.args.get('clickxe')
        click_ye = request.args.get('clickye')
        useadb = request.args.get('adb')

        devicemappings = self._mapping_manager.get_all_devicemappings()

        filename = generate_device_screenshot_path(origin, devicemappings,
                                                   self._args)
        with Image.open(filename) as screenshot:
            width, height = screenshot.size

        real_click_x = int(width / float(click_x))
        real_click_y = int(height / float(click_y))
        real_click_xe = int(width / float(click_xe))
        real_click_ye = int(height / float(click_ye))
        adb = devicemappings.get(origin, {}).get('adb', False)

        if useadb == 'True' and self._adb_connect.make_screenswipe(
                adb, origin, real_click_x, real_click_y, real_click_xe,
                real_click_ye):
            self._logger.info('MADMin: ADB screenswipe successfully ({})',
                              str(origin))
        else:
            self._logger.info('MADMin WS Swipe x:{} y:{} xe:{} ye:{} ({})',
                              str(real_click_x), str(real_click_y),
                              str(real_click_xe), str(real_click_ye),
                              str(origin))
            temp_comm = self._ws_server.get_origin_communicator(origin)
            temp_comm.touchandhold(int(real_click_x), int(real_click_y),
                                   int(real_click_xe), int(real_click_ye))

        time.sleep(2)
        return self.take_screenshot(origin, useadb)

    @auth_required
    def quit_pogo(self):
        origin = request.args.get('origin')
        useadb = request.args.get('adb')
        restart = request.args.get('restart')
        devicemappings = self._mapping_manager.get_all_devicemappings()

        adb = devicemappings.get(origin, {}).get('adb', False)
        self._logger.info('MADmin: Restart Pogo ({})', str(origin))
        if useadb == 'True' and \
                self._adb_connect.send_shell_command(adb, origin, "am force-stop com.nianticlabs.pokemongo"):
            self._logger.info(
                'MADMin: ADB shell force-stop game command successfully ({})',
                str(origin))
            if restart:
                time.sleep(1)
                started = self._adb_connect.send_shell_command(
                    adb, origin, "am start com.nianticlabs.pokemongo")
                if started:
                    self._logger.info(
                        'MADMin: ADB shell start game command successfully ({})',
                        str(origin))
                else:
                    self._logger.error(
                        'MADMin: ADB shell start game command failed ({})',
                        str(origin))
        else:
            temp_comm = self._ws_server.get_origin_communicator(origin)
            if restart:
                self._logger.info('MADMin: trying to restart game on {}',
                                  str(origin))
                temp_comm.restartApp("com.nianticlabs.pokemongo")

                time.sleep(1)
            else:
                self._logger.info('MADMin: trying to stop game on {}',
                                  str(origin))
                temp_comm.stopApp("com.nianticlabs.pokemongo")

            self._logger.info('MADMin: WS command successfully ({})',
                              str(origin))
        time.sleep(2)
        return self.take_screenshot(origin, useadb)

    @auth_required
    def restart_phone(self):
        origin = request.args.get('origin')
        useadb = request.args.get('adb')
        devicemappings = self._mapping_manager.get_all_devicemappings()

        adb = devicemappings.get(origin, {}).get('adb', False)
        self._logger.info('MADmin: Restart device ({})', str(origin))
        if (useadb == 'True' and self._adb_connect.send_shell_command(
                adb, origin,
                "am broadcast -a android.intent.action.BOOT_COMPLETED")):
            self._logger.info('MADMin: ADB shell command successfully ({})',
                              str(origin))
        else:
            temp_comm = self._ws_server.get_origin_communicator(origin)
            temp_comm.reboot()
        self._ws_server.force_disconnect(origin)
        return redirect(url_for('get_phonescreens'), code=302)

    @auth_required
    def clear_game_data(self):
        origin = request.args.get('origin')
        useadb = request.args.get('adb')
        devicemappings = self._mapping_manager.get_all_devicemappings()

        adb = devicemappings.get(origin, {}).get('adb', False)
        self._logger.info('MADmin: Clear game data for device ({})',
                          str(origin))
        if (useadb == 'True' and self._adb_connect.send_shell_command(
                adb, origin, "pm clear com.nianticlabs.pokemongo")):
            self._logger.info('MADMin: ADB shell command successfully ({})',
                              str(origin))
        else:
            temp_comm = self._ws_server.get_origin_communicator(origin)
            temp_comm.resetAppdata("com.nianticlabs.pokemongo")
        return redirect(url_for('get_phonescreens'), code=302)

    @auth_required
    def send_gps(self):
        origin = request.args.get('origin')
        devicemappings = self._mapping_manager.get_all_devicemappings()

        useadb = request.args.get('adb')
        if useadb is None:
            useadb = devicemappings.get(origin, {}).get('adb', False)

        coords = request.args.get('coords').replace(' ', '').split(',')
        sleeptime = request.args.get('sleeptime', "0")
        if len(coords) < 2:
            return 'Wrong Format!'
        self._logger.info('MADmin: Set GPS Coords {}, {} - WS Mode only! ({})',
                          str(coords[0]), str(coords[1]), str(origin))
        try:
            temp_comm = self._ws_server.get_origin_communicator(origin)
            temp_comm.setLocation(coords[0], coords[1], 0)
            if int(sleeptime) > 0:
                self._logger.info("MADmin: Set additional sleeptime: {} ({})",
                                  str(sleeptime), str(origin))
                self._ws_server.set_geofix_sleeptime_worker(origin, sleeptime)
        except Exception as e:
            self._logger.exception(
                'MADmin: Exception occurred while set gps coords: {}.', e)

        time.sleep(2)
        return self.take_screenshot(origin, useadb)

    @auth_required
    def send_text(self):
        origin = request.args.get('origin')
        useadb = request.args.get('adb')
        text = request.args.get('text')
        devicemappings = self._mapping_manager.get_all_devicemappings()

        adb = devicemappings.get(origin, {}).get('adb', False)
        if len(text) == 0:
            return 'Empty text'
        self._logger.info('MADmin: Send text ({})', str(origin))
        if useadb == 'True' and self._adb_connect.send_shell_command(
                adb, origin, 'input text "' + text + '"'):
            self._logger.info('MADMin: Send text successfully ({})',
                              str(origin))
        else:
            temp_comm = self._ws_server.get_origin_communicator(origin)
            temp_comm.sendText(text)

        time.sleep(2)
        return self.take_screenshot(origin, useadb)

    @auth_required
    def send_command(self):
        origin = request.args.get('origin')
        useadb = request.args.get('adb')
        command = request.args.get('command')
        devicemappings = self._mapping_manager.get_all_devicemappings()

        adb = devicemappings.get(origin, {}).get('adb', False)
        self._logger.info('MADmin: Sending Command ({})', str(origin))
        if command == 'home':
            cmd = "input keyevent 3"
        elif command == 'back':
            cmd = "input keyevent 4"
        if useadb == 'True' and self._adb_connect.send_shell_command(
                adb, origin, cmd):
            self._logger.info('MADMin: ADB shell command successfully ({})',
                              str(origin))
        else:
            temp_comm = self._ws_server.get_origin_communicator(origin)
            if command == 'home':
                temp_comm.homeButton()
            elif command == 'back':
                temp_comm.backButton()

        time.sleep(2)
        return self.take_screenshot(origin, useadb)

    @auth_required
    @logger.catch
    def upload(self):
        if request.method == 'POST':
            # check if the post request has the file part
            if 'file' not in request.files:
                flash('No file part')
                return redirect(url_for('upload'), code=302)
            file = request.files['file']
            if file.filename == '':
                flash('No file selected for uploading')
                return redirect(url_for('upload'), code=302)
            if file and allowed_file(file.filename):
                filename = secure_filename(file.filename)
                file.save(os.path.join(self._args.upload_path, filename))
                flash('File uploaded successfully')
                return redirect(url_for('uploaded_files'), code=302)
            else:
                flash('Allowed file type is apk only!')
                return redirect(url_for('upload'), code=302)

        return render_template('upload.html',
                               header="File Upload",
                               title="File Upload")

    @auth_required
    def get_uploaded_files(self):
        return jsonify(
            uploaded_files(self._datetimeformat,
                           self._device_updater.return_commands()))

    @auth_required
    def uploaded_files(self):
        origin = request.args.get('origin', False)
        useadb = request.args.get('adb', False)
        return render_template('uploaded_files.html',
                               responsive=str(
                                   self._args.madmin_noresponsive).lower(),
                               title="Uploaded Files",
                               origin=origin,
                               adb=useadb)

    @auth_required
    def delete_file(self):
        filename = request.args.get('filename')
        if os.path.exists(os.path.join(self._args.upload_path, filename)):
            os.remove(os.path.join(self._args.upload_path, filename))
            flash('File deleted successfully')
        return redirect(url_for('uploaded_files'), code=302)

    @auth_required
    @logger.catch
    def install_file(self):

        jobname = request.args.get('jobname')
        origin = request.args.get('origin')
        useadb = request.args.get('adb', False)
        type_ = request.args.get('type', None)

        devicemappings = self._mapping_manager.get_all_devicemappings()
        adb = devicemappings.get(origin, {}).get('adb', False)

        if os.path.exists(os.path.join(self._args.upload_path, jobname)):
            if useadb == 'True':
                if self._adb_connect.push_file(adb, origin, os.path.join(self._args.upload_path, jobname)) and  \
                    self._adb_connect.send_shell_command(
                        adb, origin, "pm install -r /sdcard/Download/" + str(jobname)):
                    flash('File installed successfully')
                else:
                    flash('File could not be installed successfully :(')
            else:
                self._device_updater.preadd_job(origin=origin,
                                                job=jobname,
                                                id_=int(time.time()),
                                                type=type_)
                flash('File successfully queued --> See Job Status')

        elif type_ != jobType.INSTALLATION:
            self._device_updater.preadd_job(origin=origin,
                                            job=jobname,
                                            id_=int(time.time()),
                                            type=type_)
            flash('Job successfully queued --> See Job Status')

        return redirect(url_for('uploaded_files',
                                origin=str(origin),
                                adb=useadb),
                        code=302)

    @auth_required
    def reload_jobs(self):
        logger.info("Reload existing jobs")
        self._device_updater.init_jobs()
        return redirect(url_for('uploaded_files'), code=302)

    @auth_required
    @logger.catch
    def get_install_log(self):
        withautojobs = request.args.get('withautojobs', False)
        return_log = []
        log = self._device_updater.get_log(withautojobs=withautojobs)
        for entry in log:
            if 'jobname' not in entry:
                entry['jobname'] = entry.get('file', 'Unknown Name')
            return_log.append(entry)

        return jsonify(return_log)

    @auth_required
    @logger.catch()
    def delete_log_entry(self):
        id_ = request.args.get('id')
        if self._device_updater.delete_log_id(id_):
            flash('Job deleted successfully')
        else:
            flash('Job could not be deleted successfully')
        return redirect(url_for('install_status'), code=302)

    @auth_required
    @logger.catch
    def install_status(self):
        withautojobs = request.args.get('withautojobs', False)
        return render_template('installation_status.html',
                               responsive=str(
                                   self._args.madmin_noresponsive).lower(),
                               title="Installation Status",
                               withautojobs=withautojobs)

    @auth_required
    @logger.catch()
    def install_file_all_devices(self):
        jobname = request.args.get('jobname', None)
        type_ = request.args.get('type', None)
        if jobname is None or type_ is None:
            flash('No File or Type selected')
            return redirect(url_for('install_status'), code=302)

        devices = self._mapping_manager.get_all_devices()
        for device in devices:
            self._device_updater.preadd_job(origin=device,
                                            job=jobname,
                                            id_=int(time.time()),
                                            type=type_)
            time.sleep(1)

        flash('Job successfully queued')
        return redirect(url_for('install_status'), code=302)

    @auth_required
    @logger.catch()
    def restart_job(self):
        id: int = request.args.get('id', None)
        if id is not None:
            self._device_updater.restart_job(id)
            flash('Job requeued')
            return redirect(url_for('install_status'), code=302)

        flash('unknown id - restart failed')
        return redirect(url_for('install_status'), code=302)

    @auth_required
    @logger.catch()
    def delete_log(self):
        onlysuccess = request.args.get('only_success', False)
        self._device_updater.delete_log(onlysuccess=onlysuccess)
        return redirect(url_for('install_status'), code=302)

    @auth_required
    def get_all_workers(self):
        devices = self._mapping_manager.get_all_devices()
        devicesreturn = []
        for device in devices:
            devicesreturn.append({'worker': device})

        return jsonify(devicesreturn)

    @auth_required
    def job_for_worker(self):
        jobname = request.args.get('jobname', None)
        type_ = request.args.get('type', None)
        devices = request.args.getlist('device[]')
        for device in devices:
            self._device_updater.preadd_job(origin=device,
                                            job=jobname,
                                            id_=int(time.time()),
                                            type=type_)
            time.sleep(1)

        flash('Job successfully queued')
        return redirect(url_for('install_status'), code=302)
Exemple #7
0
class control(object):
    def __init__(self, db, args, mapping_parser, websocket, logger, app):
        self._db = db
        self._args = args
        if self._args.madmin_time == "12":
            self._datetimeformat = '%Y-%m-%d %I:%M:%S %p'
        else:
            self._datetimeformat = '%Y-%m-%d %H:%M:%S'
        self._adb_connect = ADBConnect(self._args)

        self._mapping_parser = mapping_parser
        self._device_mapping = self._mapping_parser.get_devicemappings()

        self._ws_server = websocket
        self._ws_connected_phones: list = []
        self._logger = logger
        self._app = app
        self.add_route()

    def add_route(self):
        routes = [("/phonecontrol", self.get_phonescreens),
                  ("/take_screenshot", self.take_screenshot),
                  ("/click_screenshot", self.click_screenshot),
                  ("/swipe_screenshot", self.swipe_screenshot),
                  ("/quit_pogo", self.quit_pogo),
                  ("/restart_phone", self.restart_phone),
                  ("/send_gps", self.send_gps), ("/send_text", self.send_text),
                  ("/send_command", self.send_command)]
        for route, view_func in routes:
            self._app.route(route)(view_func)

    @auth_required
    @nocache
    def get_phonescreens(self):
        if not os.path.exists(os.path.join(self._args.temp_path, "madmin")):
            os.makedirs(os.path.join(self._args.temp_path, "madmin"))

        screens_phone = []
        ws_connected_phones = []
        if self._ws_server is not None:
            phones = self._ws_server.get_reg_origins().copy()
        else:
            phones = []
        for phonename in phones:
            ws_connected_phones.append(phonename)
            add_text = ""
            adb_option = False
            adb = self._device_mapping[phonename].get('adb', False)
            if adb is not None and self._adb_connect.check_adb_status(
                    adb) is not None:
                self._ws_connected_phones.append(adb)
                adb_option = True
                add_text = '<b>ADB</b>'
            else:
                self._ws_connected_phones.append(adb)

            filename = generate_device_screenshot_path(phonename,
                                                       self._device_mapping,
                                                       self._args)
            if os.path.isfile(filename):
                screenshot_ending: str = ".jpg"
                image_resize(filename,
                             os.path.join(self._args.temp_path, "madmin"),
                             width=250)
                screen = "screenshot/madmin/screenshot_" + str(
                    phonename) + screenshot_ending
                screens_phone.append(
                    generate_phones(phonename,
                                    add_text,
                                    adb_option,
                                    screen,
                                    filename,
                                    self._datetimeformat,
                                    dummy=False))
            else:
                screen = "static/dummy.png"
                screens_phone.append(
                    generate_phones(phonename,
                                    add_text,
                                    adb_option,
                                    screen,
                                    filename,
                                    self._datetimeformat,
                                    dummy=True))

        for phonename in self._adb_connect.return_adb_devices():
            if phonename.serial not in self._ws_connected_phones:
                for pho in self._device_mapping:
                    if phonename.serial == self._device_mapping[pho].get(
                            'adb', False):
                        adb_option = True
                        add_text = '<b>ADB - no WS<img src="/static/warning.png" width="20px" ' \
                                   'alt="NO websocket connection!"></b>'
                        filename = generate_device_screenshot_path(
                            pho, self._device_mapping, self._args)
                        if os.path.isfile(filename):
                            image_resize(filename,
                                         os.path.join(self._args.temp_path,
                                                      "madmin"),
                                         width=250)
                            screenshot_ending: str = ".jpg"
                            screen = "screenshot/madmin/screenshot_" + str(
                                pho) + screenshot_ending
                            screens_phone.append(
                                generate_phones(pho,
                                                add_text,
                                                adb_option,
                                                screen,
                                                filename,
                                                self._datetimeformat,
                                                dummy=False))
                        else:
                            screen = "static/dummy.png"
                            screens_phone.append(
                                generate_phones(pho,
                                                add_text,
                                                adb_option,
                                                screen,
                                                filename,
                                                self._datetimeformat,
                                                dummy=True))

        return render_template('phonescreens.html',
                               editform=screens_phone,
                               header="Phonecontrol",
                               title="Phonecontrol",
                               running_ocr=(self._args.only_ocr))

    @auth_required
    def take_screenshot(self, origin=None, adb=False):
        origin = request.args.get('origin')
        useadb = request.args.get('adb', False)
        self._logger.info('MADmin: Making screenshot ({})', str(origin))
        adb = self._device_mapping[origin].get('adb', False)

        if useadb == 'True' and self._adb_connect.make_screenshot(
                adb, origin, "jpg"):
            self._logger.info('MADMin: ADB screenshot successfully ({})',
                              str(origin))
        else:

            screenshot_type: ScreenshotType = ScreenshotType.JPEG
            if self._device_mapping[origin].get("screenshot_type",
                                                "jpeg") == "png":
                screenshot_type = ScreenshotType.PNG

            screenshot_quality: int = self._device_mapping[origin].get(
                "screenshot_quality", 80)

            temp_comm = self._ws_server.get_origin_communicator(origin)
            temp_comm.get_screenshot(
                generate_device_screenshot_path(origin, self._device_mapping,
                                                self._args),
                screenshot_quality, screenshot_type)

        filename = generate_device_screenshot_path(origin,
                                                   self._device_mapping,
                                                   self._args)
        image_resize(filename,
                     os.path.join(self._args.temp_path, "madmin"),
                     width=250)

        creationdate = datetime.datetime.fromtimestamp(
            creation_date(filename)).strftime(self._datetimeformat)

        return creationdate

    @auth_required
    def click_screenshot(self):
        origin = request.args.get('origin')
        click_x = request.args.get('clickx')
        click_y = request.args.get('clicky')
        useadb = request.args.get('adb')

        filename = generate_device_screenshot_path(origin,
                                                   self._device_mapping,
                                                   self._args)
        img = cv2.imread(filename, 0)
        height, width = img.shape[:2]

        real_click_x = int(width / float(click_x))
        real_click_y = int(height / float(click_y))
        adb = self._device_mapping[origin].get('adb', False)

        if useadb == 'True' and self._adb_connect.make_screenclick(
                adb, origin, real_click_x, real_click_y):
            self._logger.info('MADMin: ADB screenclick successfully ({})',
                              str(origin))
        else:
            self._logger.info('MADMin WS Click x:{} y:{} ({})',
                              str(real_click_x), str(real_click_y),
                              str(origin))
            temp_comm = self._ws_server.get_origin_communicator(origin)
            temp_comm.click(int(real_click_x), int(real_click_y))

        time.sleep(2)
        return self.take_screenshot(origin, useadb)

    @auth_required
    def swipe_screenshot(self):
        origin = request.args.get('origin')
        click_x = request.args.get('clickx')
        click_y = request.args.get('clicky')
        click_xe = request.args.get('clickxe')
        click_ye = request.args.get('clickye')
        useadb = request.args.get('adb')

        filename = generate_device_screenshot_path(origin,
                                                   self._device_mapping,
                                                   self._args)
        img = cv2.imread(filename, 0)
        height, width = img.shape[:2]

        real_click_x = int(width / float(click_x))
        real_click_y = int(height / float(click_y))
        real_click_xe = int(width / float(click_xe))
        real_click_ye = int(height / float(click_ye))
        adb = self._device_mapping[origin].get('adb', False)

        if useadb == 'True' and self._adb_connect.make_screenswipe(
                adb, origin, real_click_x, real_click_y, real_click_xe,
                real_click_ye):
            self._logger.info('MADMin: ADB screenswipe successfully ({})',
                              str(origin))
        else:
            self._logger.info('MADMin WS Swipe x:{} y:{} xe:{} ye:{} ({})',
                              str(real_click_x), str(real_click_y),
                              str(real_click_xe), str(real_click_ye),
                              str(origin))
            temp_comm = self._ws_server.get_origin_communicator(origin)
            temp_comm.touchandhold(int(real_click_x), int(real_click_y),
                                   int(real_click_xe), int(real_click_ye))

        time.sleep(2)
        return self.take_screenshot(origin, useadb)

    @auth_required
    def quit_pogo(self):
        origin = request.args.get('origin')
        useadb = request.args.get('adb')
        adb = self._device_mapping[origin].get('adb', False)
        self._logger.info('MADmin: Restart Pogo ({})', str(origin))
        if useadb == 'True' and self._adb_connect.send_shell_command(
                adb, origin, "am force-stop com.nianticlabs.pokemongo"):
            self._logger.info('MADMin: ADB shell command successfully ({})',
                              str(origin))
        else:
            temp_comm = self._ws_server.get_origin_communicator(origin)
            temp_comm.stopApp("com.nianticlabs.pokemongo")
            self._logger.info('MADMin: WS command successfully ({})',
                              str(origin))

        time.sleep(2)
        return self.take_screenshot(origin, useadb)

    @auth_required
    def restart_phone(self):
        origin = request.args.get('origin')
        useadb = request.args.get('adb')
        adb = self._device_mapping[origin].get('adb', False)
        self._logger.info('MADmin: Restart Phone ({})', str(origin))
        if useadb == 'True' and self._adb_connect.send_shell_command(
                adb, origin,
                "am broadcast -a android.intent.action.BOOT_COMPLETED"):
            self._logger.info('MADMin: ADB shell command successfully ({})',
                              str(origin))
        else:
            temp_comm = self._ws_server.get_origin_communicator(origin)
            temp_comm.reboot()
        return redirect(getBasePath(request) + '/phonecontrol')

    @auth_required
    def send_gps(self):
        origin = request.args.get('origin')

        useadb = request.args.get('adb')
        if useadb is None:
            useadb = self._device_mapping[origin].get('adb', False)

        coords = request.args.get('coords').replace(' ', '').split(',')
        sleeptime = request.args.get('sleeptime', "0")
        if len(coords) < 2:
            return 'Wrong Format!'
        self._logger.info('MADmin: Set GPS Coords {}, {} - WS Mode only! ({})',
                          str(coords[0]), str(coords[1]), str(origin))
        try:
            temp_comm = self._ws_server.get_origin_communicator(origin)
            temp_comm.setLocation(coords[0], coords[1], 0)
            if int(sleeptime) > 0:
                self._logger.info("MADmin: Set additional sleeptime: {} ({})",
                                  str(sleeptime), str(origin))
                self._ws_server.set_geofix_sleeptime_worker(origin, sleeptime)
        except Exception as e:
            self._logger.exception(
                'MADmin: Exception occurred while set gps coords: {}.', e)

        time.sleep(2)
        return self.take_screenshot(origin, useadb)

    @auth_required
    def send_text(self):
        origin = request.args.get('origin')
        useadb = request.args.get('adb')
        text = request.args.get('text')
        adb = self._device_mapping[origin].get('adb', False)
        if len(text) == 0:
            return 'Empty text'
        self._logger.info('MADmin: Send text ({})', str(origin))
        if useadb == 'True' and self._adb_connect.send_shell_command(
                adb, origin, 'input text "' + text + '"'):
            self._logger.info('MADMin: Send text successfully ({})',
                              str(origin))
        else:
            temp_comm = self._ws_server.get_origin_communicator(origin)
            temp_comm.sendText(text)

        time.sleep(2)
        return self.take_screenshot(origin, useadb)

    @auth_required
    def send_command(self):
        origin = request.args.get('origin')
        useadb = request.args.get('adb')
        command = request.args.get('command')
        adb = self._device_mapping[origin].get('adb', False)
        self._logger.info('MADmin: Sending Command ({})', str(origin))
        if command == 'home':
            cmd = "input keyevent 3"
        elif command == 'back':
            cmd = "input keyevent 4"
        if useadb == 'True' and self._adb_connect.send_shell_command(
                adb, origin, cmd):
            self._logger.info('MADMin: ADB shell command successfully ({})',
                              str(origin))
        else:
            temp_comm = self._ws_server.get_origin_communicator(origin)
            if command == 'home':
                temp_comm.homeButton()
            elif command == 'back':
                temp_comm.backButton()

        time.sleep(2)
        return self.take_screenshot(origin, useadb)
Exemple #8
0
class config(object):
    def __init__(self, db, args, logger, app):
        self._db = db
        self._args = args
        if self._args.madmin_time == "12":
            self._datetimeformat = '%Y-%m-%d %I:%M:%S %p'
        else:
            self._datetimeformat = '%Y-%m-%d %H:%M:%S'
        self._adb_connect = ADBConnect(self._args)
        self._ws_connected_phones: list = []
        self._logger = logger

        self._app = app
        self.add_route()

    def add_route(self):
        routes = [
            ("/addwalker", self.addwalker),
            ("/savesortwalker", self.savesortwalker),
            ("/delwalker", self.delwalker),
            ("/config", self.config),
            ("/delsetting", self.delsetting),
            ("/addnew", self.addnew),
            ("/showmonsidpicker", self.showmonsidpicker),
            ("/addedit", self.addedit),
            ("/showsettings", self.showsettings)
        ]
        for route, view_func in routes:
            self._app.route(route, methods=['GET', 'POST'])(view_func)

    @auth_required
    def addwalker(self):
        fieldwebsite = []
        walkervalue = ""
        walkerposition = ""
        walkermax = ""
        walkertext = ""
        edit = request.args.get('edit')
        walker = request.args.get('walker')
        add = request.args.get('add')

        walkernr = request.args.get('walkernr')

        with open('configs/mappings.json') as f:
            mapping = json.load(f)
            if 'walker' not in mapping:
                mapping['walker'] = []

        if add:
            walkerarea = request.args.get('walkerarea')
            walkertype = request.args.get('walkertype')
            walkervalue = request.args.get('walkervalue')
            walkernr = request.args.get('walkernr')
            walkermax = request.args.get('walkermax')
            walkertext = request.args.get('walkertext').replace(' ', '_')
            walkerposition = request.args.get('walkerposition', False)
            if not walkerposition:
                walkerposition = False
            oldwalkerposition = request.args.get('oldwalkerposition')
            edit = request.args.get('edit')

            walkerlist = {'walkerarea': walkerarea, 'walkertype': walkertype, 'walkervalue': walkervalue,
                          'walkermax': walkermax, 'walkertext': walkertext}

            if 'setup' not in mapping['walker'][int(walkernr)]:
                mapping['walker'][int(walkernr)]['setup'] = []

            if edit:
                if int(walkerposition) == int(oldwalkerposition):
                    mapping['walker'][int(walkernr)]['setup'][int(
                        walkerposition)] = walkerlist
                else:
                    del mapping['walker'][int(
                        walkernr)]['setup'][int(oldwalkerposition)]
                    if walkerposition:
                        mapping['walker'][int(walkernr)]['setup'].insert(
                            int(walkerposition), walkerlist)
                    else:
                        mapping['walker'][int(walkernr)]['setup'].insert(
                            999, walkerlist)
            else:
                if walkerposition:
                    mapping['walker'][int(walkernr)]['setup'].insert(
                        int(walkerposition), walkerlist)
                else:
                    mapping['walker'][int(walkernr)]['setup'].insert(
                        999, walkerlist)

            with open('configs/mappings.json', 'w') as outfile:
                json.dump(mapping, outfile, indent=4, sort_keys=True)

                return redirect(getBasePath(request) + "/config?type=walker&area=walker&block=fields&edit="
                                + str(walker), code=302)

        if walker and edit:
            walkerposition = request.args.get('walkerposition')
            _walkerval = mapping['walker'][int(
                walkernr)]['setup'][int(walkerposition)]
            walkerarea = _walkerval['walkerarea']
            walkertype = _walkerval['walkertype']
            walkervalue = _walkerval['walkervalue']
            walkermax = _walkerval.get('walkermax', '')
            walkertext = _walkerval.get('walkertext', '').replace(' ', '_')
            if walkermax is None:
                walkermax = ''
            edit = True

        fieldwebsite.append('<form action="addwalker" id="settings">')
        fieldwebsite.append(
            '<input type="hidden" name="walker" value="' + walker + '">')
        fieldwebsite.append('<input type="hidden" name="add" value=True>')
        if walker and edit:
            fieldwebsite.append(
                '<input type="hidden" name="oldwalkerposition" value=' + str(walkerposition) + '>')
            fieldwebsite.append('<input type="hidden" name="edit" value=True>')
        fieldwebsite.append(
            '<input type="hidden" name="walkernr" value=' + str(walkernr) + '>')

        req = "required"

        # lockvalue = 'readonly'
        lockvalue = ''

        _temp = '<div class="form-group"><label>Area</label><br /><small class="form-text text-muted">Select the Area' \
                '</small><select class="form-control" name="walkerarea" ' + \
                lockvalue + ' ' + req + '>'
        with open('configs/mappings.json') as f:
            mapping = json.load(f)
            if 'walker' not in mapping:
                mapping['walker'] = []
        mapping['areas'].append({'name': None})

        for option in mapping['areas']:
            sel = ''
            if edit:
                if str(walkerarea).lower() == str(option['name']).lower():
                    sel = 'selected'
            _temp = _temp + '<option value="' + str(option['name']) + '" ' + sel + '>' + str(
                option['name']) + '</option>'
            sel = ''
        _temp = _temp + '</select></div>'
        fieldwebsite.append(str(_temp))

        req = "required"
        _temp = '<div class="form-group"><label>Walkermode</label><br /><small class="form-text text-muted">' \
                'Choose the way to end the route:<br>' \
                '<b>countdown</b>: Kill worker after X seconds<br>' \
                '<b>timer</b>: Kill worker after X:XX o´clock (Format: 24h f.e. 21:30 -> 9:30 pm)<br>' \
                '<b>round</b>: Kill worker after X rounds<br>' \
                '<b>period</b>: Kill worker if outside the period (Format: 24h f.e. 7:00-21:00)<br>' \
                '<b>coords*</b>: Kill worker if no more coords are present<br>' \
                '<b>idle*</b>: Idle worker and close Pogo till time or in period (check sleepmode of phone - ' \
                'display must be on in this time!)<br>' \
                '<b>*Additionally for coords/idle (walkervalue):</b><br>' \
                '- Kill worker after X:XX o´clock (Format: 24h)<br>' \
                '- Kill worker if outside of a period (Format: 24h f.e. 7:00-21:00)<br>' \
                '</small>' \
                '<select class="form-control" name="walkertype" ' + lockvalue + ' ' + req + '>'
        _options = ('countdown#timer#round#period#coords#idle').split('#')
        for option in _options:
            if edit:
                if str(walkertype).lower() in str(option).lower():
                    sel = 'selected'
            _temp = _temp + '<option value="' + \
                    str(option) + '" ' + sel + '>' + str(option) + '</option>'
            sel = ''
        _temp = _temp + '</select></div>'
        fieldwebsite.append(str(_temp))

        fieldwebsite.append('<div class="form-group"><label>Value for Walkermode</label><br />'
                            '<small class="form-text text-muted"></small>'
                            '<input type="text" name="walkervalue" value="' + str(
            walkervalue) + '" data-rule-validatewalkervalue="true"></div>')

        fieldwebsite.append('<div class="form-group"><label>Max. Walker in Area</label><br />'
                            '<small class="form-text text-muted">Empty = infinitely</small>'
                            '<input type="text" name="walkermax" value="' + str(walkermax) + '"></div>')

        fieldwebsite.append('<div class="form-group"><label>Description</label><br />'
                            '<small class="form-text text-muted"></small>'
                            '<input type="text" name="walkertext" value="' + str(walkertext).replace('_',
                                                                                                     ' ') + '"></div>')

        fieldwebsite.append('<div class="form-group"><label>Position in Walker</label><br />'
                            '<small class="form-text text-muted">Set position in walker (0=first / empty=append on list)'
                            '</small>'
                            '<input type="text" name="walkerposition" value="' + str(walkerposition) + '"></div>')

        fieldwebsite.append(
            '<button type="submit" class="btn btn-primary">Save</button></form>')

        if edit:
            header = "Edit " + walkerarea + " (" + walker + ")"
        else:
            header = "Add new " + walker

        return render_template('parser.html', editform=fieldwebsite, header=header, title="edit settings",
                               running_ocr=(self._args.only_ocr))

    @auth_required
    def savesortwalker(self):
        walkernr = request.args.get('walkernr')
        data = request.args.getlist('position[]')
        edit = request.args.get('edit')
        datavalue = []

        with open('configs/mappings.json') as f:
            mapping = json.load(f)
            if 'walker' not in mapping:
                mapping['walker'] = []

        for ase in data:
            _temp = ase.split("|")
            walkerlist = {'walkerarea': _temp[0], 'walkertype': _temp[1], 'walkervalue': _temp[2],
                          'walkermax': _temp[3],
                          'walkertext': _temp[4]}
            datavalue.append(walkerlist)

        mapping['walker'][int(walkernr)]['setup'] = datavalue

        with open('configs/mappings.json', 'w') as outfile:
            json.dump(mapping, outfile, indent=4, sort_keys=True)

        return redirect(getBasePath(request) + "/config?type=walker&area=walker&block=fields&edit=" + str(edit),
                        code=302)

    @auth_required
    def delwalker(self):
        walker = request.args.get('walker')
        walkernr = request.args.get('walkernr')
        walkerposition = request.args.get('walkerposition')

        with open('configs/mappings.json') as f:
            mapping = json.load(f)
            if 'walker' not in mapping:
                mapping['walker'] = []

        del mapping['walker'][int(walkernr)]['setup'][int(walkerposition)]

        with open('configs/mappings.json', 'w') as outfile:
            json.dump(mapping, outfile, indent=4, sort_keys=True)

        return redirect(getBasePath(request) + "/config?type=walker&area=walker&block=fields&edit=" + str(walker),
                        code=302)

    @auth_required
    def config(self):
        fieldwebsite = []
        oldvalues = []
        sel = ''
        _walkernr = 0

        edit = False
        edit = request.args.get('edit')
        type = request.args.get('type')
        block = request.args.get('block')
        area = request.args.get('area')
        fieldwebsite.append('<form action="addedit" id="settings" method="post">')
        fieldwebsite.append(
            '<input type="hidden" name="block" value="' + block + '" />')
        fieldwebsite.append(
            '<input type="hidden" name="mode" value="' + type + '" />')
        fieldwebsite.append(
            '<input type="hidden" name="area" value="' + area + '" />')
        if edit:
            fieldwebsite.append(
                '<input type="hidden" name="edit" value="' + edit + '" />')
            with open('configs/mappings.json') as f:
                mapping = json.load(f)
                if 'walker' not in mapping:
                    mapping['walker'] = []
                if 'devicesettings' not in mapping:
                    mapping['devicesettings'] = []
                nr = 0
                for oldfields in mapping[area]:
                    if 'name' in oldfields:
                        if oldfields['name'] == edit:
                            oldvalues = oldfields
                            _checkfield = 'name'
                    if 'origin' in oldfields:
                        if oldfields['origin'] == edit:
                            oldvalues = oldfields
                            _checkfield = 'origin'
                    if 'username' in oldfields:
                        if oldfields['username'] == edit:
                            oldvalues = oldfields
                            _checkfield = 'username'
                    if 'devicepool' in oldfields:
                        if oldfields['devicepool'] == edit:
                            oldvalues = oldfields
                            _checkfield = 'devicepool'
                    if 'walkername' in oldfields:
                        if oldfields['walkername'] == edit:
                            oldvalues = oldfields
                            _checkfield = 'walker'
                            _walkernr = nr
                        nr += 1

        with open('madmin/static/vars/vars_parser.json') as f:
            vars = json.load(f)

        for area in vars[area]:
            if 'name' in area:
                if area['name'] == type:
                    _name = area['name']
                    compfields = area
            if 'origin' in area:
                if area['origin'] == type:
                    _name = area['origin']
                    compfields = area
            if 'username' in area:
                if area['username'] == type:
                    _name = area['username']
                    compfields = area
            if 'walker' in area:
                if area['walker'] == type:
                    _name = area['walker']
                    compfields = area
            if 'devicesettings' in area:
                if area['devicesettings'] == type:
                    _name = area['devicesettings']
                    compfields = area

        for field in compfields[block]:
            lock = field['settings'].get("lockonedit", False)
            showmonsidpicker = field['settings'].get("showmonsidpicker", False)
            lockvalue = 'readonly' if lock and edit else ''
            req = 'required' if field['settings'].get(
                'require', 'false') == 'true' else ''
            if field['settings']['type'] == 'text' or field['settings']['type'] == 'textarea':
                val = ''
                if edit:
                    if block == 'settings':
                        if field['name'] in oldvalues['settings'] and str(oldvalues['settings'][field['name']]) != str(
                                'None'):
                            val = str(oldvalues['settings'][field['name']])
                    else:
                        if field['name'] in oldvalues and str(oldvalues[field['name']]) != str('None'):
                            val = str(oldvalues[field['name']])

                formStr = '<div class="form-group">'
                formStr += '<label>' + str(field['name']) + '</label><br /><small class="form-text text-muted">' + str(
                    field['settings']['description']) + '</small>'

                # No idea how/where to put that link, ended with this one
                if showmonsidpicker:
                    monsidpicker_link = '<a href=showmonsidpicker?edit=' + str(edit) + '&type=' + str(
                        type) + '>[BETA ID Picker]</a>'
                    formStr += monsidpicker_link
                if field['settings']['type'] == 'text':
                    formStr += '<input type="text" name="' + \
                               str(field['name']) + '" value="' + val + \
                               '" ' + lockvalue + ' ' + req + '>'
                if field['settings']['type'] == 'textarea':
                    formStr += '<textarea rows="10" name="' + \
                               str(field['name']) + '" ' + lockvalue + \
                               ' ' + req + '>' + val + '</textarea>'
                formStr += '</div>'
                fieldwebsite.append(formStr)

            if field['settings']['type'] == 'list':
                if edit:
                    val = ''
                    fieldwebsite.append('<div class="form-group"><label>' + str(
                        field['name']) + '</label><br /><small class="form-text text-muted">' + str(
                        field['settings']['description']) + '</small></div>')

                    fieldwebsite.append('<table class="table">')
                    fieldwebsite.append(
                        '<tr><th></th><th>Nr.</th><th>Area<br>Description</th><th>Walkermode</th><th>Setting</th>'
                        '<th>Max. Devices</th><th></th></tr><tbody class="row_position">')
                    if block != 'settings':
                        if field['name'] in oldvalues and str(oldvalues[field['name']]) != str('None'):
                            val = list(oldvalues[field['name']])
                            i = 0
                            while i < len(val):
                                fieldwebsite.append('<tr id=' + str(val[i]['walkerarea']) + '|' + str(
                                    val[i]['walkertype']) + '|' + str(val[i]['walkervalue']) + '|' + str(
                                    val[i].get('walkermax', '')) + '|' + str(val[i].get('walkertext', '')).replace(' ',
                                                                                                                   '_') + '>'
                                                                                                                          '<td ><img src="static/sort.png" class="handle"></td><td>' + str(
                                    i) + '</td><td><b>' + str(val[i]['walkerarea']) + '</b><br>' + str(
                                    val[i].get('walkertext', '')).replace('_', ' ') + '</td><td>' + str(
                                    val[i]['walkertype']) + '</td><td>' + str(
                                    val[i]['walkervalue']) + '</td><td>' + str(
                                    val[i].get('walkermax', '')) + '</td><td>'
                                                                   '<a href="delwalker?walker=' + str(
                                    edit) + '&walkernr=' + str(
                                    _walkernr) + '&walkerposition=' + str(i) + '">Delete</a><br>'
                                                                               '<a href="addwalker?walker=' + str(
                                    edit) + '&walkernr=' + str(_walkernr) + '&walkerposition=' + str(
                                    i) + '&edit=True">Edit</a></form></td></tr>')
                                i += 1

                        fieldwebsite.append('</tbody></table>')
                        fieldwebsite.append(
                            '<div class="form-group"><a href="addwalker?walker=' + str(edit) + '&walkernr=' + str(
                                _walkernr) + '">Add Area</a></div>')

            if field['settings']['type'] == 'option':
                _temp = '<div class="form-group"><label>' + str(
                    field['name']) + '</label><br /><small class="form-text text-muted">' + str(
                    field['settings']['description']) + '</small><select class="form-control" name="' + str(
                    field['name']) + '" ' + lockvalue + ' ' + req + '>'
                _options = field['settings']['values'].split('|')
                for option in _options:
                    if edit:
                        if block == 'settings':
                            if field['name'] in oldvalues['settings']:
                                if str(oldvalues['settings'][field['name']]).lower() in str(option).lower():
                                    sel = 'selected'
                        else:
                            if field['name'] in oldvalues:
                                if str(oldvalues[field['name']]).lower() in str(option).lower():
                                    sel = 'selected'
                    _temp = _temp + '<option value="' + \
                            str(option) + '" ' + sel + '>' + str(option) + '</option>'
                    sel = ''
                _temp = _temp + '</select></div>'
                fieldwebsite.append(str(_temp))

            if field['settings']['type'] == 'areaselect':
                _temp = '<div class="form-group"><label>' + str(
                    field['name']) + '</label><br /><small class="form-text text-muted">' + str(
                    field['settings']['description']) + '</small><select class="form-control" name="' + str(
                    field['name']) + '" ' + lockvalue + ' ' + req + '>'
                with open('configs/mappings.json') as f:
                    mapping = json.load(f)
                    if 'walker' not in mapping:
                        mapping['walker'] = []
                mapping['areas'].append({'name': None})

                for option in mapping['areas']:
                    if edit:
                        if block == "settings":
                            if str(oldvalues[field['settings']['name']]).lower() == str(option['name']).lower():
                                sel = 'selected'
                            else:
                                if oldvalues[field['settings']['name']] == '':
                                    sel = 'selected'
                        else:
                            if field['name'] in oldvalues:
                                if str(oldvalues[field['name']]).lower() == str(option['name']).lower():
                                    sel = 'selected'
                            else:
                                if not option['name']:
                                    sel = 'selected'
                    _temp = _temp + '<option value="' + \
                            str(option['name']) + '" ' + sel + '>' + \
                            str(option['name']) + '</option>'
                    sel = ''
                _temp = _temp + '</select></div>'
                fieldwebsite.append(str(_temp))

            if field['settings']['type'] == 'adbselect':
                devices = self._adb_connect.return_adb_devices()
                _temp = '<div class="form-group"><label>' + str(
                    field['name']) + '</label><br /><small class="form-text text-muted">' + str(
                    field['settings']['description']) + '</small><select class="form-control" name="' + str(
                    field['name']) + '" ' + lockvalue + ' ' + req + '>'
                adb = {}
                adb['serial'] = []
                adb['serial'].append({'name': None})
                for device in devices:
                    adb['serial'].append({'name': device.serial})

                for option in adb['serial']:
                    if edit:
                        if block == "settings":
                            if str(oldvalues[field['settings']['name']]).lower() == str(option['name']).lower():
                                sel = 'selected'
                            else:
                                if oldvalues[field['settings']['name']] == '':
                                    sel = 'selected'
                        else:
                            if field['name'] in oldvalues:
                                if str(oldvalues[field['name']]).lower() == str(option['name']).lower():
                                    sel = 'selected'
                            else:
                                if not option['name']:
                                    sel = 'selected'
                    _temp = _temp + '<option value="' + \
                            str(option['name']) + '" ' + sel + '>' + \
                            str(option['name']) + '</option>'
                    sel = ''
                _temp = _temp + '</select></div>'
                fieldwebsite.append(str(_temp))

            if field['settings']['type'] == 'walkerselect':
                _temp = '<div class="form-group"><label>' + str(
                    field['name']) + '</label><br /><small class="form-text text-muted">' + str(
                    field['settings']['description']) + '</small><select class="form-control" name="' + str(
                    field['name']) + '" ' + lockvalue + ' ' + req + '>'
                with open('configs/mappings.json') as f:
                    mapping = json.load(f)
                    if 'walker' not in mapping:
                        mapping['walker'] = []
                for option in mapping['walker']:
                    if edit:
                        if field['name'] in oldvalues:
                            if str(oldvalues[field['name']]).lower() == str(option['walkername']).lower():
                                sel = 'selected'
                        else:
                            if not option['walkername']:
                                sel = 'selected'
                    _temp = _temp + '<option value="' + \
                            str(option['walkername']) + '" ' + sel + '>' + \
                            str(option['walkername']) + '</option>'
                    sel = ''
                _temp = _temp + '</select></div>'
                fieldwebsite.append(str(_temp))

            if field['settings']['type'] == 'poolselect':
                _temp = '<div class="form-group"><label>' + str(
                    field['name']) + '</label><br /><small class="form-text text-muted">' + str(
                    field['settings']['description']) + '</small><select class="form-control" name="' + str(
                    field['name']) + '" ' + lockvalue + ' ' + req + '>'
                with open('configs/mappings.json') as f:
                    mapping = json.load(f)
                    if 'devicesettings' not in mapping:
                        mapping['devicesettings'] = []
                mapping['devicesettings'].append({'devicepool': None})
                for option in mapping['devicesettings']:
                    if edit:
                        if field['name'] in oldvalues:
                            if str(oldvalues[field['name']]).lower() == str(option['devicepool']).lower():
                                sel = 'selected'
                        else:
                            if not option['devicepool']:
                                sel = 'selected'
                    _temp = _temp + '<option value="' + \
                            str(option['devicepool']) + '" ' + sel + '>' + \
                            str(option['devicepool']) + '</option>'
                    sel = ''
                _temp = _temp + '</select></div>'
                fieldwebsite.append(str(_temp))

            if field['settings']['type'] == 'areaoption':
                _temp = '<div class="form-group"><label>' + str(
                    field['name']) + '</label><br /><small class="form-text text-muted">' + str(
                    field['settings']['description']) + '</small><select class="form-control" name="' + str(
                    field['name']) + '" ' + lockvalue + ' ' + req + ' size=10 multiple=multiple>'
                with open('configs/mappings.json') as f:
                    mapping = json.load(f)
                    if 'walker' not in mapping:
                        mapping['walker'] = []
                mapping['areas'].append({'name': None})
                oldvalues_split = []

                if edit:
                    if block == "settings":
                        if oldvalues[field['settings']['name']] is not None:
                            oldvalues_split = oldvalues[field['settings']['name']].replace(
                                " ", "").split(",")
                    else:
                        if oldvalues[field['name']] is not None:
                            oldvalues_split = oldvalues[field['name']].replace(
                                " ", "").split(",")

                for option in mapping['areas']:
                    if edit:
                        for old_value in oldvalues_split:
                            if block == "settings":
                                if str(old_value).lower() == str(option['name']).lower():
                                    sel = 'selected'
                                else:
                                    if old_value == '':
                                        sel = 'selected'
                            else:
                                if field['name'] in oldvalues:
                                    if str(old_value).lower() == str(option['name']).lower():
                                        sel = 'selected'
                                else:
                                    if not option['name']:
                                        sel = 'selected'
                    _temp = _temp + '<option value="' + \
                            str(option['name']) + '" ' + sel + '>' + \
                            str(option['name']) + '</option>'
                    sel = ''
                _temp = _temp + '</select></div>'
                fieldwebsite.append(str(_temp))

        if edit:
            header = "Edit " + edit + " (" + type + ")"
        else:
            header = "Add new " + type

        if (type == 'walker' and edit is None) or (type != 'walker' and edit is not None) \
                or (type != 'walker' and edit is None):
            fieldwebsite.append(
                '<button type="submit" class="btn btn-primary">Save</button></form>')

        return render_template('parser.html', editform=fieldwebsite, header=header, title="edit settings",
                               walkernr=_walkernr, edit=edit, running_ocr=(self._args.only_ocr))

    @auth_required
    def delsetting(self):
        global device_mappings, areas
        edit = request.args.get('edit')
        area = request.args.get('area')

        with open('configs/mappings.json') as f:
            mapping = json.load(f)
            if 'walker' not in mapping:
                mapping['walker'] = []

        for key, entry in enumerate(mapping[area]):
            if 'name' in entry:
                _checkfield = 'name'
            if 'origin' in entry:
                _checkfield = 'origin'
            if 'username' in entry:
                _checkfield = 'username'
            if 'walkername' in entry:
                _checkfield = 'walkername'
            if 'devicepool' in entry:
                _checkfield = 'devicepool'

            if str(edit) == str(entry[_checkfield]):
                del mapping[area][key]

        with open('configs/mappings.json', 'w') as outfile:
            json.dump(mapping, outfile, indent=4, sort_keys=True)

        return redirect(getBasePath(request) + "/showsettings", code=302)

    def check_float(self, number):
        try:
            float(number)
            return True
        except ValueError:
            return False

    @auth_required
    def addedit(self):
        data = request.form.to_dict(flat=False)
        datavalue = {}

        for ase in data:
            key = ','.join(data[ase])
            datavalue[ase] = key

        edit = datavalue.get("edit", False)
        block = datavalue.get("block", False)
        area = datavalue.get("area", False)
        mode = datavalue.get("mode", False)

        with open('configs/mappings.json') as f:
            mapping = json.load(f)
            if 'walker' not in mapping:
                mapping['walker'] = []
            if 'devicesettings' not in mapping:
                mapping['devicesettings'] = []

        with open('madmin/static/vars/settings.json') as f:
            settings = json.load(f)

        if edit:
            for entry in mapping[area]:
                if 'name' in entry:
                    _checkfield = 'name'
                if 'origin' in entry:
                    _checkfield = 'origin'
                if 'username' in entry:
                    _checkfield = 'username'
                if 'walkername' in entry:
                    _checkfield = 'walkername'
                if 'devicepool' in entry:
                    _checkfield = 'devicepool'

                if str(edit) == str(entry[_checkfield]):
                    if str(block) == str("settings"):
                        for key, value in datavalue.items():
                            if value == '' or value == 'None':
                                if key in entry['settings']:
                                    del entry['settings'][key]
                            elif value in area:
                                continue
                            else:
                                if str(key) not in ('block', 'area', 'type', 'edit', 'mode'):
                                    entry['settings'][key] = self.match_type(value)

                    else:
                        for key, value in datavalue.items():
                            if value == '':
                                if key in entry:
                                    del entry[key]
                            elif value in area:
                                continue
                            else:
                                if str(key) in ('geofence'):
                                    entry[key] = value
                                elif str(key) not in ('block', 'area', 'type', 'edit'):
                                    entry[key] = self.match_type(value)

        else:
            new = {}
            for key, value in datavalue.items():
                if value != '' and value not in area:
                    if str(key) in ('geofence'):
                        new[key] = value
                    elif str(key) not in ('block', 'area', 'type', 'edit'):
                        new[key] = self.match_type(value)

            if str(block) == str("settings"):
                mapping[area]['settings'].append(new)
            else:
                if settings[area]['has_settings'] == 'true':
                    new['settings'] = {}
                mapping[area].append(new)

        with open('configs/mappings.json', 'w') as outfile:
            json.dump(mapping, outfile, indent=4, sort_keys=True)


        return redirect(getBasePath(request) + "/showsettings", code=302)

    def match_type(self, value):
        if '[' in value and ']' in value:
            if ':' in value:
                tempvalue = []
                valuearray = value.replace('[', '').replace(']', '').replace(
                    ' ', '').replace("'", '').split(',')
                for k in valuearray:
                    tempvalue.append(str(k))
                value = tempvalue
            else:
                value = list(value.replace('[', '').replace(']', '').split(','))
                value = [int(i) for i in value]
        elif value in 'true':
            value = bool(True)
        elif value in 'false':
            value = bool(False)
        elif value.isdigit():
            value = int(value)
        elif self.check_float(value):
            value = float(value)
        elif value == "None":
            value = None
        else:
            value = value.replace(' ', '_')
        return value

    @auth_required
    def showsettings(self):
        table = ''
        with open('configs/mappings.json') as f:
            mapping = json.load(f)
            if 'walker' not in mapping:
                mapping['walker'] = []
            if 'devicesettings' not in mapping:
                mapping['devicesettings'] = []

        with open('madmin/static/vars/settings.json') as f:
            settings = json.load(f)
        with open('madmin/static/vars/vars_parser.json') as f:
            vars = json.load(f)

        globalheader = '<thead><tr><th><b>Type</b></th><th>Basedata</th><th>Settings</th><th>Delete</th></tr></thead>'

        for var in vars:
            line, quickadd, quickline = '', '', ''
            header = '<tr><td colspan="4" class="header"><b>' + (var.upper()) + '</b> <a href="addnew?area=' + var + \
                     '">[Add new]</a></td><td style="display: none;"></td><td style="display: none;"></td><td style="display: none;"></td></tr>'
            subheader = '<tr><td colspan="4">' + \
                        settings[var]['description'] + \
                        '</td><td style="display: none;"></td><td style="display: none;"></td><td style="display: none;"></td></tr>'
            edit = '<td></td>'
            editsettings = '<td></td>'
            _typearea = var
            _field = settings[var]['field']
            _quick = settings[var].get('quickview', False)
            _quicksett = settings[var].get('quickview_settings', False)

            for output in mapping[var]:
                quickadd, quickline = '', ''
                mode = output.get('mode', _typearea)
                if settings[var]['could_edit']:
                    edit = '<td><a href="config?type=' + str(mode) + '&area=' + str(
                        _typearea) + '&block=fields&edit=' + str(output[_field]) + '">[Edit]</a></td>'
                else:
                    edit = '<td></td>'
                if settings[var]['has_settings'] in ('true'):
                    editsettings = '<td><a href="config?type=' + str(mode) + '&area=' + str(
                        _typearea) + '&block=settings&edit=' + str(output[_field]) + '">[Edit Settings]</a></td>'
                else:
                    editsettings = '<td></td>'
                delete = '<td><a href="delsetting?type=' + str(mode) + '&area=' + str(
                    _typearea) + '&block=settings&edit=' + str(output[_field]) + '&del=true">[Delete]</a></td>'

                line = line + '<tr><td><b>' + \
                       str(output[_field]) + '</b></td>' + str(edit) + \
                       str(editsettings) + str(delete) + '</tr>'

                if _quick == 'setup':
                    quickadd = 'Assigned areas: ' + \
                               str(len(output.get('setup', []))) + '<br />Areas: '
                    for area in output.get('setup', []):
                        quickadd = quickadd + area.get('walkerarea') + ' | '

                    quickline = quickline + '<tr><td></td><td colspan="3" class="quick">' + \
                                str(
                                    quickadd) + ' </td><td style="display: none;"></td><td style="display: none;"></td><td style="display: none;"></td>'

                elif _quick:
                    for quickfield in _quick.split('|'):
                        if output.get(quickfield, False):
                            quickadd = quickadd + \
                                       str(quickfield) + ': ' + \
                                       str(output.get(quickfield, '')).split(
                                           '\n')[0] + '<br>'
                    quickline = quickline + '<tr><td></td><td class="quick">' + \
                                str(quickadd) + '</td>'

                quickadd = ''
                if _quicksett:
                    for quickfield in _quicksett.split('|'):
                        if output['settings'].get(quickfield, False):
                            quickadd = quickadd + \
                                       str(quickfield) + ': ' + \
                                       str(output['settings'].get(
                                           quickfield, '')) + '<br>'
                    quickline = quickline + '<td colspan="2" class="quick">' + \
                                str(quickadd) + '</td><td style="display: none;"></td></tr>'

                line = line + quickline

            table = table + header + subheader + line

        return render_template('settings.html',
                               settings='<table>' + globalheader + '<tbody>' + table + '</tbody></table>',
                               title="Mapping Editor", responsive=str(self._args.madmin_noresponsive).lower(),
                               running_ocr=(self._args.only_ocr))

    @auth_required
    def addnew(self):
        area = request.args.get('area')
        line = ''
        with open('madmin/static/vars/vars_parser.json') as f:
            settings = json.load(f)
        if (len(settings[area])) == 1:
            return redirect(getBasePath(request) + '/config?type=' + area + '&area=' + area + '&block=fields', code=302)

        for output in settings[area]:
            line = line + '<h3><a href="config?type=' + str(output['name']) + '&area=' + str(
                area) + '&block=fields">' + str(output['name']) + '</a></h3><h5>' + str(
                output['description']) + '</h5><hr>'

        return render_template('sel_type.html', line=line, title="Type selector", running_ocr=(self._args.only_ocr))

    @auth_required
    def showmonsidpicker(self):
        edit = request.args.get('edit')
        type = request.args.get('type')
        header = ""
        title = ""

        if request.method == 'GET' and (not edit or not type):
            return render_template('showmonsidpicker.html', error_msg="How did you end up here? Missing params.",
                                   header=header, title=title)

        with open('configs/mappings.json') as f:
            mapping = json.load(f)

        if "areas" not in mapping:
            return render_template('showmonsidpicker.html',
                                   error_msg="No areas defined at all, please configure first.", header=header,
                                   title=title)

        this_area = None
        this_area_index = -1
        for t_area in mapping["areas"]:
            this_area_index += 1
            if t_area["name"] == edit and t_area["mode"] == type:
                this_area = t_area
                break

        if this_area == None:
            return render_template('showmonsidpicker.html',
                                   error_msg="No area (" + edit + " with mode: " + type + ") found in mappings, add it first.",
                                   header=header, title=title)

        title = "Mons ID Picker for " + edit
        header = "Editing area " + edit + " (" + type + ")"
        backurl = "config?type=" + type + "&area=areas&block=settings&edit=" + edit

        if "settings" not in this_area:
            return render_template('showmonsidpicker.html',
                                   error_msg="No settings key found for area " + edit + "(" + type + "). Configure it first.",
                                   header=header, title=title)

        if request.method == 'POST':
            new_mons_list = request.form.get('current_mons_list')
            if not new_mons_list:
                return redirect("/showsettings", code=302)

            mapping["areas"][this_area_index]["settings"]["mon_ids_iv"] = ast.literal_eval(new_mons_list)

            with open('configs/mappings.json', 'w') as outfile:
                json.dump(mapping, outfile, indent=4, sort_keys=True)
            return redirect(backurl, code=302)

        if "mon_ids_iv" not in this_area["settings"]:
            current_mons = []
        else:
            current_mons = this_area["settings"]["mon_ids_iv"]

        mondata = open_json_file('pokemon')

        current_mons_list = []

        for mon_id in current_mons:
            try:
                mon_name = i8ln(mondata[str(mon_id)]["name"])
            except KeyError:
                mon_name = "No-name-in-file-please-fix"
            current_mons_list.append({"mon_name": mon_name, "mon_id": str(mon_id)})

        # Why o.O
        stripped_mondata = {}
        for mon_id in mondata:
            stripped_mondata[mondata[str(mon_id)]["name"]] = mon_id
            if os.environ['LANGUAGE'] != "en":
                try:
                    localized_name = i8ln(mondata[str(mon_id)]["name"])
                    stripped_mondata[localized_name] = mon_id
                except KeyError:
                    pass

        formhiddeninput = '<form action="showmonsidpicker?edit=' + edit + '&type=' + type + '" id="showmonsidpicker" method="post">'
        formhiddeninput += '<input type="hidden" id="current_mons_list" name="current_mons_list" value="' + str(
            current_mons) + '">'
        formhiddeninput += '<button type="submit" class="btn btn-success">Save</button></form>'
        return render_template('showmonsidpicker.html', backurl=backurl, formhiddeninput=formhiddeninput,
                               current_mons_list=current_mons_list, stripped_mondata=stripped_mondata, header=header,
                               title=title)