-
-
Notifications
You must be signed in to change notification settings - Fork 480
feat: Add support for editing application info and new fields #2994
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 4 commits
6cabb6f
2f54fe7
fab1478
bfa2940
9893239
884cd6c
41f12a2
714c68a
734b5ce
49c90b9
76eb883
bd91789
7e5ff54
6fc48da
bde7ec3
89d3011
dfb7907
9eecbfa
ab000ac
8c0dcd7
03a46e8
0b603f5
3c398cc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -29,6 +29,7 @@ | |||||
|
|
||||||
| from . import utils | ||||||
| from .asset import Asset | ||||||
| from .flags import ApplicationFlags | ||||||
| from .permissions import Permissions | ||||||
|
|
||||||
| if TYPE_CHECKING: | ||||||
|
|
@@ -44,6 +45,7 @@ | |||||
| "AppInfo", | ||||||
| "PartialAppInfo", | ||||||
| "AppInstallParams", | ||||||
| "IntegrationTypesConfig", | ||||||
| ) | ||||||
|
|
||||||
|
|
||||||
|
|
@@ -134,11 +136,33 @@ class AppInfo: | |||||
|
|
||||||
| .. versionadded:: 2.7 | ||||||
|
|
||||||
| install_params: Optional[List[:class:`AppInstallParams`]] | ||||||
| install_params: Optional[:class:`AppInstallParams`] | ||||||
| The settings for the application's default in-app authorization link, if set. | ||||||
|
|
||||||
| .. versionadded:: 2.7 | ||||||
|
|
||||||
| integration_types_config: Optional[Dict[:class:`int`, Optional[Dict[:class:`str`, Any]]]] | ||||||
| Per-installation context configuration. Keys are ``0`` (guild) and ``1`` (user) mapping to an object containing | ||||||
| ``oauth2_install_params`` or ``None`` if cleared. | ||||||
|
|
||||||
| .. versionadded:: 2.7 | ||||||
|
|
||||||
| event_webhooks_url: Optional[:class:`str`] | ||||||
| The URL used to receive application event webhooks, if set. | ||||||
|
|
||||||
| .. versionadded:: 2.7 | ||||||
|
|
||||||
| event_webhooks_status: Optional[:class:`int`] | ||||||
| The raw event webhooks status integer from the API (``2`` enabled, ``1`` disabled) if present. | ||||||
| Prefer :attr:`event_webhooks_enabled` for a boolean form. | ||||||
Paillat-dev marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
|
|
||||||
| .. versionadded:: 2.7 | ||||||
|
|
||||||
| event_webhooks_types: Optional[List[:class:`str`]] | ||||||
| List of event webhook types subscribed to, if set. | ||||||
|
|
||||||
| .. versionadded:: 2.7 | ||||||
|
|
||||||
| tags: Optional[List[:class:`str`]] | ||||||
| The list of tags describing the content and functionality of the app, if set. | ||||||
|
|
||||||
|
|
@@ -149,6 +173,16 @@ class AppInfo: | |||||
| custom_install_url: Optional[:class:`str`] | ||||||
| The default custom authorization URL for the application, if set. | ||||||
|
|
||||||
| .. versionadded:: 2.7 | ||||||
|
|
||||||
| approximate_user_authorization_count: Optional[:class:`int`] | ||||||
| The approximate count of users who have authorized the application, if any. | ||||||
|
|
||||||
| .. versionadded:: 2.7 | ||||||
|
|
||||||
| flags: Optional[:class:`ApplicationFlags`] | ||||||
Lumabots marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
| The public application flags, if set. | ||||||
|
|
||||||
| .. versionadded:: 2.7 | ||||||
| """ | ||||||
|
|
||||||
|
|
@@ -161,6 +195,7 @@ class AppInfo: | |||||
| "bot_public", | ||||||
| "bot_require_code_grant", | ||||||
| "owner", | ||||||
| "bot", | ||||||
Lumabots marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| "_icon", | ||||||
| "_summary", | ||||||
| "verify_key", | ||||||
|
|
@@ -173,9 +208,15 @@ class AppInfo: | |||||
| "privacy_policy_url", | ||||||
| "approximate_guild_count", | ||||||
| "approximate_user_install_count", | ||||||
| "approximate_user_authorization_count", | ||||||
| "_flags", | ||||||
| "redirect_uris", | ||||||
| "interactions_endpoint_url", | ||||||
| "role_connections_verification_url", | ||||||
| "event_webhooks_url", | ||||||
| "event_webhooks_status", | ||||||
| "event_webhooks_types", | ||||||
| "integration_types_config", | ||||||
| "install_params", | ||||||
| "tags", | ||||||
| "custom_install_url", | ||||||
|
|
@@ -189,7 +230,7 @@ def __init__(self, state: ConnectionState, data: AppInfoPayload): | |||||
| self.name: str = data["name"] | ||||||
| self.description: str = data["description"] | ||||||
| self._icon: str | None = data["icon"] | ||||||
Lumabots marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
| self.rpc_origins: list[str] = data["rpc_origins"] | ||||||
| self.rpc_origins: list[str] | None = data.get("rpc_origins") | ||||||
| self.bot_public: bool = data["bot_public"] | ||||||
| self.bot_require_code_grant: bool = data["bot_require_code_grant"] | ||||||
| self.owner: User = state.create_user(data["owner"]) | ||||||
Lumabots marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
|
|
@@ -199,6 +240,7 @@ def __init__(self, state: ConnectionState, data: AppInfoPayload): | |||||
|
|
||||||
| self._summary: str = data["summary"] | ||||||
Lumabots marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| self.verify_key: str = data["verify_key"] | ||||||
| self.bot: User | None = data.get("bot") and state.create_user(data["bot"]) | ||||||
|
|
||||||
| self.guild_id: int | None = utils._get_as_snowflake(data, "guild_id") | ||||||
|
|
||||||
|
|
@@ -213,20 +255,31 @@ def __init__(self, state: ConnectionState, data: AppInfoPayload): | |||||
| self.approximate_user_install_count: int | None = data.get( | ||||||
| "approximate_user_install_count" | ||||||
| ) | ||||||
| self.approximate_user_authorization_count: int | None = data.get( | ||||||
| "approximate_user_authorization_count" | ||||||
| ) | ||||||
| raw_flags = data.get("flags") | ||||||
| self._flags: int | None = raw_flags if isinstance(raw_flags, int) else None | ||||||
Lumabots marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
| self.redirect_uris: list[str] | None = data.get("redirect_uris", []) | ||||||
Lumabots marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
| self.interactions_endpoint_url: str | None = data.get( | ||||||
| "interactions_endpoint_url" | ||||||
| ) | ||||||
| self.role_connections_verification_url: str | None = data.get( | ||||||
| "role_connections_verification_url" | ||||||
| ) | ||||||
| self.event_webhooks_url: str | None = data.get("event_webhooks_url") | ||||||
| self.event_webhooks_status: int | None = data.get("event_webhooks_status") | ||||||
| self.event_webhooks_types: list[str] | None = data.get("event_webhooks_types") | ||||||
|
|
||||||
| install_params = data.get("install_params") | ||||||
| self.install_params: AppInstallParams | None = ( | ||||||
| AppInstallParams(install_params) if install_params else None | ||||||
| ) | ||||||
| self.tags: list[str] | None = data.get("tags", []) | ||||||
Lumabots marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
| self.custom_install_url: str | None = data.get("custom_install_url") | ||||||
| self.integration_types_config: dict[int, dict[str, object] | None] | None = ( | ||||||
| data.get("integration_types_config") | ||||||
| ) | ||||||
Lumabots marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
|
|
||||||
| def __repr__(self) -> str: | ||||||
| return ( | ||||||
|
|
@@ -235,6 +288,134 @@ def __repr__(self) -> str: | |||||
| f"owner={self.owner!r}>" | ||||||
| ) | ||||||
|
|
||||||
| @property | ||||||
| def flags(self) -> ApplicationFlags | None: | ||||||
Lumabots marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| """The public application flags, if set. | ||||||
|
|
||||||
| Returns an :class:`ApplicationFlags` instance or ``None`` when not present. | ||||||
| """ | ||||||
| if self._flags is None: | ||||||
| return None | ||||||
| return ApplicationFlags._from_value(self._flags) | ||||||
|
|
||||||
| async def edit( | ||||||
Lumabots marked this conversation as resolved.
Show resolved
Hide resolved
Lumabots marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| self, | ||||||
| *, | ||||||
| description: str | None = utils.MISSING, | ||||||
| icon: bytes | str | None = utils.MISSING, | ||||||
| cover_image: bytes | str | None = utils.MISSING, | ||||||
| tags: list[str] | None = utils.MISSING, | ||||||
| terms_of_service_url: str | None = utils.MISSING, | ||||||
| privacy_policy_url: str | None = utils.MISSING, | ||||||
| interactions_endpoint_url: str | None = utils.MISSING, | ||||||
| role_connections_verification_url: str | None = utils.MISSING, | ||||||
| install_params: AppInstallParams | None = utils.MISSING, | ||||||
| custom_install_url: str | None = utils.MISSING, | ||||||
| integration_types_config: IntegrationTypesConfig | None = utils.MISSING, | ||||||
| flags: ApplicationFlags | None = utils.MISSING, | ||||||
| event_webhooks_url: str | None = utils.MISSING, | ||||||
| event_webhooks_status: bool = utils.MISSING, | ||||||
| event_webhooks_types: list[str] | None = utils.MISSING, | ||||||
| ) -> AppInfo: | ||||||
| """|coro| | ||||||
|
|
||||||
| Edit the current application's settings. | ||||||
|
|
||||||
| This method wraps the Edit Current Application endpoint and returns the updated application info. | ||||||
Lumabots marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
|
|
||||||
| Parameters | ||||||
| ---------- | ||||||
| description: Optional[:class:`str`] | ||||||
| The new application description. Pass ``None`` to clear. | ||||||
Lumabots marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
| icon: Optional[Union[:class:`bytes`, :class:`str`]] | ||||||
| New icon image. If ``bytes`` is given it will be base64 encoded automatically. If a ``str`` is given it is assumed | ||||||
| to be a pre-encoded base64 data URI or hash and sent as-is. Pass ``None`` to clear. | ||||||
| cover_image: Optional[Union[:class:`bytes`, :class:`str`]] | ||||||
| New cover image for the store embed. If ``bytes`` is given it will be base64 encoded automatically. If a ``str`` is given it is assumed | ||||||
| to be a pre-encoded base64 data URI or hash and sent as-is. Pass ``None`` to clear. | ||||||
| tags: Optional[List[:class:`str`]] | ||||||
| List of tags for the application (max 5). Pass ``None`` to clear. | ||||||
| terms_of_service_url: Optional[:class:`str`] | ||||||
| The application's Terms of Service URL. Pass ``None`` to clear. | ||||||
| privacy_policy_url: Optional[:class:`str`] | ||||||
| The application's Privacy Policy URL. Pass ``None`` to clear. | ||||||
| interactions_endpoint_url: Optional[:class:`str`] | ||||||
| The interactions endpoint callback URL. Pass ``None`` to clear. | ||||||
| role_connections_verification_url: Optional[:class:`str`] | ||||||
| The role connection verification URL for the application. Pass ``None`` to clear. | ||||||
| install_params: Optional[:class:`AppInstallParams`] | ||||||
| Settings for the application's default in-app authorization link. Pass ``None`` to clear. Omit entirely to leave unchanged. | ||||||
| custom_install_url: Optional[:class:`str`] | ||||||
| The default custom authorization URL for the application. Pass ``None`` to clear. | ||||||
| integration_types_config: Optional[:class:`IntegrationTypesConfig`] | ||||||
| Object specifying per-installation context configuration (guild and/or user). You may set contexts individually | ||||||
| and omit others to leave them unchanged. Pass the object with a context explicitly set to ``None`` to clear just that | ||||||
| context, or pass ``None`` to clear the entire integration types configuration. | ||||||
| flags: Optional[:class:`ApplicationFlags`] | ||||||
| Application public flags. Pass ``None`` to clear (not typical). | ||||||
| event_webhooks_url: Optional[:class:`str`] | ||||||
| Event webhooks callback URL for receiving application webhook events. Pass ``None`` to clear. | ||||||
| event_webhooks_status: :class:`bool` | ||||||
| Whether webhook events are enabled. ``True`` maps to API value ``2`` (enabled), ``False`` maps to ``1`` (disabled). | ||||||
| event_webhooks_types: Optional[List[:class:`str`]] | ||||||
| List of webhook event types to subscribe to. Pass ``None`` to clear. | ||||||
|
|
||||||
| Returns | ||||||
| ------- | ||||||
| :class:`.AppInfo` | ||||||
| The updated application information. | ||||||
| """ | ||||||
| payload: dict[str, object] = {} | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| if description is not utils.MISSING: | ||||||
| payload["description"] = description | ||||||
| if icon is not utils.MISSING: | ||||||
| if icon is None: | ||||||
| payload["icon"] = None | ||||||
| else: | ||||||
| payload["icon"] = utils._bytes_to_base64_data(icon) | ||||||
Lumabots marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| if cover_image is not utils.MISSING: | ||||||
| if cover_image is None: | ||||||
| payload["cover_image"] = None | ||||||
| else: | ||||||
| payload["cover_image"] = utils._bytes_to_base64_data(cover_image) | ||||||
Lumabots marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| if tags is not utils.MISSING: | ||||||
| payload["tags"] = tags | ||||||
| if terms_of_service_url is not utils.MISSING: | ||||||
| payload["terms_of_service_url"] = terms_of_service_url | ||||||
| if privacy_policy_url is not utils.MISSING: | ||||||
| payload["privacy_policy_url"] = privacy_policy_url | ||||||
| if interactions_endpoint_url is not utils.MISSING: | ||||||
| payload["interactions_endpoint_url"] = interactions_endpoint_url | ||||||
| if role_connections_verification_url is not utils.MISSING: | ||||||
| payload["role_connections_verification_url"] = ( | ||||||
| role_connections_verification_url | ||||||
| ) | ||||||
| if install_params is not utils.MISSING: | ||||||
| if install_params is None: | ||||||
| payload["install_params"] = None | ||||||
| else: | ||||||
| payload["install_params"] = install_params.to_payload() | ||||||
| if custom_install_url is not utils.MISSING: | ||||||
| payload["custom_install_url"] = custom_install_url | ||||||
| if integration_types_config is not utils.MISSING: | ||||||
| if integration_types_config is None: | ||||||
| payload["integration_types_config"] = None | ||||||
| else: | ||||||
| payload["integration_types_config"] = ( | ||||||
| integration_types_config.to_payload() | ||||||
| ) | ||||||
| if flags is not utils.MISSING: | ||||||
| payload["flags"] = None if flags is None else flags.value | ||||||
| if event_webhooks_url is not utils.MISSING: | ||||||
| payload["event_webhooks_url"] = event_webhooks_url | ||||||
| if event_webhooks_status is not utils.MISSING: | ||||||
| payload["event_webhooks_status"] = 2 if event_webhooks_status else 1 | ||||||
| if event_webhooks_types is not utils.MISSING: | ||||||
| payload["event_webhooks_types"] = event_webhooks_types | ||||||
|
|
||||||
| data = await self._state.http.edit_current_application(payload) | ||||||
| return AppInfo(self._state, data) | ||||||
|
|
||||||
| @property | ||||||
| def icon(self) -> Asset | None: | ||||||
| """Retrieves the application's icon asset, if any.""" | ||||||
|
|
@@ -278,6 +459,17 @@ def summary(self) -> str | None: | |||||
| ) | ||||||
| return self._summary | ||||||
|
|
||||||
| @property | ||||||
| def event_webhooks_enabled(self) -> bool | None: | ||||||
| """Returns whether event webhooks are enabled. | ||||||
|
|
||||||
| This is a convenience around :attr:`event_webhooks_status` where ``True`` means enabled and ``False`` means disabled. | ||||||
| ``None`` indicates the status is not present. | ||||||
| """ | ||||||
| if self.event_webhooks_status is None: | ||||||
| return None | ||||||
| return self.event_webhooks_status == 2 | ||||||
|
|
||||||
|
|
||||||
| class PartialAppInfo: | ||||||
| """Represents a partial AppInfo given by :func:`~discord.abc.GuildChannel.create_invite` | ||||||
|
|
@@ -360,3 +552,58 @@ class AppInstallParams: | |||||
| def __init__(self, data: AppInstallParamsPayload) -> None: | ||||||
| self.scopes: list[str] = data.get("scopes", []) | ||||||
| self.permissions: Permissions = Permissions(int(data["permissions"])) | ||||||
|
|
||||||
| def to_payload(self) -> dict[str, object]: | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Change in other places accordingly, else this would be documented and have to be maintained |
||||||
| """Serialize this object into an application install params payload. | ||||||
|
|
||||||
| Returns | ||||||
| ------- | ||||||
| Dict[str, Any] | ||||||
| A dict with ``scopes`` and ``permissions`` (string form) suitable for the API. | ||||||
| """ | ||||||
| if self.permissions.value > 0 and "bot" not in self.scopes: | ||||||
| raise ValueError( | ||||||
| "'bot' must be in install_params.scopes if permissions are requested" | ||||||
| ) | ||||||
| return { | ||||||
| "scopes": list(self.scopes), | ||||||
| "permissions": str(int(self.permissions.value)), | ||||||
Lumabots marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
| } | ||||||
|
|
||||||
|
|
||||||
| class IntegrationTypesConfig: | ||||||
| """Represents per-installation context configuration for an application. | ||||||
|
|
||||||
| This object is used to build the payload for the ``integration_types_config`` field when editing an application. | ||||||
|
|
||||||
| Parameters | ||||||
| ---------- | ||||||
| guild: Optional[:class:`AppInstallParams`] | ||||||
| The configuration for the guild installation context. Omit to leave unchanged; pass ``None`` to clear. | ||||||
| user: Optional[:class:`AppInstallParams`] | ||||||
| The configuration for the user installation context. Omit to leave unchanged; pass ``None`` to clear. | ||||||
| """ | ||||||
|
|
||||||
| __slots__ = ("guild", "user") | ||||||
|
|
||||||
| def __init__( | ||||||
| self, | ||||||
| *, | ||||||
| guild: AppInstallParams | None = utils.MISSING, | ||||||
| user: AppInstallParams | None = utils.MISSING, | ||||||
| ) -> None: | ||||||
| self.guild = guild | ||||||
| self.user = user | ||||||
|
|
||||||
| def _encode_install_params(self, value: AppInstallParams | None) -> dict | None: | ||||||
Lumabots marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
| if value is None: | ||||||
| return None | ||||||
| return {"oauth2_install_params": value.to_payload()} | ||||||
|
|
||||||
| def to_payload(self) -> dict[int, dict[str, object] | None]: | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Idem as above, less important here |
||||||
| payload: dict[int, dict[str, object] | None] = {} | ||||||
| if self.guild is not utils.MISSING: | ||||||
| payload[0] = self._encode_install_params(self.guild) | ||||||
| if self.user is not utils.MISSING: | ||||||
| payload[1] = self._encode_install_params(self.user) | ||||||
| return payload | ||||||
Uh oh!
There was an error while loading. Please reload this page.