diff --git a/legendary/lfs/lgndry.py b/legendary/lfs/lgndry.py index 2e9b0bf..0fac937 100644 --- a/legendary/lfs/lgndry.py +++ b/legendary/lfs/lgndry.py @@ -37,6 +37,8 @@ class LGDLFS: self._user_data = None # EGS entitlements self._entitlements = None + # EGS achievements + self._achievements = None # EGS asset data self._assets = None # EGS metadata @@ -196,6 +198,27 @@ class LGDLFS: json.dump(entitlements, open(os.path.join(self.path, 'entitlements.json'), 'w'), indent=2, sort_keys=True) + @property + def achievements(self): + if self._achievements is not None: + return self._achievements + + try: + self._achievements = json.load(open(os.path.join(self.path, 'achievements.json'))) + return self._achievements + except Exception as e: + self.log.debug(f'Failed to load achievements data: {e!r}') + return None + + @achievements.setter + def achievements(self, achievements): + if achievements is None: + raise ValueError('Achievements is none!') + + self._achievements = achievements + json.dump(achievements, open(os.path.join(self.path, 'achievements.json'), 'w'), + indent=2, sort_keys=True) + @property def assets(self): if self._assets is None: diff --git a/legendary/models/game.py b/legendary/models/game.py index 5a7eec6..30a036c 100644 --- a/legendary/models/game.py +++ b/legendary/models/game.py @@ -63,6 +63,41 @@ class Sidecar: ) +@dataclass +class Achievements: + namespace: str + total_achievements: int + total_product_xp: int + achievement_sets: List = field(default_factory=list) + platinum_rarity: Dict = field(default_factory=dict) + achievements: List = field(default_factory=list) + + @classmethod + def from_egs_json(cls, json): + json = json['data']['Achievement']['productAchievementsRecordBySandbox'] + tmp = cls( + namespace=json.get('sandboxId', ''), + total_achievements=json.get('totalAchievements', 0), + total_product_xp=json.get('totalProductXP', 0), + achievement_sets=json.get('achievementSets', []), + platinum_rarity=json.get('platinumRarity', {}), + achievements=json.get('achievements', []), + ) + return tmp + + @classmethod + def from_json(cls, json): + tmp = cls( + namespace=json.get('namespace', ''), + total_achievements=json.get('total_achievements', 0), + total_product_xp=json.get('total_product_xp', 0), + achievement_sets=json.get('achievement_sets', []), + platinum_rarity=json.get('platinum_rarity', {}), + achievements=json.get('achievements', []), + ) + return tmp + + @dataclass class Game: """ @@ -75,6 +110,7 @@ class Game: base_urls: List[str] = field(default_factory=list) metadata: Dict = field(default_factory=dict) sidecar: Optional[Sidecar] = None + achievements: Optional[Achievements] = None def app_version(self, platform='Windows'): if platform not in self.asset_infos: @@ -155,6 +191,9 @@ class Game: if sidecar := json.get('sidecar', None): tmp.sidecar = Sidecar.from_json(sidecar) + if achievements := json.get('achievements', None): + tmp.achievements = Achievements.from_json(achievements) + tmp.base_urls = json.get('base_urls', list()) return tmp @@ -163,8 +202,10 @@ class Game: """This is just here so asset_infos gets turned into a dict as well""" assets_dictified = {k: v.__dict__ for k, v in self.asset_infos.items()} sidecar_dictified = self.sidecar.__dict__ if self.sidecar else None + achievements_dictified = self.achievements.__dict__ if self.achievements else None return dict(metadata=self.metadata, asset_infos=assets_dictified, app_name=self.app_name, - app_title=self.app_title, base_urls=self.base_urls, sidecar=sidecar_dictified) + app_title=self.app_title, base_urls=self.base_urls, sidecar=sidecar_dictified, + achievements=achievements_dictified) @dataclass