Skip to content

Commit 8c1ff0c

Browse files
authored
Merge pull request #145 from Pycord-Development/slash
merge slash into restructure
2 parents 530a141 + fe4ee70 commit 8c1ff0c

File tree

23 files changed

+597
-52
lines changed

23 files changed

+597
-52
lines changed

.github/CONTRIBUTING.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ If the bug report is missing this information then it'll take us longer to fix t
3434

3535
Submitting a pull request is fairly simple, just make sure it focuses on a single aspect and doesn't manage to have scope creep and it's probably good to go. It would be incredibly lovely if the style is consistent to that found in the project. This project follows PEP-8 guidelines (mostly) with a column limit of 125.
3636

37+
### Licensing
38+
39+
By submitting a pull request, you agree that; 1) You hold the copyright on all submitted code inside said pull request; 2) You agree to transfer all rights to the owner of this repository, and; 3) If you are found to be in fault with any of the above, we shall not be held responsible in any way after the pull request has been merged.
40+
3741
### Git Commit Guidelines
3842

3943
- Use present tense (e.g. "Add feature" not "Added feature")

README.rst

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -72,22 +72,20 @@ Quick Example
7272
7373
import discord
7474
75-
class MyClient(discord.Client):
76-
async def on_ready(self):
77-
print("Logged on as", self.user)
78-
79-
async def on_message(self, message):
80-
# don't respond to ourselves
81-
if message.author == self.user:
82-
return
83-
84-
if message.content == "ping":
85-
await message.channel.send("pong")
86-
87-
client = MyClient()
88-
client.run("token")
75+
bot = discord.Bot()
76+
77+
@bot.slash_command()
78+
async def hello(ctx, name: str = None):
79+
name = name or ctx.author.name
80+
await ctx.send(f"Hello {name}!")
81+
82+
@bot.user_command(name="Say Hello")
83+
async def hi(ctx, user):
84+
await ctx.send(f"{ctx.author.mention} says hello to {user.name}!")
85+
86+
bot.run("token")
8987
90-
Bot Example
88+
Normal Commands Example
9189
~~~~~~~~~~~~~
9290

9391
.. code:: py
@@ -110,4 +108,5 @@ Links
110108

111109
- `Documentation <https://pycord.readthedocs.io/en/latest/index.html>`_
112110
- `Official Discord Server <https://discord.gg/dK2qkEJ37N>`_
111+
- `Discord Developers <https://discord.gg/discord-developers>`_
113112
- `Discord API <https://discord.gg/discord-api>`_

discord/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@
6262
from .bot import *
6363
from .app import *
6464
from .cog import Cog
65+
from .welcome_screen import *
66+
6567

6668
class VersionInfo(NamedTuple):
6769
major: int

discord/abc.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
'GuildChannel',
6363
'Messageable',
6464
'Connectable',
65+
'Mentionable'
6566
)
6667

6768
T = TypeVar('T', bound=VoiceProtocol)
@@ -1141,6 +1142,7 @@ class Messageable:
11411142
- :class:`~discord.Member`
11421143
- :class:`~discord.ext.commands.Context`
11431144
- :class:`~discord.Thread`
1145+
- :class:`~discord.ApplicationContext`
11441146
"""
11451147

11461148
__slots__ = ()
@@ -1690,4 +1692,4 @@ async def connect(
16901692

16911693
class Mentionable:
16921694
# TODO: documentation, methods if needed
1693-
pass
1695+
pass

discord/app/commands.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -405,13 +405,13 @@ async def _invoke(self, ctx: ApplicationContext) -> None:
405405
<= SlashCommandOptionType.role.value
406406
):
407407
name = "member" if op.input_type.name == "user" else op.input_type.name
408-
arg = await get_or_fetch(ctx.guild, name, int(arg))
408+
arg = await get_or_fetch(ctx.guild, name, int(arg), default=int(arg))
409409

410410
elif op.input_type == SlashCommandOptionType.mentionable:
411-
try:
412-
arg = await get_or_fetch(ctx.guild, "member", int(arg))
413-
except NotFound:
414-
arg = await get_or_fetch(ctx.guild, "role", int(arg))
411+
arg_id = int(arg)
412+
arg = await get_or_fetch(ctx.guild, "member", arg_id)
413+
if arg is None:
414+
arg = ctx.guild.get_role(arg_id) or arg_id
415415

416416
kwargs[op.name] = arg
417417

@@ -466,7 +466,7 @@ def _update_copy(self, kwargs: Dict[str, Any]):
466466

467467
class Option:
468468
def __init__(
469-
self, input_type: Any, /, description = None,**kwargs
469+
self, input_type: Any, /, description: str = None, **kwargs
470470
) -> None:
471471
self.name: Optional[str] = kwargs.pop("name", None)
472472
self.description = description or "No description provided"
@@ -501,9 +501,11 @@ def __init__(self, name: str, value: Optional[Union[str, int, float]] = None):
501501
def to_dict(self) -> Dict[str, Union[str, int, float]]:
502502
return {"name": self.name, "value": self.value}
503503

504-
def option(name, type, **kwargs):
504+
def option(name, type=None, **kwargs):
505505
"""A decorator that can be used instead of typehinting Option"""
506506
def decor(func):
507+
nonlocal type
508+
type = type or func.__annotations__.get(name, str)
507509
func.__annotations__[name] = Option(type, **kwargs)
508510
return func
509511
return decor

discord/app/context.py

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,21 @@
2424

2525
from typing import TYPE_CHECKING, Optional, Union
2626

27+
import discord.abc
28+
2729
if TYPE_CHECKING:
2830
import discord
31+
from discord.state import ConnectionState
2932

3033
from ..guild import Guild
3134
from ..interactions import Interaction, InteractionResponse
3235
from ..member import Member
3336
from ..message import Message
3437
from ..user import User
3538
from ..utils import cached_property
36-
from ..context_managers import Typing
3739

3840

39-
class ApplicationContext:
41+
class ApplicationContext(discord.abc.Messageable):
4042
"""Represents a Discord interaction context.
4143
4244
This class is not created manually and is instead passed to application
@@ -58,6 +60,10 @@ def __init__(self, bot: "discord.Bot", interaction: Interaction):
5860
self.bot = bot
5961
self.interaction = interaction
6062
self.command = None
63+
self._state: ConnectionState = self.interaction._state
64+
65+
async def _get_channel(self) -> discord.abc.Messageable:
66+
return self.channel
6167

6268
@cached_property
6369
def channel(self):
@@ -87,9 +93,6 @@ def user(self) -> Optional[Union[Member, User]]:
8793
def voice_client(self):
8894
return self.guild.voice_client
8995

90-
def typing(self):
91-
return Typing(self.channel)
92-
9396
@cached_property
9497
def response(self) -> InteractionResponse:
9598
return self.interaction.response
@@ -100,11 +103,6 @@ def response(self) -> InteractionResponse:
100103
def respond(self):
101104
return self.followup.send if self.response.is_done() else self.interaction.response.send_message
102105

103-
@property
104-
def send(self):
105-
"""Behaves like :attr:`~discord.abc.Messagable.send` if the response is done, else behaves like :attr:`~discord.app.ApplicationContext.respond`"""
106-
return self.channel.send if self.response.is_done() else self.respond
107-
108106
@property
109107
def defer(self):
110108
return self.interaction.response.defer

discord/bot.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ async def process_application_commands(self, interaction: Interaction) -> None:
234234
else:
235235
self.dispatch('application_command_completion', ctx)
236236

237-
def slash_command(self, **kwargs) -> SlashCommand:
237+
def slash_command(self, **kwargs):
238238
"""A shortcut decorator that invokes :func:`.ApplicationCommandMixin.command` and adds it to
239239
the internal command list via :meth:`~.ApplicationCommandMixin.add_application_command`.
240240
This shortcut is made specifically for :class:`.SlashCommand`.
@@ -249,7 +249,7 @@ def slash_command(self, **kwargs) -> SlashCommand:
249249
"""
250250
return self.application_command(cls=SlashCommand, **kwargs)
251251

252-
def user_command(self, **kwargs) -> UserCommand:
252+
def user_command(self, **kwargs):
253253
"""A shortcut decorator that invokes :func:`.ApplicationCommandMixin.command` and adds it to
254254
the internal command list via :meth:`~.ApplicationCommandMixin.add_application_command`.
255255
This shortcut is made specifically for :class:`.UserCommand`.
@@ -264,7 +264,7 @@ def user_command(self, **kwargs) -> UserCommand:
264264
"""
265265
return self.application_command(cls=UserCommand, **kwargs)
266266

267-
def message_command(self, **kwargs) -> MessageCommand:
267+
def message_command(self, **kwargs):
268268
"""A shortcut decorator that invokes :func:`.ApplicationCommandMixin.command` and adds it to
269269
the internal command list via :meth:`~.ApplicationCommandMixin.add_application_command`.
270270
This shortcut is made specifically for :class:`.MessageCommand`.

discord/channel.py

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545

4646
import discord.abc
4747
from .permissions import PermissionOverwrite, Permissions
48-
from .enums import ChannelType, StagePrivacyLevel, try_enum, VoiceRegion, VideoQualityMode
48+
from .enums import ChannelType, InviteTarget, StagePrivacyLevel, try_enum, VoiceRegion, VideoQualityMode
4949
from .mixins import Hashable
5050
from .object import Object
5151
from . import utils
@@ -55,6 +55,7 @@
5555
from .stage_instance import StageInstance
5656
from .threads import Thread
5757
from .iterators import ArchivedThreadIterator
58+
from .invite import Invite
5859

5960
__all__ = (
6061
'TextChannel',
@@ -1037,6 +1038,64 @@ async def edit(self, *, reason=None, **options):
10371038
# the payload will always be the proper channel payload
10381039
return self.__class__(state=self._state, guild=self.guild, data=payload) # type: ignore
10391040

1041+
async def create_activity_invite(self, event:str, **kwargs) -> Invite:
1042+
"""|coro|
1043+
1044+
A shortcut method that creates an instant activity invite.
1045+
1046+
You must have the :attr:`~discord.Permissions.create_instant_invite` permission to
1047+
do this.
1048+
1049+
Parameters
1050+
------------
1051+
event: :class:`str`
1052+
The event to create an invite for.
1053+
max_age: :class:`int`
1054+
How long the invite should last in seconds. If it's 0 then the invite
1055+
doesn't expire. Defaults to ``0``.
1056+
max_uses: :class:`int`
1057+
How many uses the invite could be used for. If it's 0 then there
1058+
are unlimited uses. Defaults to ``0``.
1059+
temporary: :class:`bool`
1060+
Denotes that the invite grants temporary membership
1061+
(i.e. they get kicked after they disconnect). Defaults to ``False``.
1062+
unique: :class:`bool`
1063+
Indicates if a unique invite URL should be created. Defaults to True.
1064+
If this is set to ``False`` then it will return a previously created
1065+
invite.
1066+
reason: Optional[:class:`str`]
1067+
The reason for creating this invite. Shows up on the audit log.
1068+
1069+
1070+
Raises
1071+
-------
1072+
InvalidArgument
1073+
If the event is not a valid event.
1074+
~discord.HTTPException
1075+
Invite creation failed.
1076+
1077+
Returns
1078+
--------
1079+
:class:`~discord.Invite`
1080+
The invite that was created.
1081+
"""
1082+
1083+
application_ids = {
1084+
'youtube' : 755600276941176913,
1085+
'poker' : 755827207812677713,
1086+
'betrayal': 773336526917861400,
1087+
'fishing' : 814288819477020702,
1088+
'chess' : 832012774040141894,
1089+
}
1090+
event = application_ids.get(event)
1091+
if event is None:
1092+
raise InvalidArgument('Invalid event.')
1093+
1094+
return await self.create_invite(
1095+
target_type=InviteTarget.embedded_application,
1096+
target_application_id=event,
1097+
**kwargs
1098+
)
10401099

10411100
class StageChannel(VocalGuildChannel):
10421101
"""Represents a Discord guild stage channel.

discord/client.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,13 +460,17 @@ async def login(self, token: str) -> None:
460460
461461
Raises
462462
------
463+
TypeError
464+
The token was in invalid type.
463465
:exc:`.LoginFailure`
464466
The wrong credentials are passed.
465467
:exc:`.HTTPException`
466468
An unknown HTTP related error occurred,
467469
usually when it isn't 200 or the known incorrect credentials
468470
passing status code.
469471
"""
472+
if not isinstance(token, str):
473+
raise TypeError(f"token must be of type str, not {token.__class__.__name__}")
470474

471475
_log.info('logging in using static token')
472476

discord/colour.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,5 +325,13 @@ def yellow(cls: Type[CT]) -> CT:
325325
"""
326326
return cls(0xFEE75C)
327327

328+
@classmethod
329+
def nitro_pink(cls: Type[CT]) -> CT:
330+
"""A factory method that returns a :class:`Colour` with a value of ``0xf47fff``.
331+
332+
.. versionadded:: 2.0
333+
"""
334+
return cls(0xf47fff)
335+
328336

329337
Color = Colour

0 commit comments

Comments
 (0)