scurrypy 0.8.5.1__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 (70) hide show
  1. scurrypy-0.8.5.1/LICENSE +16 -0
  2. scurrypy-0.8.5.1/PKG-INFO +104 -0
  3. scurrypy-0.8.5.1/README.md +92 -0
  4. scurrypy-0.8.5.1/pyproject.toml +27 -0
  5. scurrypy-0.8.5.1/scurrypy/__init__.py +16 -0
  6. scurrypy-0.8.5.1/scurrypy/addons/__init__.py +7 -0
  7. scurrypy-0.8.5.1/scurrypy/addons/addon.py +6 -0
  8. scurrypy-0.8.5.1/scurrypy/addons/addon_manager.py +79 -0
  9. scurrypy-0.8.5.1/scurrypy/addons/component_builder.py +253 -0
  10. scurrypy-0.8.5.1/scurrypy/addons/easy_bot.py +180 -0
  11. scurrypy-0.8.5.1/scurrypy/addons/embed_builder.py +58 -0
  12. scurrypy-0.8.5.1/scurrypy/addons/events.py +60 -0
  13. scurrypy-0.8.5.1/scurrypy/addons/interaction.py +244 -0
  14. scurrypy-0.8.5.1/scurrypy/addons/prefix.py +81 -0
  15. scurrypy-0.8.5.1/scurrypy/client.py +63 -0
  16. scurrypy-0.8.5.1/scurrypy/core/__init__.py +15 -0
  17. scurrypy-0.8.5.1/scurrypy/core/base_client.py +326 -0
  18. scurrypy-0.8.5.1/scurrypy/core/error.py +51 -0
  19. scurrypy-0.8.5.1/scurrypy/core/gateway.py +190 -0
  20. scurrypy-0.8.5.1/scurrypy/core/http.py +310 -0
  21. scurrypy-0.8.5.1/scurrypy/core/intents.py +96 -0
  22. scurrypy-0.8.5.1/scurrypy/core/logger.py +111 -0
  23. scurrypy-0.8.5.1/scurrypy/core/model.py +69 -0
  24. scurrypy-0.8.5.1/scurrypy/core/permissions.py +154 -0
  25. scurrypy-0.8.5.1/scurrypy/events/__init__.py +65 -0
  26. scurrypy-0.8.5.1/scurrypy/events/base_event.py +8 -0
  27. scurrypy-0.8.5.1/scurrypy/events/channel_events.py +61 -0
  28. scurrypy-0.8.5.1/scurrypy/events/gateway_events.py +32 -0
  29. scurrypy-0.8.5.1/scurrypy/events/guild_events.py +57 -0
  30. scurrypy-0.8.5.1/scurrypy/events/hello_event.py +10 -0
  31. scurrypy-0.8.5.1/scurrypy/events/interaction_events.py +188 -0
  32. scurrypy-0.8.5.1/scurrypy/events/message_events.py +45 -0
  33. scurrypy-0.8.5.1/scurrypy/events/reaction_events.py +101 -0
  34. scurrypy-0.8.5.1/scurrypy/events/ready_event.py +32 -0
  35. scurrypy-0.8.5.1/scurrypy/models/__init__.py +35 -0
  36. scurrypy-0.8.5.1/scurrypy/models/application.py +82 -0
  37. scurrypy-0.8.5.1/scurrypy/models/channel.py +75 -0
  38. scurrypy-0.8.5.1/scurrypy/models/emoji.py +51 -0
  39. scurrypy-0.8.5.1/scurrypy/models/guild.py +83 -0
  40. scurrypy-0.8.5.1/scurrypy/models/guild_member.py +36 -0
  41. scurrypy-0.8.5.1/scurrypy/models/integration.py +25 -0
  42. scurrypy-0.8.5.1/scurrypy/models/interaction.py +150 -0
  43. scurrypy-0.8.5.1/scurrypy/models/message.py +31 -0
  44. scurrypy-0.8.5.1/scurrypy/models/role.py +57 -0
  45. scurrypy-0.8.5.1/scurrypy/models/user.py +41 -0
  46. scurrypy-0.8.5.1/scurrypy/parts/__init__.py +81 -0
  47. scurrypy-0.8.5.1/scurrypy/parts/channel.py +43 -0
  48. scurrypy-0.8.5.1/scurrypy/parts/command.py +110 -0
  49. scurrypy-0.8.5.1/scurrypy/parts/component_types.py +56 -0
  50. scurrypy-0.8.5.1/scurrypy/parts/components.py +224 -0
  51. scurrypy-0.8.5.1/scurrypy/parts/components_v2.py +165 -0
  52. scurrypy-0.8.5.1/scurrypy/parts/embed.py +111 -0
  53. scurrypy-0.8.5.1/scurrypy/parts/message.py +153 -0
  54. scurrypy-0.8.5.1/scurrypy/parts/modal.py +17 -0
  55. scurrypy-0.8.5.1/scurrypy/parts/role.py +39 -0
  56. scurrypy-0.8.5.1/scurrypy/resources/__init__.py +36 -0
  57. scurrypy-0.8.5.1/scurrypy/resources/application.py +22 -0
  58. scurrypy-0.8.5.1/scurrypy/resources/base_resource.py +14 -0
  59. scurrypy-0.8.5.1/scurrypy/resources/bot_emojis.py +49 -0
  60. scurrypy-0.8.5.1/scurrypy/resources/channel.py +177 -0
  61. scurrypy-0.8.5.1/scurrypy/resources/guild.py +201 -0
  62. scurrypy-0.8.5.1/scurrypy/resources/interaction.py +214 -0
  63. scurrypy-0.8.5.1/scurrypy/resources/message.py +157 -0
  64. scurrypy-0.8.5.1/scurrypy/resources/user.py +78 -0
  65. scurrypy-0.8.5.1/scurrypy.egg-info/PKG-INFO +104 -0
  66. scurrypy-0.8.5.1/scurrypy.egg-info/SOURCES.txt +68 -0
  67. scurrypy-0.8.5.1/scurrypy.egg-info/dependency_links.txt +1 -0
  68. scurrypy-0.8.5.1/scurrypy.egg-info/requires.txt +2 -0
  69. scurrypy-0.8.5.1/scurrypy.egg-info/top_level.txt +1 -0
  70. scurrypy-0.8.5.1/setup.cfg +4 -0
@@ -0,0 +1,16 @@
1
+ Copyright (c) 2025 Furmissile. All rights reserved.
2
+
3
+ Permission is granted to view, use, modify, and distribute copies of this software
4
+ and its source code, provided that:
5
+
6
+ 1. Attribution to the original author, Furmissile, is preserved in all copies and
7
+ derivative works.
8
+ 2. The name "ScurryPy" and associated branding may not be used to promote derived
9
+ projects without explicit permission.
10
+ 3. This license and copyright notice must be included in all copies or substantial
11
+ portions of the software.
12
+ 4. This software is provided "as is", without warranty of any kind, express or
13
+ implied. The author assumes no liability for any damages arising from its use.
14
+
15
+ 5. This software may not be used for commercial purposes without written consent
16
+ from the author.
@@ -0,0 +1,104 @@
1
+ Metadata-Version: 2.4
2
+ Name: scurrypy
3
+ Version: 0.8.5.1
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
+ ## __<center> ScurryPy </center>__
14
+
15
+ [![PyPI version](https://badge.fury.io/py/scurrypy.svg)](https://badge.fury.io/py/scurrypy)
16
+
17
+ A lightweight, fully readable Discord API framework built to accommodate everything from basic bots to custom frameworks.
18
+
19
+ While ScurryPy powers many squirrel-related shenanigans, it works just as well for game bots, interactive components, and educational projects.
20
+
21
+ ## Philosophy
22
+
23
+ ScurryPy is built on a simple idea: clarity over magic.
24
+
25
+ * Every operation should be traceable.
26
+ * No hidden behavior or side effects.
27
+ * Explicit design over clever abstractions.
28
+ * If you can’t explain a function in 3–6 steps, simplify it.
29
+ * Legacy features can be removed or replaced without rewriting the library.
30
+ * Models = pure data
31
+ * Resources = HTTP logic
32
+ * Nothing mixes responsibilities.
33
+
34
+ ScurryPy is not discord.py, hikari, disnake, or any other framework.
35
+ ScurryPy is built from scratch.
36
+ It is a true Discord API wrapper built on predictable, modern Python principles.
37
+
38
+ ## Features
39
+ * Easy to extend and build frameworks on top
40
+ * Lightweight core (<1000 lines)
41
+ * Command, and event handling
42
+ * Unix shell-style wildcards for component routing
43
+ * Declarative style using decorators
44
+ * Supports both legacy and new features
45
+ * Respects Discord's rate limits
46
+ * No `__future__` hacks to avoid circular import
47
+ * Capable of sharding
48
+
49
+ ## Getting Started
50
+
51
+ *Note: This section also appears in the documentation, but here are complete examples ready to use with your bot credentials.*
52
+
53
+ ### Installation
54
+
55
+ To install the ScurryPy package, run:
56
+
57
+ ```bash
58
+ pip install scurrypy
59
+ ```
60
+
61
+ > **About the Following Examples**:
62
+ These examples are built using [EasyBot](https://scurry-works.github.io/scurrypy/addons/easy_bot), an extension of ScurryPy designed with pre-packaged convenience!
63
+
64
+ ## Minimal Slash Command
65
+
66
+ The following demonstrates building and responding to a slash command.
67
+
68
+ ```py
69
+ import scurrypy
70
+ from scurrypy.addons.easy_bot import EasyBot
71
+
72
+ client = EasyBot(token=TOKEN, application_id=APP_ID)
73
+
74
+ @client.slash_command("hello", "Say hello", guild_ids=GUILD_ID) # specify guild ID for guild command
75
+ async def hello(bot, interaction: scurrypy.Interaction):
76
+ await interaction.respond("Hello!")
77
+
78
+ client.run()
79
+ ```
80
+
81
+ ## Minimal Prefix Command (Legacy)
82
+
83
+ The following demonstrates building and responding to a message prefix command.
84
+
85
+ ```py
86
+ import scurrypy
87
+ from scurrypy.addons.easy_bot import EasyBot
88
+
89
+ client = EasyBot(token=TOKEN, application_id=APP_ID, prefix="!")
90
+
91
+ @client.prefix("ping")
92
+ async def ping_cmd(bot, message: scurrypy.Message):
93
+ await message.send("Pong!")
94
+
95
+ client.run()
96
+ ```
97
+
98
+ ## Building on Top of ScurryPy
99
+
100
+ ScurryPy is designed to be easy to extend with your own abstractions.
101
+ See [Addons](https://scurry-works.github.io/scurrypy/addons) documentation for details!
102
+
103
+ ## Like What You See?
104
+ Explore the full [documentation](https://scurry-works.github.io/scurrypy) for more examples, guides, and API reference.
@@ -0,0 +1,92 @@
1
+ ## __<center> ScurryPy </center>__
2
+
3
+ [![PyPI version](https://badge.fury.io/py/scurrypy.svg)](https://badge.fury.io/py/scurrypy)
4
+
5
+ A lightweight, fully readable Discord API framework built to accommodate everything from basic bots to custom frameworks.
6
+
7
+ While ScurryPy powers many squirrel-related shenanigans, it works just as well for game bots, interactive components, and educational projects.
8
+
9
+ ## Philosophy
10
+
11
+ ScurryPy is built on a simple idea: clarity over magic.
12
+
13
+ * Every operation should be traceable.
14
+ * No hidden behavior or side effects.
15
+ * Explicit design over clever abstractions.
16
+ * If you can’t explain a function in 3–6 steps, simplify it.
17
+ * Legacy features can be removed or replaced without rewriting the library.
18
+ * Models = pure data
19
+ * Resources = HTTP logic
20
+ * Nothing mixes responsibilities.
21
+
22
+ ScurryPy is not discord.py, hikari, disnake, or any other framework.
23
+ ScurryPy is built from scratch.
24
+ It is a true Discord API wrapper built on predictable, modern Python principles.
25
+
26
+ ## Features
27
+ * Easy to extend and build frameworks on top
28
+ * Lightweight core (<1000 lines)
29
+ * Command, and event handling
30
+ * Unix shell-style wildcards for component routing
31
+ * Declarative style using decorators
32
+ * Supports both legacy and new features
33
+ * Respects Discord's rate limits
34
+ * No `__future__` hacks to avoid circular import
35
+ * Capable of sharding
36
+
37
+ ## Getting Started
38
+
39
+ *Note: This section also appears in the documentation, but here are complete examples ready to use with your bot credentials.*
40
+
41
+ ### Installation
42
+
43
+ To install the ScurryPy package, run:
44
+
45
+ ```bash
46
+ pip install scurrypy
47
+ ```
48
+
49
+ > **About the Following Examples**:
50
+ These examples are built using [EasyBot](https://scurry-works.github.io/scurrypy/addons/easy_bot), an extension of ScurryPy designed with pre-packaged convenience!
51
+
52
+ ## Minimal Slash Command
53
+
54
+ The following demonstrates building and responding to a slash command.
55
+
56
+ ```py
57
+ import scurrypy
58
+ from scurrypy.addons.easy_bot import EasyBot
59
+
60
+ client = EasyBot(token=TOKEN, application_id=APP_ID)
61
+
62
+ @client.slash_command("hello", "Say hello", guild_ids=GUILD_ID) # specify guild ID for guild command
63
+ async def hello(bot, interaction: scurrypy.Interaction):
64
+ await interaction.respond("Hello!")
65
+
66
+ client.run()
67
+ ```
68
+
69
+ ## Minimal Prefix Command (Legacy)
70
+
71
+ The following demonstrates building and responding to a message prefix command.
72
+
73
+ ```py
74
+ import scurrypy
75
+ from scurrypy.addons.easy_bot import EasyBot
76
+
77
+ client = EasyBot(token=TOKEN, application_id=APP_ID, prefix="!")
78
+
79
+ @client.prefix("ping")
80
+ async def ping_cmd(bot, message: scurrypy.Message):
81
+ await message.send("Pong!")
82
+
83
+ client.run()
84
+ ```
85
+
86
+ ## Building on Top of ScurryPy
87
+
88
+ ScurryPy is designed to be easy to extend with your own abstractions.
89
+ See [Addons](https://scurry-works.github.io/scurrypy/addons) documentation for details!
90
+
91
+ ## Like What You See?
92
+ Explore the full [documentation](https://scurry-works.github.io/scurrypy) for more examples, guides, and API reference.
@@ -0,0 +1,27 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "scurrypy"
7
+ version = "0.8.5.1"
8
+
9
+ description = "Dataclass-driven Discord API Wrapper in Python"
10
+ readme = "README.md"
11
+ authors = [{ name = "Furmissile" }]
12
+ requires-python = ">=3.10"
13
+ dependencies = [
14
+ "aiohttp>=3.8.0",
15
+ "websockets>=11.0.0"
16
+ ]
17
+
18
+ [tool.setuptools]
19
+ packages = [
20
+ "scurrypy",
21
+ "scurrypy.events",
22
+ "scurrypy.addons",
23
+ "scurrypy.resources",
24
+ "scurrypy.parts",
25
+ "scurrypy.core",
26
+ "scurrypy.models"
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 .models import *
15
+ from .core import *
16
+ from .addons import *
@@ -0,0 +1,7 @@
1
+ # scurrypy/plugins
2
+
3
+ from .addon import Addon
4
+
5
+ __all__ = [
6
+ "Addon"
7
+ ]
@@ -0,0 +1,6 @@
1
+ class Addon:
2
+ """Defines the minimal setup for an addon."""
3
+
4
+ def setup(self):
5
+ """Called when adding the child addon."""
6
+ raise NotImplementedError("Missing setup function.")
@@ -0,0 +1,79 @@
1
+ import inspect
2
+ from ..core.base_client import BaseClient
3
+ from .addon import Addon
4
+
5
+ class AddonManager:
6
+ """Defines constraits for custom addons."""
7
+
8
+ def __init__(self, client: BaseClient):
9
+ self.client = client
10
+
11
+ # --- validation ---
12
+
13
+ def _check_event(self, handler):
14
+ """Inspects the addon's event handler.
15
+
16
+ Args:
17
+ handler (callable): addon's handler
18
+
19
+ Raises:
20
+ TypeError: invalid parameters
21
+ """
22
+ sig = inspect.signature(handler)
23
+ if len(sig.parameters) != 1:
24
+ raise TypeError(
25
+ f"Addon listener '{handler.__name__}' must accept exactly one arg (event)."
26
+ )
27
+
28
+ def _check_hook(self, handler):
29
+ """Inspects the addon's hook handler.
30
+
31
+ Args:
32
+ handler (callable): addon's handler
33
+
34
+ Raises:
35
+ TypeError: invalid parameters
36
+ """
37
+ sig = inspect.signature(handler)
38
+ if len(sig.parameters) != 0:
39
+ raise TypeError(
40
+ f"Addon hook '{handler.__name__}' must accept no parameters."
41
+ )
42
+
43
+ # --- registration ---
44
+
45
+ def add(self, addon: Addon):
46
+ """Helper function to auto-register an addon on instantiation.
47
+
48
+ Args:
49
+ addon (Addon): the addon object
50
+ """
51
+ addon.setup()
52
+
53
+ def add_event_listener(self, event_name: str, handler):
54
+ """Register an addon's handler to an event name to receive the event.
55
+
56
+ Args:
57
+ event_name (str): name of event to receive
58
+ handler (callable): addon's handler
59
+ """
60
+ self._check_event(handler)
61
+ self.client.add_event_listener(event_name, handler)
62
+
63
+ def add_startup_hook(self, handler):
64
+ """Register an addon's handler to run on startup.
65
+
66
+ Args:
67
+ handler (callable): addon's handler
68
+ """
69
+ self._check_hook(handler)
70
+ self.client.add_startup_hook(handler)
71
+
72
+ def add_shutdown_hook(self, handler):
73
+ """Register an addon's handler to run on shutdown.
74
+
75
+ Args:
76
+ handler (callable): addon's handler
77
+ """
78
+ self._check_hook(handler)
79
+ self.client.add_shutdown_hook(handler)
@@ -0,0 +1,253 @@
1
+ from .addon import Addon
2
+
3
+ from ..parts.components import *
4
+
5
+ class ComponentBuilder(Addon):
6
+
7
+ @staticmethod
8
+ def _basic_button(style: int, custom_id: str, label: str = None, emoji: str | EmojiModel = None, disabled: bool = False):
9
+ if emoji:
10
+ if isinstance(emoji, str):
11
+ emoji = EmojiModel(name=emoji)
12
+ elif not isinstance(emoji, EmojiModel):
13
+ raise TypeError(f"EasyBot.primary expects type str or EmojiModel, got {type(emoji).__name__}")
14
+
15
+ return Button(
16
+ style=style,
17
+ custom_id=custom_id,
18
+ label=label,
19
+ emoji=emoji ,
20
+ disabled=disabled
21
+ )
22
+
23
+ @staticmethod
24
+ def primary(custom_id: str, label: str = None, emoji: str | EmojiModel = None, disabled: bool = False):
25
+ """Builds a primary button
26
+
27
+ Args:
28
+ custom_id (str): unique button identifier
29
+ label (str, optional): user-facing label
30
+ emoji (str | EmojiModel, optional): emoji icon as str or EmojiModel if custom
31
+ disabled (bool, optional): Whether the button should be disabled. Defaults to False.
32
+
33
+ Returns:
34
+ (Button): the button object
35
+ """
36
+ return ComponentBuilder._basic_button(ButtonStyles.PRIMARY, custom_id, label, emoji, disabled)
37
+
38
+ @staticmethod
39
+ def secondary(custom_id: str, label: str = None, emoji: str | EmojiModel = None, disabled: bool = False):
40
+ """Builds a secondary button
41
+
42
+ Args:
43
+ custom_id (str): unique button identifier
44
+ label (str, optional): user-facing label
45
+ emoji (str | EmojiModel, optional): emoji icon as str or EmojiModel if custom
46
+ disabled (bool, optional): Whether the button should be disabled. Defaults to False.
47
+
48
+ Returns:
49
+ (Button): the button object
50
+ """
51
+ return ComponentBuilder._basic_button(ButtonStyles.SECONDARY, custom_id, label, emoji, disabled)
52
+
53
+ @staticmethod
54
+ def success(custom_id: str, label: str = None, emoji: str | EmojiModel = None, disabled: bool = False):
55
+ """Builds a success button
56
+
57
+ Args:
58
+ custom_id (str): unique button identifier
59
+ label (str, optional): user-facing label
60
+ emoji (str | EmojiModel, optional): emoji icon as str or EmojiModel if custom
61
+ disabled (bool, optional): Whether the button should be disabled. Defaults to False.
62
+
63
+ Returns:
64
+ (Button): the button object
65
+ """
66
+ return ComponentBuilder._basic_button(ButtonStyles.SUCCESS, custom_id, label, emoji, disabled)
67
+
68
+ @staticmethod
69
+ def danger(custom_id: str, label: str = None, emoji: str | EmojiModel = None, disabled: bool = False):
70
+ """Builds a danger button
71
+
72
+ Args:
73
+ custom_id (str): unique button identifier
74
+ label (str, optional): user-facing label
75
+ emoji (str | EmojiModel, optional): emoji icon as str or EmojiModel if custom
76
+ disabled (bool, optional): Whether the button should be disabled. Defaults to False.
77
+
78
+ Returns:
79
+ (Button): the button object
80
+ """
81
+ return ComponentBuilder._basic_button(ButtonStyles.DANGER, custom_id, label, emoji, disabled)
82
+
83
+ @staticmethod
84
+ def link(url: str, label: str = None, emoji: str | EmojiModel = None, disabled: bool = False):
85
+ """Builds a link button
86
+
87
+ Args:
88
+ url (str): button URL to open
89
+ label (str, optional): user-facing label
90
+ emoji (str | EmojiModel, optional): emoji icon as str or EmojiModel if custom
91
+ disabled (bool, optional): Whether the button should be disabled. Defaults to False.
92
+
93
+ Returns:
94
+ (Button): the button object
95
+ """
96
+ btn = ComponentBuilder._basic_button(ButtonStyles.LINK, label, emoji, disabled)
97
+ btn.url = url
98
+ return btn
99
+
100
+ @staticmethod
101
+ def row(components: list[ActionRowChild]):
102
+ """Shorthand for action row.
103
+
104
+ Args:
105
+ components (list[ActionRowChild]): the action row objects.
106
+
107
+ Returns:
108
+ (ActionRowPart): the action row object
109
+ """
110
+ if not isinstance(components, list):
111
+ components = [components]
112
+
113
+ return ActionRowPart(components)
114
+
115
+ @staticmethod
116
+ def option(
117
+ label: str,
118
+ value: str,
119
+ description: str = None,
120
+ emoji: EmojiModel | str = None,
121
+ default: bool = False
122
+ ):
123
+ """Builds a string menu select option.
124
+
125
+ Args:
126
+ label (str): user-facing label
127
+ value (str): unique identifier
128
+ description (str, optional): option descriptor
129
+ emoji (EmojiModel | str, optional): emoji icon as str or EmojiModel if custom
130
+ default (bool, optional): Whether this value should be the default if none is selected. Defaults to False.
131
+
132
+ Raises:
133
+ (TypeError): invalid `emoji` type
134
+
135
+ Returns:
136
+ (SelectOption): the SelectOption object
137
+ """
138
+ if emoji:
139
+ if isinstance(emoji, str):
140
+ emoji = EmojiModel(name=emoji)
141
+ elif not isinstance(emoji, EmojiModel):
142
+ raise TypeError(f"EasyBot.primary expects type str or EmojiModel, got {type(emoji).__name__}")
143
+
144
+ return SelectOption(
145
+ label=label,
146
+ value=value,
147
+ description=description,
148
+ emoji=emoji,
149
+ default=default
150
+ )
151
+
152
+ @staticmethod
153
+ def short_text(
154
+ custom_id: str,
155
+ required: bool = True,
156
+ placeholder: str | None = None,
157
+ min_length: int | None = None,
158
+ max_length: int | None = None
159
+ ):
160
+ """Builds a TextInput with `TextInputStyles.SHORT` style.
161
+
162
+ Args:
163
+ custom_id (str): unique identifier
164
+ required (bool, optional): Whether this field is required. Defaults to True.
165
+ placeholder (str | None, optional): default text if nothing is entered
166
+ min_length (int | None, optional): minimum input length
167
+ max_length (int | None, optional): maximum input length
168
+
169
+ Returns:
170
+ (TextInput): the TextInput object
171
+ """
172
+ return TextInput(
173
+ style=TextInputStyles.SHORT,
174
+ custom_id=custom_id,
175
+ required=required,
176
+ placeholder=placeholder,
177
+ min_length=min_length,
178
+ max_length=max_length
179
+ )
180
+
181
+ @staticmethod
182
+ def long_text(
183
+ custom_id: str,
184
+ required: bool = True,
185
+ placeholder: str | None = None,
186
+ min_length: int | None = None,
187
+ max_length: int | None = None
188
+ ):
189
+ """Builds a TextInput with `TextInputStyles.PARAGRAPH` style.
190
+
191
+ Args:
192
+ custom_id (str): unique identifier
193
+ required (bool, optional): Whether this field is required. Defaults to True.
194
+ placeholder (str | None, optional): default text if nothing is entered
195
+ min_length (int | None, optional): minimum input length
196
+ max_length (int | None, optional): maximum input length
197
+
198
+ Returns:
199
+ (TextInput): the TextInput object
200
+ """
201
+ return TextInput(
202
+ style=TextInputStyles.PARAGRAPH,
203
+ custom_id=custom_id,
204
+ required=required,
205
+ placeholder=placeholder,
206
+ min_length=min_length,
207
+ max_length=max_length
208
+ )
209
+
210
+ @staticmethod
211
+ def role_value(id: int):
212
+ """Builds a default role value.
213
+
214
+ Args:
215
+ id (int): role ID
216
+
217
+ Returns:
218
+ (DefaultValue): the DefaultValue object
219
+ """
220
+ return DefaultValue(
221
+ id=id,
222
+ type='role'
223
+ )
224
+
225
+ @staticmethod
226
+ def user_value(id: int):
227
+ """Builds a default user value.
228
+
229
+ Args:
230
+ id (int): user ID
231
+
232
+ Returns:
233
+ (DefaultValue): the DefaultValue object
234
+ """
235
+ return DefaultValue(
236
+ id=id,
237
+ type='user'
238
+ )
239
+
240
+ @staticmethod
241
+ def channel_value(id: int):
242
+ """Builds a default channel value.
243
+
244
+ Args:
245
+ id (int): channel ID
246
+
247
+ Returns:
248
+ (DefaultValue): the DefaultValue object
249
+ """
250
+ return DefaultValue(
251
+ id=id,
252
+ type='channel'
253
+ )