scurrypy 0.3.2__tar.gz → 0.3.3__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.

Potentially problematic release.


This version of scurrypy might be problematic. Click here for more details.

Files changed (67) hide show
  1. scurrypy-0.3.3/PKG-INFO +92 -0
  2. scurrypy-0.3.3/README.md +82 -0
  3. scurrypy-0.3.3/discord/__init__.py +223 -0
  4. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/client.py +25 -17
  5. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/dispatch/event_dispatcher.py +19 -30
  6. scurrypy-0.3.3/discord/events/__init__.py +1 -0
  7. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/events/guild_events.py +1 -1
  8. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/logger.py +4 -3
  9. scurrypy-0.3.3/discord/models/__init__.py +1 -0
  10. scurrypy-0.3.3/discord/parts/__init__.py +2 -0
  11. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/parts/message.py +2 -1
  12. scurrypy-0.3.3/discord/resources/__init__.py +1 -0
  13. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/resources/interaction.py +0 -2
  14. {scurrypy-0.3.2 → scurrypy-0.3.3}/pyproject.toml +1 -1
  15. scurrypy-0.3.3/scurrypy.egg-info/PKG-INFO +92 -0
  16. scurrypy-0.3.2/PKG-INFO +0 -85
  17. scurrypy-0.3.2/README.md +0 -75
  18. scurrypy-0.3.2/discord/__init__.py +0 -10
  19. scurrypy-0.3.2/discord/events/__init__.py +0 -33
  20. scurrypy-0.3.2/discord/models/__init__.py +0 -8
  21. scurrypy-0.3.2/discord/parts/__init__.py +0 -28
  22. scurrypy-0.3.2/discord/resources/__init__.py +0 -10
  23. scurrypy-0.3.2/scurrypy.egg-info/PKG-INFO +0 -85
  24. {scurrypy-0.3.2 → scurrypy-0.3.3}/LICENSE +0 -0
  25. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/client_like.py +0 -0
  26. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/config.py +0 -0
  27. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/dispatch/__init__.py +0 -0
  28. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/dispatch/command_dispatcher.py +0 -0
  29. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/dispatch/prefix_dispatcher.py +0 -0
  30. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/error.py +0 -0
  31. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/events/channel_events.py +0 -0
  32. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/events/hello_event.py +0 -0
  33. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/events/interaction_events.py +0 -0
  34. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/events/message_events.py +0 -0
  35. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/events/reaction_events.py +0 -0
  36. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/events/ready_event.py +0 -0
  37. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/gateway.py +0 -0
  38. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/http.py +0 -0
  39. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/intents.py +0 -0
  40. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/model.py +0 -0
  41. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/models/application.py +0 -0
  42. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/models/emoji.py +0 -0
  43. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/models/guild.py +0 -0
  44. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/models/integration.py +0 -0
  45. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/models/interaction.py +0 -0
  46. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/models/member.py +0 -0
  47. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/models/role.py +0 -0
  48. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/models/user.py +0 -0
  49. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/parts/action_row.py +0 -0
  50. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/parts/attachment.py +0 -0
  51. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/parts/channel.py +0 -0
  52. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/parts/command.py +0 -0
  53. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/parts/component_types.py +0 -0
  54. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/parts/components_v2.py +0 -0
  55. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/parts/embed.py +0 -0
  56. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/parts/modal.py +0 -0
  57. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/parts/role.py +0 -0
  58. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/resources/application.py +0 -0
  59. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/resources/bot_emojis.py +0 -0
  60. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/resources/channel.py +0 -0
  61. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/resources/guild.py +0 -0
  62. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/resources/message.py +0 -0
  63. {scurrypy-0.3.2 → scurrypy-0.3.3}/discord/resources/user.py +0 -0
  64. {scurrypy-0.3.2 → scurrypy-0.3.3}/scurrypy.egg-info/SOURCES.txt +0 -0
  65. {scurrypy-0.3.2 → scurrypy-0.3.3}/scurrypy.egg-info/dependency_links.txt +0 -0
  66. {scurrypy-0.3.2 → scurrypy-0.3.3}/scurrypy.egg-info/top_level.txt +0 -0
  67. {scurrypy-0.3.2 → scurrypy-0.3.3}/setup.cfg +0 -0
@@ -0,0 +1,92 @@
1
+ Metadata-Version: 2.4
2
+ Name: scurrypy
3
+ Version: 0.3.3
4
+ Summary: Discord API Wrapper in Python
5
+ Author: Furmissile
6
+ Requires-Python: >=3.10
7
+ Description-Content-Type: text/markdown
8
+ License-File: LICENSE
9
+ Dynamic: license-file
10
+
11
+ # __Welcome to ScurryPy__
12
+
13
+ [![PyPI version](https://badge.fury.io/py/scurrypy.svg)](https://badge.fury.io/py/scurrypy)
14
+
15
+ Yet another Discord API wrapper in Python!
16
+
17
+ While this wrapper is mainly used for various squirrel-related shenanigans, it can also be used for more generic bot purposes.
18
+
19
+ ## Features
20
+ * Command and event handling
21
+ * Declarative style using decorators
22
+ * Supports both legacy and new features
23
+ * Respects Discord's rate limits
24
+
25
+ ## Some things to consider...
26
+ * This is an early version — feedback, ideas, and contributions are very welcome! That said, there may be bumps along the way, so expect occasional bugs and quirks.
27
+ * Certain features are not yet supported, while others are intentionally omitted. See the [docs](https://furmissile.github.io/scurrypy) for full details.
28
+
29
+ ## Getting Started
30
+ *Note: This section also appears in the documentation, but here are complete examples ready to use with your bot credentials.*
31
+
32
+ ### Installation
33
+ To install the ScurryPy package, run:
34
+ ```bash
35
+ pip install scurrypy
36
+ ```
37
+
38
+ ### Minimal Slash Command
39
+ The following demonstrates building and responding to a slash command.
40
+
41
+ *Note: Adjust `dotenv_path` if your `.env` file is not in the same directory as this script.*
42
+
43
+ ```python
44
+ import discord, os
45
+ from dotenv import load_dotenv
46
+
47
+ load_dotenv(dotenv_path='./path/to/env')
48
+
49
+ client = discord.Client(
50
+ token=os.getenv("DISCORD_TOKEN"),
51
+ application_id=APPLICATION_ID # replace with your bot's user ID
52
+ )
53
+
54
+ @client.command(
55
+ command=discord.SlashCommand(
56
+ name='example',
57
+ description='Demonstrate the minimal slash command!'
58
+ ),
59
+ guild_id=GUILD_ID # must be a guild ID your bot is in
60
+ )
61
+ async def example(bot: discord.Client, event: discord.InteractionEvent):
62
+ await event.interaction.respond(f'Hello, {event.interaction.member.user.username}!')
63
+
64
+ client.run()
65
+ ```
66
+
67
+ ### Minimal Prefix Command (Legacy)
68
+ The following demonstrates building and responding to a message prefix command.
69
+
70
+ ```python
71
+ import discord, os
72
+ from dotenv import load_dotenv
73
+
74
+ load_dotenv(dotenv_path='./path/to/env')
75
+
76
+ client = discord.Client(
77
+ token=os.getenv("DISCORD_TOKEN"),
78
+ application_id=APPLICATION_ID, # replace with your bot's user ID
79
+ intents=discord.set_intents(message_content=True),
80
+ prefix='!' # your custom prefix
81
+ )
82
+
83
+ @client.prefix_command
84
+ async def ping(bot: discord.Client, event: discord.MessageCreateEvent):
85
+ # The function name is the name of the command
86
+ await event.message.send("Pong!")
87
+
88
+ client.run()
89
+ ```
90
+
91
+ ## Like what you see?
92
+ Check out the full [documentation](https://furmissile.github.io/scurrypy) for more examples, guides, and API reference!
@@ -0,0 +1,82 @@
1
+ # __Welcome to ScurryPy__
2
+
3
+ [![PyPI version](https://badge.fury.io/py/scurrypy.svg)](https://badge.fury.io/py/scurrypy)
4
+
5
+ Yet another Discord API wrapper in Python!
6
+
7
+ While this wrapper is mainly used for various squirrel-related shenanigans, it can also be used for more generic bot purposes.
8
+
9
+ ## Features
10
+ * Command and event handling
11
+ * Declarative style using decorators
12
+ * Supports both legacy and new features
13
+ * Respects Discord's rate limits
14
+
15
+ ## Some things to consider...
16
+ * This is an early version — feedback, ideas, and contributions are very welcome! That said, there may be bumps along the way, so expect occasional bugs and quirks.
17
+ * Certain features are not yet supported, while others are intentionally omitted. See the [docs](https://furmissile.github.io/scurrypy) for full details.
18
+
19
+ ## Getting Started
20
+ *Note: This section also appears in the documentation, but here are complete examples ready to use with your bot credentials.*
21
+
22
+ ### Installation
23
+ To install the ScurryPy package, run:
24
+ ```bash
25
+ pip install scurrypy
26
+ ```
27
+
28
+ ### Minimal Slash Command
29
+ The following demonstrates building and responding to a slash command.
30
+
31
+ *Note: Adjust `dotenv_path` if your `.env` file is not in the same directory as this script.*
32
+
33
+ ```python
34
+ import discord, os
35
+ from dotenv import load_dotenv
36
+
37
+ load_dotenv(dotenv_path='./path/to/env')
38
+
39
+ client = discord.Client(
40
+ token=os.getenv("DISCORD_TOKEN"),
41
+ application_id=APPLICATION_ID # replace with your bot's user ID
42
+ )
43
+
44
+ @client.command(
45
+ command=discord.SlashCommand(
46
+ name='example',
47
+ description='Demonstrate the minimal slash command!'
48
+ ),
49
+ guild_id=GUILD_ID # must be a guild ID your bot is in
50
+ )
51
+ async def example(bot: discord.Client, event: discord.InteractionEvent):
52
+ await event.interaction.respond(f'Hello, {event.interaction.member.user.username}!')
53
+
54
+ client.run()
55
+ ```
56
+
57
+ ### Minimal Prefix Command (Legacy)
58
+ The following demonstrates building and responding to a message prefix command.
59
+
60
+ ```python
61
+ import discord, os
62
+ from dotenv import load_dotenv
63
+
64
+ load_dotenv(dotenv_path='./path/to/env')
65
+
66
+ client = discord.Client(
67
+ token=os.getenv("DISCORD_TOKEN"),
68
+ application_id=APPLICATION_ID, # replace with your bot's user ID
69
+ intents=discord.set_intents(message_content=True),
70
+ prefix='!' # your custom prefix
71
+ )
72
+
73
+ @client.prefix_command
74
+ async def ping(bot: discord.Client, event: discord.MessageCreateEvent):
75
+ # The function name is the name of the command
76
+ await event.message.send("Pong!")
77
+
78
+ client.run()
79
+ ```
80
+
81
+ ## Like what you see?
82
+ Check out the full [documentation](https://furmissile.github.io/scurrypy) for more examples, guides, and API reference!
@@ -0,0 +1,223 @@
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__)
@@ -1,26 +1,10 @@
1
- import asyncio
2
-
3
- from .logger import Logger
4
- from .gateway import GatewayClient
5
- from .http import HTTPClient
1
+ from .config import BaseConfig
6
2
  from .intents import Intents
7
3
  from .error import DiscordError
8
- from .config import BaseConfig
9
4
  from .client_like import ClientLike
10
5
 
11
- from .resources.guild import Guild
12
- from .resources.channel import Channel
13
- from .resources.message import Message
14
- from .resources.bot_emojis import BotEmojis
15
- from .resources.user import User
16
- from .resources.application import Application
17
-
18
6
  from .parts.command import SlashCommand, MessageCommand, UserCommand
19
7
 
20
- from .dispatch.event_dispatcher import EventDispatcher
21
- from .dispatch.prefix_dispatcher import PrefixDispatcher
22
- from .dispatch.command_dispatcher import CommandDispatcher
23
-
24
8
  class Client(ClientLike):
25
9
  """Main entry point for Discord bots.
26
10
  Ties together the moving parts: gateway, HTTP, event dispatching, command handling, and resource managers.
@@ -45,6 +29,14 @@ class Client(ClientLike):
45
29
  prefix (str, optional): set message prefix if using command prefixes
46
30
  quiet (bool, optional): if INFO, DEBUG, and WARN should be logged
47
31
  """
32
+ from .logger import Logger
33
+ from .gateway import GatewayClient
34
+ from .http import HTTPClient
35
+ from .resources.bot_emojis import BotEmojis
36
+ from .dispatch.event_dispatcher import EventDispatcher
37
+ from .dispatch.prefix_dispatcher import PrefixDispatcher
38
+ from .dispatch.command_dispatcher import CommandDispatcher
39
+
48
40
  self.token = token
49
41
  self.application_id = application_id
50
42
  self.config = config
@@ -154,6 +146,8 @@ class Client(ClientLike):
154
146
  Returns:
155
147
  (Application): the Application resource
156
148
  """
149
+ from .resources.application import Application
150
+
157
151
  return Application(application_id, self._http)
158
152
 
159
153
  def guild_from_id(self, guild_id: int):
@@ -165,6 +159,8 @@ class Client(ClientLike):
165
159
  Returns:
166
160
  (Guild): the Guild resource
167
161
  """
162
+ from .resources.guild import Guild
163
+
168
164
  return Guild(guild_id, self._http)
169
165
 
170
166
  def channel_from_id(self, channel_id: int):
@@ -176,6 +172,8 @@ class Client(ClientLike):
176
172
  Returns:
177
173
  (Channel): the Channel resource
178
174
  """
175
+ from .resources.channel import Channel
176
+
179
177
  return Channel(channel_id, self._http)
180
178
 
181
179
  def message_from_id(self, channel_id: int, message_id: int):
@@ -188,6 +186,8 @@ class Client(ClientLike):
188
186
  Returns:
189
187
  (Message): the Message resource
190
188
  """
189
+ from .resources.message import Message
190
+
191
191
  return Message(message_id, channel_id, self._http)
192
192
 
193
193
  def user_from_id(self, user_id: int):
@@ -199,6 +199,8 @@ class Client(ClientLike):
199
199
  Returns:
200
200
  (User): the User resource
201
201
  """
202
+ from .resources.user import User
203
+
202
204
  return User(user_id, self._http)
203
205
 
204
206
  async def clear_guild_commands(self, guild_id: int):
@@ -215,6 +217,8 @@ class Client(ClientLike):
215
217
 
216
218
  async def _listen(self):
217
219
  """Main event loop for incoming gateway requests."""
220
+ import asyncio
221
+
218
222
  while True:
219
223
  try:
220
224
  message = await self._ws.receive()
@@ -270,6 +274,8 @@ class Client(ClientLike):
270
274
  """Runs the main lifecycle of the bot.
271
275
  Handles connection setup, heartbeat management, event loop, and automatic reconnects.
272
276
  """
277
+ import asyncio
278
+
273
279
  while True:
274
280
  try:
275
281
  await self._http.start_session()
@@ -338,6 +344,8 @@ class Client(ClientLike):
338
344
  Handles starting the session, WS, and heartbeat, reconnection logic,
339
345
  setting up emojis and hooks, and then listens for gateway events.
340
346
  """
347
+ import asyncio
348
+
341
349
  try:
342
350
  asyncio.run(self.start())
343
351
  except KeyboardInterrupt:
@@ -1,42 +1,19 @@
1
+ from importlib import import_module
1
2
  from ..client_like import ClientLike
2
3
 
3
- from ..events.ready_event import *
4
- from ..events.reaction_events import *
5
- from ..events.guild_events import *
6
- from ..events.message_events import *
7
- from ..events.channel_events import *
8
- from ..events.interaction_events import *
9
-
10
4
  from ..resources.message import Message
11
5
 
12
6
  class EventDispatcher:
13
7
  """Central hub for handling Discord Gateway events."""
14
- RESOURCE_MAP = { # maps discord events to their respective dataclass
15
- 'READY': ReadyEvent,
16
-
17
- "MESSAGE_CREATE": MessageCreateEvent,
18
- "MESSAGE_UPDATE": MessageUpdateEvent,
19
- 'MESSAGE_DELETE': MessageDeleteEvent,
20
-
21
- 'MESSAGE_REACTION_ADD': ReactionAddEvent,
22
- 'MESSAGE_REACTION_REMOVE': ReactionRemoveEvent,
23
- 'MESSAGE_REACTION_REMOVE_ALL': ReactionRemoveAllEvent,
24
- 'MESSAGE_REACTION_REMOVE_EMOJI': ReactionRemoveEmojiEvent,
25
-
26
- 'CHANNEL_CREATE': GuildChannelCreateEvent,
27
- 'CHANNEL_UPDATE': GuildChannelUpdateEvent,
28
- 'CHANNEL_DELETE': GuildChannelDeleteEvent,
29
8
 
30
- 'CHANNEL_PINS_UPDATE': ChannelPinsUpdateEvent,
31
-
32
- 'GUILD_CREATE': GuildCreateEvent,
33
- 'GUILD_UPDATE': GuildUpdateEvent,
34
- 'GUILD_DELETE': GuildDeleteEvent,
35
-
36
- 'INTERACTION_CREATE': InteractionEvent
9
+ RESOURCE_MAP = { # maps discord events to their respective dataclass (lazy loading)
10
+ 'READY': ('discord.events.ready_event', 'ReadyEvent'),
37
11
 
12
+ 'MESSAGE_CREATE': ('discord.events.message_events', 'MessageCreateEvent')
13
+
38
14
  # and other events...
39
15
  }
16
+
40
17
  """Mapping of event names to respective dataclass."""
41
18
 
42
19
  def __init__(self, client: ClientLike):
@@ -75,9 +52,21 @@ class EventDispatcher:
75
52
  event_name (str): name of the event
76
53
  data (dict): Discord's raw event payload
77
54
  """
78
- cls = self.RESOURCE_MAP.get(event_name)
55
+ module_info = self.RESOURCE_MAP.get(event_name)
56
+
57
+ if not module_info:
58
+ return
79
59
 
60
+ module_name, class_name = module_info
61
+
62
+ module = import_module(module_name)
63
+ if not module:
64
+ print(f"Cannot find module '{module_name}'!")
65
+ return
66
+
67
+ cls = getattr(module, class_name)
80
68
  if not cls:
69
+ print(f"Cannot find class '{class_name}'!")
81
70
  return
82
71
 
83
72
  if isinstance(cls, Message) and cls.author.id == self.application_id:
@@ -0,0 +1 @@
1
+ # discord/events
@@ -1,5 +1,5 @@
1
1
  from dataclasses import dataclass
2
- from ..models import MemberModel
2
+ from ..models.member import MemberModel
3
3
  from ..resources.channel import Channel
4
4
 
5
5
  @dataclass
@@ -1,6 +1,3 @@
1
- from datetime import datetime
2
- import copy
3
-
4
1
  class Logger:
5
2
  """A utility class for logging messages, supporting log levels, color-coded console output,
6
3
  optional file logging, and redaction of sensitive information.
@@ -51,6 +48,8 @@ class Logger:
51
48
  Returns:
52
49
  (str): timestamp formatted in YYYY-MM-DD HH:MM:SS
53
50
  """
51
+ from datetime import datetime
52
+
54
53
  return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
55
54
 
56
55
  def _log(self, level: str, color: str, message: str):
@@ -140,6 +139,8 @@ class Logger:
140
139
  return [_redact(item) for item in obj]
141
140
  return obj
142
141
 
142
+ import copy
143
+
143
144
  return _redact(copy.deepcopy(data))
144
145
 
145
146
  def close(self):
@@ -0,0 +1 @@
1
+ # discord/models
@@ -0,0 +1,2 @@
1
+ # discord/parts
2
+
@@ -1,4 +1,3 @@
1
- import os
2
1
  from dataclasses import dataclass, field
3
2
  from typing import Optional, TypedDict, Unpack, Literal
4
3
  from discord.model import DataModel
@@ -114,6 +113,8 @@ class MessageBuilder(DataModel):
114
113
  Returns:
115
114
  (MessageBuilder): self
116
115
  """
116
+ import os
117
+
117
118
  self.attachments.append(
118
119
  _Attachment(
119
120
  id=len(self.attachments),
@@ -0,0 +1 @@
1
+ # discord/resources
@@ -6,8 +6,6 @@ from ..model import DataModel
6
6
 
7
7
  from ..parts.modal import ModalBuilder
8
8
  from ..parts.message import *
9
- from ..parts.embed import *
10
- from ..parts.component_types import *
11
9
 
12
10
  from ..models.guild import GuildModel
13
11
  from ..models.member import MemberModel
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "scurrypy"
7
- version = "0.3.2"
7
+ version = "0.3.3"
8
8
 
9
9
  description = "Discord API Wrapper in Python"
10
10
  readme = "README.md"
@@ -0,0 +1,92 @@
1
+ Metadata-Version: 2.4
2
+ Name: scurrypy
3
+ Version: 0.3.3
4
+ Summary: Discord API Wrapper in Python
5
+ Author: Furmissile
6
+ Requires-Python: >=3.10
7
+ Description-Content-Type: text/markdown
8
+ License-File: LICENSE
9
+ Dynamic: license-file
10
+
11
+ # __Welcome to ScurryPy__
12
+
13
+ [![PyPI version](https://badge.fury.io/py/scurrypy.svg)](https://badge.fury.io/py/scurrypy)
14
+
15
+ Yet another Discord API wrapper in Python!
16
+
17
+ While this wrapper is mainly used for various squirrel-related shenanigans, it can also be used for more generic bot purposes.
18
+
19
+ ## Features
20
+ * Command and event handling
21
+ * Declarative style using decorators
22
+ * Supports both legacy and new features
23
+ * Respects Discord's rate limits
24
+
25
+ ## Some things to consider...
26
+ * This is an early version — feedback, ideas, and contributions are very welcome! That said, there may be bumps along the way, so expect occasional bugs and quirks.
27
+ * Certain features are not yet supported, while others are intentionally omitted. See the [docs](https://furmissile.github.io/scurrypy) for full details.
28
+
29
+ ## Getting Started
30
+ *Note: This section also appears in the documentation, but here are complete examples ready to use with your bot credentials.*
31
+
32
+ ### Installation
33
+ To install the ScurryPy package, run:
34
+ ```bash
35
+ pip install scurrypy
36
+ ```
37
+
38
+ ### Minimal Slash Command
39
+ The following demonstrates building and responding to a slash command.
40
+
41
+ *Note: Adjust `dotenv_path` if your `.env` file is not in the same directory as this script.*
42
+
43
+ ```python
44
+ import discord, os
45
+ from dotenv import load_dotenv
46
+
47
+ load_dotenv(dotenv_path='./path/to/env')
48
+
49
+ client = discord.Client(
50
+ token=os.getenv("DISCORD_TOKEN"),
51
+ application_id=APPLICATION_ID # replace with your bot's user ID
52
+ )
53
+
54
+ @client.command(
55
+ command=discord.SlashCommand(
56
+ name='example',
57
+ description='Demonstrate the minimal slash command!'
58
+ ),
59
+ guild_id=GUILD_ID # must be a guild ID your bot is in
60
+ )
61
+ async def example(bot: discord.Client, event: discord.InteractionEvent):
62
+ await event.interaction.respond(f'Hello, {event.interaction.member.user.username}!')
63
+
64
+ client.run()
65
+ ```
66
+
67
+ ### Minimal Prefix Command (Legacy)
68
+ The following demonstrates building and responding to a message prefix command.
69
+
70
+ ```python
71
+ import discord, os
72
+ from dotenv import load_dotenv
73
+
74
+ load_dotenv(dotenv_path='./path/to/env')
75
+
76
+ client = discord.Client(
77
+ token=os.getenv("DISCORD_TOKEN"),
78
+ application_id=APPLICATION_ID, # replace with your bot's user ID
79
+ intents=discord.set_intents(message_content=True),
80
+ prefix='!' # your custom prefix
81
+ )
82
+
83
+ @client.prefix_command
84
+ async def ping(bot: discord.Client, event: discord.MessageCreateEvent):
85
+ # The function name is the name of the command
86
+ await event.message.send("Pong!")
87
+
88
+ client.run()
89
+ ```
90
+
91
+ ## Like what you see?
92
+ Check out the full [documentation](https://furmissile.github.io/scurrypy) for more examples, guides, and API reference!
scurrypy-0.3.2/PKG-INFO DELETED
@@ -1,85 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: scurrypy
3
- Version: 0.3.2
4
- Summary: Discord API Wrapper in Python
5
- Author: Furmissile
6
- Requires-Python: >=3.10
7
- Description-Content-Type: text/markdown
8
- License-File: LICENSE
9
- Dynamic: license-file
10
-
11
- # __Welcome to ScurryPy__
12
-
13
- [![PyPI version](https://badge.fury.io/py/scurrypy.svg)](https://badge.fury.io/py/scurrypy)
14
-
15
- Yet another Discord API wrapper in Python!
16
-
17
- While this wrapper is mainly used for various squirrel-related shenanigans, it can also be used for more generic bot purposes.
18
-
19
- ## Features
20
- * Command and event handling
21
- * Declarative style using decorators
22
- * Supports both legacy and new features
23
- * Respects Discord's rate limits
24
-
25
- ## Something things to consider...
26
- * This is an early version — feedback, ideas, and contributions are welcome! With that said, there will be bumps in the road so expect bugs and other flaws!
27
- * Some features are not yet supported, such as sharding and automod, while others, like voice, will never be supported. While this library can handle many of your basic needs, common features such as sharding or auto-mod actions are not yet implemented. See the [license](LICENSE) for details on usage.
28
-
29
-
30
- ## Getting Started
31
- While this tab shows up in the docs, here are some complete examples where all you need to do is pop in your bot's credentials!
32
-
33
- ## Installation
34
- To install the ScurryPy package, run:
35
- ```bash
36
- pip install scurrypy
37
- ```
38
-
39
- ## Minimal Slash Command
40
- The following demonstrates building and responding to a slash command.
41
- ```python
42
- import discord, os
43
- from dotenv import load_dotenv
44
-
45
- load_dotenv(dotenv_path='./path/to/env') # omit argument if your env file is on the same level
46
-
47
- bot = discord.Client(
48
- token=os.getenv("DISCORD_TOKEN"),
49
- application_id=APPLICATION_ID # replace with your bot's user ID
50
- )
51
-
52
- @bot.command(
53
- command=discord.SlashCommand(name='example', description='Demonstrate the minimal slash command!'),
54
- guild_id=GUILD_ID # must be a guild ID your bot is in!
55
- )
56
- async def example(bot: discord.Client, event: discord.InteractionEvent):
57
- await event.interaction.respond(f'Hello, {event.interaction.member.user.username}!')
58
-
59
- bot.run()
60
- ```
61
-
62
- ## Minimal Prefix Command (Legacy)
63
- The following demonstrates building and responding to a message prefix command.
64
- ```python
65
- import discord, os
66
- from dotenv import load_dotenv
67
-
68
- load_dotenv(dotenv_path='./path/to/env') # omit argument if your env file is on the same level
69
-
70
- bot = discord.Client(
71
- token=os.getenv("DISCORD_TOKEN"),
72
- application_id=APPLICATION_ID, # replace with your bot's user ID
73
- intents=discord.set_intents(message_content=True),
74
- prefix='!' # your custom prefix
75
- )
76
-
77
- @bot.prefix_command
78
- async def ping(bot: discord.Client, event: discord.MessageCreateEvent): # the function name is the name of the command!
79
- await event.message.send(f"Pong!")
80
-
81
- bot.run()
82
- ```
83
-
84
- ## Like what you see?
85
- See the [docs](https://furmissile.github.io/scurrypy) for more!
scurrypy-0.3.2/README.md DELETED
@@ -1,75 +0,0 @@
1
- # __Welcome to ScurryPy__
2
-
3
- [![PyPI version](https://badge.fury.io/py/scurrypy.svg)](https://badge.fury.io/py/scurrypy)
4
-
5
- Yet another Discord API wrapper in Python!
6
-
7
- While this wrapper is mainly used for various squirrel-related shenanigans, it can also be used for more generic bot purposes.
8
-
9
- ## Features
10
- * Command and event handling
11
- * Declarative style using decorators
12
- * Supports both legacy and new features
13
- * Respects Discord's rate limits
14
-
15
- ## Something things to consider...
16
- * This is an early version — feedback, ideas, and contributions are welcome! With that said, there will be bumps in the road so expect bugs and other flaws!
17
- * Some features are not yet supported, such as sharding and automod, while others, like voice, will never be supported. While this library can handle many of your basic needs, common features such as sharding or auto-mod actions are not yet implemented. See the [license](LICENSE) for details on usage.
18
-
19
-
20
- ## Getting Started
21
- While this tab shows up in the docs, here are some complete examples where all you need to do is pop in your bot's credentials!
22
-
23
- ## Installation
24
- To install the ScurryPy package, run:
25
- ```bash
26
- pip install scurrypy
27
- ```
28
-
29
- ## Minimal Slash Command
30
- The following demonstrates building and responding to a slash command.
31
- ```python
32
- import discord, os
33
- from dotenv import load_dotenv
34
-
35
- load_dotenv(dotenv_path='./path/to/env') # omit argument if your env file is on the same level
36
-
37
- bot = discord.Client(
38
- token=os.getenv("DISCORD_TOKEN"),
39
- application_id=APPLICATION_ID # replace with your bot's user ID
40
- )
41
-
42
- @bot.command(
43
- command=discord.SlashCommand(name='example', description='Demonstrate the minimal slash command!'),
44
- guild_id=GUILD_ID # must be a guild ID your bot is in!
45
- )
46
- async def example(bot: discord.Client, event: discord.InteractionEvent):
47
- await event.interaction.respond(f'Hello, {event.interaction.member.user.username}!')
48
-
49
- bot.run()
50
- ```
51
-
52
- ## Minimal Prefix Command (Legacy)
53
- The following demonstrates building and responding to a message prefix command.
54
- ```python
55
- import discord, os
56
- from dotenv import load_dotenv
57
-
58
- load_dotenv(dotenv_path='./path/to/env') # omit argument if your env file is on the same level
59
-
60
- bot = discord.Client(
61
- token=os.getenv("DISCORD_TOKEN"),
62
- application_id=APPLICATION_ID, # replace with your bot's user ID
63
- intents=discord.set_intents(message_content=True),
64
- prefix='!' # your custom prefix
65
- )
66
-
67
- @bot.prefix_command
68
- async def ping(bot: discord.Client, event: discord.MessageCreateEvent): # the function name is the name of the command!
69
- await event.message.send(f"Pong!")
70
-
71
- bot.run()
72
- ```
73
-
74
- ## Like what you see?
75
- See the [docs](https://furmissile.github.io/scurrypy) for more!
@@ -1,10 +0,0 @@
1
- # discord
2
-
3
- from .logger import Logger
4
- from .client import Client
5
- from .intents import Intents, set_intents
6
- from .config import BaseConfig
7
-
8
- from .events import *
9
- from .resources import *
10
- from .parts import *
@@ -1,33 +0,0 @@
1
- # discord/events
2
-
3
- from .ready_event import ReadyEvent
4
-
5
- from .reaction_events import (
6
- ReactionAddEvent,
7
- ReactionRemoveEvent,
8
- ReactionRemoveEmojiEvent,
9
- ReactionRemoveAllEvent
10
- )
11
-
12
- from .guild_events import (
13
- GuildCreateEvent,
14
- GuildUpdateEvent,
15
- GuildDeleteEvent
16
- )
17
-
18
- from .message_events import (
19
- MessageCreateEvent,
20
- MessageUpdateEvent,
21
- MessageDeleteEvent
22
- )
23
-
24
- from .channel_events import (
25
- GuildChannelCreateEvent,
26
- GuildChannelUpdateEvent,
27
- GuildChannelDeleteEvent,
28
- ChannelPinsUpdateEvent
29
- )
30
-
31
- from .interaction_events import (
32
- InteractionEvent
33
- )
@@ -1,8 +0,0 @@
1
- # discord/models
2
-
3
- from .application import ApplicationModel
4
- from .emoji import EmojiModel
5
- from .guild import GuildModel
6
- from .member import MemberModel
7
- from .user import UserModel
8
- from .role import RoleModel
@@ -1,28 +0,0 @@
1
- # discord/parts
2
-
3
- from .channel import GuildChannel
4
- from .role import Role
5
- from .message import MessageBuilder
6
- from .modal import ModalBuilder
7
- from .embed import EmbedBuilder
8
- from .action_row import (
9
- ActionRow,
10
- StringSelect,
11
- UserSelect,
12
- RoleSelect,
13
- ChannelSelect,
14
- MentionableSelect
15
- )
16
-
17
- from .command import (
18
- SlashCommand,
19
- MessageCommand,
20
- UserCommand
21
- )
22
-
23
- from .components_v2 import (
24
- Container,
25
- Section,
26
- MediaGalleryItem,
27
- Label
28
- )
@@ -1,10 +0,0 @@
1
- # discord/resources
2
-
3
- from .guild import Guild
4
- from .channel import Channel
5
- from .message import Message
6
- from .bot_emojis import BotEmojis
7
- from .user import User
8
- from .interaction import Interaction
9
- from .application import Application
10
- from .interaction import Interaction
@@ -1,85 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: scurrypy
3
- Version: 0.3.2
4
- Summary: Discord API Wrapper in Python
5
- Author: Furmissile
6
- Requires-Python: >=3.10
7
- Description-Content-Type: text/markdown
8
- License-File: LICENSE
9
- Dynamic: license-file
10
-
11
- # __Welcome to ScurryPy__
12
-
13
- [![PyPI version](https://badge.fury.io/py/scurrypy.svg)](https://badge.fury.io/py/scurrypy)
14
-
15
- Yet another Discord API wrapper in Python!
16
-
17
- While this wrapper is mainly used for various squirrel-related shenanigans, it can also be used for more generic bot purposes.
18
-
19
- ## Features
20
- * Command and event handling
21
- * Declarative style using decorators
22
- * Supports both legacy and new features
23
- * Respects Discord's rate limits
24
-
25
- ## Something things to consider...
26
- * This is an early version — feedback, ideas, and contributions are welcome! With that said, there will be bumps in the road so expect bugs and other flaws!
27
- * Some features are not yet supported, such as sharding and automod, while others, like voice, will never be supported. While this library can handle many of your basic needs, common features such as sharding or auto-mod actions are not yet implemented. See the [license](LICENSE) for details on usage.
28
-
29
-
30
- ## Getting Started
31
- While this tab shows up in the docs, here are some complete examples where all you need to do is pop in your bot's credentials!
32
-
33
- ## Installation
34
- To install the ScurryPy package, run:
35
- ```bash
36
- pip install scurrypy
37
- ```
38
-
39
- ## Minimal Slash Command
40
- The following demonstrates building and responding to a slash command.
41
- ```python
42
- import discord, os
43
- from dotenv import load_dotenv
44
-
45
- load_dotenv(dotenv_path='./path/to/env') # omit argument if your env file is on the same level
46
-
47
- bot = discord.Client(
48
- token=os.getenv("DISCORD_TOKEN"),
49
- application_id=APPLICATION_ID # replace with your bot's user ID
50
- )
51
-
52
- @bot.command(
53
- command=discord.SlashCommand(name='example', description='Demonstrate the minimal slash command!'),
54
- guild_id=GUILD_ID # must be a guild ID your bot is in!
55
- )
56
- async def example(bot: discord.Client, event: discord.InteractionEvent):
57
- await event.interaction.respond(f'Hello, {event.interaction.member.user.username}!')
58
-
59
- bot.run()
60
- ```
61
-
62
- ## Minimal Prefix Command (Legacy)
63
- The following demonstrates building and responding to a message prefix command.
64
- ```python
65
- import discord, os
66
- from dotenv import load_dotenv
67
-
68
- load_dotenv(dotenv_path='./path/to/env') # omit argument if your env file is on the same level
69
-
70
- bot = discord.Client(
71
- token=os.getenv("DISCORD_TOKEN"),
72
- application_id=APPLICATION_ID, # replace with your bot's user ID
73
- intents=discord.set_intents(message_content=True),
74
- prefix='!' # your custom prefix
75
- )
76
-
77
- @bot.prefix_command
78
- async def ping(bot: discord.Client, event: discord.MessageCreateEvent): # the function name is the name of the command!
79
- await event.message.send(f"Pong!")
80
-
81
- bot.run()
82
- ```
83
-
84
- ## Like what you see?
85
- See the [docs](https://furmissile.github.io/scurrypy) for more!
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes