scurrypy 0.6.5__tar.gz → 0.7.2__tar.gz

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 (64) hide show
  1. {scurrypy-0.6.5/scurrypy.egg-info → scurrypy-0.7.2}/PKG-INFO +32 -28
  2. {scurrypy-0.6.5 → scurrypy-0.7.2}/README.md +31 -27
  3. {scurrypy-0.6.5 → scurrypy-0.7.2}/pyproject.toml +4 -2
  4. scurrypy-0.7.2/scurrypy/__init__.py +16 -0
  5. {scurrypy-0.6.5 → scurrypy-0.7.2}/scurrypy/client.py +13 -9
  6. scurrypy-0.7.2/scurrypy/core/__init__.py +16 -0
  7. {scurrypy-0.6.5/scurrypy → scurrypy-0.7.2/scurrypy/core}/http.py +28 -54
  8. {scurrypy-0.6.5/scurrypy → scurrypy-0.7.2/scurrypy/core}/intents.py +1 -1
  9. scurrypy-0.7.2/scurrypy/dispatch/__init__.py +7 -0
  10. {scurrypy-0.6.5 → scurrypy-0.7.2}/scurrypy/dispatch/command_dispatcher.py +1 -1
  11. {scurrypy-0.6.5 → scurrypy-0.7.2}/scurrypy/dispatch/event_dispatcher.py +4 -1
  12. {scurrypy-0.6.5 → scurrypy-0.7.2}/scurrypy/dispatch/prefix_dispatcher.py +1 -1
  13. scurrypy-0.7.2/scurrypy/events/__init__.py +62 -0
  14. {scurrypy-0.6.5 → scurrypy-0.7.2}/scurrypy/events/channel_events.py +1 -1
  15. {scurrypy-0.6.5 → scurrypy-0.7.2}/scurrypy/events/gateway_events.py +1 -1
  16. {scurrypy-0.6.5 → scurrypy-0.7.2}/scurrypy/events/guild_events.py +21 -1
  17. {scurrypy-0.6.5 → scurrypy-0.7.2}/scurrypy/events/hello_event.py +1 -1
  18. {scurrypy-0.6.5 → scurrypy-0.7.2}/scurrypy/events/interaction_events.py +1 -1
  19. {scurrypy-0.6.5 → scurrypy-0.7.2}/scurrypy/events/message_events.py +1 -1
  20. {scurrypy-0.6.5 → scurrypy-0.7.2}/scurrypy/events/reaction_events.py +1 -1
  21. {scurrypy-0.6.5 → scurrypy-0.7.2}/scurrypy/events/ready_event.py +1 -1
  22. scurrypy-0.7.2/scurrypy/models/__init__.py +15 -0
  23. scurrypy-0.7.2/scurrypy/models/emoji.py +50 -0
  24. scurrypy-0.7.2/scurrypy/models/guild.py +37 -0
  25. scurrypy-0.7.2/scurrypy/models/interaction.py +31 -0
  26. scurrypy-0.7.2/scurrypy/models/role.py +54 -0
  27. scurrypy-0.7.2/scurrypy/models/user.py +95 -0
  28. scurrypy-0.7.2/scurrypy/parts/__init__.py +79 -0
  29. {scurrypy-0.6.5 → scurrypy-0.7.2}/scurrypy/parts/channel.py +1 -1
  30. {scurrypy-0.6.5 → scurrypy-0.7.2}/scurrypy/parts/command.py +1 -1
  31. {scurrypy-0.6.5 → scurrypy-0.7.2}/scurrypy/parts/components.py +1 -1
  32. {scurrypy-0.6.5 → scurrypy-0.7.2}/scurrypy/parts/components_v2.py +1 -1
  33. {scurrypy-0.6.5 → scurrypy-0.7.2}/scurrypy/parts/embed.py +1 -1
  34. {scurrypy-0.6.5 → scurrypy-0.7.2}/scurrypy/parts/message.py +1 -1
  35. {scurrypy-0.6.5 → scurrypy-0.7.2}/scurrypy/parts/modal.py +1 -1
  36. {scurrypy-0.6.5 → scurrypy-0.7.2}/scurrypy/parts/role.py +1 -1
  37. scurrypy-0.7.2/scurrypy/resources/__init__.py +45 -0
  38. {scurrypy-0.6.5 → scurrypy-0.7.2}/scurrypy/resources/application.py +2 -2
  39. {scurrypy-0.6.5 → scurrypy-0.7.2}/scurrypy/resources/bot_emojis.py +1 -1
  40. {scurrypy-0.6.5 → scurrypy-0.7.2}/scurrypy/resources/channel.py +2 -2
  41. {scurrypy-0.6.5 → scurrypy-0.7.2}/scurrypy/resources/guild.py +2 -2
  42. {scurrypy-0.6.5 → scurrypy-0.7.2}/scurrypy/resources/interaction.py +2 -2
  43. {scurrypy-0.6.5 → scurrypy-0.7.2}/scurrypy/resources/message.py +13 -5
  44. {scurrypy-0.6.5 → scurrypy-0.7.2}/scurrypy/resources/user.py +2 -2
  45. {scurrypy-0.6.5 → scurrypy-0.7.2/scurrypy.egg-info}/PKG-INFO +32 -28
  46. {scurrypy-0.6.5 → scurrypy-0.7.2}/scurrypy.egg-info/SOURCES.txt +15 -9
  47. scurrypy-0.6.5/scurrypy/__init__.py +0 -429
  48. scurrypy-0.6.5/scurrypy/dispatch/__init__.py +0 -1
  49. scurrypy-0.6.5/scurrypy/events/__init__.py +0 -1
  50. scurrypy-0.6.5/scurrypy/models.py +0 -258
  51. scurrypy-0.6.5/scurrypy/parts/__init__.py +0 -2
  52. scurrypy-0.6.5/scurrypy/resources/__init__.py +0 -1
  53. {scurrypy-0.6.5 → scurrypy-0.7.2}/LICENSE +0 -0
  54. {scurrypy-0.6.5/scurrypy → scurrypy-0.7.2/scurrypy/core}/client_like.py +0 -0
  55. {scurrypy-0.6.5/scurrypy → scurrypy-0.7.2/scurrypy/core}/config.py +0 -0
  56. {scurrypy-0.6.5/scurrypy → scurrypy-0.7.2/scurrypy/core}/error.py +0 -0
  57. {scurrypy-0.6.5/scurrypy → scurrypy-0.7.2/scurrypy/core}/gateway.py +0 -0
  58. {scurrypy-0.6.5/scurrypy → scurrypy-0.7.2/scurrypy/core}/logger.py +0 -0
  59. {scurrypy-0.6.5/scurrypy → scurrypy-0.7.2/scurrypy/core}/model.py +0 -0
  60. {scurrypy-0.6.5 → scurrypy-0.7.2}/scurrypy/parts/component_types.py +0 -0
  61. {scurrypy-0.6.5 → scurrypy-0.7.2}/scurrypy.egg-info/dependency_links.txt +0 -0
  62. {scurrypy-0.6.5 → scurrypy-0.7.2}/scurrypy.egg-info/requires.txt +0 -0
  63. {scurrypy-0.6.5 → scurrypy-0.7.2}/scurrypy.egg-info/top_level.txt +0 -0
  64. {scurrypy-0.6.5 → scurrypy-0.7.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: scurrypy
3
- Version: 0.6.5
3
+ Version: 0.7.2
4
4
  Summary: Dataclass-driven Discord API Wrapper in Python
5
5
  Author: Furmissile
6
6
  Requires-Python: >=3.10
@@ -10,16 +10,17 @@ Requires-Dist: aiohttp>=3.8.0
10
10
  Requires-Dist: websockets>=11.0.0
11
11
  Dynamic: license-file
12
12
 
13
- # __ScurryPy__
13
+ ## __<center> ScurryPy </center>__
14
14
 
15
15
  [![PyPI version](https://badge.fury.io/py/scurrypy.svg)](https://badge.fury.io/py/scurrypy)
16
16
 
17
- A dataclass-driven Discord API wrapper in Python!
17
+ A lightweight, fully readable Discord API framework built to accommodate everything from basic bots to custom frameworks.
18
18
 
19
- While this wrapper is mainly used for various squirrel-related shenanigans, it can also be used for more generic bot purposes.
19
+ While ScurryPy powers many squirrel-related shenanigans, it works just as well for game bots, interactive components, and educational projects.
20
20
 
21
21
  ## Features
22
- * Easy to extend
22
+ * Easy to extend and build frameworks on top
23
+ * Lightweight core (<1000 lines)
23
24
  * Command, and event handling
24
25
  * Unix shell-style wildcards for component routing
25
26
  * Declarative style using decorators
@@ -28,29 +29,6 @@ While this wrapper is mainly used for various squirrel-related shenanigans, it c
28
29
  * No `__future__` hacks to avoid circular import
29
30
  * Capable of sharding
30
31
 
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
- - **Method**: New Python process per measurement
39
- - **Tool**: See benchmarks folder
40
-
41
- ### Results Summary
42
-
43
- ```
44
- Library Time (ms) Memory Δ (MB) Objects
45
- --------------------------------------------------------
46
- scurrypy 8.9 0.44 1417
47
- hikari 1710.3 27.67 53658
48
- discord 252.5 7.64 14099
49
- disnake 185.9 6.31 12111
50
- ```
51
-
52
- *(See `benchmark.py` for how this test was done.)*
53
-
54
32
  ## Getting Started
55
33
 
56
34
  *Note: This section also appears in the documentation, but here are complete examples ready to use with your bot credentials.*
@@ -106,5 +84,31 @@ async def on_ping(bot: scurrypy.Client, event: scurrypy.MessageCreateEvent):
106
84
  client.run()
107
85
  ```
108
86
 
87
+ ## Building on Top of ScurryPy
88
+
89
+ ScurryPy is designed to be easy to extend with your own abstractions.
90
+
91
+ The following demonstrates integrating a custom cache into your client configuration:
92
+
93
+ ```py
94
+ class CacheProtocol(Protocol):
95
+ async def get_user(self, user_id: int) ...
96
+
97
+ # and the rest...
98
+
99
+ class MyCache(CacheProtocol):
100
+ # your implementation...
101
+
102
+ class MyConfig(BaseConfig):
103
+ cache: MyCache
104
+ # other stuff here...
105
+
106
+ client = scurrypy.Client(
107
+ token = 'your-token',
108
+ application_id = 123456789012345,
109
+ config = MyConfig()
110
+ )
111
+ ```
112
+
109
113
  ## Like What You See?
110
114
  Explore the full [documentation](https://furmissile.github.io/scurrypy) for more examples, guides, and API reference.
@@ -1,13 +1,14 @@
1
- # __ScurryPy__
1
+ ## __<center> ScurryPy </center>__
2
2
 
3
3
  [![PyPI version](https://badge.fury.io/py/scurrypy.svg)](https://badge.fury.io/py/scurrypy)
4
4
 
5
- A dataclass-driven Discord API wrapper in Python!
5
+ A lightweight, fully readable Discord API framework built to accommodate everything from basic bots to custom frameworks.
6
6
 
7
- While this wrapper is mainly used for various squirrel-related shenanigans, it can also be used for more generic bot purposes.
7
+ While ScurryPy powers many squirrel-related shenanigans, it works just as well for game bots, interactive components, and educational projects.
8
8
 
9
9
  ## Features
10
- * Easy to extend
10
+ * Easy to extend and build frameworks on top
11
+ * Lightweight core (<1000 lines)
11
12
  * Command, and event handling
12
13
  * Unix shell-style wildcards for component routing
13
14
  * Declarative style using decorators
@@ -16,29 +17,6 @@ While this wrapper is mainly used for various squirrel-related shenanigans, it c
16
17
  * No `__future__` hacks to avoid circular import
17
18
  * Capable of sharding
18
19
 
19
- ## Benchmarks
20
- Not convinced ScurryPy has a place among top libraries? See the benchmarks below!
21
-
22
- ### Test Environment
23
-
24
- - **Python**: 3.11.6
25
- - **OS**: Windows 11
26
- - **Method**: New Python process per measurement
27
- - **Tool**: See benchmarks folder
28
-
29
- ### Results Summary
30
-
31
- ```
32
- Library Time (ms) Memory Δ (MB) Objects
33
- --------------------------------------------------------
34
- scurrypy 8.9 0.44 1417
35
- hikari 1710.3 27.67 53658
36
- discord 252.5 7.64 14099
37
- disnake 185.9 6.31 12111
38
- ```
39
-
40
- *(See `benchmark.py` for how this test was done.)*
41
-
42
20
  ## Getting Started
43
21
 
44
22
  *Note: This section also appears in the documentation, but here are complete examples ready to use with your bot credentials.*
@@ -94,5 +72,31 @@ async def on_ping(bot: scurrypy.Client, event: scurrypy.MessageCreateEvent):
94
72
  client.run()
95
73
  ```
96
74
 
75
+ ## Building on Top of ScurryPy
76
+
77
+ ScurryPy is designed to be easy to extend with your own abstractions.
78
+
79
+ The following demonstrates integrating a custom cache into your client configuration:
80
+
81
+ ```py
82
+ class CacheProtocol(Protocol):
83
+ async def get_user(self, user_id: int) ...
84
+
85
+ # and the rest...
86
+
87
+ class MyCache(CacheProtocol):
88
+ # your implementation...
89
+
90
+ class MyConfig(BaseConfig):
91
+ cache: MyCache
92
+ # other stuff here...
93
+
94
+ client = scurrypy.Client(
95
+ token = 'your-token',
96
+ application_id = 123456789012345,
97
+ config = MyConfig()
98
+ )
99
+ ```
100
+
97
101
  ## Like What You See?
98
102
  Explore the full [documentation](https://furmissile.github.io/scurrypy) for more examples, guides, and API reference.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "scurrypy"
7
- version = "0.6.5"
7
+ version = "0.7.2"
8
8
 
9
9
  description = "Dataclass-driven Discord API Wrapper in Python"
10
10
  readme = "README.md"
@@ -21,5 +21,7 @@ packages = [
21
21
  "scurrypy.dispatch",
22
22
  "scurrypy.events",
23
23
  "scurrypy.resources",
24
- "scurrypy.parts"
24
+ "scurrypy.parts",
25
+ "scurrypy.core",
26
+ "scurrypy.models"
25
27
  ]
@@ -0,0 +1,16 @@
1
+ # scurrypy
2
+
3
+ from .client import Client
4
+
5
+ __all__ = [
6
+ # top-level modules
7
+ "Client"
8
+ ]
9
+
10
+ # imports listed __all__ libs
11
+ from .events import *
12
+ from .parts import *
13
+ from .resources import *
14
+ from .dispatch import *
15
+ from .models import *
16
+ from .core import *
@@ -1,9 +1,9 @@
1
1
  import asyncio
2
2
 
3
- from .config import BaseConfig
4
- from .intents import Intents
5
- from .gateway import GatewayClient
6
- from .client_like import ClientLike
3
+ from .core.config import BaseConfig
4
+ from .core.intents import Intents
5
+ from .core.gateway import GatewayClient
6
+ from .core.client_like import ClientLike
7
7
 
8
8
  from .parts.command import SlashCommand, MessageCommand, UserCommand
9
9
 
@@ -18,6 +18,7 @@ class Client(ClientLike):
18
18
  intents: int = Intents.DEFAULT,
19
19
  config: BaseConfig = None,
20
20
  debug_mode: bool = False,
21
+ sync_commands: bool = True,
21
22
  prefix = None,
22
23
  quiet: bool = False
23
24
  ):
@@ -27,6 +28,7 @@ class Client(ClientLike):
27
28
  application_id (int): the bot's user ID
28
29
  intents (int, optional): gateway intents. Defaults to Intents.DEFAULT.
29
30
  config (BaseConfig, optional): user-defined config data
31
+ sync_commands (bool, optional): toggle registering commands. Defaults to True.
30
32
  debug_mode (bool, optional): toggle debug messages. Defaults to False.
31
33
  prefix (str, optional): set message prefix if using command prefixes
32
34
  quiet (bool, optional): if INFO, DEBUG, and WARN should be logged
@@ -36,8 +38,8 @@ class Client(ClientLike):
36
38
  if not application_id:
37
39
  raise ValueError("Application ID is required")
38
40
 
39
- from .logger import Logger
40
- from .http import HTTPClient
41
+ from .core.logger import Logger
42
+ from .core.http import HTTPClient
41
43
  from .resources.bot_emojis import BotEmojis
42
44
  from .dispatch.event_dispatcher import EventDispatcher
43
45
  from .dispatch.prefix_dispatcher import PrefixDispatcher
@@ -47,6 +49,7 @@ class Client(ClientLike):
47
49
  self.intents = intents
48
50
  self.application_id = application_id
49
51
  self.config = config
52
+ self.sync_commands = sync_commands
50
53
 
51
54
  self._logger = Logger(debug_mode, quiet)
52
55
 
@@ -282,11 +285,12 @@ class Client(ClientLike):
282
285
  await hook(self)
283
286
  self._logger.log_high_priority("Hooks set up.")
284
287
 
285
- await self.command_dispatcher.register_guild_commands()
288
+ if self.sync_commands:
289
+ await self.command_dispatcher.register_guild_commands()
286
290
 
287
- await self.command_dispatcher.register_global_commands()
291
+ await self.command_dispatcher.register_global_commands()
288
292
 
289
- self._logger.log_high_priority("Commands set up.")
293
+ self._logger.log_high_priority("Commands set up.")
290
294
 
291
295
  tasks = await asyncio.create_task(self._start_shards())
292
296
 
@@ -0,0 +1,16 @@
1
+ # scurrypy/core
2
+
3
+ # from .client_like import ClientLike
4
+ from .config import BaseConfig
5
+ # from .error import DiscordError
6
+ # from .gateway import GatewayClient
7
+ # from .http import HTTPClient
8
+ from .intents import Intents, set_intents
9
+ from .logger import Logger
10
+ # from .model import DataModel
11
+
12
+ __all__ = [
13
+ "BaseConfig",
14
+ "Intents", 'set_intents',
15
+ "Logger"
16
+ ]
@@ -171,54 +171,6 @@ class HTTPClient:
171
171
  bucket.sleep_task = None
172
172
  self.logger.log_high_priority(f"Bucket {endpoint} reset after {bucket.reset_after}s")
173
173
 
174
- async def _make_payload(self, data: dict, files: list):
175
- """Return (data, headers) for aiohttp request — supports multipart.
176
-
177
- Args:
178
- data (dict): request data
179
- files (list): relevant files
180
-
181
- Returns:
182
- (tuple[aiohttp.FormData, dict]): form data and headers
183
- """
184
- headers = {}
185
- if not files:
186
- return data, headers
187
-
188
- form = aiohttp.FormData()
189
- if data:
190
- form.add_field("payload_json", json.dumps(data))
191
-
192
- for idx, file_path in enumerate(files):
193
- async with aiofiles.open(file_path, 'rb') as f:
194
- data = await f.read()
195
- form.add_field(
196
- f'files[{idx}]',
197
- data,
198
- filename=file_path.split('/')[-1],
199
- content_type='application/octet-stream'
200
- )
201
-
202
- return form, headers
203
-
204
- async def _prepare_payload(self, item: RequestItem):
205
- """Prepares the payload based on `RequestItem`.
206
-
207
- Args:
208
- item (RequestItem): the request object
209
-
210
- Returns:
211
- (dict): kwargs to pass to session.request
212
- """
213
- kwargs = {}
214
- if item.files and any(item.files):
215
- payload, headers = await self._make_payload(item.data, item.files)
216
- kwargs = {"data": payload, "headers": headers}
217
- else:
218
- kwargs = {"json": item.data}
219
-
220
- return kwargs
221
-
222
174
  async def _check_global_rate_limit(self):
223
175
  """Checks if the global rate limit is after now (active)."""
224
176
  now = asyncio.get_event_loop().time()
@@ -291,6 +243,34 @@ class HTTPClient:
291
243
  elif bucket.sleep_task and not bucket.sleep_task.done():
292
244
  await bucket.sleep_task
293
245
 
246
+ async def _prepare_payload(self, item: RequestItem):
247
+ """Prepares the payload based on `RequestItem`.
248
+
249
+ Args:
250
+ item (RequestItem): the request object
251
+
252
+ Returns:
253
+ (dict): kwargs to pass to session.request
254
+ """
255
+ if item.files and any(item.files):
256
+ # payload = await self._make_payload(item.data, item.files)
257
+ form = aiohttp.FormData()
258
+ form.add_field("payload_json", json.dumps(item.data))
259
+
260
+ for idx, file_path in enumerate(item.files):
261
+ async with aiofiles.open(file_path, 'rb') as f:
262
+ f_data = await f.read()
263
+ form.add_field(
264
+ f'files[{idx}]',
265
+ f_data,
266
+ filename=file_path.split('/')[-1],
267
+ content_type='application/octet-stream'
268
+ )
269
+
270
+ return {"data": form}
271
+
272
+ return {"json": item.data}
273
+
294
274
  async def _send(self, item: RequestItem):
295
275
  """Core HTTP request executor.
296
276
 
@@ -312,25 +292,19 @@ class HTTPClient:
312
292
 
313
293
  kwargs = await self._prepare_payload(item)
314
294
 
315
- # --- SEND REQUEST ---
316
-
317
295
  url = f"{self.BASE.rstrip('/')}/{item.endpoint.lstrip('/')}"
318
296
 
319
297
  async with self.session.request(
320
298
  method=item.method, url=url, params=item.params, timeout=15, **kwargs
321
299
  ) as resp:
322
300
 
323
- # Update global rate limit if triggered
324
301
  if resp.headers.get("X-RateLimit-Global") == "true":
325
302
  retry_after = float(resp.headers.get("Retry-After", 0))
326
303
  self.global_reset = asyncio.get_event_loop().time() + retry_after
327
304
 
328
- # Bucket handling (endpoint-specific rate limits)
329
305
  bucket_id = resp.headers.get('x-ratelimit-bucket')
330
306
 
331
307
  if bucket_id:
332
- # grab lock from dict of bucket locks with a lock on dict access
333
308
  await self._update_bucket_rate_limit(resp, bucket_id, item.endpoint)
334
309
 
335
- # Handle response
336
310
  return await self._parse_response(resp)
@@ -54,7 +54,7 @@ class IntentFlagParams(TypedDict, total=False):
54
54
  message_content: bool
55
55
 
56
56
  def set_intents(**flags: Unpack[IntentFlagParams]):
57
- """Set bot intents. See [`Intents`][scurrypy.intents.Intents]
57
+ """Set bot intents. See [`Intents`][scurrypy.core.intents.Intents]
58
58
  `Intents.DEFAULT` = (GUILDS | GUILD_MESSAGES) will also be set.
59
59
 
60
60
  Args:
@@ -0,0 +1,7 @@
1
+ # scurrypy/dispatch
2
+
3
+ from .command_dispatcher import InteractionTypes
4
+
5
+ __all__ = [
6
+ "InteractionTypes"
7
+ ]
@@ -1,6 +1,6 @@
1
1
  import fnmatch
2
2
 
3
- from ..client_like import ClientLike
3
+ from ..core.client_like import ClientLike
4
4
 
5
5
  from ..events.interaction_events import ApplicationCommandData, MessageComponentData, ModalData, InteractionEvent
6
6
  from ..resources.interaction import Interaction, InteractionDataTypes
@@ -1,5 +1,5 @@
1
1
  import importlib
2
- from ..client_like import ClientLike
2
+ from ..core.client_like import ClientLike
3
3
 
4
4
  from ..resources.message import Message
5
5
 
@@ -12,6 +12,8 @@ class EventDispatcher:
12
12
  'GUILD_CREATE': ('scurrypy.events.guild_events', 'GuildCreateEvent'),
13
13
  'GUILD_UPDATE': ('scurrypy.events.guild_events', 'GuildUpdateEvent'),
14
14
  'GUILD_DELETE': ('scurrypy.events.guild_events', 'GuildDeleteEvent'),
15
+ 'GUILD_MEMBER_ADD': ('scurrypy.events.guild_events', 'GuildMemberAddEvent'),
16
+ 'GUILD_MEMBER_REMOVE': ('scurrypy.events.guild_events', 'GuildMemberRemoveEvent'),
15
17
 
16
18
  'CHANNEL_CREATE': ('scurrypy.events.channel_events', 'GuildChannelCreateEvent'),
17
19
  'CHANNEL_UPDATE': ('scurrypy.events.channel_events', 'GuildChannelUpdateEvent'),
@@ -90,6 +92,7 @@ class EventDispatcher:
90
92
 
91
93
  handler = self._handlers.get(event_name, None)
92
94
  if handler:
95
+ print(data)
93
96
  obj = cls.from_dict(data, self._http)
94
97
  obj.config = self.config
95
98
  await handler(self.bot, obj)
@@ -1,4 +1,4 @@
1
- from ..client_like import ClientLike
1
+ from ..core.client_like import ClientLike
2
2
 
3
3
  from ..events.message_events import MessageCreateEvent
4
4
 
@@ -0,0 +1,62 @@
1
+ # scurrypy/events
2
+
3
+ from .channel_events import (
4
+ # GuildChannelEvent,
5
+ GuildChannelCreateEvent,
6
+ GuildChannelUpdateEvent,
7
+ GuildChannelDeleteEvent,
8
+ ChannelPinsUpdateEvent,
9
+ )
10
+
11
+ # from .gateway_events import (
12
+ # SessionStartLimit,
13
+ # GatewayEvent
14
+ # )
15
+
16
+ from .guild_events import (
17
+ # GuildEvent,
18
+ GuildCreateEvent,
19
+ GuildUpdateEvent,
20
+ GuildDeleteEvent,
21
+
22
+ GuildMemberAddEvent,
23
+ GuildMemberRemoveEvent
24
+ )
25
+
26
+ # from .hello_event import HelloEvent
27
+
28
+ from .interaction_events import (
29
+ # ApplicationCommandOptionData,
30
+ # ApplicationCommandData,
31
+ # MessageComponentData,
32
+ # ModalComponentData,
33
+ # ModalComponent,
34
+ # ModalData,
35
+ InteractionEvent
36
+ )
37
+
38
+ from .message_events import (
39
+ MessageCreateEvent,
40
+ MessageUpdateEvent,
41
+ MessageDeleteEvent,
42
+ )
43
+
44
+ from .reaction_events import (
45
+ ReactionType,
46
+ ReactionAddEvent,
47
+ ReactionRemoveEvent,
48
+ ReactionRemoveEmojiEvent,
49
+ ReactionRemoveAllEvent,
50
+ )
51
+
52
+ from .ready_event import ReadyEvent
53
+
54
+ __all__ = [
55
+ "GuildChannelCreateEvent", "GuildChannelUpdateEvent", "GuildChannelDeleteEvent", "ChannelPinsUpdateEvent",
56
+ "GuildCreateEvent", "GuildUpdateEvent", "GuildDeleteEvent",
57
+ "GuildMemberAddEvent", "GuildMemberRemoveEvent",
58
+ "InteractionEvent",
59
+ "MessageCreateEvent", "MessageUpdateEvent", "MessageDeleteEvent",
60
+ "ReactionType", "ReactionAddEvent", "ReactionRemoveEvent", "ReactionRemoveEmojiEvent", "ReactionRemoveAllEvent",
61
+ "ReadyEvent"
62
+ ]
@@ -1,5 +1,5 @@
1
1
  from dataclasses import dataclass
2
- from ..model import DataModel
2
+ from ..core.model import DataModel
3
3
  from typing import Optional
4
4
 
5
5
  @dataclass
@@ -1,5 +1,5 @@
1
1
  from dataclasses import dataclass
2
- from ..model import DataModel
2
+ from ..core.model import DataModel
3
3
 
4
4
  @dataclass
5
5
  class SessionStartLimit(DataModel):
@@ -1,5 +1,5 @@
1
1
  from dataclasses import dataclass
2
- from ..model import DataModel
2
+ from ..core.model import DataModel
3
3
 
4
4
  from ..models import MemberModel
5
5
  from ..resources.channel import Channel
@@ -34,3 +34,23 @@ class GuildUpdateEvent(GuildEvent):
34
34
  class GuildDeleteEvent(GuildEvent):
35
35
  """Received when the bot has left a guild or the guild was deleted."""
36
36
  pass
37
+
38
+ from ..models.user import MemberModel, UserModel
39
+
40
+ @dataclass
41
+ class GuildMemberAddEvent(MemberModel):
42
+ """Received when a member joins a guild the bot is in."""
43
+
44
+ guild_id: int
45
+ """ID of the guild."""
46
+
47
+
48
+ @dataclass
49
+ class GuildMemberRemoveEvent(DataModel):
50
+ """Received when a member leaves or is kicked/banned from a guild the bot is in."""
51
+
52
+ guild_id: int
53
+ """ID of the guild."""
54
+
55
+ user: UserModel
56
+ """User object of the user leaving the guild."""
@@ -1,5 +1,5 @@
1
1
  from dataclasses import dataclass
2
- from ..model import DataModel
2
+ from ..core.model import DataModel
3
3
 
4
4
  @dataclass
5
5
  class HelloEvent(DataModel):
@@ -1,6 +1,6 @@
1
1
  from dataclasses import dataclass, field
2
2
  from typing import Optional
3
- from ..model import DataModel
3
+ from ..core.model import DataModel
4
4
 
5
5
  from ..resources.interaction import Interaction
6
6
  from ..parts.components import ComponentTypes
@@ -1,6 +1,6 @@
1
1
  from dataclasses import dataclass
2
2
  from typing import Optional
3
- from ..model import DataModel
3
+ from ..core.model import DataModel
4
4
 
5
5
  from ..resources.message import Message
6
6
  from ..models import MemberModel
@@ -1,6 +1,6 @@
1
1
  from dataclasses import dataclass
2
2
  from typing import Optional
3
- from ..model import DataModel
3
+ from ..core.model import DataModel
4
4
 
5
5
  from ..models import MemberModel, EmojiModel
6
6
 
@@ -1,5 +1,5 @@
1
1
  from dataclasses import dataclass
2
- from ..model import DataModel
2
+ from ..core.model import DataModel
3
3
 
4
4
  from ..models import UserModel, ReadyGuildModel, ApplicationModel
5
5
 
@@ -0,0 +1,15 @@
1
+ # scurrypy/models
2
+
3
+ from .emoji import EmojiModel
4
+ from .guild import ReadyGuildModel, GuildModel
5
+ from .interaction import InteractionCallbackDataModel, InteractionCallbackModel
6
+ from .role import RoleColors, RoleModel
7
+ from .user import UserModel, MemberModel, ApplicationModel, IntegrationModel
8
+
9
+ __all__ = [
10
+ "EmojiModel",
11
+ "ReadyGuildModel", "GuildModel",
12
+ "InteractionCallbackDataModel", "InteractionCallbackModel",
13
+ "RoleColors", "RoleModel",
14
+ "UserModel", "MemberModel", "ApplicationModel", "IntegrationModel"
15
+ ]