Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

5.13 #1690

Merged
merged 20 commits into from
Jun 26, 2024
Merged

5.13 #1690

Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
2f570a2
fix: add extension name before loading in cmds (#1680)
AstreaTSS May 19, 2024
fecf3d3
feat: option to hide paginator buttons on stop (#1660)
mifuyutsuki May 19, 2024
bca121e
fix: correctly unpack startup tasks in AutoShardClient (#1688)
mifuyutsuki May 30, 2024
cfe3199
fix: allow Extension.drop() to pop re.Pattern listeners (#1683)
mifuyutsuki Jun 7, 2024
a96a834
feat: add webhook message functions (#1689)
Lacosst0 Jun 7, 2024
457ac02
feat: add required_tag and make channel flags editable (#1693)
AstreaTSS Jun 8, 2024
8aea2c7
feat: update entitlements with new properties and functions (#1692)
AstreaTSS Jun 8, 2024
ecb9fca
feat: add support for user-installable apps (#1647)
AstreaTSS Jun 8, 2024
ebb420a
ci: specify language_version to python 3.10 (#1696)
AstreaTSS Jun 16, 2024
e08495b
docs: use jump_url instead of content for default intents situation (…
AstreaTSS Jun 18, 2024
720d935
feat: add message type 44, set message type 14-17/36-39 to be deletab…
ItsRqtl Jun 18, 2024
e893c18
feat: add bulk banning (#1695)
AstreaTSS Jun 20, 2024
d65e2a0
fix: allow removing files and embeds by editing (#1697)
ItsRqtl Jun 20, 2024
2eef35d
fix: adjust astimezone checks (#1703)
AstreaTSS Jun 20, 2024
59471c4
feat: add polls (#1691)
AstreaTSS Jun 20, 2024
545f9e2
feat/fix: improve typehinting of wait_fors (#1694)
AstreaTSS Jun 20, 2024
de8c91d
feat: make context have generic client types (#1699)
AstreaTSS Jun 20, 2024
a1263df
feat: add premium buttons (#1701)
AstreaTSS Jun 20, 2024
896b094
chore: Bump version to 5.13.0
silasary Jun 22, 2024
cf395d1
fix: correctly set responded in edit_origin (#1704)
ItsRqtl Jun 25, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ repos:
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
language: python
- repo: https://github.com/psf/black
rev: 24.2.0
hooks:
Expand All @@ -48,6 +49,9 @@ repos:
# name: isort Formatting
# language: python
# types: [file, python]

default_language_version:
python: python3.10
ci:
autoupdate_branch: "unstable"
autofix_prs: true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ search:
- [Invite](invite)
- [Message](message)
- [Modals](modals)
- [Poll](poll)
- [Reaction](reaction)
- [Role](role)
- [Scheduled event](scheduled_event)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
::: interactions.models.discord.poll
2 changes: 1 addition & 1 deletion docs/src/Guides/01 Getting Started.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ async def on_ready():
@listen()
async def on_message_create(event):
# This event is called when a message is sent in a channel the bot can see
print(f"message received: {event.message.content}")
print(f"message received: {event.message.jump_url}")


bot.start("Put your token here")
Expand Down
71 changes: 61 additions & 10 deletions docs/src/Guides/03 Creating Commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -423,18 +423,69 @@ There are two ways to define permissions.

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

### Blocking Commands in DMs
## Usable Contexts

You can also block commands in DMs. To do that, just set `dm_permission` to false.
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.

```py
@slash_command(
name="my_guild_only_command",
dm_permission=False,
)
async def my_command_function(ctx: SlashContext):
...
```
As with permissions, there are two ways to define the context.

=== ":one: Decorators"

```python
from interactions import contexts

@slash_command(name="my_guild_only_command")
@contexts(guild=True, bot_dm=False, private_channel=False)
async def my_command_function(ctx: SlashContext):
...
```

=== ":two: Function Definition"

```python
from interactions import ContextType

@slash_command(
name="my_command",
contexts=[ContextType.GUILD],
)
async def my_command_function(ctx: SlashContext):
...
```

## Integration Types

Applications can be installed/integrated in different ways:
- 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.
- You can also install the application to a *user*, where the application can then be used by the user anywhere they desire.

By default, commands can only be used in guild integrations. Like many other properties, this can be changed.

There are two ways to define this:

=== ":one: Decorators"

```python
from interactions import integration_types

@slash_command(name="my_command")
@integration_types(guild=True, user=True)
async def my_command_function(ctx: SlashContext):
...
```

=== ":two: Function Definition"

```python
from interactions import IntegrationType

@slash_command(
name="my_command",
integration_types=[IntegrationType.GUILD_INSTALL, IntegrationType.USER_INSTALL],
)
async def my_command_function(ctx: SlashContext):
...
```

## Checks

Expand Down
30 changes: 30 additions & 0 deletions interactions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
MentionPrefix,
Missing,
MISSING,
POLL_MAX_ANSWERS,
POLL_MAX_DURATION_HOURS,
PREMIUM_GUILD_LIMITS,
SELECT_MAX_NAME_LENGTH,
SELECTS_MAX_OPTIONS,
Expand All @@ -37,6 +39,7 @@
smart_cache,
T,
T_co,
ClientT,
utils,
)
from .client import const
Expand Down Expand Up @@ -83,6 +86,7 @@
BrandColors,
BrandColours,
Buckets,
BulkBanResponse,
Button,
ButtonStyle,
CallbackObject,
Expand All @@ -104,9 +108,11 @@
ComponentContext,
ComponentType,
ConsumeRest,
contexts,
context_menu,
ContextMenu,
ContextMenuContext,
ContextType,
Converter,
cooldown,
Cooldown,
Expand Down Expand Up @@ -179,6 +185,8 @@
IDConverter,
InputText,
IntegrationExpireBehaviour,
IntegrationType,
integration_types,
Intents,
InteractionCommand,
InteractionContext,
Expand Down Expand Up @@ -214,6 +222,7 @@
MessageConverter,
MessageFlags,
MessageInteraction,
MessageInteractionMetadata,
MessageReference,
MessageType,
MFALevel,
Expand All @@ -238,6 +247,12 @@
PartialEmojiConverter,
PermissionOverwrite,
Permissions,
Poll,
PollAnswer,
PollAnswerCount,
PollLayoutType,
PollMedia,
PollResults,
PremiumTier,
PremiumType,
process_allowed_mentions,
Expand Down Expand Up @@ -403,6 +418,7 @@
"BrandColors",
"BrandColours",
"Buckets",
"BulkBanResponse",
"Button",
"ButtonStyle",
"CallbackObject",
Expand All @@ -415,6 +431,7 @@
"ChannelType",
"check",
"Client",
"ClientT",
"ClientUser",
"Color",
"COLOR_TYPES",
Expand All @@ -426,10 +443,12 @@
"ComponentType",
"ConsumeRest",
"const",
"contexts",
"context_menu",
"CONTEXT_MENU_NAME_LENGTH",
"ContextMenu",
"ContextMenuContext",
"ContextType",
"Converter",
"cooldown",
"Cooldown",
Expand Down Expand Up @@ -519,6 +538,8 @@
"IDConverter",
"InputText",
"IntegrationExpireBehaviour",
"IntegrationType",
"integration_types",
"Intents",
"InteractionCommand",
"InteractionContext",
Expand Down Expand Up @@ -558,6 +579,7 @@
"MessageConverter",
"MessageFlags",
"MessageInteraction",
"MessageInteractionMetadata",
"MessageReference",
"MessageType",
"MFALevel",
Expand All @@ -584,6 +606,14 @@
"PartialEmojiConverter",
"PermissionOverwrite",
"Permissions",
"Poll",
"PollAnswer",
"PollAnswerCount",
"PollLayoutType",
"POLL_MAX_ANSWERS",
"POLL_MAX_DURATION_HOURS",
"PollMedia",
"PollResults",
"PREMIUM_GUILD_LIMITS",
"PremiumTier",
"PremiumType",
Expand Down
4 changes: 4 additions & 0 deletions interactions/api/events/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
MessageCreate,
MessageDelete,
MessageDeleteBulk,
MessagePollVoteAdd,
MessagePollVoteRemove,
MessageReactionAdd,
MessageReactionRemove,
MessageReactionRemoveAll,
Expand Down Expand Up @@ -159,6 +161,8 @@
"MessageCreate",
"MessageDelete",
"MessageDeleteBulk",
"MessagePollVoteAdd",
"MessagePollVoteRemove",
"MessageReactionAdd",
"MessageReactionRemove",
"MessageReactionRemoveAll",
Expand Down
69 changes: 69 additions & 0 deletions interactions/api/events/discord.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ async def an_event_handler(event: ChannelCreate):
"MessageCreate",
"MessageDelete",
"MessageDeleteBulk",
"MessagePollVoteAdd",
"MessagePollVoteRemove",
"MessageReactionAdd",
"MessageReactionRemove",
"MessageReactionRemoveAll",
Expand Down Expand Up @@ -115,6 +117,7 @@ async def an_event_handler(event: ChannelCreate):
from interactions.models.discord.entitlement import Entitlement
from interactions.models.discord.guild import Guild, GuildIntegration
from interactions.models.discord.message import Message
from interactions.models.discord.poll import Poll
from interactions.models.discord.reaction import Reaction
from interactions.models.discord.role import Role
from interactions.models.discord.scheduled_event import ScheduledEvent
Expand Down Expand Up @@ -588,6 +591,72 @@ class MessageReactionRemoveEmoji(MessageReactionRemoveAll):
"""The emoji that was removed"""


@attrs.define(eq=False, order=False, hash=False, kw_only=False)
class BaseMessagePollEvent(BaseEvent):
user_id: "Snowflake_Type" = attrs.field(repr=False)
"""The ID of the user that voted"""
channel_id: "Snowflake_Type" = attrs.field(repr=False)
"""The ID of the channel the poll is in"""
message_id: "Snowflake_Type" = attrs.field(repr=False)
"""The ID of the message the poll is in"""
answer_id: int = attrs.field(repr=False)
"""The ID of the answer the user voted for"""
guild_id: "Optional[Snowflake_Type]" = attrs.field(repr=False, default=None)
"""The ID of the guild the poll is in"""

def get_message(self) -> "Optional[Message]":
"""Get the message object if it is cached"""
return self.client.cache.get_message(self.channel_id, self.message_id)

def get_user(self) -> "Optional[User]":
"""Get the user object if it is cached"""
return self.client.get_user(self.user_id)

def get_channel(self) -> "Optional[TYPE_ALL_CHANNEL]":
"""Get the channel object if it is cached"""
return self.client.get_channel(self.channel_id)

def get_guild(self) -> "Optional[Guild]":
"""Get the guild object if it is cached"""
return self.client.get_guild(self.guild_id) if self.guild_id is not None else None

def get_poll(self) -> "Optional[Poll]":
"""Get the poll object if it is cached"""
message = self.get_message()
return message.poll if message is not None else None

async def fetch_message(self) -> "Message":
"""Fetch the message the poll is in"""
return await self.client.cache.fetch_message(self.channel_id, self.message_id)

async def fetch_user(self) -> "User":
"""Fetch the user that voted"""
return await self.client.fetch_user(self.user_id)

async def fetch_channel(self) -> "TYPE_ALL_CHANNEL":
"""Fetch the channel the poll is in"""
return await self.client.fetch_channel(self.channel_id)

async def fetch_guild(self) -> "Optional[Guild]":
"""Fetch the guild the poll is in"""
return await self.client.fetch_guild(self.guild_id) if self.guild_id is not None else None

async def fetch_poll(self) -> "Poll":
"""Fetch the poll object"""
message = await self.fetch_message()
return message.poll


@attrs.define(eq=False, order=False, hash=False, kw_only=False)
class MessagePollVoteAdd(BaseMessagePollEvent):
"""Dispatched when a user votes in a poll"""


@attrs.define(eq=False, order=False, hash=False, kw_only=False)
class MessagePollVoteRemove(BaseMessagePollEvent):
"""Dispatched when a user remotes a votes in a poll"""


@attrs.define(eq=False, order=False, hash=False, kw_only=False)
class PresenceUpdate(BaseEvent):
"""A user's presence has changed."""
Expand Down
38 changes: 38 additions & 0 deletions interactions/api/events/processors/message_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,41 @@ async def _on_raw_message_delete_bulk(self, event: "RawGatewayEvent") -> None:
event.data.get("ids"),
)
)

@Processor.define()
async def _on_raw_message_poll_vote_add(self, event: "RawGatewayEvent") -> None:
"""
Process raw message poll vote add event and dispatch a processed poll vote add event.

Args:
event: raw poll vote add event

"""
self.dispatch(
events.MessagePollVoteAdd(
event.data.get("guild_id", None),
event.data["channel_id"],
event.data["message_id"],
event.data["user_id"],
event.data["option"],
)
)

@Processor.define()
async def _on_raw_message_poll_vote_remove(self, event: "RawGatewayEvent") -> None:
"""
Process raw message poll vote remove event and dispatch a processed poll vote remove event.

Args:
event: raw poll vote remove event

"""
self.dispatch(
events.MessagePollVoteRemove(
event.data.get("guild_id", None),
event.data["channel_id"],
event.data["message_id"],
event.data["user_id"],
event.data["option"],
)
)
Loading
Loading