Browse Source

Merge branch 'master' into feature/guild_onboarding

pull/9260/head
Josh 2 years ago
parent
commit
a8501385ea
  1. 2
      discord/app_commands/models.py
  2. 24
      discord/audit_logs.py
  3. 4
      discord/channel.py
  4. 21
      discord/ext/commands/core.py
  5. 11
      discord/flags.py
  6. 11
      discord/guild.py
  7. 2
      discord/message.py
  8. 1
      discord/state.py
  9. 4
      discord/threads.py
  10. 2
      discord/utils.py
  11. 38
      docs/api.rst
  12. 7
      docs/discord.rst
  13. BIN
      docs/images/discord_create_bot_user.png

2
discord/app_commands/models.py

@ -673,7 +673,7 @@ class AppCommandThread(Hashable):
archiver_id: Optional[:class:`int`]
The user's ID that archived this thread.
auto_archive_duration: :class:`int`
The duration in minutes until the thread is automatically archived due to inactivity.
The duration in minutes until the thread is automatically hidden from the channel list.
Usually a value of 60, 1440, 4320 and 10080.
archive_timestamp: :class:`datetime.datetime`
An aware timestamp of when the thread's archived status was last updated in UTC.

24
discord/audit_logs.py

@ -76,6 +76,7 @@ if TYPE_CHECKING:
from .types.onboarding import Prompt as PromptPayload, PromptOption as PromptOptionPayload
from .user import User
from .app_commands import AppCommand
from .webhook import Webhook
TargetType = Union[
Guild,
@ -91,6 +92,9 @@ if TYPE_CHECKING:
Object,
PartialIntegration,
AutoModRule,
ScheduledEvent,
Webhook,
AppCommand,
None,
]
@ -597,6 +601,7 @@ class AuditLogEntry(Hashable):
integrations: Mapping[int, PartialIntegration],
app_commands: Mapping[int, AppCommand],
automod_rules: Mapping[int, AutoModRule],
webhooks: Mapping[int, Webhook],
data: AuditLogEntryPayload,
guild: Guild,
):
@ -606,6 +611,7 @@ class AuditLogEntry(Hashable):
self._integrations: Mapping[int, PartialIntegration] = integrations
self._app_commands: Mapping[int, AppCommand] = app_commands
self._automod_rules: Mapping[int, AutoModRule] = automod_rules
self._webhooks: Mapping[int, Webhook] = webhooks
self._from_data(data)
def _from_data(self, data: AuditLogEntryPayload) -> None:
@ -744,12 +750,11 @@ class AuditLogEntry(Hashable):
if self.action.target_type is None:
return None
if self._target_id is None:
return None
try:
converter = getattr(self, '_convert_target_' + self.action.target_type)
except AttributeError:
if self._target_id is None:
return None
return Object(id=self._target_id)
else:
return converter(self._target_id)
@ -782,7 +787,12 @@ class AuditLogEntry(Hashable):
def _convert_target_channel(self, target_id: int) -> Union[abc.GuildChannel, Object]:
return self.guild.get_channel(target_id) or Object(id=target_id)
def _convert_target_user(self, target_id: int) -> Union[Member, User, Object]:
def _convert_target_user(self, target_id: Optional[int]) -> Optional[Union[Member, User, Object]]:
# For some reason the member_disconnect and member_move action types
# do not have a non-null target_id so safeguard against that
if target_id is None:
return None
return self._get_member(target_id) or Object(id=target_id, type=Member)
def _convert_target_role(self, target_id: int) -> Union[Role, Object]:
@ -862,3 +872,9 @@ class AuditLogEntry(Hashable):
def _convert_target_auto_moderation(self, target_id: int) -> Union[AutoModRule, Object]:
return self._automod_rules.get(target_id) or Object(target_id, type=AutoModRule)
def _convert_target_webhook(self, target_id: int) -> Union[Webhook, Object]:
# circular import
from .webhook import Webhook
return self._webhooks.get(target_id) or Object(target_id, type=Webhook)

4
discord/channel.py

@ -737,7 +737,7 @@ class TextChannel(discord.abc.Messageable, discord.abc.GuildChannel, Hashable):
If ``None`` is passed then a private thread is created.
Defaults to ``None``.
auto_archive_duration: :class:`int`
The duration in minutes before a thread is automatically archived for inactivity.
The duration in minutes before a thread is automatically hidden from the channel list.
If not provided, the channel's default auto archive duration is used.
Must be one of ``60``, ``1440``, ``4320``, or ``10080``, if provided.
@ -2607,7 +2607,7 @@ class ForumChannel(discord.abc.GuildChannel, Hashable):
name: :class:`str`
The name of the thread.
auto_archive_duration: :class:`int`
The duration in minutes before a thread is automatically archived for inactivity.
The duration in minutes before a thread is automatically hidden from the channel list.
If not provided, the channel's default auto archive duration is used.
Must be one of ``60``, ``1440``, ``4320``, or ``10080``, if provided.

21
discord/ext/commands/core.py

@ -2036,7 +2036,7 @@ def has_role(item: Union[int, str], /) -> Check[Any]:
# ctx.guild is None doesn't narrow ctx.author to Member
if isinstance(item, int):
role = discord.utils.get(ctx.author.roles, id=item) # type: ignore
role = ctx.author.get_role(item) # type: ignore
else:
role = discord.utils.get(ctx.author.roles, name=item) # type: ignore
if role is None:
@ -2083,8 +2083,12 @@ def has_any_role(*items: Union[int, str]) -> Callable[[T], T]:
raise NoPrivateMessage()
# ctx.guild is None doesn't narrow ctx.author to Member
getter = functools.partial(discord.utils.get, ctx.author.roles)
if any(getter(id=item) is not None if isinstance(item, int) else getter(name=item) is not None for item in items):
if any(
ctx.author.get_role(item) is not None
if isinstance(item, int)
else discord.utils.get(ctx.author.roles, name=item) is not None
for item in items
):
return True
raise MissingAnyRole(list(items))
@ -2113,11 +2117,10 @@ def bot_has_role(item: int, /) -> Callable[[T], T]:
if ctx.guild is None:
raise NoPrivateMessage()
me = ctx.me
if isinstance(item, int):
role = discord.utils.get(me.roles, id=item)
role = ctx.me.get_role(item)
else:
role = discord.utils.get(me.roles, name=item)
role = discord.utils.get(ctx.me.roles, name=item)
if role is None:
raise BotMissingRole(item)
return True
@ -2144,8 +2147,10 @@ def bot_has_any_role(*items: int) -> Callable[[T], T]:
raise NoPrivateMessage()
me = ctx.me
getter = functools.partial(discord.utils.get, me.roles)
if any(getter(id=item) is not None if isinstance(item, int) else getter(name=item) is not None for item in items):
if any(
me.get_role(item) is not None if isinstance(item, int) else discord.utils.get(me.roles, name=item) is not None
for item in items
):
return True
raise BotMissingAnyRole(list(items))

11
discord/flags.py

@ -25,6 +25,7 @@ DEALINGS IN THE SOFTWARE.
from __future__ import annotations
from functools import reduce
from operator import or_
from typing import TYPE_CHECKING, Any, Callable, ClassVar, Dict, Iterator, List, Optional, Tuple, Type, TypeVar, overload
from .enums import UserFlags
@ -1566,7 +1567,15 @@ class ArrayFlags(BaseFlags):
@classmethod
def _from_value(cls: Type[Self], value: List[int]) -> Self:
self = cls.__new__(cls)
self.value = reduce(lambda a, b: a | (1 << b - 1), value, 0)
# This is a micro-optimization given the frequency this object can be created.
# (1).__lshift__ is used in place of lambda x: 1 << x
# prebinding to a method of a constant rather than define a lambda.
# Pairing this with map, is essentially equivalent to (1 << x for x in value)
# reduction using operator.or_ instead of defining a lambda each call
# Discord sends these starting with a value of 1
# Rather than subtract 1 from each element prior to left shift,
# we shift right by 1 once at the end.
self.value = reduce(or_, map((1).__lshift__, value), 0) >> 1
return self
def to_array(self) -> List[int]:

11
discord/guild.py

@ -319,9 +319,9 @@ class Guild(Hashable):
)
_PREMIUM_GUILD_LIMITS: ClassVar[Dict[Optional[int], _GuildLimit]] = {
None: _GuildLimit(emoji=50, stickers=5, bitrate=96e3, filesize=8388608),
0: _GuildLimit(emoji=50, stickers=5, bitrate=96e3, filesize=8388608),
1: _GuildLimit(emoji=100, stickers=15, bitrate=128e3, filesize=8388608),
None: _GuildLimit(emoji=50, stickers=5, bitrate=96e3, filesize=26214400),
0: _GuildLimit(emoji=50, stickers=5, bitrate=96e3, filesize=26214400),
1: _GuildLimit(emoji=100, stickers=15, bitrate=128e3, filesize=26214400),
2: _GuildLimit(emoji=150, stickers=30, bitrate=256e3, filesize=52428800),
3: _GuildLimit(emoji=250, stickers=60, bitrate=384e3, filesize=104857600),
}
@ -3861,6 +3861,7 @@ class Guild(Hashable):
# avoid circular import
from .app_commands import AppCommand
from .webhook import Webhook
while True:
retrieve = 100 if limit is None else min(limit, 100)
@ -3887,6 +3888,9 @@ class Guild(Hashable):
)
automod_rule_map = {rule.id: rule for rule in automod_rules}
webhooks = (Webhook.from_state(data=raw_webhook, state=self._state) for raw_webhook in data.get('webhooks', []))
webhook_map = {webhook.id: webhook for webhook in webhooks}
count = 0
for count, raw_entry in enumerate(raw_entries, 1):
@ -3900,6 +3904,7 @@ class Guild(Hashable):
integrations=integration_map,
app_commands=app_command_map,
automod_rules=automod_rule_map,
webhooks=webhook_map,
guild=self,
)

2
discord/message.py

@ -1215,7 +1215,7 @@ class PartialMessage(Hashable):
name: :class:`str`
The name of the thread.
auto_archive_duration: :class:`int`
The duration in minutes before a thread is automatically archived for inactivity.
The duration in minutes before a thread is automatically hidden from the channel list.
If not provided, the channel's default auto archive duration is used.
Must be one of ``60``, ``1440``, ``4320``, or ``10080``, if provided.

1
discord/state.py

@ -1108,6 +1108,7 @@ class ConnectionState(Generic[ClientT]):
integrations={},
app_commands={},
automod_rules={},
webhooks={},
data=data,
guild=guild,
)

4
discord/threads.py

@ -122,7 +122,7 @@ class Thread(Messageable, Hashable):
archiver_id: Optional[:class:`int`]
The user's ID that archived this thread.
auto_archive_duration: :class:`int`
The duration in minutes until the thread is automatically archived due to inactivity.
The duration in minutes until the thread is automatically hidden from the channel list.
Usually a value of 60, 1440, 4320 and 10080.
archive_timestamp: :class:`datetime.datetime`
An aware timestamp of when the thread's archived status was last updated in UTC.
@ -608,7 +608,7 @@ class Thread(Messageable, Hashable):
Whether non-moderators can add other non-moderators to this thread.
Only available for private threads.
auto_archive_duration: :class:`int`
The new duration in minutes before a thread is automatically archived for inactivity.
The new duration in minutes before a thread is automatically hidden from the channel list.
Must be one of ``60``, ``1440``, ``4320``, or ``10080``.
slowmode_delay: :class:`int`
Specifies the slowmode rate limit for user in this thread, in seconds.

2
discord/utils.py

@ -900,7 +900,7 @@ _MARKDOWN_ESCAPE_REGEX = re.compile(fr'(?P<markdown>{_MARKDOWN_ESCAPE_SUBREGEX}|
_URL_REGEX = r'(?P<url><[^: >]+:\/[^ >]+>|(?:https?|steam):\/\/[^\s<]+[^<.,:;\"\'\]\s])'
_MARKDOWN_STOCK_REGEX = fr'(?P<markdown>[_\\~|\*`]|{_MARKDOWN_ESCAPE_COMMON})'
_MARKDOWN_STOCK_REGEX = fr'(?P<markdown>[_\\~|\*`#-]|{_MARKDOWN_ESCAPE_COMMON})'
def remove_markdown(text: str, *, ignore_links: bool = True) -> str:

38
docs/api.rst

@ -3477,6 +3477,12 @@ AuditLogDiff
:type: :class:`str`
.. attribute:: guild
The guild of something.
:type: :class:`Guild`
.. attribute:: icon
A guild's or role's icon. See also :attr:`Guild.icon` or :attr:`Role.icon`.
@ -4051,6 +4057,38 @@ AuditLogDiff
:type: :class:`ChannelFlags`
.. attribute:: default_thread_slowmode_delay
The default slowmode delay for threads created in this text channel or forum.
See also :attr:`TextChannel.default_thread_slowmode_delay` and :attr:`ForumChannel.default_thread_slowmode_delay`
:type: :class:`int`
.. attribute:: applied_tags
The applied tags of a forum post.
See also :attr:`Thread.applied_tags`
:type: List[Union[:class:`ForumTag`, :class:`Object`]]
.. attribute:: available_tags
The available tags of a forum.
See also :attr:`ForumChannel.available_tags`
:type: Sequence[:class:`ForumTag`]
.. attribute:: default_reaction_emoji
The default_reaction_emoji for forum posts.
See also :attr:`ForumChannel.default_reaction_emoji`
:type: :class:`default_reaction_emoji`
.. attribute:: options
The onboarding prompt options associated with this onboarding prompt.

7
docs/discord.rst

@ -21,12 +21,7 @@ Creating a Bot account is a pretty straightforward process.
.. image:: /images/discord_create_app_form.png
:alt: The new application form filled in.
5. Create a Bot User by navigating to the "Bot" tab and clicking "Add Bot".
- Click "Yes, do it!" to continue.
.. image:: /images/discord_create_bot_user.png
:alt: The Add Bot button.
5. Navigate to the "Bot" tab to configure it.
6. Make sure that **Public Bot** is ticked if you want others to invite your bot.
- You should also make sure that **Require OAuth2 Code Grant** is unchecked unless you

BIN
docs/images/discord_create_bot_user.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Loading…
Cancel
Save