Пример #1
0
async def test_start_achievements_import(plugin, write, mocker):
    game_achievements_import_success = mocker.patch.object(
        plugin, "game_achievements_import_success")
    game_achievements_import_failure = mocker.patch.object(
        plugin, "game_achievements_import_failure")
    achievements_import_finished = mocker.patch.object(
        plugin, "achievements_import_finished")

    game_ids = ["1", "5", "9"]
    error = BackendError()
    achievements = [
        Achievement(achievement_id="lvl10", unlock_time=1548421241),
        Achievement(achievement_name="Got level 20", unlock_time=1548422395)
    ]
    plugin.get_unlocked_achievements.coro.side_effect = [
        achievements, [], error
    ]
    await plugin.start_achievements_import(game_ids)

    with pytest.raises(ImportInProgress):
        await plugin.start_achievements_import(["4", "8"])

    # wait until all tasks are finished
    for _ in range(4):
        await asyncio.sleep(0)

    plugin.get_unlocked_achievements.coro.assert_has_calls(
        [call("1"), call("5"), call("9")])
    game_achievements_import_success.assert_has_calls(
        [call("1", achievements), call("5", [])])
    game_achievements_import_failure.assert_called_once_with("9", error)
    achievements_import_finished.assert_called_once_with()
Пример #2
0
async def test_get_achievements_success(authenticated_plugin, backend_client, steam_id):
    authenticated_plugin._stats_cache = {"236850": {'achievements': [{'unlock_time': 1551887210, 'name': 'name 1'},
                                                                     {'unlock_time': 1551887134, 'name': 'name 2'}]}}
    achievements = await authenticated_plugin.get_unlocked_achievements("236850", None)
    assert achievements == [
            Achievement(1551887210, None, "name 1"),
            Achievement(1551887134, None, "name 2")
        ]
Пример #3
0
async def test_trailing_whitespace(authenticated_plugin):
    authenticated_plugin._stats_cache = {"236850": {'achievements': [{'unlock_time': 1551887210, 'name': 'name 1 '},
                                                                     {'unlock_time': 1551887134, 'name': 'name 2    '}]}}
    achievements = await authenticated_plugin.get_unlocked_achievements("236850", None)
    assert achievements == [
        Achievement(1551887210, None, "name 1"),
        Achievement(1551887134, None, "name 2")
    ]
def cache():
    cache = Cache()
    cache.update(
        "131",
        [Achievement(1563289123, "abc"),
         Achievement(1563289141, "efg")], Fingerprint(1563289641, 123))
    cache.update("871", [Achievement(156327123, "yik", "Achievement")],
                 Fingerprint(None, 13))
    return cache
async def test_get_unlocked_achievements_success(plugin, read, write):
    plugin.prepare_achievements_context.return_value = async_return_value(5)
    request = {
        "jsonrpc": "2.0",
        "id": "3",
        "method": "start_achievements_import",
        "params": {
            "game_ids": ["14"]
        }
    }
    read.side_effect = [async_return_value(create_message(request)), async_return_value(b"", 10)]
    plugin.get_unlocked_achievements.return_value = async_return_value([
        Achievement(achievement_id="lvl10", unlock_time=1548421241),
        Achievement(achievement_name="Got level 20", unlock_time=1548422395),
        Achievement(achievement_id="lvl30", achievement_name="Got level 30", unlock_time=1548495633)
    ])
    await plugin.run()
    plugin.prepare_achievements_context.assert_called_with(["14"])
    plugin.get_unlocked_achievements.assert_called_with("14", 5)
    plugin.achievements_import_complete.asert_called_with()

    assert get_messages(write) == [
        {
            "jsonrpc": "2.0",
            "id": "3",
            "result": None
        },
        {
            "jsonrpc": "2.0",
            "method": "game_achievements_import_success",
            "params": {
                "game_id": "14",
                "unlocked_achievements": [
                    {
                        "achievement_id": "lvl10",
                        "unlock_time": 1548421241
                    },
                    {
                        "achievement_name": "Got level 20",
                        "unlock_time": 1548422395
                    },
                    {
                        "achievement_id": "lvl30",
                        "achievement_name": "Got level 30",
                        "unlock_time": 1548495633
                    }
                ]
            }
        },
        {
            "jsonrpc": "2.0",
            "method": "achievements_import_finished",
            "params": None
        }
    ]
async def test_achievements(api_mock, plugin):
    api_mock.get_me.return_value = {
        "user_achievements": [{
            "achieved_at": "2020-03-26T19:58:36+00:00",
            "achievement_id": 128
        }, {
            "achieved_at": "2020-04-20T21:32:31+00:00",
            "achievement_id": 54
        }],
    }
    expected = [Achievement(12131132, 128), Achievement(23123123, 54)]
    context = await plugin.prepare_achievements_context([OSU])
    await plugin.get_unlocked_achievements(OSU, context) == expected
Пример #7
0
async def test_get_achievements_success(authenticated_plugin, backend_client, steam_id):
    context = {
        "236850": GameTime(game_id="236850", time_played=86820, last_played_time=1549385500),
        "281990": GameTime(game_id="281990", time_played=78, last_played_time=1549385500)
    }
    backend_client.get_achievements.return_value = [
        (1551887210, "name 1"),
        (1551887134, "name 2")
    ]
    achievements = await authenticated_plugin.get_unlocked_achievements("236850", context)
    assert achievements == [
            Achievement(1551887210, None, "name 1"),
            Achievement(1551887134, None, "name 2")
        ]
    backend_client.get_achievements.assert_called_once_with(steam_id, "236850")
async def test_initialize_cache(create_authenticated_plugin, backend_client,
                                steam_id, login):
    cache = {
        "achievements":
        """{
            "17923": {
                "achievements": [
                    {
                        "unlock_time": 1549383000,
                        "achievement_id": null,
                        "achievement_name": "name"
                    }
                ],
                "fingerprint": {
                    "time_played": 1549385501,
                    "last_played_time": 180
                }
            }
        }"""
    }
    plugin = await create_authenticated_plugin(steam_id, login, cache)

    context = {
        "17923":
        GameTime(game_id="17923", time_played=180, last_played_time=1549385501)
    }
    achievements = await plugin.get_unlocked_achievements("17923", context)
    assert achievements == [Achievement(1549383000, None, "name")]
    backend_client.get_achievements.assert_not_called()
Пример #9
0
    async def get_unlocked_achievements(self, game_id: str, context: Any) -> List[Achievement]:
        result = list()

        if game_id != self.GAME_ID:
            logging.warn('plugin/get_unlocked_achievements: unknown game_id %s' % game_id)
            return result

        if not self.__imported_achievements:
            self.__imported_achievements = list()

        self.__imported_achievements.clear()
        for achievement_id in await self._gw2_api.get_account_achievements():
            #check for existence    
            if not self.__is_achievement_exists(achievement_id):
                continue

            #save unlock time
            cache_key = 'achievement_%s' % achievement_id
            if cache_key not in self.persistent_cache:
                self.persistent_cache[cache_key] = int(time.time())

            #append to list
            result.append(Achievement(self.persistent_cache.get(cache_key), achievement_id, self.__get_achievement_name(achievement_id)))

        self.push_cache()
        return result
Пример #10
0
        async def get_unlocked_achievements(self, game_id, context):
            # The Social Club API has an authentication endpoint located at https://scapi.rockstargames.com/
            # achievements/awardedAchievements?title=[game-id]&platform=pc&rockstarId=[rockstar-ID], which returns a
            # list of the user's unlocked achievements for the specified game. It uses the Social Club standard for
            # authentication (a request header named Authorization containing "Bearer [Bearer-Token]").

            title_id = get_game_title_id_from_ros_title_id(game_id)
            if games_cache[title_id]["achievementId"] is None or \
                    (games_cache[title_id]["isPreOrder"]):
                return []
            log.debug("ROCKSTAR_ACHIEVEMENT_CHECK: Beginning achievements check for " +
                      title_id + " (Achievement ID: " + get_achievement_id_from_ros_title_id(game_id) + ")...")
            # Now, we can begin getting the user's achievements for the specified game.
            achievement_id = get_achievement_id_from_ros_title_id(game_id)
            url = (f"https://scapi.rockstargames.com/achievements/awardedAchievements?title={achievement_id}"
                   f"&platform=pc&rockstarId={self._http_client.get_rockstar_id()}")
            unlocked_achievements = await self._http_client.get_json_from_request_strict(url)
            achievements_dict = unlocked_achievements["awardedAchievements"]
            achievements_list = []
            for key, value in achievements_dict.items():
                # What if an achievement is added to the Social Club after the cache was already made? In this event, we
                # need to refresh the cache.
                achievement_num = key
                unlock_time = await get_unix_epoch_time_from_date(value["dateAchieved"])
                achievements_list.append(Achievement(unlock_time, achievement_id=achievement_num))
            return achievements_list
Пример #11
0
 def parser(json_data: Dict) -> List[Achievement]:
     return [
         Achievement(achievement_id=key,
                     achievement_name=value["name"],
                     unlock_time=value["u"])
         for key, value in json_data.items() if value.get("complete")
     ]
Пример #12
0
 async def _get_achievements(self, game_id):
     achievements = await self._client.get_achievements(
         self._steam_id, game_id)
     return [
         Achievement(unlock_time, None, name)
         for unlock_time, name in achievements
     ]
Пример #13
0
async def test_initialize_cache(create_authenticated_plugin, backend_client, steam_id, miniprofile, login):

    plugin = await create_authenticated_plugin(steam_id, login,miniprofile,{})
    plugin._stats_cache = {"17923": {'achievements': [{'unlock_time': 123,'name':'name'}]}}
    achievements = await plugin.get_unlocked_achievements("17923", None)
    assert achievements == [
        Achievement(123, None , "name")
    ]
    backend_client.get_achievements.assert_not_called()
Пример #14
0
 async def get_unlocked_achievements(self, game_id, context):
     me = await self._api.get_me()
     return [
         Achievement(achievement_id=medal['achievement_id'],
                     unlock_time=int(
                         datetime.fromisoformat(
                             medal['achieved_at']).timestamp()))
         for medal in me.get('user_achievements', [])
     ]
Пример #15
0
def test_success(plugin, readline, write):
    request = {
        "jsonrpc": "2.0",
        "id": "3",
        "method": "import_unlocked_achievements",
        "params": {
            "game_id": "14"
        }
    }
    readline.side_effect = [json.dumps(request), ""]
    plugin.get_unlocked_achievements.coro.return_value = [
        Achievement(achievement_id="lvl10", unlock_time=1548421241),
        Achievement(achievement_name="Got level 20", unlock_time=1548422395),
        Achievement(achievement_id="lvl30",
                    achievement_name="Got level 30",
                    unlock_time=1548495633)
    ]
    asyncio.run(plugin.run())
    plugin.get_unlocked_achievements.assert_called_with(game_id="14")
    response = json.loads(write.call_args[0][0])

    assert response == {
        "jsonrpc": "2.0",
        "id": "3",
        "result": {
            "unlocked_achievements": [{
                "achievement_id": "lvl10",
                "unlock_time": 1548421241
            }, {
                "achievement_name": "Got level 20",
                "unlock_time": 1548422395
            }, {
                "achievement_id": "lvl30",
                "achievement_name": "Got level 30",
                "unlock_time": 1548495633
            }]
        }
    }
Пример #16
0
    async def import_games_achievements(self, _game_ids):
        game_ids = set(_game_ids)
        error = UnknownError()
        try:
            achievement_sets = {
            }  # 'offerId' to 'achievementSet' names mapping
            for offer_id, achievement_set in (
                    await
                    self._backend_client.get_achievements_sets(self._persona_id
                                                               )).items():
                if not achievement_set:
                    self.game_achievements_import_success(offer_id, [])
                    game_ids.remove(offer_id)
                else:
                    achievement_sets[offer_id] = achievement_set

            if not achievement_sets:
                return

            for offer_id, achievements in (
                    await self._backend_client.get_achievements(
                        self._persona_id, achievement_sets)).items():
                try:
                    self.game_achievements_import_success(
                        offer_id, [
                            Achievement(achievement_id=key,
                                        achievement_name=value["name"],
                                        unlock_time=value["u"])
                            for key, value in achievements.items()
                            if value["complete"]
                        ])
                except KeyError:
                    self.game_achievements_import_failure(
                        offer_id, UnknownBackendResponse())
                except ApplicationError as error:
                    self.game_achievements_import_failure(offer_id, error)
                finally:
                    game_ids.remove(offer_id)
        except KeyError:
            error = UnknownBackendResponse()
        except ApplicationError as _error:
            error = _error
        except Exception:
            pass  # handled below
        finally:
            # any other exceptions or not answered game_ids are responded with an error
            [
                self.game_achievements_import_failure(game_id, error)
                for game_id in game_ids
            ]
Пример #17
0
async def test_game_achievements_import_success(plugin, write):
    achievements = [
        Achievement(achievement_id="lvl10", unlock_time=1548421241),
        Achievement(achievement_name="Got level 20", unlock_time=1548422395)
    ]
    plugin.game_achievements_import_success("134", achievements)
    response = json.loads(write.call_args[0][0])

    assert response == {
        "jsonrpc": "2.0",
        "method": "game_achievements_import_success",
        "params": {
            "game_id":
            "134",
            "unlocked_achievements": [{
                "achievement_id": "lvl10",
                "unlock_time": 1548421241
            }, {
                "achievement_name": "Got level 20",
                "unlock_time": 1548422395
            }]
        }
    }
Пример #18
0
def from_dict(dict_: dict) -> Cache:
    cache = Cache()
    for key, value in dict_.items():
        try:
            achievements = value["achievements"]
            achievements = [
                Achievement(**achievement) for achievement in achievements
            ]
            fingerprint = value["fingerprint"]
            fingerprint = Fingerprint(**fingerprint)
        except (KeyError, TypeError, AssertionError) as error:
            raise ValueError(
                "Failed to deserialize cache from dictionary") from error
        cache.update(key, achievements, fingerprint)
    return cache
Пример #19
0
        def achievement_parser(achievement_tag: Optional[AchievementTag]) -> Achievement:
            name_tag = achievement_tag.h2
            if not name_tag:
                raise UnknownBackendResponse("Cannot find achievement name tag")

            achievement_name = achievement_tag.h2.get_text()
            if not achievement_name:
                raise UnknownBackendResponse("Failed to parse achievement name")

            return Achievement(
                unlock_time=self._achievements_cache.setdefault(
                    achievement_name
                    , Timestamp(int(datetime.utcnow().timestamp()))
                )
                , achievement_name=achievement_name
            )
async def test_unlock_achievement(plugin, write):
    achievement = Achievement(achievement_id="lvl20", unlock_time=1548422395)
    plugin.unlock_achievement("14", achievement)
    response = json.loads(write.call_args[0][0])

    assert response == {
        "jsonrpc": "2.0",
        "method": "achievement_unlocked",
        "params": {
            "game_id": "14",
            "achievement": {
                "achievement_id": "lvl20",
                "unlock_time": 1548422395
            }
        }
    }
Пример #21
0
    async def get_unlocked_achievements(self, game_id: str, context: Any) -> List[Achievement]:
        logger.info(f"Asked for achievs for {game_id}")
        game_stats = self._stats_cache.get(game_id)
        achievements = []
        if game_stats:
            if 'achievements' not in game_stats:
                return []
            for achievement in game_stats['achievements']:

                # Fix for trailing whitespace in some achievement names which resulted in achievements not matching with website data
                achi_name = achievement['name']
                achi_name = achi_name.strip()
                if not achi_name:
                    achi_name = achievement['name']

                achievements.append(Achievement(achievement['unlock_time'], achievement_id=None, achievement_name=achi_name))
        return achievements
Пример #22
0
    def trop2ach(self, trophy_id: int) -> Achievement:

        trophy_state = self.tropusr.table6[trophy_id].trophy_state
        unlocked = int.from_bytes(trophy_state, byteorder='big')

        if bool(unlocked):
            unlock_timestamp = self.tropusr.table6[trophy_id].timestamp2
            unlock_time = int.from_bytes(unlock_timestamp, byteorder='big')

            pad_tid = format(trophy_id, '03d')
            name = self.tropconf.root.find('.//trophy[@id="' + pad_tid +
                                           '"]/name')

            ach = Achievement(unlock_time, None, name.text)
            return ach
        else:
            return None
Пример #23
0
    async def task_check_for_achievements(self):
        if self.__imported_achievements:
            for achievement_id in self._gw2_api.get_account_achievements():
                if achievement_id not in self.__imported_achievements:
                    #check for existence
                    if not self.__is_achievement_exists(achievement_id):
                        continue

                    #mark as processed
                    self.__imported_achievements.append(achievement_id)
                    
                    #save unlock time
                    cache_key = 'achievement_%s' % achievement_id
                    self.persistent_cache[cache_key] = int(time.time())

                    #push to galaxy
                    self.unlock_achievement(self.GAME_ID, Achievement(self.persistent_cache.get(cache_key), achievement_id, self.__get_achievement_name(achievement_id)))

        await asyncio.sleep(self.SLEEP_CHECK_ACHIEVEMENTS)
Пример #24
0
 async def get_unlocked_challenges(self, game_id):
     """Challenges are a unique uplay club feature and don't directly translate to achievements"""
     if not self.client.is_authenticated():
         raise AuthenticationRequired()
     for game in self.games_collection:
         if game.space_id == game_id or game.launch_id == game_id:
             if not game.space_id:
                 return []
             challenges = await self.client.get_challenges(game.space_id)
             return [
                 Achievement(achievement_id=challenge["id"],
                             achievement_name=challenge["name"],
                             unlock_time=int(
                                 datetime.datetime.timestamp(
                                     dateutil.parser.parse(
                                         challenge["completionDate"]))))
                 for challenge in challenges["actions"]
                 if challenge["isCompleted"] and not challenge["isBadge"]
             ]
Пример #25
0
    async def _get_wow_achievements(self):
        achievements = []
        try:
            characters_data = await self.backend_client.get_wow_character_data(
            )
            characters_data = characters_data["characters"]

            wow_character_data = await asyncio.gather(
                *[
                    self.backend_client.get_wow_character_achievements(
                        character["realm"], character["name"])
                    for character in characters_data
                ],
                return_exceptions=True,
            )

            for data in wow_character_data:
                if isinstance(data, requests.Timeout) or isinstance(
                        data, requests.ConnectionError):
                    raise data

            wow_achievement_data = [
                list(
                    zip(
                        data["achievements"]["achievementsCompleted"],
                        data["achievements"]["achievementsCompletedTimestamp"],
                    )) for data in wow_character_data if type(data) is dict
            ]

            already_in = set()

            for char_ach in wow_achievement_data:
                for ach in char_ach:
                    if ach[0] not in already_in:
                        achievements.append(
                            Achievement(achievement_id=ach[0],
                                        unlock_time=int(ach[1] / 1000)))
                        already_in.add(ach[0])
        except (AccessTokenExpired, BackendError) as e:
            log.exception(str(e))
        with open('wow.json', 'w') as f:
            f.write(json.dumps(achievements, cls=DataclassJSONEncoder))
        return achievements
Пример #26
0
    async def _get_sc2_achievements(self):
        account_data = await self.backend_client.get_sc2_player_data(self.authentication_client.user_details["id"])

        # TODO what if more sc2 accounts?
        assert len(account_data) == 1
        account_data = account_data[0]

        profile_data = await self.backend_client.get_sc2_profile_data(
                                                         account_data["regionId"], account_data["realmId"],
                                                         account_data["profileId"]
                                                         )

        sc2_achievement_data = [
            Achievement(achievement_id=achievement["achievementId"], unlock_time=achievement["completionDate"])
            for achievement in profile_data["earnedAchievements"]
            if achievement["isComplete"]
        ]

        with open('sc2.json', 'w') as f:
            f.write(json.dumps(sc2_achievement_data, cls=DataclassJSONEncoder))
        return sc2_achievement_data
Пример #27
0
    async def get_unlocked_achievements(self, game_id):
        if not self._http_client.is_authenticated():
            raise AuthenticationRequired()

        try:
            achievement_set = (await self._get_offers(
                [game_id]))[0]["platforms"][0]["achievementSetOverride"]
            if achievement_set is None:
                return []

            achievements = await self._backend_client.get_achievements(
                self._persona_id, {game_id: achievement_set})

            return [
                Achievement(achievement_id=key,
                            achievement_name=value["name"],
                            unlock_time=value["u"])
                for key, value in achievements[game_id].items()
                if value["complete"]
            ]
        except (KeyError, IndexError):
            raise UnknownBackendResponse()
Пример #28
0
            "trophyId": 5,
            "fromUser": {
                "onlineId": "user-id",
                "earned": False,
                "earnedDate": "1987-02-07T10:14:42Z"
            },
            "trophyName": "achievement 5",
            "groupId": "022"
        },
    ]
}

UNLOCKED_ACHIEVEMENTS = [
    Achievement(
        achievement_id="NPWR11556_00_1",
        achievement_name="achievement 1",
        unlock_time=538304493.0,
    ),
    Achievement(achievement_id="NPWR11556_00_2",
                achievement_name="achievement 2",
                unlock_time=1318782798.0)
]

TROPHIES_CACHE = Cache()
TROPHIES_CACHE._entries = {
    "NPWR11556_00": CacheEntry(value=UNLOCKED_ACHIEVEMENTS,
                               timestamp=1490374318.0)
}

BACKEND_USER_PROFILES = {
    "start":
Пример #29
0
def test_initialization_no_unlock_time():
    with raises(Exception):
        Achievement(achievement_id="lvl30", achievement_name="Got level 30")
Пример #30
0
def test_initialization_no_id_nor_name():
    with raises(AssertionError):
        Achievement(unlock_time=1234567890)