Skip to content

Commit 87f814f

Browse files
authored
Merge pull request #1690 from interactions-py/unstable
5.13
2 parents a8f6fcf + cf395d1 commit 87f814f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1522
-359
lines changed

.pre-commit-config.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ repos:
3434
hooks:
3535
- id: ruff
3636
args: [--fix, --exit-non-zero-on-fix]
37+
language: python
3738
- repo: https://github.com/psf/black
3839
rev: 24.2.0
3940
hooks:
@@ -48,6 +49,9 @@ repos:
4849
# name: isort Formatting
4950
# language: python
5051
# types: [file, python]
52+
53+
default_language_version:
54+
python: python3.10
5155
ci:
5256
autoupdate_branch: "unstable"
5357
autofix_prs: true

docs/src/API Reference/API Reference/models/Discord/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ search:
2222
- [Invite](invite)
2323
- [Message](message)
2424
- [Modals](modals)
25+
- [Poll](poll)
2526
- [Reaction](reaction)
2627
- [Role](role)
2728
- [Scheduled event](scheduled_event)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
::: interactions.models.discord.poll

docs/src/Guides/01 Getting Started.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ async def on_ready():
7676
@listen()
7777
async def on_message_create(event):
7878
# This event is called when a message is sent in a channel the bot can see
79-
print(f"message received: {event.message.content}")
79+
print(f"message received: {event.message.jump_url}")
8080

8181

8282
bot.start("Put your token here")

docs/src/Guides/03 Creating Commands.md

Lines changed: 61 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -423,18 +423,69 @@ There are two ways to define permissions.
423423

424424
Multiple permissions are defined with the bitwise OR operator `|`.
425425

426-
### Blocking Commands in DMs
426+
## Usable Contexts
427427

428-
You can also block commands in DMs. To do that, just set `dm_permission` to false.
428+
You can control where slash commands (and other application commands) can be used using - in guilds, in DMs, and/or other private channels. By default, commands can be used in all contexts.
429429

430-
```py
431-
@slash_command(
432-
name="my_guild_only_command",
433-
dm_permission=False,
434-
)
435-
async def my_command_function(ctx: SlashContext):
436-
...
437-
```
430+
As with permissions, there are two ways to define the context.
431+
432+
=== ":one: Decorators"
433+
434+
```python
435+
from interactions import contexts
436+
437+
@slash_command(name="my_guild_only_command")
438+
@contexts(guild=True, bot_dm=False, private_channel=False)
439+
async def my_command_function(ctx: SlashContext):
440+
...
441+
```
442+
443+
=== ":two: Function Definition"
444+
445+
```python
446+
from interactions import ContextType
447+
448+
@slash_command(
449+
name="my_command",
450+
contexts=[ContextType.GUILD],
451+
)
452+
async def my_command_function(ctx: SlashContext):
453+
...
454+
```
455+
456+
## Integration Types
457+
458+
Applications can be installed/integrated in different ways:
459+
- The one you are familiar with is the *guild* integration, where the application is installed in a specific guild, and so the entire guild can use the application.
460+
- You can also install the application to a *user*, where the application can then be used by the user anywhere they desire.
461+
462+
By default, commands can only be used in guild integrations. Like many other properties, this can be changed.
463+
464+
There are two ways to define this:
465+
466+
=== ":one: Decorators"
467+
468+
```python
469+
from interactions import integration_types
470+
471+
@slash_command(name="my_command")
472+
@integration_types(guild=True, user=True)
473+
async def my_command_function(ctx: SlashContext):
474+
...
475+
```
476+
477+
=== ":two: Function Definition"
478+
479+
```python
480+
from interactions import IntegrationType
481+
482+
@slash_command(
483+
name="my_command",
484+
integration_types=[IntegrationType.GUILD_INSTALL, IntegrationType.USER_INSTALL],
485+
)
486+
async def my_command_function(ctx: SlashContext):
487+
...
488+
```
438489

439490
## Checks
440491

interactions/__init__.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
MentionPrefix,
2626
Missing,
2727
MISSING,
28+
POLL_MAX_ANSWERS,
29+
POLL_MAX_DURATION_HOURS,
2830
PREMIUM_GUILD_LIMITS,
2931
SELECT_MAX_NAME_LENGTH,
3032
SELECTS_MAX_OPTIONS,
@@ -37,6 +39,7 @@
3739
smart_cache,
3840
T,
3941
T_co,
42+
ClientT,
4043
utils,
4144
)
4245
from .client import const
@@ -83,6 +86,7 @@
8386
BrandColors,
8487
BrandColours,
8588
Buckets,
89+
BulkBanResponse,
8690
Button,
8791
ButtonStyle,
8892
CallbackObject,
@@ -104,9 +108,11 @@
104108
ComponentContext,
105109
ComponentType,
106110
ConsumeRest,
111+
contexts,
107112
context_menu,
108113
ContextMenu,
109114
ContextMenuContext,
115+
ContextType,
110116
Converter,
111117
cooldown,
112118
Cooldown,
@@ -179,6 +185,8 @@
179185
IDConverter,
180186
InputText,
181187
IntegrationExpireBehaviour,
188+
IntegrationType,
189+
integration_types,
182190
Intents,
183191
InteractionCommand,
184192
InteractionContext,
@@ -214,6 +222,7 @@
214222
MessageConverter,
215223
MessageFlags,
216224
MessageInteraction,
225+
MessageInteractionMetadata,
217226
MessageReference,
218227
MessageType,
219228
MFALevel,
@@ -238,6 +247,12 @@
238247
PartialEmojiConverter,
239248
PermissionOverwrite,
240249
Permissions,
250+
Poll,
251+
PollAnswer,
252+
PollAnswerCount,
253+
PollLayoutType,
254+
PollMedia,
255+
PollResults,
241256
PremiumTier,
242257
PremiumType,
243258
process_allowed_mentions,
@@ -403,6 +418,7 @@
403418
"BrandColors",
404419
"BrandColours",
405420
"Buckets",
421+
"BulkBanResponse",
406422
"Button",
407423
"ButtonStyle",
408424
"CallbackObject",
@@ -415,6 +431,7 @@
415431
"ChannelType",
416432
"check",
417433
"Client",
434+
"ClientT",
418435
"ClientUser",
419436
"Color",
420437
"COLOR_TYPES",
@@ -426,10 +443,12 @@
426443
"ComponentType",
427444
"ConsumeRest",
428445
"const",
446+
"contexts",
429447
"context_menu",
430448
"CONTEXT_MENU_NAME_LENGTH",
431449
"ContextMenu",
432450
"ContextMenuContext",
451+
"ContextType",
433452
"Converter",
434453
"cooldown",
435454
"Cooldown",
@@ -519,6 +538,8 @@
519538
"IDConverter",
520539
"InputText",
521540
"IntegrationExpireBehaviour",
541+
"IntegrationType",
542+
"integration_types",
522543
"Intents",
523544
"InteractionCommand",
524545
"InteractionContext",
@@ -558,6 +579,7 @@
558579
"MessageConverter",
559580
"MessageFlags",
560581
"MessageInteraction",
582+
"MessageInteractionMetadata",
561583
"MessageReference",
562584
"MessageType",
563585
"MFALevel",
@@ -584,6 +606,14 @@
584606
"PartialEmojiConverter",
585607
"PermissionOverwrite",
586608
"Permissions",
609+
"Poll",
610+
"PollAnswer",
611+
"PollAnswerCount",
612+
"PollLayoutType",
613+
"POLL_MAX_ANSWERS",
614+
"POLL_MAX_DURATION_HOURS",
615+
"PollMedia",
616+
"PollResults",
587617
"PREMIUM_GUILD_LIMITS",
588618
"PremiumTier",
589619
"PremiumType",

interactions/api/events/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
MessageCreate,
4242
MessageDelete,
4343
MessageDeleteBulk,
44+
MessagePollVoteAdd,
45+
MessagePollVoteRemove,
4446
MessageReactionAdd,
4547
MessageReactionRemove,
4648
MessageReactionRemoveAll,
@@ -159,6 +161,8 @@
159161
"MessageCreate",
160162
"MessageDelete",
161163
"MessageDeleteBulk",
164+
"MessagePollVoteAdd",
165+
"MessagePollVoteRemove",
162166
"MessageReactionAdd",
163167
"MessageReactionRemove",
164168
"MessageReactionRemoveAll",

interactions/api/events/discord.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ async def an_event_handler(event: ChannelCreate):
7272
"MessageCreate",
7373
"MessageDelete",
7474
"MessageDeleteBulk",
75+
"MessagePollVoteAdd",
76+
"MessagePollVoteRemove",
7577
"MessageReactionAdd",
7678
"MessageReactionRemove",
7779
"MessageReactionRemoveAll",
@@ -115,6 +117,7 @@ async def an_event_handler(event: ChannelCreate):
115117
from interactions.models.discord.entitlement import Entitlement
116118
from interactions.models.discord.guild import Guild, GuildIntegration
117119
from interactions.models.discord.message import Message
120+
from interactions.models.discord.poll import Poll
118121
from interactions.models.discord.reaction import Reaction
119122
from interactions.models.discord.role import Role
120123
from interactions.models.discord.scheduled_event import ScheduledEvent
@@ -588,6 +591,72 @@ class MessageReactionRemoveEmoji(MessageReactionRemoveAll):
588591
"""The emoji that was removed"""
589592

590593

594+
@attrs.define(eq=False, order=False, hash=False, kw_only=False)
595+
class BaseMessagePollEvent(BaseEvent):
596+
user_id: "Snowflake_Type" = attrs.field(repr=False)
597+
"""The ID of the user that voted"""
598+
channel_id: "Snowflake_Type" = attrs.field(repr=False)
599+
"""The ID of the channel the poll is in"""
600+
message_id: "Snowflake_Type" = attrs.field(repr=False)
601+
"""The ID of the message the poll is in"""
602+
answer_id: int = attrs.field(repr=False)
603+
"""The ID of the answer the user voted for"""
604+
guild_id: "Optional[Snowflake_Type]" = attrs.field(repr=False, default=None)
605+
"""The ID of the guild the poll is in"""
606+
607+
def get_message(self) -> "Optional[Message]":
608+
"""Get the message object if it is cached"""
609+
return self.client.cache.get_message(self.channel_id, self.message_id)
610+
611+
def get_user(self) -> "Optional[User]":
612+
"""Get the user object if it is cached"""
613+
return self.client.get_user(self.user_id)
614+
615+
def get_channel(self) -> "Optional[TYPE_ALL_CHANNEL]":
616+
"""Get the channel object if it is cached"""
617+
return self.client.get_channel(self.channel_id)
618+
619+
def get_guild(self) -> "Optional[Guild]":
620+
"""Get the guild object if it is cached"""
621+
return self.client.get_guild(self.guild_id) if self.guild_id is not None else None
622+
623+
def get_poll(self) -> "Optional[Poll]":
624+
"""Get the poll object if it is cached"""
625+
message = self.get_message()
626+
return message.poll if message is not None else None
627+
628+
async def fetch_message(self) -> "Message":
629+
"""Fetch the message the poll is in"""
630+
return await self.client.cache.fetch_message(self.channel_id, self.message_id)
631+
632+
async def fetch_user(self) -> "User":
633+
"""Fetch the user that voted"""
634+
return await self.client.fetch_user(self.user_id)
635+
636+
async def fetch_channel(self) -> "TYPE_ALL_CHANNEL":
637+
"""Fetch the channel the poll is in"""
638+
return await self.client.fetch_channel(self.channel_id)
639+
640+
async def fetch_guild(self) -> "Optional[Guild]":
641+
"""Fetch the guild the poll is in"""
642+
return await self.client.fetch_guild(self.guild_id) if self.guild_id is not None else None
643+
644+
async def fetch_poll(self) -> "Poll":
645+
"""Fetch the poll object"""
646+
message = await self.fetch_message()
647+
return message.poll
648+
649+
650+
@attrs.define(eq=False, order=False, hash=False, kw_only=False)
651+
class MessagePollVoteAdd(BaseMessagePollEvent):
652+
"""Dispatched when a user votes in a poll"""
653+
654+
655+
@attrs.define(eq=False, order=False, hash=False, kw_only=False)
656+
class MessagePollVoteRemove(BaseMessagePollEvent):
657+
"""Dispatched when a user remotes a votes in a poll"""
658+
659+
591660
@attrs.define(eq=False, order=False, hash=False, kw_only=False)
592661
class PresenceUpdate(BaseEvent):
593662
"""A user's presence has changed."""

interactions/api/events/processors/message_events.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,41 @@ async def _on_raw_message_delete_bulk(self, event: "RawGatewayEvent") -> None:
8383
event.data.get("ids"),
8484
)
8585
)
86+
87+
@Processor.define()
88+
async def _on_raw_message_poll_vote_add(self, event: "RawGatewayEvent") -> None:
89+
"""
90+
Process raw message poll vote add event and dispatch a processed poll vote add event.
91+
92+
Args:
93+
event: raw poll vote add event
94+
95+
"""
96+
self.dispatch(
97+
events.MessagePollVoteAdd(
98+
event.data.get("guild_id", None),
99+
event.data["channel_id"],
100+
event.data["message_id"],
101+
event.data["user_id"],
102+
event.data["option"],
103+
)
104+
)
105+
106+
@Processor.define()
107+
async def _on_raw_message_poll_vote_remove(self, event: "RawGatewayEvent") -> None:
108+
"""
109+
Process raw message poll vote remove event and dispatch a processed poll vote remove event.
110+
111+
Args:
112+
event: raw poll vote remove event
113+
114+
"""
115+
self.dispatch(
116+
events.MessagePollVoteRemove(
117+
event.data.get("guild_id", None),
118+
event.data["channel_id"],
119+
event.data["message_id"],
120+
event.data["user_id"],
121+
event.data["option"],
122+
)
123+
)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy