scurrypy 0.4__py3-none-any.whl → 0.6.6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. scurrypy/__init__.py +429 -0
  2. scurrypy/client.py +335 -0
  3. {discord → scurrypy}/client_like.py +8 -1
  4. scurrypy/dispatch/command_dispatcher.py +205 -0
  5. {discord → scurrypy}/dispatch/event_dispatcher.py +21 -21
  6. {discord → scurrypy}/dispatch/prefix_dispatcher.py +31 -12
  7. {discord → scurrypy}/error.py +6 -18
  8. {discord → scurrypy}/events/channel_events.py +2 -1
  9. scurrypy/events/gateway_events.py +31 -0
  10. {discord → scurrypy}/events/guild_events.py +2 -1
  11. {discord → scurrypy}/events/interaction_events.py +28 -13
  12. {discord → scurrypy}/events/message_events.py +8 -5
  13. {discord → scurrypy}/events/reaction_events.py +1 -2
  14. {discord → scurrypy}/events/ready_event.py +1 -3
  15. scurrypy/gateway.py +183 -0
  16. scurrypy/http.py +310 -0
  17. {discord → scurrypy}/intents.py +5 -7
  18. {discord → scurrypy}/logger.py +14 -61
  19. scurrypy/model.py +71 -0
  20. scurrypy/models.py +258 -0
  21. scurrypy/parts/channel.py +42 -0
  22. scurrypy/parts/command.py +90 -0
  23. scurrypy/parts/components.py +224 -0
  24. scurrypy/parts/components_v2.py +144 -0
  25. scurrypy/parts/embed.py +83 -0
  26. scurrypy/parts/message.py +134 -0
  27. scurrypy/parts/modal.py +16 -0
  28. {discord → scurrypy}/parts/role.py +2 -14
  29. {discord → scurrypy}/resources/application.py +1 -2
  30. {discord → scurrypy}/resources/bot_emojis.py +1 -1
  31. {discord → scurrypy}/resources/channel.py +9 -8
  32. {discord → scurrypy}/resources/guild.py +14 -16
  33. {discord → scurrypy}/resources/interaction.py +50 -43
  34. {discord → scurrypy}/resources/message.py +15 -16
  35. {discord → scurrypy}/resources/user.py +3 -4
  36. scurrypy-0.6.6.dist-info/METADATA +108 -0
  37. scurrypy-0.6.6.dist-info/RECORD +47 -0
  38. {scurrypy-0.4.dist-info → scurrypy-0.6.6.dist-info}/licenses/LICENSE +1 -1
  39. scurrypy-0.6.6.dist-info/top_level.txt +1 -0
  40. discord/__init__.py +0 -223
  41. discord/client.py +0 -375
  42. discord/dispatch/command_dispatcher.py +0 -163
  43. discord/gateway.py +0 -155
  44. discord/http.py +0 -280
  45. discord/model.py +0 -90
  46. discord/models/__init__.py +0 -1
  47. discord/models/application.py +0 -37
  48. discord/models/emoji.py +0 -34
  49. discord/models/guild.py +0 -35
  50. discord/models/integration.py +0 -23
  51. discord/models/interaction.py +0 -26
  52. discord/models/member.py +0 -27
  53. discord/models/role.py +0 -53
  54. discord/models/user.py +0 -15
  55. discord/parts/action_row.py +0 -208
  56. discord/parts/channel.py +0 -20
  57. discord/parts/command.py +0 -102
  58. discord/parts/components_v2.py +0 -353
  59. discord/parts/embed.py +0 -154
  60. discord/parts/message.py +0 -194
  61. discord/parts/modal.py +0 -21
  62. scurrypy-0.4.dist-info/METADATA +0 -130
  63. scurrypy-0.4.dist-info/RECORD +0 -54
  64. scurrypy-0.4.dist-info/top_level.txt +0 -1
  65. {discord → scurrypy}/config.py +0 -0
  66. {discord → scurrypy}/dispatch/__init__.py +0 -0
  67. {discord → scurrypy}/events/__init__.py +0 -0
  68. {discord → scurrypy}/events/hello_event.py +0 -0
  69. {discord → scurrypy}/parts/__init__.py +0 -0
  70. {discord → scurrypy}/parts/component_types.py +0 -0
  71. {discord → scurrypy}/resources/__init__.py +0 -0
  72. {scurrypy-0.4.dist-info → scurrypy-0.6.6.dist-info}/WHEEL +0 -0
@@ -4,12 +4,10 @@ from typing import Optional, Unpack
4
4
  from ..http import HTTPClient
5
5
  from ..model import DataModel
6
6
 
7
- from ..parts.modal import ModalBuilder
8
- from ..parts.message import *
7
+ from ..parts.modal import ModalPart
8
+ from ..parts.message import MessagePart, MessageFlagParams
9
9
 
10
- from ..models.guild import GuildModel
11
- from ..models.member import MemberModel
12
- from ..models.interaction import InteractionCallbackModel
10
+ from ..models import GuildModel, MemberModel, InteractionCallbackModel
13
11
 
14
12
  from .channel import Channel
15
13
 
@@ -38,8 +36,9 @@ class InteractionCallbackTypes:
38
36
  """Acknowledge an interaction and edit a response later. User sees a loading state."""
39
37
 
40
38
  DEFERRED_UPDATE_MESSAGE = 6
41
- """Acknowledge an interaction and edit the original message later.
42
- The user does NOT see a loading state. (Components only)
39
+ """
40
+ Acknowledge an interaction and edit the original message later.
41
+ The user does NOT see a loading state. (Components only)
43
42
  """
44
43
 
45
44
  UPDATE_MESSAGE = 7
@@ -68,7 +67,7 @@ class Interaction(DataModel):
68
67
  """HTTP session for requests."""
69
68
 
70
69
  type: int
71
- """Type of interaction."""
70
+ """Type of interaction. See [`InteractionTypes`][scurrypy.dispatch.command_dispatcher.InteractionTypes]."""
72
71
 
73
72
  channel_id: int
74
73
  """ID of the channel where the interaction was sent."""
@@ -97,81 +96,89 @@ class Interaction(DataModel):
97
96
  channel: Optional[Channel] = None
98
97
  """Partial channel object the interaction was invoked."""
99
98
 
100
- async def respond(self, message: str | MessageBuilder, with_response: bool = False, **flags: Unpack[MessageFlagParams]):
99
+ def _prepare_message(self, message: MessagePart, t: int):
100
+ """Prepares a message to be sent to HTTPClient.
101
+
102
+ Args:
103
+ message (MessagePart): the message content
104
+ t (int): the interaction type. See [`InteractionTypes`][scurrypy.dispatch.command_dispatcher.InteractionTypes].
105
+
106
+ Returns:
107
+ (dict): the complete interaction content payload
108
+ """
109
+ # set attachment IDs (if any)
110
+ if message.attachments:
111
+ for idx, file in enumerate(message.attachments):
112
+ file.id = idx
113
+
114
+ return {'type': t, 'data': message.to_dict()}
115
+
116
+ async def respond(self, message: str | MessagePart, with_response: bool = False, **flags: Unpack[MessageFlagParams]):
101
117
  """Create a message in response to an interaction.
102
118
 
103
119
  Args:
104
- message (str | MessageBuilder): content as a string or from MessageBuilder
120
+ message (str | MessagePart): content as a string or from MessagePart
105
121
  with_response (bool, optional): if the interaction data should be returned. Defaults to False.
122
+ **flags: message flags to set. (set respective flag to True to toggle.)
106
123
 
107
124
  Raises:
108
- TypeError: invalid type
125
+ TypeError: invalid `message` type
109
126
  """
110
127
  if isinstance(message, str):
111
- message = MessageBuilder(content=message).set_flags(**flags)
112
- elif not isinstance(message, MessageBuilder):
113
- raise TypeError(f"Interaction.respond expects type str or MessageBuilder, got {type(message).__name__}")
114
-
115
- content = {
116
- 'type': InteractionCallbackTypes.CHANNEL_MESSAGE_WITH_SOURCE,
117
- 'data': message._to_dict()
118
- }
119
-
120
- params = {'with_response': with_response}
121
-
128
+ message = MessagePart(content=message).set_flags(**flags)
129
+ elif not isinstance(message, MessagePart):
130
+ raise TypeError(f"Interaction.respond expects type str or MessagePart, got {type(message).__name__}")
131
+
122
132
  data = await self._http.request(
123
133
  'POST',
124
134
  f'/interactions/{self.id}/{self.token}/callback',
125
- content,
135
+ data=self._prepare_message(message, InteractionCallbackTypes.CHANNEL_MESSAGE_WITH_SOURCE),
126
136
  files=[fp.path for fp in message.attachments],
127
- params=params)
137
+ params={'with_response': with_response}
138
+ )
128
139
 
129
140
  if with_response:
130
141
  return InteractionCallbackModel.from_dict(data, self._http)
131
142
 
132
- async def update(self, message: str | MessageBuilder, **flags: Unpack[MessageFlagParams]):
143
+ async def update(self, message: str | MessagePart, **flags: Unpack[MessageFlagParams]):
133
144
  """Update a message in response to an interaction.
134
145
 
135
146
  Args:
136
- message (str | MessageBuilder): content as a string or from MessageBuilder
147
+ message (str | MessagePart): content as a string or from MessagePart
148
+ **flags: message flags to set
137
149
 
138
150
  Raises:
139
- TypeError: invalid type
151
+ TypeError: invalid `message` type
140
152
  """
141
153
  if isinstance(message, str):
142
- message = MessageBuilder(content=message).set_flags(**flags)
143
- elif not isinstance(message, MessageBuilder):
144
- raise TypeError(f"Interaction.update expects type str or MessageBuilder, got {type(message).__name__}")
145
-
146
- content = {
147
- 'type': InteractionCallbackTypes.UPDATE_MESSAGE,
148
- 'data': message._to_dict()
149
- }
154
+ message = MessagePart(content=message).set_flags(**flags)
155
+ elif not isinstance(message, MessagePart):
156
+ raise TypeError(f"Interaction.update expects type str or MessagePart, got {type(message).__name__}")
150
157
 
151
158
  await self._http.request(
152
159
  'POST',
153
160
  f'/interactions/{self.id}/{self.token}/callback',
154
- content,
161
+ data=self._prepare_message(message, InteractionCallbackTypes.UPDATE_MESSAGE),
155
162
  files=[fp.path for fp in message.attachments])
156
163
 
157
- async def respond_modal(self, modal: ModalBuilder):
164
+ async def respond_modal(self, modal: ModalPart):
158
165
  """Create a modal in response to an interaction.
159
166
 
160
167
  Args:
161
- modal (ModalBuilder): modal data
168
+ modal (ModalPart): modal data
162
169
 
163
170
  Raises:
164
- TypeError: invalid type
171
+ TypeError: invalid `modal` type
165
172
  """
166
- if not isinstance(modal, ModalBuilder):
167
- raise TypeError(f"Interaction.respond_modal expects type ModalBuilder, got {type(modal).__name__}")
173
+ if not isinstance(modal, ModalPart):
174
+ raise TypeError(f"Interaction.respond_modal expects type ModalPart, got {type(modal).__name__}")
168
175
 
169
176
  content = {
170
177
  'type': InteractionCallbackTypes.MODAL,
171
- 'data': modal._to_dict()
178
+ 'data': modal.to_dict()
172
179
  }
173
180
 
174
181
  await self._http.request(
175
182
  'POST',
176
183
  f'/interactions/{self.id}/{self.token}/callback',
177
- content)
184
+ data=content)
@@ -4,9 +4,8 @@ from typing import Optional
4
4
  from ..http import HTTPClient
5
5
  from ..model import DataModel
6
6
 
7
- from ..models.user import UserModel
8
- from ..models.emoji import EmojiModel
9
- from ..parts.message import MessageBuilder
7
+ from ..models import UserModel, EmojiModel
8
+ from ..parts.message import MessagePart
10
9
 
11
10
  @dataclass
12
11
  class Message(DataModel):
@@ -41,7 +40,7 @@ class Message(DataModel):
41
40
  self.__dict__.update(Message.from_dict(data, self._http).__dict__)
42
41
 
43
42
  async def fetch(self):
44
- """Fetches the message data based on the given channel id and message id.
43
+ """Fetches the message data based on the given channel ID and message id.
45
44
 
46
45
  Returns:
47
46
  (Message): the message object
@@ -50,67 +49,67 @@ class Message(DataModel):
50
49
 
51
50
  return Message.from_dict(data, self._http)
52
51
 
53
- async def send(self, message: str | MessageBuilder):
52
+ async def send(self, message: str | MessagePart):
54
53
  """Sends a new message to the current channel.
55
54
 
56
55
  Permissions:
57
56
  * SEND_MESSAGES → required to senf your own messages
58
57
 
59
58
  Args:
60
- message (str | MessageBuilder): can be just text or the MessageBuilder for dynamic messages
59
+ message (str | MessagePart): can be just text or the MessagePart for dynamic messages
61
60
 
62
61
  Returns:
63
62
  (Message): the new Message object with all fields populated
64
63
  """
65
64
  if isinstance(message, str):
66
- message = MessageBuilder(content=message)
65
+ message = MessagePart(content=message)
67
66
 
68
67
  data = await self._http.request(
69
68
  "POST",
70
69
  f"/channels/{self.channel_id}/messages",
71
- message._to_dict(),
70
+ data=message.to_dict(),
72
71
  files=[fp.path for fp in message.attachments] if message.attachments else None
73
72
  )
74
73
  return Message.from_dict(data, self._http)
75
74
 
76
- async def edit(self, message: str | MessageBuilder):
75
+ async def edit(self, message: str | MessagePart):
77
76
  """Edits this message.
78
77
 
79
78
  Permissions:
80
79
  * MANAGE_MESSAGES → ONLY if editing another user's message
81
80
 
82
81
  Args:
83
- message (str | MessageBuilder): can be just text or the MessageBuilder for dynamic messages
82
+ message (str | MessagePart): can be just text or the MessagePart for dynamic messages
84
83
  """
85
84
  if isinstance(message, str):
86
- message = MessageBuilder(content=message)
85
+ message = MessagePart(content=message)
87
86
 
88
87
  data = await self._http.request(
89
88
  "PATCH",
90
89
  f"/channels/{self.channel_id}/messages/{self.id}",
91
- message._to_dict(),
90
+ data=message.to_dict(),
92
91
  files=[fp.path for fp in message.attachments] if message.attachments else None)
93
92
 
94
93
  self._update(data)
95
94
 
96
- async def reply(self, message: str | MessageBuilder):
95
+ async def reply(self, message: str | MessagePart):
97
96
  """Reply to this message with a new message.
98
97
 
99
98
  Permissions:
100
99
  * SEND_MESSAGES → required to send the message
101
100
 
102
101
  Args:
103
- message (str | MessageBuilder): the new message
102
+ message (str | MessagePart): the new message
104
103
  """
105
104
  if isinstance(message, str):
106
- message = MessageBuilder(content=message)
105
+ message = MessagePart(content=message)
107
106
 
108
107
  message = message._set_reference(self.id, self.channel_id)
109
108
 
110
109
  await self._http.request(
111
110
  'POST',
112
111
  f"/channels/{self.channel_id}/messages",
113
- message._to_dict(),
112
+ data=message.to_dict(),
114
113
  files=[fp.path for fp in message.attachments] if message.attachments else None)
115
114
 
116
115
  async def crosspost(self):
@@ -4,8 +4,7 @@ from typing import Optional, TypedDict, Unpack
4
4
  from ..http import HTTPClient
5
5
  from ..model import DataModel
6
6
 
7
- from ..models.guild import GuildModel
8
- from ..models.member import MemberModel
7
+ from ..models import GuildModel, MemberModel
9
8
 
10
9
  class FetchUserGuildsParams(TypedDict, total=False):
11
10
  before: int
@@ -78,7 +77,7 @@ class User(DataModel):
78
77
  Requires the OAuth2 guilds scope!
79
78
 
80
79
  Args:
81
- kwargs: Field-specific data
80
+ **kwargs: user guilds fetch params
82
81
  !!! note
83
82
  If no kwargs are provided, default to 200 guilds limit.
84
83
 
@@ -101,7 +100,7 @@ class User(DataModel):
101
100
  Requires the OAuth2 guilds.members.read scope!
102
101
 
103
102
  Args:
104
- guild_id (int): id of guild to fetch data from
103
+ guild_id (int): ID of guild to fetch data from
105
104
 
106
105
  Returns:
107
106
  (MemberModel): member data from guild
@@ -0,0 +1,108 @@
1
+ Metadata-Version: 2.4
2
+ Name: scurrypy
3
+ Version: 0.6.6
4
+ Summary: Dataclass-driven Discord API Wrapper in Python
5
+ Author: Furmissile
6
+ Requires-Python: >=3.10
7
+ Description-Content-Type: text/markdown
8
+ License-File: LICENSE
9
+ Requires-Dist: aiohttp>=3.8.0
10
+ Requires-Dist: websockets>=11.0.0
11
+ Dynamic: license-file
12
+
13
+ # __ScurryPy__
14
+
15
+ [![PyPI version](https://badge.fury.io/py/scurrypy.svg)](https://badge.fury.io/py/scurrypy)
16
+
17
+ A dataclass-driven Discord API wrapper in Python!
18
+
19
+ While this wrapper is mainly used for various squirrel-related shenanigans, it can also be used for more generic bot purposes.
20
+
21
+ ## Features
22
+ * Easy to extend
23
+ * Command, and event handling
24
+ * Unix shell-style wildcards for component routing
25
+ * Declarative style using decorators
26
+ * Supports both legacy and new features
27
+ * Respects Discord's rate limits
28
+ * No `__future__` hacks to avoid circular import
29
+ * Capable of sharding
30
+
31
+ ## Benchmarks
32
+ Not convinced ScurryPy has a place among top libraries? See the benchmarks below!
33
+
34
+ ### Test Environment
35
+
36
+ - **Python**: 3.11.6
37
+ - **OS**: Windows 11
38
+
39
+ ### Results Summary
40
+
41
+ ```
42
+ Library Time (ms) Memory Δ (MB) Objects
43
+ --------------------------------------------------------
44
+ scurrypy 8.9 0.44 1417
45
+ hikari 1710.3 27.67 53658
46
+ discord 252.5 7.64 14099
47
+ disnake 185.9 6.31 12111
48
+ ```
49
+
50
+ *(See `tests/benchmark.py` for how this test was done.)*
51
+
52
+ ## Getting Started
53
+
54
+ *Note: This section also appears in the documentation, but here are complete examples ready to use with your bot credentials.*
55
+
56
+ ### Installation
57
+
58
+ To install the ScurryPy package, run:
59
+
60
+ ```bash
61
+ pip install scurrypy
62
+ ```
63
+
64
+ ## Minimal Slash Command
65
+
66
+ The following demonstrates building and responding to a slash command.
67
+
68
+ ```py
69
+ import scurrypy
70
+
71
+ client = scurrypy.Client(
72
+ token='your-token',
73
+ application_id=APPLICATION_ID # your bot's application ID
74
+ )
75
+
76
+ @client.command(
77
+ scurrypy.SlashCommand('example', 'Demonstrate the minimal slash command!'),
78
+ GUILD_ID # must be a guild ID your bot is in
79
+ )
80
+ async def example(bot: scurrypy.Client, event: scurrypy.InteractionEvent):
81
+ await event.interaction.respond(f'Hello, {event.interaction.member.user.username}!')
82
+
83
+ client.run()
84
+ ```
85
+
86
+ ## Minimal Prefix Command (Legacy)
87
+
88
+ The following demonstrates building and responding to a message prefix command.
89
+
90
+ ```py
91
+ import scurrypy
92
+
93
+ client = scurrypy.Client(
94
+ token='your-token',
95
+ application_id=APPLICATION_ID, # your bot's application ID
96
+ intents=scurrypy.set_intents(message_content=True),
97
+ prefix='!' # your custom prefix
98
+ )
99
+
100
+ @client.prefix_command("ping")
101
+ async def on_ping(bot: scurrypy.Client, event: scurrypy.MessageCreateEvent):
102
+ await event.message.send("Pong!")
103
+
104
+ client.run()
105
+ ```
106
+
107
+ ## Like What You See?
108
+ Explore the full [documentation](https://furmissile.github.io/scurrypy) for more examples, guides, and API reference.
@@ -0,0 +1,47 @@
1
+ scurrypy/__init__.py,sha256=K5ErF9oKh8onuCb5hgurv1RUJ3X7V2dkm1RumNyc7mc,10258
2
+ scurrypy/client.py,sha256=1_JP2N_rkywx3OS_Hkk9Mh_7W9gsPyeMUo4PrMR0eA0,12131
3
+ scurrypy/client_like.py,sha256=aeHt2g5R0x86RjW1ExckjmkBSo4W4_FvZfLjcRsUoC8,586
4
+ scurrypy/config.py,sha256=OH1A2mNKhDlGvQYASEsVUx2pNxP1YQ2a7a7z-IM5xFg,200
5
+ scurrypy/error.py,sha256=8-YaSVf-fZ8FDAzP-_JWGo86HI3MEcU6C4RAXgnSGiw,1801
6
+ scurrypy/gateway.py,sha256=5qyRRVpG4rQ2o75olPWMEvo_1sO2Pk4sNV1WFvn20S4,6673
7
+ scurrypy/http.py,sha256=KxEXPPraxEayaIZDPFxsQ9o_zsxbZkt5Bjs3zqXrwU4,10785
8
+ scurrypy/intents.py,sha256=PiTC48ommAdDnZHiJWBHKVx5n2ESO1KXWR7jCUv_lPs,2707
9
+ scurrypy/logger.py,sha256=_P12YGaaD6X79-q9_KT1727gcKn2n3CFDpnTOtNZfxQ,3235
10
+ scurrypy/model.py,sha256=vJS2pxJ9yS1zxypWNUnbkqzNqBDaytTUDiXfLM0k364,2372
11
+ scurrypy/models.py,sha256=MnBguAdtGTbbiAUZp8Y6Z45FBPq9vCKtWGqWnGHdjwk,6222
12
+ scurrypy/dispatch/__init__.py,sha256=m7ixrbNhOV9QRORXPw6LSwxofQMAvLmPFBweBZu9ACc,20
13
+ scurrypy/dispatch/command_dispatcher.py,sha256=1vC4cRO2CZdDN02lMUWBk5wpI5x-89cLMi1eQ7YYdoo,7953
14
+ scurrypy/dispatch/event_dispatcher.py,sha256=ij77mHNfleVlKMJk5WfXQSSe3eRWtPfCY1amPiejpEM,3770
15
+ scurrypy/dispatch/prefix_dispatcher.py,sha256=Qrd5luIi-1Y0ZtpQ6xcHRp9Up5wZnNMBm3p8-kwnWNk,2592
16
+ scurrypy/events/__init__.py,sha256=xE8YtJ7NKZkm7MLnohDQIbezh3ColmLR-3BMiZabt3k,18
17
+ scurrypy/events/channel_events.py,sha256=ZTby2wSTNyd_rqt4PzEt4r-WlfcNPGCxJusoizL-ScA,1573
18
+ scurrypy/events/gateway_events.py,sha256=jvTECmiQjabAHIDvKMzLDVx4BNU4gLaRKR-jFAewoV0,735
19
+ scurrypy/events/guild_events.py,sha256=qzQjVeHugC2yzPxARtnTEV7t50S8UZJJHTnPueI4IJY,895
20
+ scurrypy/events/hello_event.py,sha256=O8Ketu_N943cnGaFkGsAHfWhgKXFQCYCqSD3EqdsXjA,225
21
+ scurrypy/events/interaction_events.py,sha256=ZQXwdpN9b5RvITPbLm9yxatvSo2AgP_MxnimIsbm8Tc,4769
22
+ scurrypy/events/message_events.py,sha256=ht5TApYq0vS_-1w8bizJUkO9E00YcSA6-auWFXX7vTE,1578
23
+ scurrypy/events/reaction_events.py,sha256=j6twbQca3whp-vW0xDhA8fX0vsWL0aqenDms6tzZVNU,2609
24
+ scurrypy/events/ready_event.py,sha256=FpT6zwy14ftOwncbKhUcadYeH1zo5J2icNreGasNwpY,729
25
+ scurrypy/parts/__init__.py,sha256=yROb-BqEw-FKXqq_-0WbP33U-Arm_9NpJuEamXpvjeA,19
26
+ scurrypy/parts/channel.py,sha256=iyYUq3swQkGeOkR4aM7tpvaiP2xtOJ69Asuf4G3nuIg,1194
27
+ scurrypy/parts/command.py,sha256=PtgGqh-5qjvKuDkVgLJh5Cw0GP1T55g4DgzMvFivnJw,2321
28
+ scurrypy/parts/component_types.py,sha256=qr1R0jzXpE_h9Xv4P5DyYRSuhxS0Qnm9aag-JKrJvBA,131
29
+ scurrypy/parts/components.py,sha256=RTg456-zothOtYkMv0vbCxQ-e_b14xObxMnMunHDWV8,7760
30
+ scurrypy/parts/components_v2.py,sha256=lHcq_F25uHoS-ZkhtetFsrRD0ser6sROHu0F8X-68h4,5481
31
+ scurrypy/parts/embed.py,sha256=-K6MqBB0r1GlGHJQtAVIQ6FcTnncYccIGY6sRPHuVsc,2056
32
+ scurrypy/parts/message.py,sha256=GHI2mZ4DCiwB2eGAoNw8c09Kw6YTkJe7QQF9IxXwLlQ,4130
33
+ scurrypy/parts/modal.py,sha256=u7M01oLMkBJP1P6QUvciYWVMEXHvmLw1AnG_jHxbg-w,417
34
+ scurrypy/parts/role.py,sha256=fnEIlbZih-X-vDkr1zXtN9xYcpQtcsgTLZZVY_SAQh4,622
35
+ scurrypy/resources/__init__.py,sha256=EdzYKftSLqqr3Bpzc0_90kfozJXOtp9jNTIHhCTt_-0,21
36
+ scurrypy/resources/application.py,sha256=DIjv64Jboj7ub1j_PKp9aVzVOGRxvcC3axm3Hx5plqY,2733
37
+ scurrypy/resources/bot_emojis.py,sha256=gNbe6xbiEf9X3Tl1lgGulrv9zUSj9qzi8_JPzLVwink,1695
38
+ scurrypy/resources/channel.py,sha256=QGS5IWw_zvquyC4pWhBf4nvhzRaZUBtM1D562dQvEzU,6992
39
+ scurrypy/resources/guild.py,sha256=H5rsv6xSUxQ9y66JAb1U2gGpGLujGxpMVIZuJYp52_I,8143
40
+ scurrypy/resources/interaction.py,sha256=LPNR3cqbBHg5BV1bgyy8EGqelKT-zNMLZBGlFAh4PVM,6582
41
+ scurrypy/resources/message.py,sha256=PudYpCQdEUf8R7jpKtV2ZVwWZ0s7vVranCZYlkMQvkw,7471
42
+ scurrypy/resources/user.py,sha256=8pXP6gN2oHV7aFoD9ayNCVk5-UPDPzkflATSiD_PvgY,3058
43
+ scurrypy-0.6.6.dist-info/licenses/LICENSE,sha256=lFWI-P5B2ASgxejVH-WesuAFVXwbfr9moST2RrdlIMQ,791
44
+ scurrypy-0.6.6.dist-info/METADATA,sha256=o33AWKvEcwnFQD8ndujDoCUprgXftORWdYK7Bl3YV-8,3040
45
+ scurrypy-0.6.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
46
+ scurrypy-0.6.6.dist-info/top_level.txt,sha256=cP1rrlCOPlavqRZ3JbawO-xKi4QcIWa2VHz2DBf3po4,9
47
+ scurrypy-0.6.6.dist-info/RECORD,,
@@ -13,4 +13,4 @@ and its source code, provided that:
13
13
  implied. The author assumes no liability for any damages arising from its use.
14
14
 
15
15
  5. This software may not be used for commercial purposes without written consent
16
- from the author.
16
+ from the author.
@@ -0,0 +1 @@
1
+ scurrypy
discord/__init__.py DELETED
@@ -1,223 +0,0 @@
1
- # discord
2
-
3
- import importlib
4
- from typing import TYPE_CHECKING
5
-
6
- __all__ = [
7
- # top-level
8
- "Logger",
9
- "Client",
10
- "Intents",
11
- "set_intents",
12
- "BaseConfig",
13
-
14
- # events
15
- "ReadyEvent",
16
- "ReactionAddEvent",
17
- "ReactionRemoveEvent",
18
- "ReactionRemoveEmojiEvent",
19
- "ReactionRemoveAllEvent",
20
- "GuildCreateEvent",
21
- "GuildUpdateEvent",
22
- "GuildDeleteEvent",
23
- "MessageCreateEvent",
24
- "MessageUpdateEvent",
25
- "MessageDeleteEvent",
26
- "GuildChannelCreateEvent",
27
- "GuildChannelUpdateEvent",
28
- "GuildChannelDeleteEvent",
29
- "ChannelPinsUpdateEvent",
30
- "InteractionEvent",
31
-
32
- # models
33
- "ApplicationModel",
34
- "EmojiModel",
35
- "GuildModel",
36
- "MemberModel",
37
- "UserModel",
38
- "RoleModel",
39
-
40
- # parts
41
- "GuildChannel",
42
- "Role",
43
- "MessageBuilder",
44
- "ModalBuilder",
45
- "EmbedBuilder",
46
- "ActionRow",
47
- "StringSelect",
48
- "UserSelect",
49
- "RoleSelect",
50
- "ChannelSelect",
51
- "MentionableSelect",
52
- "SlashCommand",
53
- "MessageCommand",
54
- "UserCommand",
55
- "Container",
56
- "Section",
57
- "MediaGalleryItem",
58
- "Label",
59
-
60
- # resources
61
- "Guild",
62
- "Channel",
63
- "Message",
64
- "BotEmojis",
65
- "User",
66
- "Interaction",
67
- "Application",
68
- ]
69
-
70
- # For editor support / autocomplete
71
- if TYPE_CHECKING:
72
- from .logger import Logger
73
- from .client import Client
74
- from .intents import Intents, set_intents
75
- from .config import BaseConfig
76
-
77
- # events
78
- from .events.ready_event import ReadyEvent
79
- from .events.reaction_events import (
80
- ReactionAddEvent,
81
- ReactionRemoveEvent,
82
- ReactionRemoveEmojiEvent,
83
- ReactionRemoveAllEvent,
84
- )
85
- from .events.guild_events import (
86
- GuildCreateEvent,
87
- GuildUpdateEvent,
88
- GuildDeleteEvent,
89
- )
90
- from .events.message_events import (
91
- MessageCreateEvent,
92
- MessageUpdateEvent,
93
- MessageDeleteEvent,
94
- )
95
- from .events.channel_events import (
96
- GuildChannelCreateEvent,
97
- GuildChannelUpdateEvent,
98
- GuildChannelDeleteEvent,
99
- ChannelPinsUpdateEvent,
100
- )
101
- from .events.interaction_events import InteractionEvent
102
-
103
- # models
104
- from .models.application import ApplicationModel
105
- from .models.emoji import EmojiModel
106
- from .models.guild import GuildModel
107
- from .models.member import MemberModel
108
- from .models.user import UserModel
109
- from .models.role import RoleModel
110
-
111
- # parts
112
- from .parts.channel import GuildChannel
113
- from .parts.role import Role
114
- from .parts.message import MessageBuilder
115
- from .parts.modal import ModalBuilder
116
- from .parts.embed import EmbedBuilder
117
- from .parts.action_row import (
118
- ActionRow,
119
- StringSelect,
120
- UserSelect,
121
- RoleSelect,
122
- ChannelSelect,
123
- MentionableSelect
124
- )
125
-
126
- from .parts.command import (
127
- SlashCommand,
128
- MessageCommand,
129
- UserCommand
130
- )
131
-
132
- from .parts.components_v2 import (
133
- Container,
134
- Section,
135
- MediaGalleryItem,
136
- Label
137
- )
138
-
139
- # resources
140
- from .resources.guild import Guild
141
- from .resources.channel import Channel
142
- from .resources.message import Message
143
- from .resources.bot_emojis import BotEmojis
144
- from .resources.user import User
145
- from .resources.interaction import Interaction
146
- from .resources.application import Application
147
-
148
- # Lazy loader
149
- def __getattr__(name: str):
150
- if name not in __all__:
151
- raise AttributeError(f"module {__name__} has no attribute {name}")
152
-
153
- mapping = {
154
- # top-level
155
- "Logger": "discord.logger",
156
- "Client": "discord.client",
157
- "Intents": "discord.intents",
158
- "set_intents": "discord.intents",
159
- "BaseConfig": "discord.config",
160
-
161
- # events
162
- "ReadyEvent": "discord.events.ready_event",
163
- "ReactionAddEvent": "discord.events.reaction_events",
164
- "ReactionRemoveEvent": "discord.events.reaction_events",
165
- "ReactionRemoveEmojiEvent": "discord.events.reaction_events",
166
- "ReactionRemoveAllEvent": "discord.events.reaction_events",
167
- "GuildCreateEvent": "discord.events.guild_events",
168
- "GuildUpdateEvent": "discord.events.guild_events",
169
- "GuildDeleteEvent": "discord.events.guild_events",
170
- "MessageCreateEvent": "discord.events.message_events",
171
- "MessageUpdateEvent": "discord.events.message_events",
172
- "MessageDeleteEvent": "discord.events.message_events",
173
- "GuildChannelCreateEvent": "discord.events.channel_events",
174
- "GuildChannelUpdateEvent": "discord.events.channel_events",
175
- "GuildChannelDeleteEvent": "discord.events.channel_events",
176
- "ChannelPinsUpdateEvent": "discord.events.channel_events",
177
- "InteractionEvent": "discord.events.interaction_events",
178
-
179
- # models
180
- 'ApplicationModel': "discord.models.application",
181
- 'EmojiModel': "discord.models.emoji",
182
- 'GuildModel': "discord.models.guild",
183
- 'MemberModel': "discord.models.member",
184
- 'UserModel': "discord.models.user",
185
- 'RoleModel': "discord.models.role",
186
-
187
- # parts
188
- 'GuildChannel': "discord.parts.channel",
189
- 'Role': "discord.parts.role",
190
- 'MessageBuilder': "discord.parts.message",
191
- 'ModalBuilder': "discord.parts.modal",
192
- 'EmbedBuilder': "discord.parts.embed",
193
- 'ActionRow': "discord.parts.action_row",
194
- 'StringSelect': "discord.parts.action_row",
195
- 'UserSelect': "discord.parts.action_row",
196
- 'RoleSelect': "discord.parts.action_row",
197
- 'ChannelSelect': "discord.parts.action_row",
198
- 'MentionableSelect': "discord.parts.action_row",
199
- 'SlashCommand': "discord.parts.command",
200
- 'MessageCommand': "discord.parts.command",
201
- 'UserCommand': "discord.parts.command",
202
- 'Container': "discord.parts.components_v2",
203
- 'Section': "discord.parts.components_v2",
204
- 'MediaGalleryItem': "discord.parts.components_v2",
205
- 'Label': "discord.parts.components_v2",
206
-
207
- # resources
208
- 'Guild': "discord.resources.guild",
209
- 'Channel': "discord.resources.channel",
210
- 'Message': "discord.resources.message",
211
- 'BotEmojis': "discord.resources.bot_emojis",
212
- 'User': "discord.resources.user",
213
- 'Interaction': "discord.resources.interaction",
214
- 'Application': "discord.resources.application"
215
- }
216
-
217
- module = importlib.import_module(mapping[name])
218
- attr = getattr(module, name)
219
- globals()[name] = attr # cache it for future lookups
220
- return attr
221
-
222
- def __dir__():
223
- return sorted(list(globals().keys()) + __all__)