コード例 #1
0
def get_running_mission() -> typing.Union['MissionPath', str]:
    """

    Returns: currently running mission as a MissionPath instance

    """
    mission = None
    if core.Status.mission_file and core.Status.mission_file != 'unknown':
        mission_path = Path(core.Status.mission_file)
        if mission_path.parent == 'AUTO':
            mission_path = Path(mission_path.parent.parent, mission_path.name)
        mission = MissionPath(mission_path)

    else:
        try:
            dcs_settings = _get_settings_file_path().read_text()
        except FileNotFoundError:
            LOGGER.error(
                'please start a DCS server at least once before using ESST')
            sys.exit(1)
        else:
            for line in dcs_settings.split('\n'):
                if '[1]' in line:
                    mission = MissionPath(line.split('"')[1])
                    break

    if mission:
        LOGGER.debug('returning active mission: %s', mission.name)
        return mission

    LOGGER.error('current mission is "%s", but that file does not exist',
                 mission)
    return ''
コード例 #2
0
ファイル: dcs.py プロジェクト: theendsofinvention/esst
 def _command():
     if self.app.nice() != self.valid_priorities[
             DCSConfig.DCS_CPU_PRIORITY()]:
         LOGGER.debug('setting DCS process priority to: %s',
                      DCSConfig.DCS_CPU_PRIORITY())
         self.app.nice(
             self.valid_priorities[DCSConfig.DCS_CPU_PRIORITY()])
コード例 #3
0
    async def on_ready(self):
        """
        Triggers when the bot is ready.
        """
        if not self.ready:
            self._user = self.client.user
            await self._update_profile()
            LOGGER.debug('Logged in as: %s', self.client.user.name)
            try:
                self._server = set(self.client.servers).pop()
            except KeyError:
                LOGGER.error('Your discord bot has not server to connect to\n'
                             'Go to https://discordapp.com/developers/applications/me to create a bot, and note '
                             'the client ID.\n'
                             'Use the client ID in the following URL to join you bot to your Discord server:\n'
                             'https://discordapp.com/oauth2/authorize?client_id=CLIENT_ID&scope=bot')
            else:
                self._member = self.server.get_member(self.user.id)
                if self.user.display_name != DiscordBotConfig.DISCORD_BOT_NAME():
                    await self.client.change_nickname(self.member, DiscordBotConfig.DISCORD_BOT_NAME())
                await self._update_presence()

            await self.get_channel()

            self._ready = True
コード例 #4
0
def _write_dedi_config():
    dedi_cfg_path = Path(FS.variant_saved_games_path, 'Config/dedicated.lua')
    if not dedi_cfg_path.exists():
        LOGGER.info('writing %s', dedi_cfg_path)
        dedi_cfg_path.write_text(DEDI_CFG)
    else:
        LOGGER.debug('file already exists: %s', dedi_cfg_path)
コード例 #5
0
 async def _run(self):
     if CTX.discord_can_start:
         LOGGER.debug('starting Discord client')
         self._create_client()
         await self.client.start(DiscordBotConfig.DISCORD_TOKEN())
     else:
         await asyncio.sleep(1)
コード例 #6
0
ファイル: listener.py プロジェクト: theendsofinvention/esst
    async def run(self):
        """
        Infinite loop that manages a UDP socket and does two things:

        1. Retrieve incoming messages from DCS and update :py:class:`esst.core.status.status`
        2. Sends command to the DCS application via the socket
        """
        if not CTX.start_listener_loop:
            LOGGER.debug('skipping startup of socket loop')
            return

        try:
            self.sock.bind(self.server_address)
        except socket.error as exc:
            if exc.errno == 10048:
                LOGGER.error(
                    'cannot bind socket, maybe another instance of ESST is already running?'
                )
                sys.exit(-1)

        self.sock.settimeout(1)

        while not CTX.exit:
            await self._read_socket()
            await self._parse_commands()
            await self._monitor_server_startup()
            await self._monitor_server()
            await asyncio.sleep(0.1)

        self.sock.close()
        LOGGER.debug('end of listener loop')
コード例 #7
0
ファイル: sentry.py プロジェクト: theendsofinvention/esst
    def captureException(self, exc_info=None, **kwargs):
        """Captures an exception"""
        self.set_context()

        LOGGER.debug('capturing exception')
        for k, context_provider in self.registered_contexts.items():
            self.extra_context({k: context_provider.get_context()})
        super(Sentry, self).captureException(exc_info, **kwargs)
コード例 #8
0
 def write_settings_file(self):
     """
     Writes currently known station to UR settings file
     """
     LOGGER.debug('writing UR settings to: %s', FS.ur_voice_settings_file)
     stations = '\n'.join(self._stations)
     full_text = f'Start of VSS DB\n{stations}\nEnd of VSS DB'
     FS.ur_voice_settings_file.write_text(full_text)
コード例 #9
0
def _get_ur_install_path_from_registry() -> typing.Union[Path, None]:
    LOGGER.debug('searching for base "Saved Games" folder')
    try:
        with winreg.OpenKey(A_REG, r"Software\sSoft\UniversRadio") as key:
            # noinspection SpellCheckingInspection
            return Path(winreg.QueryValueEx(key, "Install_Dir")[0])
    except FileNotFoundError:
        return None
コード例 #10
0
 def poll():
     """
     Checks that UR voice service is running
     """
     LOGGER.debug('polling UR voice service')
     proc = psutil.Process(URVoiceService.pid)
     if not proc.status() == psutil.STATUS_RUNNING:
         raise RuntimeError('UR voice service stopped')
コード例 #11
0
ファイル: dcs.py プロジェクト: theendsofinvention/esst
 async def _try_to_connect_to_existing_dcs_application(self):
     if self.app and self.app.is_running():
         return
     LOGGER.debug('connecting to existing DCS application')
     await self._check_if_dcs_is_running()
     if self.process_pid:
         self._app = psutil.Process(self.process_pid)
         await self._wait_for_dcs_to_start()
コード例 #12
0
ファイル: commands.py プロジェクト: theendsofinvention/esst
 def _queue_kill(queue: Queue):
     while DCS.there_are_connected_players():
         if not queue.empty():
             queue.get_nowait()
             LOGGER.debug('queued DCS kill has been cancelled')
             return
         time.sleep(5)
     LOGGER.info('executing planned DCS restart')
     DCS.kill()
コード例 #13
0
ファイル: commands.py プロジェクト: theendsofinvention/esst
    def send_file(file_path: str):
        """
        Sends a file to the active channel

        Args:
            file_path: path to the file to send

        """
        LOGGER.debug('sending file to Discord: %s', file_path)
        CTX.discord_file_queue.put(file_path)
コード例 #14
0
ファイル: server.py プロジェクト: theendsofinvention/esst
    async def run(self):
        """
        Entry point of the loop
        """
        if not CTX.start_server_loop:
            LOGGER.debug('skipping server loop')
            return
        CTX.loop.run_in_executor(None, self._update_status)

        LOGGER.debug('end of Server computer loop')
コード例 #15
0
ファイル: listener.py プロジェクト: theendsofinvention/esst
 async def _parse_commands(self):
     await asyncio.sleep(0.1)
     if not CTX.listener_cmd_queue.empty():
         command = CTX.listener_cmd_queue.get_nowait()
         if command not in KNOWN_COMMANDS:
             raise ValueError(f'unknown command: {command}')
         else:
             command = {'cmd': command}
             command = json.dumps(command) + '\n'
             LOGGER.debug('sending command via socket: %s', command)
             self.cmd_sock.sendto(command.encode(), self.cmd_address)
コード例 #16
0
ファイル: init.py プロジェクト: theendsofinvention/esst
def init_atis_module():
    """
    Initialize the ATIS module
    """
    LOGGER.info('initializing ATIS module')
    discover_ur_install_path()
    if CTX.sentry:
        LOGGER.debug('registering ATIS contexts for Sentry')
        CTX.sentry.register_context(context_name='ATIS', context_provider=_ATISStatus)
        CTX.sentry.register_context(context_name='UR', context_provider=_URStatus)
    elib_wx.Config.dummy_icao_code = ATISConfig.DEFAULT_ICAO()
コード例 #17
0
ファイル: game_gui.py プロジェクト: theendsofinvention/esst
def install_game_gui_hooks():
    """
    Installs the GameGUI hooks in DCS Scripts folder
    """
    _remove_old_file()

    if CTX.dcs_install_hooks:
        LOGGER.debug('installing GameGUI hooks')
        _install_hook()
    else:
        LOGGER.debug('skipping installation of GameGUI hooks')
コード例 #18
0
ファイル: dcs.py プロジェクト: theendsofinvention/esst
    async def _wait_for_dcs_to_start(self):
        async def _wait_for_process():
            while True:
                if core.CTX.exit:
                    return
                await asyncio.sleep(0.1)
                if self.app.is_running():
                    break

        LOGGER.debug('waiting for DCS to spool up')
        await _wait_for_process()
        LOGGER.debug('process is ready')
コード例 #19
0
ファイル: commands.py プロジェクト: theendsofinvention/esst
    def there_are_connected_players() -> bool:
        """

        Returns: bool indicating if there are connected players
        """
        connected_players = bool(Status.players)
        if connected_players:
            LOGGER.debug('there are %s connected player(s)',
                         len(Status.players))
        else:
            LOGGER.debug('there is no connected players')
        return connected_players
コード例 #20
0
ファイル: dcs.py プロジェクト: theendsofinvention/esst
        async def _no_more_mr_nice_guy():
            if not self.app or not self.app.is_running():
                return True
            LOGGER.debug('killing dcs.exe application')
            self.app.kill()
            now_ = utils.now()
            while self.app.is_running():
                await asyncio.sleep(1)
                if utils.now() - now_ > 10:
                    return False

            return True
コード例 #21
0
ファイル: github.py プロジェクト: theendsofinvention/esst
def _make_request(endpoint):
    url = f'{BASE_URL}{endpoint}'
    LOGGER.debug(url)
    req = requests.get(url)
    if req.ok:
        return json.loads(req.text or req.content)
    if req.text or req.content:
        resp = json.loads(req.text or req.content)
        if resp['message']:
            raise ConnectionError(
                f'Request failed: {url}\nMessage: {resp["message"]}')

    raise ConnectionError(f'Request failed: {url}')
コード例 #22
0
def set_active_mission(mission_path_as_str: str, metar: str = None):
    """
    Sets the mission as active in "serverSettings.lua"

    Args:
        mission_path_as_str: path or name of the MIZ file
        metar: METAR string for this mission
    """
    LOGGER.debug('setting active mission: %s', mission_path_as_str)
    if metar:
        LOGGER.debug('using METAR: %s', metar)
    mission_path = MissionPath(mission_path_as_str)
    mission_path.set_as_active(metar)
コード例 #23
0
ファイル: dcs.py プロジェクト: theendsofinvention/esst
 async def _get_dcs_version_from_executable(self):
     # noinspection PyBroadException
     core.Status.dcs_version = utils.get_product_version(str(FS.dcs_exe))
     LOGGER.debug('DCS version: %s', core.Status.dcs_version)
     simplified_version = int(''.join(
         core.Status.dcs_version.split('.')[:3]))
     LOGGER.debug('simplified version: %s', simplified_version)
     if simplified_version <= 157:
         pass
     elif simplified_version >= 158:
         mission_editor_lua.inject_mission_editor_code()
         autoexec_cfg.inject_silent_crash_report()
     setup_config_for_dedicated_run()
     return True
コード例 #24
0
ファイル: server.py プロジェクト: theendsofinvention/esst
    def __init__(self):

        if not CTX.start_server_loop:
            LOGGER.debug('skipping server loop init')
            return

        ServerStatus.logical_cpus = psutil.cpu_count()
        ServerStatus.physical_cpus = psutil.cpu_count(logical=False)
        ServerStatus.cpu_frequency = psutil.cpu_freq().max
        ServerStatus.total_memory = psutil.virtual_memory().total
        ServerStatus.swap_size = psutil.swap_memory().total
        ServerStatus.boot_time = datetime.datetime.fromtimestamp(
            psutil.boot_time()
        ).strftime("%Y-%m-%d %H:%M:%S")
コード例 #25
0
def inject_silent_crash_report() -> bool:
    """
    Injects code needed for the new login method in MissionEditor.lua

    :return: success of the operation
    :rtype: bool
    """

    FS.ensure_path(FS.saved_games_path, 'saved games')
    autoexec_path = FS.ensure_path(FS.dcs_autoexec_file,
                                   'dcs autoexec file',
                                   must_exist=False)
    utils.create_versioned_backup(autoexec_path, file_must_exist=False)

    if autoexec_path.exists():
        LOGGER.debug('autoexec.cfg already exists, reading')
        content = autoexec_path.read_text(encoding='utf8')
    else:
        LOGGER.debug('autoexec.cfg does not exist, creating')
        content = ''

    if _SILENT_CRASH_REPORT in content:
        LOGGER.debug('silent crash report already enabled')
        return True

    content = f'{content}{_SILENT_CRASH_REPORT}'
    LOGGER.debug('writing new "autoexec.cfg" content: %s', content)
    autoexec_path.write_text(content)
    return True
コード例 #26
0
def get_latest_mission_from_github():
    """
    Downloads the latest mission from a Github repository

    The repository needs to have releases (tagged)
    The function will download the first MIZ file found in the latest release
    """
    if core.CTX.dcs_auto_mission:
        LOGGER.debug('getting latest mission from Github')
        commands.DCS.block_start('loading mission')
        if DCSConfig.DCS_AUTO_MISSION_GH_OWNER(
        ) and DCSConfig.DCS_AUTO_MISSION_GH_REPO():
            LOGGER.debug('looking for newer mission file')
            latest_version, asset_name, download_url = utils.get_latest_release(
                DCSConfig.DCS_AUTO_MISSION_GH_OWNER(),
                DCSConfig.DCS_AUTO_MISSION_GH_REPO())
            LOGGER.debug('latest release: %s', latest_version)
            local_file = MissionPath(Path(_get_mission_folder(), asset_name))
            if not local_file:
                LOGGER.info('downloading new mission: %s', asset_name)
                req = requests.get(download_url)
                if req.ok:
                    local_file.path.write_bytes(req.content)
                    local_file.set_as_active()
                else:
                    LOGGER.error('failed to download latest mission')
        else:
            LOGGER.warning('no config values given for [auto mission]')
        commands.DCS.unblock_start('loading mission')
    else:
        LOGGER.debug('skipping mission update')
コード例 #27
0
def initial_setup():
    """
    Runs at the start of the DCS loop, to initialize the first mission
    """
    LOGGER.debug('initializing first mission')
    mission = get_running_mission()
    if isinstance(mission, MissionPath):
        LOGGER.info('building METAR for initial mission: %s',
                    mission.orig_name)
        weather = elib_wx.Weather(str(mission.path))
        core.Status.metar = weather
        esst.atis.create.generate_atis(weather)
    else:
        LOGGER.error('no initial mission found')
コード例 #28
0
def write_server_settings(mission_file_path: typing.Optional[str] = None) -> None:
    """
    Write "serverSettings.lua"
    :param mission_file_path: path to the mission file to set as active
    :type mission_file_path: str or None
    """
    LOGGER.debug('writing server settings')
    if mission_file_path is None:
        LOGGER.debug('no mission file given, using current mission')
        _mission_file_path = _get_current_mission_path()
    else:
        _mission_file_path = mission_file_path
    LOGGER.debug('mission file path: %s', _mission_file_path)
    template_option = dict(
        mission_file_path=_mission_file_path,
        is_public=str(DCSServerConfig.public()).lower(),
        description=DCSServerConfig.description(),
        require_pure_textures=str(DCSServerConfig.requires_pure_textures()).lower(),
        allow_change_tailno=str(DCSServerConfig.allow_change_tail_number()).lower(),
        allow_ownship_export=str(DCSServerConfig.allow_export_own_ship()).lower(),
        allow_object_export=str(DCSServerConfig.allow_export_objects()).lower(),
        pause_on_load=str(DCSServerConfig.pause_on_load()).lower(),
        allow_sensor_export=str(DCSServerConfig.allow_export_sensors()).lower(),
        event_Takeoff=str(DCSServerConfig.report_takeoff()).lower(),
        pause_without_clients=str(DCSServerConfig.pause_without_client()).lower(),
        client_outbound_limit=DCSServerConfig.outbound_limit(),
        client_inbound_limit=DCSServerConfig.inbound_limit(),
        event_Role=str(DCSServerConfig.report_role_change()).lower(),
        allow_change_skin=str(DCSServerConfig.allow_change_skin()).lower(),
        event_Connect=str(DCSServerConfig.report_connect()).lower(),
        event_Ejecting=str(DCSServerConfig.report_eject()).lower(),
        event_Kill=str(DCSServerConfig.report_kill()).lower(),
        event_Crash=str(DCSServerConfig.report_crash()).lower(),
        resume_mode=DCSServerConfig.pause_resume_mode(),
        maxPing=DCSServerConfig.max_ping(),
        require_pure_models=str(DCSServerConfig.requires_pure_models()).lower(),
        require_pure_clients=str(DCSServerConfig.requires_pure_clients()).lower(),
        name=DCSServerConfig.name(),
        port=DCSServerConfig.port(),
        password=DCSServerConfig.password(),
        bind_address=DCSServerConfig.bind_address(),
        maxPlayers=DCSServerConfig.max_players()
    )
    LOGGER.debug('rendering settings.lua template with options\n%s', pprint.pformat(template_option))
    content = Template(utils.read_template('settings.lua')).render(**template_option)
    server_settings = _get_server_settings_path()
    LOGGER.debug('settings file path: %s', server_settings)
    utils.create_versioned_backup(server_settings)
    server_settings.write_text(content)
コード例 #29
0
ファイル: commands.py プロジェクト: theendsofinvention/esst
    def restart(force: bool = False):
        """
        Sets the context to restart the DCS application

        Returns: None if restart is OK, err as a str otherwise

        """
        CANCEL_QUEUED_KILL.put(1)
        if DCS.there_are_connected_players() and not force:
            LOGGER.error(
                'there are connected players; cannot restart the server now '
                ' (use "--force" to kill anyway)')
            return
        LOGGER.debug('setting context for DCS restart')
        CTX.dcs_do_restart = True
コード例 #30
0
ファイル: dcs.py プロジェクト: theendsofinvention/esst
    async def _start_new_dcs_application_if_needed(self):
        async def _start_dcs_app():
            LOGGER.debug('starting DCS application process: %s', FS.dcs_exe)
            self._app = psutil.Popen(str(FS.dcs_exe))

        if self.app and self.app.is_running():
            return
        LOGGER.debug('starting new DCS application')
        cmd_chain = [
            _start_dcs_app,
            self._wait_for_dcs_to_start,
        ]
        # rotate_dcs_log()
        await self._execute_cmd_chain(cmd_chain)
        await self._check_if_dcs_is_running()