diff --git a/discordrpc/presence.py b/discordrpc/presence.py index f2d179a..05861c6 100644 --- a/discordrpc/presence.py +++ b/discordrpc/presence.py @@ -9,8 +9,8 @@ RPCException, InvalidID, DiscordNotOpened, ButtonError, InvalidActivityType, ActivityTypeDisabled, ) -from .types import Activity, StatusDisplay, User, Application -from .utils import remove_none, get_app_info +from .types import Activity, StatusDisplay, User, Application, Asset, AssetManager +from .utils import remove_none, get_app_info, get_assets from functools import cached_property import logging import time @@ -70,6 +70,10 @@ def App(self): self._app_info = get_app_info(self.app_id) return Application(self._app_info) + @cached_property + def assets(self): + return AssetManager(self.app_id, get_assets(self.app_id)) + def set_activity( self, name: str = None, state: str = None, details: str = None, act_type: Activity = Activity.Playing, status_type: StatusDisplay = StatusDisplay.Name, @@ -99,6 +103,9 @@ def set_activity( if buttons and len(buttons) > 2: raise ButtonError("Max 2 buttons allowed") + large_image = large_image.name if isinstance(large_image, Asset) else large_image + small_image = small_image.name if isinstance(small_image, Asset) else small_image + activity = None if not clear: if type(party_id) == int: diff --git a/discordrpc/types.py b/discordrpc/types.py index b32a2c8..0faf3b4 100644 --- a/discordrpc/types.py +++ b/discordrpc/types.py @@ -32,8 +32,7 @@ def _parse_avatar(self, data:dict, size:int=1024) -> str: else: return f"https://cdn.discordapp.com/embed/avatars/0.png" - def __str__(self): - return f"User({self.name})" + def __str__(self): return f"User({self.name})" class Application(): def __init__(self, data:dict=None): @@ -50,5 +49,29 @@ def _parse_icon(self, icon_id:str, size:int=512) -> str: return f"https://cdn.discordapp.com/app-icons/{self.id}/{icon_id}.png?size={size}" return "https://cdn.discordapp.com/embed/avatars/1.png" - def __str__(self): - return f"Application({self.name})" + def __str__(self): return f"Application({self.name})" + +class Asset(): + def __init__(self, app_id:int, data:dict=None, size:int=1024): + data = data or {} + self.app_id: int = app_id + self.id: int = int(data.get("id", 0)) + self.name: str = data.get("name") + self.type: int = int(data.get("type", 0)) + self.url: str = f"https://cdn.discordapp.com/app-assets/{self.app_id}/{self.id}.png?size={size}" + + def __str__(self): return f"Asset({self.name})" + def __repr__(self): return str(self) + +class AssetManager(list): + def __init__(self, app_id:int, assets_list:list=None): + super().__init__( + Asset(app_id, asset) + for asset in assets_list + ) + def get(self, name: str) -> Asset: + return next((asset for asset in self if asset.name == name), None) + + @property + def names(self) -> list: + return list(map(lambda asset: asset.name, self)) diff --git a/discordrpc/utils.py b/discordrpc/utils.py index 19a308a..badf2d4 100644 --- a/discordrpc/utils.py +++ b/discordrpc/utils.py @@ -48,7 +48,7 @@ def progress_bar(current:int, duration:int) -> dict: "ts_start": current_time, "ts_end": finish_time } -def get_app_info(app_id): +def get_app_info(app_id:int) -> dict: try: req = urllib.request.Request(f"https://discord.com/api/v10/applications/{app_id}/rpc") req.add_header('User-Agent', 'Discord-RPC/1.0') @@ -57,4 +57,15 @@ def get_app_info(app_id): return json.loads(response.read().decode('utf-8')) except Exception as e: log.error(f"Failed to fetch application info: {e}") - return {} \ No newline at end of file + return {} + +def get_assets(app_id:int) -> list: + try: + req = urllib.request.Request(f"https://discord.com/api/v10/oauth2/applications/{app_id}/assets") + req.add_header('User-Agent', 'Discord-RPC/1.0') + with urllib.request.urlopen(req) as response: + if response.status == 200: + return json.loads(response.read().decode('utf-8')) + except Exception as e: + log.error(f"Failed to fetch application assets: {e}") + return [] diff --git a/examples/assets.py b/examples/assets.py new file mode 100644 index 0000000..35564e5 --- /dev/null +++ b/examples/assets.py @@ -0,0 +1,14 @@ +import discordrpc + +rpc = discordrpc.RPC(app_id=123456789) + +print(rpc.assets.names) + +for asset in rpc.assets: + print(asset.url) + +rpc.set_activity( + state="Assets example", + large_image=rpc.assets.get("cat") +) +rpc.run()