Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 84 additions & 1 deletion discord/appinfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ class AppInfo:
"bot_public",
"bot_require_code_grant",
"owner",
"bot",
"_icon",
"_summary",
"verify_key",
Expand All @@ -173,9 +174,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",
Expand All @@ -189,7 +196,7 @@ def __init__(self, state: ConnectionState, data: AppInfoPayload):
self.name: str = data["name"]
self.description: str = data["description"]
self._icon: str | None = data["icon"]
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"])
Expand All @@ -199,6 +206,7 @@ def __init__(self, state: ConnectionState, data: AppInfoPayload):

self._summary: str = data["summary"]
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")

Expand All @@ -213,20 +221,30 @@ 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"
)
self.flags: int | None = data.get("flags")
self.redirect_uris: list[str] | None = data.get("redirect_uris", [])
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", [])
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")
)

def __repr__(self) -> str:
return (
Expand All @@ -235,6 +253,71 @@ def __repr__(self) -> str:
f"owner={self.owner!r}>"
)

async def edit(
self,
*,
description: str | None = utils.MISSING,
terms_of_service_url: str | None = utils.MISSING,
privacy_policy_url: str | None = utils.MISSING,
role_connections_verification_url: str | None = utils.MISSING,
interactions_endpoint_url: str | None = utils.MISSING,
tags: list[str] | None = utils.MISSING,
install_params: dict | None = utils.MISSING,
custom_install_url: 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.

Parameters
----------
description: Optional[:class:`str`]
The new application description. Pass ``None`` to clear.
terms_of_service_url: Optional[:class:`str`]
The application's Terms of Service URL.
privacy_policy_url: Optional[:class:`str`]
The application's Privacy Policy URL.
role_connections_verification_url: Optional[:class:`str`]
The role connection verification URL for the application.
interactions_endpoint_url: Optional[:class:`str`]
The interactions endpoint callback URL.
tags: Optional[List[:class:`str`]]
List of tags for the application (max 5).
install_params: Optional[:class:`dict`]
Dict with keys ``scopes`` (list[str]) and ``permissions`` (str) used for default install link.
custom_install_url: Optional[:class:`str`]
The default custom authorization URL for the application.

Returns
-------
:class:`.AppInfo`
The updated application information.
"""
payload: dict[str, object] = {}
if description is not utils.MISSING:
payload["description"] = description
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 role_connections_verification_url is not utils.MISSING:
payload["role_connections_verification_url"] = (
role_connections_verification_url
)
if interactions_endpoint_url is not utils.MISSING:
payload["interactions_endpoint_url"] = interactions_endpoint_url
if tags is not utils.MISSING:
payload["tags"] = tags
if install_params is not utils.MISSING:
payload["install_params"] = install_params
if custom_install_url is not utils.MISSING:
payload["custom_install_url"] = custom_install_url

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."""
Expand Down
13 changes: 3 additions & 10 deletions discord/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
from .invite import Invite
from .iterators import EntitlementIterator, GuildIterator
from .mentions import AllowedMentions
from .monetization import SKU, Entitlement
from .monetization import SKU
from .object import Object
from .soundboard import SoundboardSound
from .stage_instance import StageInstance
Expand All @@ -77,20 +77,15 @@
if TYPE_CHECKING:
from .abc import GuildChannel, PrivateChannel, Snowflake, SnowflakeTime
from .channel import (
CategoryChannel,
DMChannel,
ForumChannel,
StageChannel,
TextChannel,
VoiceChannel,
)
from .interactions import Interaction
from .member import Member
from .message import Message
from .poll import Poll
from .soundboard import SoundboardSound
from .threads import Thread, ThreadMember
from .ui.item import Item, ViewItem
from .threads import Thread
from .ui.item import ViewItem
from .voice_client import VoiceProtocol

__all__ = ("Client",)
Expand Down Expand Up @@ -1922,8 +1917,6 @@ async def application_info(self) -> AppInfo:
Retrieving the information failed somehow.
"""
data = await self.http.application_info()
if "rpc_origins" not in data:
data["rpc_origins"] = None
return AppInfo(self._connection, data)

async def fetch_user(self, user_id: int, /) -> User:
Expand Down
5 changes: 5 additions & 0 deletions discord/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -3213,6 +3213,11 @@ def get_answer_voters(
def application_info(self) -> Response[appinfo.AppInfo]:
return self.request(Route("GET", "/oauth2/applications/@me"))

def edit_current_application(
self, payload: dict[str, Any]
) -> Response[appinfo.AppInfo]:
return self.request(Route("PATCH", "/applications/@me"), json=payload)

def get_application(
self, application_id: Snowflake, /
) -> Response[appinfo.PartialAppInfo]:
Expand Down
78 changes: 54 additions & 24 deletions discord/types/appinfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,43 +25,73 @@

from __future__ import annotations

from typing import Literal

from typing_extensions import NotRequired, TypedDict

from .guild import Guild
from .snowflake import Snowflake
from .team import Team
from .user import User
from .user import PartialUser

ApplicationIntegrationType = Literal[0, 1]
ApplicationEventWebhookStatus = Literal[1, 2, 3]


class AppInstallParams(TypedDict):
scopes: list[str]
permissions: str


class ApplicationIntegrationTypeConfiguration(TypedDict, total=False):
oauth2_install_params: AppInstallParams


class BaseAppInfo(TypedDict):
id: Snowflake
name: str
verify_key: str
icon: str | None
summary: str
description: str
terms_of_service_url: NotRequired[str]
privacy_policy_url: NotRequired[str]
hook: NotRequired[bool]
max_participants: NotRequired[int]

verify_key: str
# Deprecated by Discord but still present in some payloads; prefer 'description'.
summary: NotRequired[str]

class AppInfo(BaseAppInfo):
team: NotRequired[Team]
icon: NotRequired[str | None]
cover_image: NotRequired[str]
guild_id: NotRequired[Snowflake]
primary_sku_id: NotRequired[Snowflake]
slug: NotRequired[str]
rpc_origins: list[str]
owner: User
bot_public: bool
bot_require_code_grant: bool
guild: NotRequired[Guild]
bot: NotRequired[PartialUser]
owner: NotRequired[PartialUser]
team: NotRequired[Team | None]
rpc_origins: NotRequired[list[str]]
bot_public: NotRequired[bool]
bot_require_code_grant: NotRequired[bool]
terms_of_service_url: NotRequired[str | None]
privacy_policy_url: NotRequired[str | None]
tags: NotRequired[list[str]]
install_params: NotRequired[AppInstallParams]
custom_install_url: NotRequired[str]
integration_types_config: NotRequired[
dict[
ApplicationIntegrationType,
ApplicationIntegrationTypeConfiguration | None,
]
]


class PartialAppInfo(BaseAppInfo):
rpc_origins: NotRequired[list[str]]
cover_image: NotRequired[str]
flags: NotRequired[int]
class AppInfo(BaseAppInfo, total=False):
primary_sku_id: Snowflake
slug: str
flags: int
approximate_guild_count: int
approximate_user_install_count: int
approximate_user_authorization_count: int
redirect_uris: list[str]
interactions_endpoint_url: str | None
role_connections_verification_url: str | None
event_webhooks_url: str | None
event_webhooks_status: ApplicationEventWebhookStatus
event_webhooks_types: list[str]


class AppInstallParams(TypedDict):
scopes: list[str]
permissions: str
class PartialAppInfo(BaseAppInfo, total=False):
pass
Loading