Skip to content

Commit

Permalink
Merge branch 'master' into bridge-hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
baronkobama authored Jun 27, 2022
2 parents 8b1497b + 8ababc0 commit 7415a09
Show file tree
Hide file tree
Showing 29 changed files with 177 additions and 112 deletions.
13 changes: 10 additions & 3 deletions discord/activity.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@
buttons: list[dict]
label: str (max: 32)
url: str (max: 512)
NOTE: Bots cannot access a user's activity button URLs. When received through the
gateway, the type of the buttons field will be list[str].
There are also activity flags which are mostly uninteresting for the library atm.
Expand Down Expand Up @@ -186,13 +188,18 @@ class Activity(BaseActivity):
- ``id``: A string representing the party ID.
- ``size``: A list of up to two integer elements denoting (current_size, maximum_size).
buttons: List[:class:`dict`]
An list of dictionaries representing custom buttons shown in a rich presence.
buttons: Union[List[:class:`dict`], List[:class:`str`]]
A list of dictionaries representing custom buttons shown in a rich presence.
Each dictionary contains the following keys:
- ``label``: A string representing the text shown on the button.
- ``url``: A string representing the URL opened upon clicking the button.
.. note::
Bots cannot access a user's activity button URLs. Therefore the type of this attribute
will be List[:class:`str`] when received through the gateway.
.. versionadded:: 2.0
emoji: Optional[:class:`PartialEmoji`]
Expand Down Expand Up @@ -230,7 +237,7 @@ def __init__(self, **kwargs):
self.flags: int = kwargs.pop("flags", 0)
self.sync_id: Optional[str] = kwargs.pop("sync_id", None)
self.session_id: Optional[str] = kwargs.pop("session_id", None)
self.buttons: List[ActivityButton] = kwargs.pop("buttons", [])
self.buttons: List[str] = kwargs.pop("buttons", [])

activity_type = kwargs.pop("type", -1)
self.type: ActivityType = (
Expand Down
3 changes: 1 addition & 2 deletions discord/audit_logs.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,6 @@ class AuditLogChanges:
"default_notifications",
_enum_transformer(enums.NotificationLevel),
),
"region": (None, _enum_transformer(enums.VoiceRegion)),
"rtc_region": (None, _enum_transformer(enums.VoiceRegion)),
"video_quality_mode": (None, _enum_transformer(enums.VideoQualityMode)),
"privacy_level": (None, _enum_transformer(enums.StagePrivacyLevel)),
Expand Down Expand Up @@ -602,5 +601,5 @@ def _convert_target_sticker(self, target_id: int) -> Union[GuildSticker, Object]
def _convert_target_thread(self, target_id: int) -> Union[Thread, Object]:
return self.guild.get_thread(target_id) or Object(id=target_id)

def _convert_target_scheduled_event(self, target_id: int) -> Union[ScheduledEvent, None]:
def _convert_target_scheduled_event(self, target_id: int) -> Union[ScheduledEvent, Object]:
return self.guild.get_scheduled_event(target_id) or Object(id=target_id)
4 changes: 3 additions & 1 deletion discord/channel.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,12 +191,14 @@ def __repr__(self) -> str:
return f"<{self.__class__.__name__} {joined}>"

def _update(self, guild: Guild, data: Union[TextChannelPayload, ForumChannelPayload]) -> None:
# This data will always exist
self.guild: Guild = guild
self.name: str = data["name"]
self.category_id: Optional[int] = utils._get_as_snowflake(data, "parent_id")
self._type: int = data["type"]

if not data.get("_invoke_flag"):
# This data may be missing depending on how this object is being created/updated
if not data.pop("_invoke_flag", False):
self.topic: Optional[str] = data.get("topic")
self.position: int = data.get("position")
self.nsfw: bool = data.get("nsfw", False)
Expand Down
12 changes: 3 additions & 9 deletions discord/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
from .backoff import ExponentialBackoff
from .channel import PartialMessageable, _threaded_channel_factory
from .emoji import Emoji
from .enums import ChannelType, Status, VoiceRegion
from .enums import ChannelType, Status
from .errors import *
from .flags import ApplicationFlags, Intents
from .gateway import *
Expand Down Expand Up @@ -1319,7 +1319,6 @@ async def create_guild(
self,
*,
name: str,
region: Union[VoiceRegion, str] = VoiceRegion.us_west,
icon: bytes = MISSING,
code: str = MISSING,
) -> Guild:
Expand All @@ -1333,9 +1332,6 @@ async def create_guild(
----------
name: :class:`str`
The name of the guild.
region: :class:`.VoiceRegion`
The region for the voice communication server.
Defaults to :attr:`.VoiceRegion.us_west`.
icon: Optional[:class:`bytes`]
The :term:`py:bytes-like object` representing the icon. See :meth:`.ClientUser.edit`
for more details on what is expected.
Expand All @@ -1362,12 +1358,10 @@ async def create_guild(
else:
icon_base64 = None

region_value = str(region)

if code:
data = await self.http.create_from_template(code, name, region_value, icon_base64)
data = await self.http.create_from_template(code, name, icon_base64)
else:
data = await self.http.create_guild(name, region_value, icon_base64)
data = await self.http.create_guild(name, icon_base64)
return Guild(data=data, state=self._connection)

async def fetch_stage_instance(self, channel_id: int, /) -> StageInstance:
Expand Down
23 changes: 14 additions & 9 deletions discord/commands/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
Union,
)

from ..channel import _guild_channel_factory
from ..channel import _threaded_guild_channel_factory
from ..enums import MessageType, SlashCommandOptionType, try_enum, Enum as DiscordEnum
from ..errors import (
ApplicationCommandError,
Expand All @@ -61,6 +61,7 @@
from ..message import Attachment, Message
from ..object import Object
from ..role import Role
from ..threads import Thread
from ..user import User
from ..utils import async_all, find, utcnow
from .context import ApplicationContext, AutocompleteContext
Expand Down Expand Up @@ -689,7 +690,7 @@ def _parse_options(self, params, *, check_params: bool = True) -> List[Option]:

if not isinstance(option, Option):
if isinstance(p_obj.default, Option):
p_obj.default.input_type = option
p_obj.default.input_type = SlashCommandOptionType.from_datatype(option)
option = p_obj.default
else:
option = Option(option)
Expand Down Expand Up @@ -812,10 +813,12 @@ async def _invoke(self, ctx: ApplicationContext) -> None:
else:
arg = Object(id=int(arg))
elif (_data := resolved.get(f"{op.input_type.name}s", {}).get(arg)) is not None:
if op.input_type is SlashCommandOptionType.channel and int(arg) in ctx.guild._channels:
arg = ctx.guild.get_channel(int(arg))
if op.input_type is SlashCommandOptionType.channel and (
int(arg) in ctx.guild._channels or int(arg) in ctx.guild._threads
):
arg = ctx.guild.get_channel_or_thread(int(arg))
_data["_invoke_flag"] = True
arg._update(ctx.guild, _data)
arg._update(_data) if isinstance(arg, Thread) else arg._update(ctx.guild, _data)
else:
obj_type = None
kw = {}
Expand All @@ -826,10 +829,12 @@ async def _invoke(self, ctx: ApplicationContext) -> None:
kw["guild"] = ctx.guild
elif op.input_type is SlashCommandOptionType.channel:
# NOTE:
# This is a fallback in case the channel is not found in the guild's channels.
# If this fallback occurs, at the very minimum, permissions will be incorrect
# due to a lack of permission_overwrite data.
obj_type = _guild_channel_factory(_data["type"])[0]
# This is a fallback in case the channel/thread is not found in the
# guild's channels/threads. For channels, if this fallback occurs, at the very minimum,
# permissions will be incorrect due to a lack of permission_overwrite data.
# For threads, if this fallback occurs, info like thread owner id, message count,
# flags, and more will be missing due to a lack of data sent by Discord.
obj_type = _threaded_guild_channel_factory(_data["type"])[0]
kw["guild"] = ctx.guild
elif op.input_type is SlashCommandOptionType.attachment:
obj_type = Attachment
Expand Down
8 changes: 8 additions & 0 deletions discord/commands/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@


class ThreadOption:
"""Represents a class that can be passed as the input_type for an Option class.
Parameters
-----------
thread_type: Literal["public", "private", "news"]
The thread type to expect for this options input.
"""

def __init__(self, thread_type: Literal["public", "private", "news"]):
type_map = {
"public": ChannelType.public_thread,
Expand Down
2 changes: 1 addition & 1 deletion discord/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,7 @@ def target_type(self) -> Optional[str]:
return "scheduled_event"
elif v < 113:
return "thread"
elif v < 121:
elif v < 122:
return "application_command_permission"


Expand Down
26 changes: 23 additions & 3 deletions discord/ext/commands/converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ class ObjectConverter(IDConverter[discord.Object]):
"""

async def convert(self, ctx: Context, argument: str) -> discord.Object:
match = self._get_id_match(argument) or re.match(r"<(?:@(?:!|&)?|#)([0-9]{15,20})>$", argument)
match = self._get_id_match(argument) or re.match(r"<(?:@[!&]?|#)([0-9]{15,20})>$", argument)

if match is None:
raise ObjectNotFound(argument)
Expand Down Expand Up @@ -563,6 +563,25 @@ async def convert(self, ctx: Context, argument: str) -> discord.CategoryChannel:
return GuildChannelConverter._resolve_channel(ctx, argument, "categories", discord.CategoryChannel)


class ForumChannelConverter(IDConverter[discord.ForumChannel]):
"""Converts to a :class:`~discord.ForumChannel`.
All lookups are via the local guild. If in a DM context, then the lookup
is done by the global cache.
The lookup strategy is as follows (in order):
1. Lookup by ID.
2. Lookup by mention.
3. Lookup by name
.. versionadded:: 2.0
"""

async def convert(self, ctx: Context, argument: str) -> discord.ForumChannel:
return GuildChannelConverter._resolve_channel(ctx, argument, "forum_channels", discord.ForumChannel)


class ThreadConverter(IDConverter[discord.Thread]):
"""Coverts to a :class:`~discord.Thread`.
Expand Down Expand Up @@ -767,7 +786,7 @@ class EmojiConverter(IDConverter[discord.Emoji]):
"""

async def convert(self, ctx: Context, argument: str) -> discord.Emoji:
match = self._get_id_match(argument) or re.match(r"<a?:[a-zA-Z0-9\_]{1,32}:([0-9]{15,20})>$", argument)
match = self._get_id_match(argument) or re.match(r"<a?:\w{1,32}:([0-9]{15,20})>$", argument)
result = None
bot = ctx.bot
guild = ctx.guild
Expand Down Expand Up @@ -801,7 +820,7 @@ class PartialEmojiConverter(Converter[discord.PartialEmoji]):
"""

async def convert(self, ctx: Context, argument: str) -> discord.PartialEmoji:
match = re.match(r"<(a?):([a-zA-Z0-9\_]{1,32}):([0-9]{15,20})>$", argument)
match = re.match(r"<(a?):(\w{1,32}):([0-9]{15,20})>$", argument)

if match:
emoji_animated = bool(match.group(1))
Expand Down Expand Up @@ -1043,6 +1062,7 @@ def is_generic_type(tp: Any, *, _GenericAlias: Type = _GenericAlias) -> bool:
discord.Emoji: EmojiConverter,
discord.PartialEmoji: PartialEmojiConverter,
discord.CategoryChannel: CategoryChannelConverter,
discord.ForumChannel: ForumChannelConverter,
discord.Thread: ThreadConverter,
discord.abc.GuildChannel: GuildChannelConverter,
discord.GuildSticker: GuildStickerConverter,
Expand Down
4 changes: 2 additions & 2 deletions discord/ext/commands/flags.py
Original file line number Diff line number Diff line change
Expand Up @@ -342,9 +342,9 @@ def __new__(
aliases = {key.casefold(): value.casefold() for key, value in aliases.items()}
regex_flags = re.IGNORECASE

keys = list(re.escape(k) for k in flags)
keys = [re.escape(k) for k in flags]
keys.extend(re.escape(a) for a in aliases)
keys = sorted(keys, key=lambda t: len(t), reverse=True)
keys = sorted(keys, key=len, reverse=True)

joined = "|".join(keys)
pattern = re.compile(
Expand Down
8 changes: 3 additions & 5 deletions discord/gateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -395,11 +395,9 @@ async def identify(self):
"d": {
"token": self.token,
"properties": {
"$os": sys.platform,
"$browser": "pycord",
"$device": "pycord",
"$referrer": "",
"$referring_domain": "",
"os": sys.platform,
"browser": "pycord",
"device": "pycord",
},
"compress": True,
"large_threshold": 250,
Expand Down
15 changes: 2 additions & 13 deletions discord/guild.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,6 @@ class Guild(Hashable):
All stickers that the guild owns.
.. versionadded:: 2.0
region: :class:`VoiceRegion`
The region the guild belongs on. There is a chance that the region
will be a :class:`str` if the value is not recognised by the enumerator.
afk_timeout: :class:`int`
The timeout to get sent to the AFK channel.
afk_channel: Optional[:class:`VoiceChannel`]
Expand Down Expand Up @@ -280,7 +277,6 @@ class Guild(Hashable):
"name",
"id",
"unavailable",
"region",
"owner_id",
"mfa_level",
"emojis",
Expand Down Expand Up @@ -355,8 +351,8 @@ def _add_member(self, member: Member, /) -> None:
self._members[member.id] = member

def _get_and_update_member(self, payload: MemberPayload, user_id: int, cache_flag: bool, /) -> Member:
# we always get the member, and we only update if the cache_flag (this cache flag should
# always be MemberCacheFlag.interaction or MemberCacheFlag.option) is set to True
# we always get the member, and we only update if the cache_flag (this cache
# flag should always be MemberCacheFlag.interaction) is set to True
if user_id in self._members:
member = self.get_member(user_id)
member._update(payload) if cache_flag else None
Expand Down Expand Up @@ -483,7 +479,6 @@ def _from_data(self, guild: GuildPayload) -> None:
self._member_count: int = member_count

self.name: str = guild.get("name")
self.region: VoiceRegion = try_enum(VoiceRegion, guild.get("region"))
self.verification_level: VerificationLevel = try_enum(VerificationLevel, guild.get("verification_level"))
self.default_notifications: NotificationLevel = try_enum(
NotificationLevel, guild.get("default_message_notifications")
Expand Down Expand Up @@ -1592,7 +1587,6 @@ async def edit(
splash: Optional[bytes] = MISSING,
discovery_splash: Optional[bytes] = MISSING,
community: bool = MISSING,
region: Optional[Union[str, VoiceRegion]] = MISSING,
afk_channel: Optional[VoiceChannel] = MISSING,
owner: Snowflake = MISSING,
afk_timeout: int = MISSING,
Expand Down Expand Up @@ -1651,8 +1645,6 @@ async def edit(
community: :class:`bool`
Whether the guild should be a Community guild. If set to ``True``\, both ``rules_channel``
and ``public_updates_channel`` parameters are required.
region: Union[:class:`str`, :class:`VoiceRegion`]
The new region for the guild's voice communication.
afk_channel: Optional[:class:`VoiceChannel`]
The new channel that is the AFK channel. Could be ``None`` for no AFK channel.
afk_timeout: :class:`int`
Expand Down Expand Up @@ -1779,9 +1771,6 @@ async def edit(

fields["owner_id"] = owner.id

if region is not MISSING:
fields["region"] = str(region)

if verification_level is not MISSING:
if not isinstance(verification_level, VerificationLevel):
raise InvalidArgument("verification_level field must be of type VerificationLevel")
Expand Down
Loading

0 comments on commit 7415a09

Please sign in to comment.