diff --git a/disnake/appinfo.py b/disnake/appinfo.py index 15468f1eb5..9b35eba55e 100644 --- a/disnake/appinfo.py +++ b/disnake/appinfo.py @@ -2,12 +2,13 @@ from __future__ import annotations -from typing import TYPE_CHECKING, List, Optional +from typing import TYPE_CHECKING, Any, Dict, List, Optional, overload from . import utils -from .asset import Asset +from .asset import Asset, AssetBytes from .flags import ApplicationFlags from .permissions import Permissions +from .utils import MISSING if TYPE_CHECKING: from .guild import Guild @@ -20,6 +21,7 @@ ) from .user import User + __all__ = ( "AppInfo", "PartialAppInfo", @@ -64,6 +66,12 @@ def to_url(self) -> str: """ return utils.oauth_url(self._app_id, scopes=self.scopes, permissions=self.permissions) + def to_dict(self) -> Dict[str, Any]: + return { + "scopes": self.scopes, + "permissions": self.permissions.value, + } + class AppInfo: """Represents the application info for the bot provided by Discord. @@ -280,6 +288,94 @@ def summary(self) -> str: ) return self._summary + @overload + async def edit( + self, + *, + description: str = ..., + flags: ApplicationFlags = ..., + icon: Optional[AssetBytes] = ..., + cover_image: Optional[AssetBytes] = ..., + custom_install_url: Optional[str] = ..., + install_params: Optional[InstallParams] = ..., + role_connections_verification_url: str = ..., + interactions_endpoint_url: Optional[str] = ..., + tags: Optional[List[str]] = ..., + ) -> AppInfo: + ... + + @overload + async def edit(self) -> AppInfo: + ... + + async def edit( + self, + *, + flags: ApplicationFlags = MISSING, + icon: Optional[AssetBytes] = MISSING, + cover_image: Optional[AssetBytes] = MISSING, + install_params: Optional[InstallParams] = MISSING, + **fields: Any, + ) -> AppInfo: + """|coro| + + Edit's the application's information. + + All parameters are optional. + + Returns a new :class:`AppInfo` with the updated information. + + .. versionadded:: 2.10 + + Parameters + ---------- + description: Optional[:class:`str`] + The application's description. + flags: Optional[:class:`ApplicationFlags`] + The application's public flags. + tags: Optional[List[:class:`str`]] + The application's tags. + install_params: Optional[:class:`InstallParams`] + The installation parameters for this application. + custom_install_url: Optional[:class:`str`] + The custom installation url for this application. + role_connections_verification_url: Optional[:class:`str`] + The application's role connection verification entry point, + which when configured will render the app as a verification method + in the guild role verification configuration. + icon: |resource_type| + Update the application's icon asset, if any. + cover_image: |resource_type| + Retrieves the cover image on a store embed, if any. + + Raises + ------ + HTTPException + Editing the information failed somehow. + + Returns + ------- + :class:`.AppInfo` + The bot's new application information. + """ + if install_params is not MISSING: + fields["install_params"] = None if install_params is None else install_params.to_dict() + + if icon is not MISSING: + fields["icon"] = await utils._assetbytes_to_base64_data(icon) + + if cover_image is not MISSING: + fields["cover_image"] = await utils._assetbytes_to_base64_data(cover_image) + + if flags is not MISSING: + fields["flags"] = flags.value + + data = await self._state.http.edit_application_info(**fields) + + if "rpc_origins" not in data: + data["rpc_origins"] = None + return AppInfo(self._state, data) + class PartialAppInfo: """Represents a partial AppInfo given by :func:`~disnake.abc.GuildChannel.create_invite`. diff --git a/disnake/client.py b/disnake/client.py index 80b3d67c65..1a879c8184 100644 --- a/disnake/client.py +++ b/disnake/client.py @@ -42,7 +42,7 @@ ApplicationCommand, GuildApplicationCommandPermissions, ) -from .appinfo import AppInfo +from .appinfo import AppInfo, InstallParams from .application_role_connection import ApplicationRoleConnectionMetadata from .backoff import ExponentialBackoff from .channel import PartialMessageable, _threaded_channel_factory @@ -2372,6 +2372,92 @@ async def application_info(self) -> AppInfo: data["rpc_origins"] = None return AppInfo(self._connection, data) + @overload + async def edit_application_info( + self, + *, + description: str = ..., + flags: ApplicationFlags = ..., + icon: Optional[AssetBytes] = ..., + cover_image: Optional[AssetBytes] = ..., + custom_install_url: Optional[str] = ..., + install_params: Optional[InstallParams] = ..., + role_connections_verification_url: str = ..., + interactions_endpoint_url: Optional[str] = ..., + tags: Optional[List[str]] = ..., + ) -> AppInfo: + ... + + @overload + async def edit_application_info(self) -> AppInfo: + ... + + async def edit_application_info( + self, + *, + flags: ApplicationFlags = MISSING, + icon: Optional[AssetBytes] = MISSING, + cover_image: Optional[AssetBytes] = MISSING, + install_params: Optional[InstallParams] = MISSING, + **fields: Any, + ) -> AppInfo: + """|coro| + + Edit's the application's information. + + All parameters are optional. + + .. versionadded:: 2.10 + + Parameters + ---------- + description: Optional[:class:`str`] + The application's description. + flags: Optional[:class:`ApplicationFlags`] + The application's public flags. + tags: Optional[List[:class:`str`]] + The application's tags. + install_params: Optional[:class:`InstallParams`] + The installation parameters for this application. + custom_install_url: Optional[:class:`str`] + The custom installation url for this application. + role_connections_verification_url: Optional[:class:`str`] + The application's role connection verification entry point, + which when configured will render the app as a verification method + in the guild role verification configuration. + icon: |resource_type| + Update the application's icon asset, if any. + cover_image: |resource_type| + Retrieves the cover image on a store embed, if any. + + Raises + ------ + HTTPException + Editing the information failed somehow. + + Returns + ------- + :class:`.AppInfo` + The bot's application information. + """ + if install_params is not MISSING: + fields["install_params"] = None if install_params is None else install_params.to_dict() + + if icon is not MISSING: + fields["icon"] = await utils._assetbytes_to_base64_data(icon) + + if cover_image is not MISSING: + fields["cover_image"] = await utils._assetbytes_to_base64_data(cover_image) + + if flags is not MISSING: + fields["flags"] = flags.value + + data = await self.http.edit_application_info(**fields) + + if "rpc_origins" not in data: + data["rpc_origins"] = None + return AppInfo(self._connection, data) + async def fetch_user(self, user_id: int, /) -> User: """|coro| diff --git a/disnake/http.py b/disnake/http.py index f0d157d671..08a11d92a3 100644 --- a/disnake/http.py +++ b/disnake/http.py @@ -2794,6 +2794,9 @@ def get_voice_regions(self) -> Response[List[voice.VoiceRegion]]: def application_info(self) -> Response[appinfo.AppInfo]: return self.request(Route("GET", "/oauth2/applications/@me")) + def edit_application_info(self, **fields: Any) -> Response[appinfo.AppInfo]: + return self.request(Route("PATCH", "/applications/@me"), json=fields) + def get_application_role_connection_metadata_records( self, application_id: Snowflake ) -> Response[List[application_role_connection.ApplicationRoleConnectionMetadata]]: