コード例 #1
0
async def test_meta_miniprofile_pair_utf8():
    level_db_parser = LevelDbParser(12345678)
    db_log_directory = os.path.dirname(os.path.abspath(__file__))
    open_db_log = level_db_parser._read_db_log_file(db_log_directory, 'utf-8')
    user_json_start, user_json_end, encoding = level_db_parser._find_last_meta_miniprofile_pair(
        open_db_log)

    assert user_json_start == USER_JSON_START_UTF8 and user_json_end == USER_JSON_END_UTF8
コード例 #2
0
async def test_read_db_file_utf8():
    level_db_parser = LevelDbParser(12345678)
    db_log_directory = os.path.dirname(os.path.abspath(__file__))
    open_db_log = level_db_parser._read_db_log_file(db_log_directory)

    open_db_log = open_db_log.encode('utf-8')
    open_db_log = hashlib.md5(open_db_log)
    open_db_log = open_db_log.digest()

    assert open_db_log == PARSED_LVLDB_UTF8_MD5
コード例 #3
0
async def test_retrieve_jsons():
    level_db_parser = LevelDbParser(12345678)
    db_log_directory = os.path.dirname(os.path.abspath(__file__))
    open_db_log = level_db_parser._read_db_log_file(db_log_directory,
                                                    'utf-16-le')
    user_json_start, user_json_end, encoding = level_db_parser._find_last_meta_miniprofile_pair(
        open_db_log)

    collections_list = level_db_parser._retrieve_jsons(open_db_log,
                                                       user_json_start,
                                                       user_json_end)

    collections_list = json.dumps(collections_list)
    collections_list = collections_list.encode('utf-16-le')
    hash = hashlib.md5(collections_list)

    assert hash.digest() == RETRIEVED_JSONS_MD5
コード例 #4
0
    async def prepare_game_library_settings_context(
            self, game_ids: List[str]) -> Any:
        if self._steam_id is None:
            raise AuthenticationRequired()

        if not self._level_db_parser:
            self._level_db_parser = LevelDbParser(self._miniprofile_id)

        self._level_db_parser.parse_leveldb()

        if not self._level_db_parser.lvl_db_is_present:
            return None
        else:
            leveldb_static_games_collections_dict = self._level_db_parser.get_static_collections_tags(
            )
            logger.info(
                f"Leveldb static settings dict {leveldb_static_games_collections_dict}"
            )
            return leveldb_static_games_collections_dict
コード例 #5
0
class SteamPlugin(Plugin):
    def __init__(self, reader, writer, token):
        super().__init__(Platform.Steam, __version__, reader, writer, token)
        self._steam_id = None
        self._miniprofile_id = None
        self._level_db_parser = None
        self._regmon = get_steam_registry_monitor()
        self._local_games_cache: Optional[List[LocalGame]] = None
        self._ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
        self._ssl_context.load_verify_locations(certifi.where())
        self._http_client = AuthenticatedHttpClient()
        self._client = SteamHttpClient(self._http_client)
        self._persistent_storage_state = PersistentCacheState()
        self._servers_cache = ServersCache(self._client, self._ssl_context,
                                           self.persistent_cache,
                                           self._persistent_storage_state)
        self._friends_cache = FriendsCache()
        self._games_cache = GamesCache()
        self._translations_cache = dict()
        self._steam_client = WebSocketClient(self._client, self._ssl_context,
                                             self._servers_cache,
                                             self._friends_cache,
                                             self._games_cache,
                                             self._translations_cache)
        self._achievements_cache = Cache()
        self._achievements_cache_updated = False

        self._achievements_semaphore = asyncio.Semaphore(20)
        self._tags_semaphore = asyncio.Semaphore(5)

        self._library_settings_import_iterator = 0
        self._last_launch: Timestamp = 0

        self._update_local_games_task = None
        self._update_owned_games_task = None
        self._owned_games_parsed = None

        def user_presence_update_handler(user_id: str, user_info: UserInfo):
            self.update_user_presence(
                user_id, from_user_info(user_info, self._translations_cache))

        self._friends_cache.updated_handler = user_presence_update_handler

    def _store_cookies(self, cookies):
        credentials = {"cookies": morsels_to_dicts(cookies)}
        self.store_credentials(credentials)

    @staticmethod
    def _create_two_factor_fake_cookie():
        return Cookie(
            # random SteamID with proper "instance", "type" and "universe" fields
            # (encoded in most significant bits)
            name="steamMachineAuth{}".format(
                random.randint(1, 2**32 - 1) + 0x01100001 * 2**32),
            # 40-bit random string encoded as hex
            value=hex(random.getrandbits(20 * 8))[2:].upper())

    async def shutdown(self):
        self._regmon.close()
        await self._steam_client.close()
        await self._http_client.close()
        await self._steam_client.wait_closed()

    def handshake_complete(self):
        achievements_cache_ = self.persistent_cache.get("achievements")
        if achievements_cache_ is not None:
            try:
                achievements_cache_ = json.loads(achievements_cache_)
                self._achievements_cache = achievements_cache.from_dict(
                    achievements_cache_)
            except Exception:
                logger.exception("Can not deserialize achievements cache")

    async def _do_auth(self, morsels):
        cookies = [(morsel.key, morsel) for morsel in morsels]

        self._http_client.update_cookies(cookies)
        self._http_client.set_cookies_updated_callback(self._store_cookies)
        self._force_utc()

        try:
            profile_url = await self._client.get_profile()
        except UnknownBackendResponse:
            raise InvalidCredentials()

        async def set_profile_data(profile_url):
            try:
                self._steam_id, self._miniprofile_id, login = await self._client.get_profile_data(
                    profile_url)
                self.create_task(self._steam_client.run(),
                                 "Run WebSocketClient")
                return login
            except AccessDenied:
                raise InvalidCredentials()

        try:
            login = await set_profile_data(profile_url)
        except UnfinishedAccountSetup:
            await self._client.setup_steam_profile(profile_url)
            login = await set_profile_data(profile_url)

        self._http_client.set_auth_lost_callback(self.lost_authentication)

        if "steamRememberLogin" in (cookie[0] for cookie in cookies):
            logging.debug("Remember login cookie present")
        else:
            logging.debug("Remember login cookie not present")

        return Authentication(self._steam_id, login)

    def _force_utc(self):
        cookies = SimpleCookie()
        cookies["timezoneOffset"] = "0,0"
        morsel = cookies["timezoneOffset"]
        morsel["domain"] = "steamcommunity.com"
        # override encoding (steam does not fallow RFC 6265)
        morsel.set("timezoneOffset", "0,0", "0,0")
        self._http_client.update_cookies(cookies)

    async def authenticate(self, stored_credentials=None):
        if not stored_credentials:
            if await self._client.get_steamcommunity_response_status() != 200:
                logger.error("Steamcommunity website not accessible")
            return NextStep("web_session", AUTH_PARAMS,
                            [self._create_two_factor_fake_cookie()],
                            {re.escape(LOGIN_URI): [JS_PERSISTENT_LOGIN]})

        cookies = stored_credentials.get("cookies", [])
        morsels = parse_stored_cookies(cookies)
        return await self._do_auth(morsels)

    async def pass_login_credentials(self, step, credentials, cookies):
        try:
            morsels = dicts_to_morsels(cookies)
        except Exception:
            raise InvalidParams()

        auth_info = await self._do_auth(morsels)
        self._store_cookies(morsels)
        return auth_info

    async def get_owned_games(self):
        if self._steam_id is None:
            raise AuthenticationRequired()

        await self._games_cache.wait_ready(90)
        owned_games = []
        self._games_cache.add_game_lever = True
        try:
            for game_id, game_title in self._games_cache:
                owned_games.append(
                    Game(str(game_id), game_title, [],
                         LicenseInfo(LicenseType.SinglePurchase, None)))
        except (KeyError, ValueError):
            logger.exception("Can not parse backend response")
            raise UnknownBackendResponse()
        finally:
            self._owned_games_parsed = True

        return owned_games

    async def prepare_game_times_context(self, game_ids: List[str]) -> Any:
        if self._steam_id is None:
            raise AuthenticationRequired()

        return await self._get_game_times_dict()

    async def get_game_time(self, game_id: str, context: Any) -> GameTime:
        game_time = context.get(game_id)
        if game_time is None:
            raise UnknownError("Game {} not owned".format(game_id))
        return game_time

    async def _get_game_times_dict(self) -> Dict[str, GameTime]:
        games = await self._client.get_games(self._steam_id)

        game_times = {}

        try:
            for game in games:
                game_id = str(game["appid"])
                last_played = game.get("last_played")
                if last_played == 86400:
                    # 86400 is used as sentinel value for games no supporting last_played
                    last_played = None
                game_times[game_id] = GameTime(
                    game_id,
                    int(
                        float(game.get("hours_forever", "0").replace(",", ""))
                        * 60), last_played)
        except (KeyError, ValueError):
            logger.exception("Can not parse backend response")
            raise UnknownBackendResponse()

        return game_times

    async def prepare_game_library_settings_context(
            self, game_ids: List[str]) -> Any:
        if self._steam_id is None:
            raise AuthenticationRequired()

        if not self._level_db_parser:
            self._level_db_parser = LevelDbParser(self._miniprofile_id)

        self._level_db_parser.parse_leveldb()

        if not self._level_db_parser.lvl_db_is_present:
            return None
        else:
            leveldb_static_games_collections_dict = self._level_db_parser.get_static_collections_tags(
            )
            logger.info(
                f"Leveldb static settings dict {leveldb_static_games_collections_dict}"
            )
            return leveldb_static_games_collections_dict

    async def get_game_library_settings(self, game_id: str,
                                        context: Any) -> GameLibrarySettings:
        if not context:
            return GameLibrarySettings(game_id, None, None)
        else:
            game_tags = context.get(game_id)
            if not game_tags:
                return GameLibrarySettings(game_id, [], False)

            hidden = False
            for tag in game_tags:
                if tag.lower() == 'hidden':
                    hidden = True
            if hidden:
                game_tags.remove('hidden')
            return GameLibrarySettings(game_id, game_tags, hidden)

    async def prepare_achievements_context(self, game_ids: List[str]) -> Any:
        if self._steam_id is None:
            raise AuthenticationRequired()

        return await self._get_game_times_dict()

    async def get_unlocked_achievements(self, game_id: str,
                                        context: Any) -> List[Achievement]:
        game_time = await self.get_game_time(game_id, context)

        fingerprint = achievements_cache.Fingerprint(
            game_time.last_played_time, game_time.time_played)
        achievements = self._achievements_cache.get(game_id, fingerprint)

        if achievements is not None:
            # return from cache
            return achievements

        # fetch from backend and update cache
        achievements = await self._get_achievements(game_id)
        self._achievements_cache.update(game_id, achievements, fingerprint)
        self._achievements_cache_updated = True
        return achievements

    def achievements_import_complete(self) -> None:
        if self._achievements_cache_updated:
            self._persistent_storage_state.modified = True
            self._achievements_cache_updated = False

    async def _get_achievements(self, game_id):
        async with self._achievements_semaphore:
            achievements = await self._client.get_achievements(
                self._steam_id, game_id)
            return [
                Achievement(unlock_time, None, name)
                for unlock_time, name in achievements
            ]

    async def get_friends(self):
        if self._steam_id is None:
            raise AuthenticationRequired()

        return await self._client.get_friends(self._steam_id)

    async def prepare_user_presence_context(self, user_ids: List[str]) -> Any:
        return await self._steam_client.get_friends_info(user_ids)

    async def get_user_presence(self, user_id: str,
                                context: Any) -> UserPresence:
        user_info = context.get(user_id)
        if user_info is None:
            raise UnknownError(
                "User {} not in friend list (plugin only supports fetching presence for friends)"
                .format(user_id))

        return from_user_info(user_info, self._translations_cache)

    async def _update_owned_games(self):
        new_games = self._games_cache.get_added_games()
        iter = 0
        for game in new_games:
            iter += 1
            self.add_game(
                Game(game,
                     new_games[game], [],
                     license_info=LicenseInfo(LicenseType.SinglePurchase)))
            if iter >= 5:
                iter = 0
                await asyncio.sleep(1)

    def tick(self):
        if self._local_games_cache is not None and \
                (self._update_local_games_task is None or self._update_local_games_task.done()) and \
                self._regmon.is_updated():
            self._update_local_games_task = self.create_task(
                self._update_local_games(), "Update local games")
        if self._update_owned_games_task is None or self._update_owned_games_task.done(
        ) and self._owned_games_parsed:
            self._update_owned_games_task = self.create_task(
                self._update_owned_games(), "Update owned games")

        if self._persistent_storage_state.modified:
            # serialize
            self.persistent_cache["achievements"] = achievements_cache.as_dict(
                self._achievements_cache)
            self.push_cache()
            self._persistent_storage_state.modified = False

    async def _update_local_games(self):
        loop = asyncio.get_running_loop()
        new_list = await loop.run_in_executor(None, local_games_list)
        notify_list = get_state_changes(self._local_games_cache, new_list)
        self._local_games_cache = new_list
        for game in notify_list:
            if LocalGameState.Running in game.local_game_state:
                self._last_launch = time.time()
            self.update_local_game_status(game)

    async def get_local_games(self):
        loop = asyncio.get_running_loop()
        self._local_games_cache = await loop.run_in_executor(
            None, local_games_list)
        return self._local_games_cache

    @staticmethod
    def _steam_command(command, game_id):
        if is_uri_handler_installed("steam"):
            webbrowser.open("steam://{}/{}".format(command, game_id))
        else:
            webbrowser.open("https://store.steampowered.com/about/")

    async def launch_game(self, game_id):
        SteamPlugin._steam_command("launch", game_id)

    async def install_game(self, game_id):
        SteamPlugin._steam_command("install", game_id)

    async def uninstall_game(self, game_id):
        SteamPlugin._steam_command("uninstall", game_id)

    async def shutdown_platform_client(self) -> None:
        launch_debounce_time = 3
        if time.time() < self._last_launch + launch_debounce_time:
            # workaround for quickly closed game (Steam sometimes dumps false positive just after a launch)
            logging.info(
                'Ignoring shutdown request because game was launched a moment ago'
            )
            return
        if is_windows():
            exe = get_client_executable()
            if exe is None:
                return
            cmd = '"{}" -shutdown -silent'.format(exe)
        else:
            cmd = "osascript -e 'quit app \"Steam\"'"
        logger.debug("Running command '%s'", cmd)
        process = await asyncio.create_subprocess_shell(
            cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
        await process.communicate()
コード例 #6
0
class SteamPlugin(Plugin):
    def __init__(self, reader, writer, token):
        super().__init__(Platform.Steam, __version__, reader, writer, token)
        self._steam_id = None
        self._miniprofile_id = None
        self._own_games: List = []
        self._family_sharing_games: List[str] = []
        self._own_friends: List[FriendInfo] = []

        self._level_db_parser = None
        self._regmon = get_steam_registry_monitor()
        self._local_games_cache: List[LocalGame] = []
        self._http_client = AuthenticatedHttpClient()
        self._client = SteamHttpClient(self._http_client)
        self._achievements_cache = Cache()
        self._achievements_cache_updated = False

        self._achievements_semaphore = asyncio.Semaphore(20)
        self._tags_semaphore = asyncio.Semaphore(5)

        self._library_settings_import_iterator = 0
        self._game_tags_cache = {}

        self._update_task = self.create_task(self._update_local_games(),
                                             "Update local games")

    def _store_cookies(self, cookies):
        credentials = {"cookies": morsels_to_dicts(cookies)}
        self.store_credentials(credentials)

    @staticmethod
    def _create_two_factor_fake_cookie():
        return Cookie(
            # random SteamID with proper "instance", "type" and "universe" fields
            # (encoded in most significant bits)
            name="steamMachineAuth{}".format(
                random.randint(1, 2**32 - 1) + 0x01100001 * 2**32),
            # 40-bit random string encoded as hex
            value=hex(random.getrandbits(20 * 8))[2:].upper())

    async def shutdown(self):
        self._regmon.close()
        await self._http_client.close()

    def handshake_complete(self):
        achievements_cache_ = self.persistent_cache.get("achievements")
        if achievements_cache_ is not None:
            try:
                achievements_cache_ = json.loads(achievements_cache_)
                self._achievements_cache = achievements_cache.from_dict(
                    achievements_cache_)
            except Exception:
                logging.exception("Can not deserialize achievements cache")

    async def _do_auth(self, morsels):
        cookies = [(morsel.key, morsel) for morsel in morsels]

        self._http_client.update_cookies(cookies)
        self._http_client.set_cookies_updated_callback(self._store_cookies)
        self._force_utc()

        try:
            profile_url = await self._client.get_profile()
        except UnknownBackendResponse:
            raise InvalidCredentials()

        try:
            self._steam_id, self._miniprofile_id, login = await self._client.get_profile_data(
                profile_url)
        except AccessDenied:
            raise InvalidCredentials()

        self._http_client.set_auth_lost_callback(self.lost_authentication)

        return Authentication(self._steam_id, login)

    def _force_utc(self):
        cookies = SimpleCookie()
        cookies["timezoneOffset"] = "0,0"
        morsel = cookies["timezoneOffset"]
        morsel["domain"] = "steamcommunity.com"
        # override encoding (steam does not fallow RFC 6265)
        morsel.set("timezoneOffset", "0,0", "0,0")
        self._http_client.update_cookies(cookies)

    async def authenticate(self, stored_credentials=None):
        if not stored_credentials:
            return NextStep("web_session", AUTH_PARAMS,
                            [self._create_two_factor_fake_cookie()],
                            {re.escape(LOGIN_URI): [JS_PERSISTENT_LOGIN]})

        cookies = stored_credentials.get("cookies", [])
        morsels = parse_stored_cookies(cookies)
        return await self._do_auth(morsels)

    async def pass_login_credentials(self, step, credentials, cookies):
        try:
            morsels = dicts_to_morsels(cookies)
        except Exception:
            raise InvalidParams()

        auth_info = await self._do_auth(morsels)
        self._store_cookies(morsels)
        return auth_info

    async def get_owned_games(self):
        if self._steam_id is None:
            raise AuthenticationRequired()

        games = await self._client.get_games(self._steam_id)

        owned_games = []

        try:
            for game in games:
                owned_games.append(
                    Game(str(game["appid"]), game["name"], [],
                         LicenseInfo(LicenseType.SinglePurchase, None)))
        except (KeyError, ValueError):
            logging.exception("Can not parse backend response")
            raise UnknownBackendResponse()

        self._own_games = games

        game_ids = list(map(lambda x: x.game_id, owned_games))
        other_games = await self.get_steam_sharing_games(game_ids)
        for i in other_games:
            owned_games.append(i)

        return owned_games

    async def get_steam_sharing_games(self, owngames: List[str]) -> List[Game]:
        profiles = list(
            filter(
                lambda x: x.user_name.endswith(FRIEND_SHARING_END_PATTERN + "*"
                                               ), self._own_friends))
        newgames: List[Game] = []
        self._family_sharing_games = []
        for i in profiles:
            othergames = await self._client.get_games(i.user_id)

            try:
                for game in othergames:
                    hasit = any(f == str(game["appid"])
                                for f in owngames) or any(
                                    f.game_id == str(game["appid"])
                                    for f in newgames)
                    if not hasit:
                        self._family_sharing_games.append(str(game["appid"]))
                        newgame = Game(
                            str(game["appid"]), game["name"], [],
                            LicenseInfo(LicenseType.OtherUserLicense,
                                        i.user_name))
                        newgames.append(newgame)
            except (KeyError, ValueError):
                logging.exception("Can not parse backend response")
                raise UnknownBackendResponse()
        return newgames

    async def prepare_game_times_context(self, game_ids: List[str]) -> Any:
        if self._steam_id is None:
            raise AuthenticationRequired()

        return await self._get_game_times_dict()

    async def get_game_time(self, game_id: str, context: Any) -> GameTime:
        game_time = context.get(game_id)
        if game_time is None:
            logging.exception("Game {} not owned".format(game_id))
        return game_time

    async def _get_game_times_dict(self) -> Dict[str, GameTime]:
        games = self._own_games

        game_times = {}

        try:
            for game in games:
                game_id = str(game["appid"])
                last_played = game.get("last_played")
                if last_played == NO_LAST_PLAY:
                    last_played = None
                game_times[game_id] = GameTime(
                    game_id,
                    int(
                        float(game.get("hours_forever", "0").replace(",", ""))
                        * 60), last_played)
        except (KeyError, ValueError):
            logging.exception("Can not parse backend response")
            raise UnknownBackendResponse()

        try:
            steamFolder = get_configuration_folder()
            vdfFile = os.path.join(steamFolder, "userdata",
                                   self._miniprofile_id, "config",
                                   "localconfig.vdf")
            logging.debug(f"Users Localconfig.vdf {vdfFile}")
            data = load_vdf(vdfFile)
            timedata = data["UserLocalConfigStore"]["Software"]["Valve"][
                "Steam"]["Apps"]
            for gameid in self._family_sharing_games:
                playTime = 0
                lastPlayed = NO_LAST_PLAY
                if gameid in timedata:
                    item = timedata[gameid]
                    if 'playtime' in item:
                        playTime = item["playTime"]
                    if 'lastplayed' in item:
                        lastPlayed = item["LastPlayed"]
                game_times[gameid] = GameTime(gameid, playTime, lastPlayed)
        except (KeyError, ValueError):
            logging.exception("Can not parse friend games")

        return game_times

    async def prepare_game_library_settings_context(
            self, game_ids: List[str]) -> Any:
        if self._steam_id is None:
            raise AuthenticationRequired()

        if not self._level_db_parser:
            self._level_db_parser = LevelDbParser(self._miniprofile_id)

        self._level_db_parser.parse_leveldb()

        if not self._level_db_parser.lvl_db_is_present:
            return None
        else:
            leveldb_static_games_collections_dict = self._level_db_parser.get_static_collections_tags(
            )
            logging.info(
                f"Leveldb static settings dict {leveldb_static_games_collections_dict}"
            )
            return leveldb_static_games_collections_dict

    async def get_game_library_settings(self, game_id: str,
                                        context: Any) -> GameLibrarySettings:
        if not context:
            return GameLibrarySettings(game_id, None, None)
        else:
            game_tags = context.get(game_id)
            if not game_tags:
                return GameLibrarySettings(game_id, [], False)

            hidden = False
            for tag in game_tags:
                if tag.lower() == 'hidden':
                    hidden = True
            if hidden:
                game_tags.remove('hidden')
            return GameLibrarySettings(game_id, game_tags, hidden)

    async def prepare_achievements_context(self, game_ids: List[str]) -> Any:
        if self._steam_id is None:
            raise AuthenticationRequired()

        return await self._get_game_times_dict()

    async def get_unlocked_achievements(self, game_id: str,
                                        context: Any) -> List[Achievement]:
        game_time = await self.get_game_time(game_id, context)
        if game_time.time_played == 0:
            return []

        fingerprint = achievements_cache.Fingerprint(
            game_time.last_played_time, game_time.time_played)
        achievements = self._achievements_cache.get(game_id, fingerprint)

        if achievements is not None:
            # return from cache
            return achievements

        # fetch from backend and update cache
        achievements = await self._get_achievements(game_id)
        self._achievements_cache.update(game_id, achievements, fingerprint)
        self._achievements_cache_updated = True
        return achievements

    def achievements_import_complete(self) -> None:
        if self._achievements_cache_updated:
            self.push_cache()
            self._achievements_cache_updated = False

    async def _get_achievements(self, game_id):
        async with self._achievements_semaphore:
            achievements = await self._client.get_achievements(
                self._steam_id, game_id)
            return [
                Achievement(unlock_time, None, name)
                for unlock_time, name in achievements
            ]

    async def get_friends(self):
        if self._steam_id is None:
            raise AuthenticationRequired()

        self._own_friends = [
            FriendInfo(user_id=user_id, user_name=user_name)
            for user_id, user_name in (
                await self._client.get_friends(self._steam_id)).items()
        ]

        return self._own_friends

    def tick(self):
        if self._update_task.done() and self._regmon.is_updated():
            self._update_task = self.create_task(self._update_local_games(),
                                                 "Update local games")

    async def _update_local_games(self):
        loop = asyncio.get_running_loop()
        new_list = await loop.run_in_executor(None, local_games_list)
        notify_list = get_state_changes(self._local_games_cache, new_list)
        self._local_games_cache = new_list
        for local_game_notify in notify_list:
            self.update_local_game_status(local_game_notify)

    async def get_local_games(self):
        return self._local_games_cache

    @staticmethod
    def _steam_command(command, game_id):
        if is_uri_handler_installed("steam"):
            webbrowser.open("steam://{}/{}".format(command, game_id))
        else:
            webbrowser.open("https://store.steampowered.com/about/")

    async def launch_game(self, game_id):
        SteamPlugin._steam_command("launch", game_id)

    async def install_game(self, game_id):
        SteamPlugin._steam_command("install", game_id)

    async def uninstall_game(self, game_id):
        SteamPlugin._steam_command("uninstall", game_id)

    async def shutdown_platform_client(self) -> None:
        if is_windows():
            exe = get_client_executable()
            if exe is None:
                return
            cmd = '"{}" -shutdown -silent'.format(exe)
        else:
            cmd = "osascript -e 'quit app \"Steam\"'"
        logging.debug("Running command '%s'", cmd)
        process = await asyncio.create_subprocess_shell(
            cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
        await process.communicate()
コード例 #7
0
async def test_parser_initialization_fail():
    with pytest.raises(TypeError):
        LevelDbParser()
コード例 #8
0
async def test_parser_initialization_ok():
    LevelDbParser(12345678)