Skip to content

Commit 712584b

Browse files
authored
Merge branch 'master' into master
2 parents 04e2bc8 + b872cfe commit 712584b

35 files changed

+461
-288
lines changed

.gitignore

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
*.py[cod]
33
*.log
44
*.egg-info
5-
venv
6-
.venv
5+
venv/
6+
.venv/
77
docs/_build
88
docs/crowdin.py
99
*.buildinfo
@@ -15,5 +15,9 @@ docs/crowdin.py
1515
*.flac
1616
*.mo
1717
.idea/
18+
.DS_Store
19+
.python-version
20+
__pycache__
1821
.vs/slnx.sqlite
1922
env/
23+
build/

README.rst

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
pycord
2-
==========
2+
======
33

44
.. image:: https://discord.com/api/guilds/881207955029110855/embed.png
55
:target: https://pycord.dev/discord
@@ -17,7 +17,7 @@ pycord
1717
A fork of discord.py. PyCord is a modern, easy to use, feature-rich, and async ready API wrapper for Discord written in Python.
1818

1919
Key Features
20-
-------------
20+
------------
2121

2222
- Modern Pythonic API using ``async`` and ``await``.
2323
- Proper rate limit handling.
@@ -49,6 +49,15 @@ Otherwise to get voice support you should run the following command:
4949
# Windows
5050
py -3 -m pip install -U py-cord[voice]
5151
52+
To install additional packages for speedup, run the following command:
53+
54+
.. code:: sh
55+
56+
# Linux/macOS
57+
python3 -m pip install -U "py-cord[speed]"
58+
# Windows
59+
py -3 -m pip install -U py-cord[speed]
60+
5261
5362
To install the development version, do the following:
5463

@@ -60,17 +69,19 @@ To install the development version, do the following:
6069
6170
6271
Optional Packages
63-
~~~~~~~~~~~~~~~~~~
72+
~~~~~~~~~~~~~~~~~
6473

6574
* `PyNaCl <https://pypi.org/project/PyNaCl/>`__ (for voice support)
75+
* `aiodns <https://pypi.org/project/aiodns/>`__, `Brotli <https://pypi.org/project/Brotli/>`__, `cchardet <https://pypi.org/project/cchardet/>`__ (for aiohttp speedup)
76+
* `orjson <https://pypi.org/project/orjson/>`__ (for json speedup)
6677

6778
Please note that while installing voice support on Linux, you must install the following packages via your preferred package manager (e.g. ``apt``, ``dnf``, etc) BEFORE running the above commands:
6879

6980
* libffi-dev (or ``libffi-devel`` on some systems)
7081
* python-dev (e.g. ``python3.6-dev`` for Python 3.6)
7182

7283
Quick Example
73-
--------------
84+
-------------
7485

7586
.. code:: py
7687
@@ -89,8 +100,8 @@ Quick Example
89100
90101
bot.run("token")
91102
92-
Normal Commands Example
93-
~~~~~~~~~~~~~
103+
Traditional Commands Example
104+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
94105

95106
.. code:: py
96107
@@ -110,9 +121,9 @@ You can find more examples in the examples directory.
110121
Note: Make sure you do not reveal your bot token to anyone, it can grant access to your bot.
111122

112123
Links
113-
------
124+
-----
114125

115126
- `Documentation <https://docs.pycord.dev/en/master/index.html>`_
116-
- `Official Discord Server <https://pycord.dev/discord>`_
117-
- `Discord Developers <https://discord.gg/discord-developers>`_
118-
- `Discord API <https://discord.gg/discord-api>`_
127+
- `Our Official Discord Server <https://pycord.dev/discord>`_
128+
- `Official Discord Developers Server <https://discord.gg/discord-developers>`_
129+
- `Unofficial Discord API Server <https://discord.gg/discord-api>`_

discord/commands/commands.py

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,21 +26,22 @@
2626
from __future__ import annotations
2727

2828
import asyncio
29-
import types
3029
import functools
3130
import inspect
31+
import re
32+
import types
3233
from collections import OrderedDict
3334
from typing import Any, Callable, Dict, List, Optional, Union, TYPE_CHECKING
3435

36+
from .context import ApplicationContext, AutocompleteContext
37+
from .errors import ApplicationCommandError, CheckFailure, ApplicationCommandInvokeError
38+
from .permissions import Permission
3539
from ..enums import SlashCommandOptionType, ChannelType
40+
from ..errors import ValidationError, ClientException
3641
from ..member import Member
37-
from ..user import User
3842
from ..message import Message
39-
from .context import ApplicationContext, AutocompleteContext
43+
from ..user import User
4044
from ..utils import find, get_or_fetch, async_all
41-
from ..errors import ValidationError, ClientException
42-
from .errors import ApplicationCommandError, CheckFailure, ApplicationCommandInvokeError
43-
from .permissions import Permission
4445

4546
__all__ = (
4647
"_BaseCommand",
@@ -390,7 +391,7 @@ def __init__(self, func: Callable, *args, **kwargs) -> None:
390391
self.cog = None
391392

392393
params = self._get_signature_parameters()
393-
self.options: List[Option] = self._parse_options(params)
394+
self.options: List[Option] = kwargs.get('options') or self._parse_options(params)
394395

395396
try:
396397
checks = func.__commands_checks__
@@ -459,6 +460,9 @@ def _parse_options(self, params) -> List[Option]:
459460
option.name = p_name
460461
option._parameter_name = p_name
461462

463+
validate_chat_input_name(option.name)
464+
validate_chat_input_description(option.description)
465+
462466
final_options.append(option)
463467

464468
return final_options
@@ -645,7 +649,7 @@ def __init__(
645649
minmax_types = (int, float, type(None))
646650
else:
647651
minmax_types = (type(None),)
648-
minmax_typehint = Optional[Union[minmax_types]] # type: ignore
652+
minmax_typehint = Optional[Union[minmax_types]] # type: ignore
649653

650654
self.min_value: minmax_typehint = kwargs.pop("min_value", None)
651655
self.max_value: minmax_typehint = kwargs.pop("max_value", None)
@@ -1128,24 +1132,33 @@ def command(**kwargs):
11281132
"""
11291133
return application_command(**kwargs)
11301134

1135+
1136+
docs = "https://discord.com/developers/docs"
1137+
1138+
11311139
# Validation
11321140
def validate_chat_input_name(name: Any):
1141+
# Must meet the regex ^[\w-]{1,32}$
11331142
if not isinstance(name, str):
1134-
raise TypeError("Name of a command must be a string.")
1135-
if " " in name:
1136-
raise ValidationError("Name of a chat input command cannot have spaces.")
1137-
if not name.islower():
1138-
raise ValidationError("Name of a chat input command must be lowercase.")
1139-
if len(name) > 32 or len(name) < 1:
1143+
raise TypeError(f"Chat input command names and options must be of type str. Received {name}")
1144+
if not re.match(r"^[\w-]{1,32}$", name):
1145+
raise ValidationError(
1146+
r'Chat input command names and options must follow the regex "^[\w-]{1,32}$". For more information, see '
1147+
f"{docs}/interactions/application-commands#application-command-object-application-command-naming. Received "
1148+
f"{name}"
1149+
)
1150+
if not 1 <= len(name) <= 32:
11401151
raise ValidationError(
1141-
"Name of a chat input command must be less than 32 characters and non empty."
1152+
f"Chat input command names and options must be 1-32 characters long. Received {name}"
11421153
)
1154+
if not name.lower() == name: # Can't use islower() as it fails if none of the chars can be lower. See #512.
1155+
raise ValidationError(f"Chat input command names and options must be lowercase. Received {name}")
11431156

11441157

11451158
def validate_chat_input_description(description: Any):
11461159
if not isinstance(description, str):
1147-
raise TypeError("Description of a command must be a string.")
1148-
if len(description) > 100 or len(description) < 1:
1160+
raise TypeError(f"Command description must be of type str. Received {description}")
1161+
if not 1 <= len(description) <= 100:
11491162
raise ValidationError(
1150-
"Description of a chat input command must be less than 100 characters and non empty."
1163+
f"Command description must be 1-100 characters long. Received {description}"
11511164
)

discord/commands/context.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ def author(self) -> Optional[Union[Member, User]]:
109109

110110
@property
111111
def voice_client(self):
112+
if self.guild is None:
113+
return None
114+
112115
return self.guild.voice_client
113116

114117
@cached_property

discord/enums.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -669,26 +669,26 @@ def from_datatype(cls, datatype):
669669
class EmbeddedActivity(Enum):
670670
awkword = 879863881349087252
671671
betrayal = 773336526917861400
672-
cg2_qa = 832012815819604009
673-
cg2_staging = 832012730599735326
674-
cg3_dev = 832012682520428625
675-
cg3_prod = 832013003968348200
676-
cg3_qa = 832012894068801636
677-
cg3_staging = 832012938398400562
678-
cg4_dev = 832013108234289153
679-
cg4_prod = 832025144389533716
680-
cg4_qa = 832025114077298718
681-
cg4_staging = 832025061657280566
682-
chess_in_the_park_dev = 832012586023256104
672+
checkers_in_the_park = 832013003968348200
673+
checkers_in_the_park_dev = 832012682520428625
674+
checkers_in_the_park_staging = 832012938398400562
675+
checkers_in_the_park_qa = 832012894068801636
683676
chess_in_the_park = 832012774040141894
677+
chess_in_the_park_dev = 832012586023256104
678+
chest_in_the_park_staging = 832012730599735326
679+
chest_in_the_park_qa = 832012815819604009
684680
decoders_dev = 891001866073296967
685681
doodle_crew = 878067389634314250
686682
doodle_crew_dev = 878067427668275241
687683
fishington = 814288819477020702
688684
letter_tile = 879863686565621790
689-
pn_staging = 763116274876022855
685+
ocho = 832025144389533716
686+
ocho_dev = 832013108234289153
687+
ocho_staging = 832025061657280566
688+
ocho_qa = 832025114077298718
690689
poker_night = 755827207812677713
691-
poker_qa = 801133024841957428
690+
poker_night_staging = 763116274876022855
691+
poker_night_qa = 801133024841957428
692692
putts = 832012854282158180
693693
sketchy_artist = 879864070101172255
694694
sketchy_artist_dev = 879864104980979792

discord/ext/commands/bot.py

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -922,22 +922,6 @@ async def on_message(self, message):
922922
await self.process_commands(message)
923923

924924

925-
926-
927-
928-
929-
930-
931-
932-
933-
934-
935-
936-
937-
938-
939-
940-
941925
class Bot(BotBase, discord.Bot):
942926
"""Represents a discord bot.
943927

discord/ext/tasks/__init__.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -565,11 +565,13 @@ def _get_next_sleep_time(self) -> datetime.datetime:
565565

566566
if self._current_loop == 0:
567567
self._time_index += 1
568-
return datetime.datetime.combine(datetime.datetime.now(datetime.timezone.utc), next_time)
568+
if next_time > datetime.datetime.now(datetime.timezone.utc).timetz():
569+
return datetime.datetime.combine(datetime.datetime.now(datetime.timezone.utc), next_time)
570+
else:
571+
return datetime.datetime.combine(datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(days=1), next_time)
569572

570-
next_date = self._last_iteration
571-
if self._time_index == 0:
572-
# we can assume that the earliest time should be scheduled for "tomorrow"
573+
next_date = cast(datetime.datetime, self._last_iteration)
574+
if next_time < next_date.timetz():
573575
next_date += datetime.timedelta(days=1)
574576

575577
self._time_index += 1

discord/flags.py

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -376,11 +376,6 @@ def bug_hunter(self):
376376
""":class:`bool`: Returns ``True`` if the user is a Bug Hunter"""
377377
return UserFlags.bug_hunter.value
378378

379-
@flag_value
380-
def mfa_sms(self):
381-
""":class:`bool`: Returns ``True`` if the user has SMS recovery for 2FA enabled"""
382-
return UserFlags.mfa_sms.value
383-
384379
@flag_value
385380
def premium_promo_dismissed(self):
386381
""":class:`bool`: Returns ``True`` if the user is marked as dismissed Nitro promotion"""
@@ -411,11 +406,6 @@ def team_user(self):
411406
""":class:`bool`: Returns ``True`` if the user is a Team User."""
412407
return UserFlags.team_user.value
413408

414-
@flag_value
415-
def partner_or_verification_application(self):
416-
""":class:`bool`: Relates to partner/verification applications."""
417-
return UserFlags.partner_or_verification_application.value
418-
419409
@flag_value
420410
def system(self):
421411
""":class:`bool`: Returns ``True`` if the user is a system user (i.e. represents Discord officially)."""
@@ -426,16 +416,6 @@ def bug_hunter_level_2(self):
426416
""":class:`bool`: Returns ``True`` if the user is a Bug Hunter Level 2"""
427417
return UserFlags.bug_hunter_level_2.value
428418

429-
@flag_value
430-
def has_unread_urgent_messages(self):
431-
""":class:`bool`: Returns ``True`` if the user has a unread urgent messages."""
432-
return UserFlags.has_unread_urgent_messages.value
433-
434-
@flag_value
435-
def underage_deleted(self):
436-
""":class:`bool`: Returns ``True`` if the user has a pending deletion for being underage in DOB prompt"""
437-
return UserFlags.underage_deleted.value
438-
439419
@flag_value
440420
def verified_bot(self):
441421
""":class:`bool`: Returns ``True`` if the user is a Verified Bot."""
@@ -470,14 +450,6 @@ def bot_http_interactions(self):
470450
"""
471451
return UserFlags.bot_http_interactions.value
472452

473-
@flag_value
474-
def spammer(self):
475-
""":class:`bool`: Returns ``True`` if the user is disabled for being a spammer.
476-
477-
.. versionadded:: 2.0
478-
"""
479-
return UserFlags.spammer.value
480-
481453
def all(self) -> List[UserFlags]:
482454
"""List[:class:`UserFlags`]: Returns all public flags the user has."""
483455
return [public_flag for public_flag in UserFlags if self._has_flag(public_flag.value)]

discord/guild.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3025,7 +3025,7 @@ async def edit_welcome_screen(
30253025
self,
30263026
*,
30273027
description: Optional[str] = ...,
3028-
welcome_channels: Optional[List[WelcomeChannel]] = ...,
3028+
welcome_channels: Optional[List[WelcomeScreenChannel]] = ...,
30293029
enabled: Optional[bool] = ...,
30303030
) -> WelcomeScreen:
30313031
...

discord/http.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@
8585
threads,
8686
voice,
8787
sticker,
88+
welcome_screen,
8889
)
8990
from .types.snowflake import Snowflake, SnowflakeList
9091
from .types.message import Attachment

0 commit comments

Comments
 (0)