Skip to content

Commit 00ebd1b

Browse files
authored
chore!: pre-release for 4.1.1-rc.1 (#703)
chore!: pre-release for 4.1.1-rc.1
2 parents 711ae0f + 5dd14fa commit 00ebd1b

Some content is hidden

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

50 files changed

+2258
-366
lines changed

.github/FUNDING.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# These are supported funding model platforms
22

33
github: [goverfl0w]
4-
open_collective: discordinteractions
4+
open_collective: interactions-py

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ repos:
2929
- id: check-merge-conflict
3030
name: Merge Conflicts
3131
- repo: https://github.com/psf/black
32-
rev: 22.1.0
32+
rev: 22.3.0
3333
hooks:
3434
- id: black
3535
name: Black Formatting

docs/quickstart.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ But how to send it? You can't use ``ctx.send`` for it. Take a look at :ref:`Moda
354354
355355
Modals
356356
******
357-
Modals are a new way to interact with a user. Currently only a ``TextInput`` component is supported. You can have up to three ``TextInput`` in a Modal.
357+
Modals are a new way to interact with a user. Currently only a ``TextInput`` component is supported. You can have up to five ``TextInput`` in a Modal.
358358
359359
.. code-block:: python
360360

examples/bot.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# This code shows a very brief and small example of how to create a bot with our library.
2+
# This example does not cover all the features of the library, but it is enough to get you started.
3+
# In order to learn more about how to use the library, please head over to our documentation:
4+
# https://interactionspy.rtfd.io/en/latest/
5+
6+
# The first thing you need to do is import the library.
7+
import interactions
8+
9+
# Now, let's create an instance of a bot.
10+
# When you make a bot, we refer to it as the "client."
11+
# The client is the main object that interacts with the Gateway, what talks to Discord.
12+
# The client is also the main object that interacts with the API, what makes requests with Discord.
13+
client = interactions.Client("your bot token will go here.")
14+
15+
# With our client established, let's have the library inform us when the client is ready.
16+
# These are known as event listeners. An event listener can be established in one of two ways.
17+
# You can provide the name of the event, prefixed by an "on_", or by telling the event decorator what event it is.
18+
@client.event
19+
async def on_ready():
20+
# We can use the client "me" attribute to get information about the bot.
21+
print(f"We're online! We've logged in as {client.me.name}.")
22+
23+
# We're also able to use property methods to gather additional data.
24+
print(f"Our latency is {round(client.latency)} ms.")
25+
26+
27+
@client.event("message_create")
28+
async def name_this_however_you_want(message: interactions.Message):
29+
# Whenever we specify any other event type that isn't "READY," the function underneath
30+
# the decorator will most likely have an argument required. This argument is the data
31+
# that is being supplied back to us developers, which we call a data model.
32+
33+
# In this example, we're listening to messages being created. This means we can expect
34+
# a "message" argument to be passed to the function, which will be the data model of such.
35+
36+
# We can use the data model to access the data we need.
37+
print(
38+
f"We've received a message from {message.author.name}. The message is: {message.content}."
39+
)
40+
41+
42+
# Now, let's create a command.
43+
# A command is a function that is called when a user types out a command.
44+
# The command is called with a context object, which contains information about the user, the channel, and the guild.
45+
# Context is what we call the described information given from an interaction response, what comes from a command.
46+
# The context object in this case is a class for commands, but can also be one for components if used that way.
47+
@client.command(name="hello-world", description='A command that says "hello world!"')
48+
async def hello_world(ctx: interactions.CommandContext):
49+
# "ctx" is an abbreviation of the context object.
50+
# You don't need to type hint this, but it's recommended to do so.
51+
52+
# Now, let's send back a response.
53+
# Note that when you make an interaction response, you can no longer run anything in this function.
54+
# The interaction response should be the LAST thing you do when a command is ran.
55+
await ctx.send("hello world!")
56+
57+
# Because of this, this line of code right here will not execute.
58+
print("we ran.")
59+
60+
61+
# After we've declared all of the bot code we want, we need to tell the library to run our bot.
62+
# In this example, we've decided to do some things in a different way without explicitly saying it:
63+
64+
# - we'll be syncing the commands automatically.
65+
# if you want to do this manually, you can do it by passing disable_sync=False in the Client
66+
# object on line 8.
67+
# - we are not setting a presence.
68+
# - we are not automatically sharding, and registering the connection under 1 shard.
69+
# - we are using default intents, which are Gateway intents excluding privileged ones.
70+
client.start()

interactions/__init__.py

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,14 @@
11
"""
2-
(interactions)
3-
discord-interactions
2+
interactions.py
43
5-
Easy, simple, scalable and modular: a Python API wrapper for interactions.
4+
Easy, simple, scalable and modular: a Python library for interactions.
65
76
To see the documentation, please head over to the link here:
8-
https://discord-interactions.rtfd.io/en/latest for ``stable`` builds.
9-
https://discord-interactions.rtfd.io/en/unstable for ``unstable`` builds.
7+
https://interactionspy.rtfd.io/en/latest for ``stable`` builds.
8+
https://interactionspy.rtfd.io/en/unstable for ``unstable`` builds.
109
11-
(c) 2021 goverfl0w.
12-
Co-authored by DeltaXW.
10+
(c) 2021 interactions-py.
1311
"""
14-
from .api.models.channel import * # noqa: F401 F403
15-
from .api.models.flags import * # noqa: F401 F403
16-
from .api.models.guild import * # noqa: F401 F403
17-
from .api.models.gw import * # noqa: F401 F403
18-
from .api.models.member import * # noqa: F401 F403
19-
from .api.models.message import * # noqa: F401 F403
20-
from .api.models.misc import * # noqa: F401 F403
21-
from .api.models.presence import * # noqa: F401 F403
22-
from .api.models.role import * # noqa: F401 F403
23-
from .api.models.team import * # noqa: F401 F403
24-
from .api.models.user import * # noqa: F401 F403
12+
from .client import * # noqa: F401 F403 isort: skip
13+
from .api import * # noqa: F401 F403
2514
from .base import * # noqa: F401 F403
26-
from .client import * # noqa: F401 F403
27-
from .context import * # noqa: F401 F403
28-
from .decor import * # noqa: F401 F403
29-
from .enums import * # noqa: F401 F403
30-
from .models.command import * # noqa: F401 F403
31-
from .models.component import * # noqa: F401 F403
32-
from .models.misc import * # noqa: F401 F403

interactions/api/__init__.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@
22
interactions.api
33
44
This section of the library maintains and
5-
handles all of the Gateway and HTTP
6-
work.
5+
handles all the Gateway and HTTP work.
76
"""
8-
from ..base import * # noqa: F401 F403
97
from .cache import * # noqa: F401 F403
108
from .enums import * # noqa: F401 F403
119
from .error import * # noqa: F401 F403

interactions/api/enums.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# Normal libraries
21
from enum import IntEnum
32

43
# TODO: post-v4: Implement this into the new error system at a later point.

interactions/api/gateway/__init__.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
"""
2+
interactions.api.gateway
3+
4+
This section of the library maintains and
5+
handles all of the Gateway work.
6+
"""
7+
from .client import * # noqa: F401 F403
8+
from .heartbeat import * # noqa: F401 F403

interactions/api/gateway.py renamed to interactions/api/gateway/client.py

Lines changed: 28 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
from json import dumps, loads
55

66
from asyncio import (
7-
AbstractEventLoop,
87
Event,
98
Task,
109
ensure_future,
@@ -17,41 +16,23 @@
1716
from time import perf_counter
1817
from typing import Any, Dict, List, Optional, Tuple, Union
1918

20-
from aiohttp import WSMessage
21-
22-
from ..base import get_logger
23-
from ..enums import InteractionType, OptionType
24-
from ..models.command import Option
25-
from .dispatch import Listener
26-
from .enums import OpCodeType
27-
from .error import GatewayException
28-
from .http.client import HTTPClient
29-
from .models.flags import Intents
30-
from .models.misc import MISSING
31-
from .models.presence import ClientPresence
19+
from aiohttp import WSMessage, WSMsgType
20+
from aiohttp.http import WS_CLOSED_MESSAGE, WS_CLOSING_MESSAGE
21+
22+
from ...base import get_logger
23+
from ...client.enums import InteractionType, OptionType
24+
from ...client.models import Option
25+
from ..dispatch import Listener
26+
from ..enums import OpCodeType
27+
from ..error import GatewayException
28+
from ..http.client import HTTPClient
29+
from ..models.flags import Intents
30+
from ..models.misc import MISSING
31+
from ..models.presence import ClientPresence
32+
from .heartbeat import _Heartbeat
3233

3334
log = get_logger("gateway")
3435

35-
__all__ = ("_Heartbeat", "WebSocketClient")
36-
37-
38-
class _Heartbeat:
39-
"""An internal class representing the heartbeat in a WebSocket connection."""
40-
41-
event: Event
42-
delay: float
43-
44-
def __init__(self, loop: AbstractEventLoop) -> None:
45-
"""
46-
:param loop: The event loop to base the asynchronous manager.
47-
:type loop: AbstractEventLoop
48-
"""
49-
try:
50-
self.event = Event(loop=loop) if version_info < (3, 10) else Event()
51-
except TypeError:
52-
pass
53-
self.delay = 0.0
54-
5536

5637
class WebSocketClient:
5738
"""
@@ -198,7 +179,7 @@ async def _establish_connection(
198179

199180
if stream is None:
200181
continue
201-
if self._client is None:
182+
if self._client is None or stream == WS_CLOSED_MESSAGE or stream == WSMsgType.CLOSE:
202183
await self._establish_connection()
203184
break
204185

@@ -397,7 +378,7 @@ def __contextualize(self, data: dict) -> object:
397378
_context = "ComponentContext"
398379

399380
data["client"] = self._http
400-
context: object = getattr(__import__("interactions.context"), _context)
381+
context: object = getattr(__import__("interactions.client.context"), _context)
401382

402383
return context(**data)
403384

@@ -536,6 +517,18 @@ async def __receive_packet_stream(self) -> Optional[Dict[str, Any]]:
536517
"""
537518

538519
packet: WSMessage = await self._client.receive()
520+
521+
if packet == WSMsgType.CLOSE:
522+
await self._client.close()
523+
return packet
524+
525+
elif packet == WS_CLOSED_MESSAGE:
526+
return packet
527+
528+
elif packet == WS_CLOSING_MESSAGE:
529+
await self._client.close()
530+
return WS_CLOSED_MESSAGE
531+
539532
return loads(packet.data) if packet and isinstance(packet.data, str) else None
540533

541534
async def _send_packet(self, data: Dict[str, Any]) -> None:

interactions/api/gateway.pyi renamed to interactions/api/gateway/client.pyi

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,17 @@ from typing import Any, Dict, List, Optional, Tuple, Union, Iterable
88

99
from aiohttp import ClientWebSocketResponse
1010

11-
from ..models import Option
12-
from ..api.models.misc import MISSING
13-
from ..api.models.presence import ClientPresence
14-
from .dispatch import Listener
15-
from .http.client import HTTPClient
16-
from .models.flags import Intents
11+
from .heartbeat import _Heartbeat
12+
from ...client.models import Option
13+
from ...api.models.misc import MISSING
14+
from ...api.models.presence import ClientPresence
15+
from ..dispatch import Listener
16+
from ..http.client import HTTPClient
17+
from ..models.flags import Intents
1718

1819
log: Logger
1920
__all__: Iterable[str]
2021

21-
class _Heartbeat:
22-
event: Event
23-
delay: float
24-
def __init__(self, loop: AbstractEventLoop) -> None: ...
25-
2622
class WebSocketClient:
2723
_loop: AbstractEventLoop
2824
_dispatch: Listener
@@ -42,7 +38,6 @@ class WebSocketClient:
4238
_last_ack: float
4339
latency: float
4440
ready: Event
45-
4641
def __init__(
4742
self,
4843
token: str,
@@ -53,7 +48,9 @@ class WebSocketClient:
5348
async def _manage_heartbeat(self) -> None: ...
5449
async def __restart(self): ...
5550
async def _establish_connection(
56-
self, shard: Optional[List[Tuple[int]]] = MISSING, presence: Optional[ClientPresence] = MISSING
51+
self,
52+
shard: Optional[List[Tuple[int]]] = MISSING,
53+
presence: Optional[ClientPresence] = MISSING,
5754
) -> None: ...
5855
async def _handle_connection(
5956
self,
@@ -64,7 +61,9 @@ class WebSocketClient:
6461
async def wait_until_ready(self) -> None: ...
6562
def _dispatch_event(self, event: str, data: dict) -> None: ...
6663
def __contextualize(self, data: dict) -> object: ...
67-
def __sub_command_context(self, data: Union[dict, Option], _context: Optional[object] = MISSING) -> Union[Tuple[str], dict]: ...
64+
def __sub_command_context(
65+
self, data: Union[dict, Option], _context: Optional[object] = MISSING
66+
) -> Union[Tuple[str], dict]: ...
6867
def __option_type_context(self, context: object, type: int) -> dict: ...
6968
@property
7069
async def __receive_packet_stream(self) -> Optional[Dict[str, Any]]: ...

0 commit comments

Comments
 (0)