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.
- scurrypy-0.8.5.1/LICENSE +16 -0
- scurrypy-0.8.5.1/PKG-INFO +104 -0
- scurrypy-0.8.5.1/README.md +92 -0
- scurrypy-0.8.5.1/pyproject.toml +27 -0
- scurrypy-0.8.5.1/scurrypy/__init__.py +16 -0
- scurrypy-0.8.5.1/scurrypy/addons/__init__.py +7 -0
- scurrypy-0.8.5.1/scurrypy/addons/addon.py +6 -0
- scurrypy-0.8.5.1/scurrypy/addons/addon_manager.py +79 -0
- scurrypy-0.8.5.1/scurrypy/addons/component_builder.py +253 -0
- scurrypy-0.8.5.1/scurrypy/addons/easy_bot.py +180 -0
- scurrypy-0.8.5.1/scurrypy/addons/embed_builder.py +58 -0
- scurrypy-0.8.5.1/scurrypy/addons/events.py +60 -0
- scurrypy-0.8.5.1/scurrypy/addons/interaction.py +244 -0
- scurrypy-0.8.5.1/scurrypy/addons/prefix.py +81 -0
- scurrypy-0.8.5.1/scurrypy/client.py +63 -0
- scurrypy-0.8.5.1/scurrypy/core/__init__.py +15 -0
- scurrypy-0.8.5.1/scurrypy/core/base_client.py +326 -0
- scurrypy-0.8.5.1/scurrypy/core/error.py +51 -0
- scurrypy-0.8.5.1/scurrypy/core/gateway.py +190 -0
- scurrypy-0.8.5.1/scurrypy/core/http.py +310 -0
- scurrypy-0.8.5.1/scurrypy/core/intents.py +96 -0
- scurrypy-0.8.5.1/scurrypy/core/logger.py +111 -0
- scurrypy-0.8.5.1/scurrypy/core/model.py +69 -0
- scurrypy-0.8.5.1/scurrypy/core/permissions.py +154 -0
- scurrypy-0.8.5.1/scurrypy/events/__init__.py +65 -0
- scurrypy-0.8.5.1/scurrypy/events/base_event.py +8 -0
- scurrypy-0.8.5.1/scurrypy/events/channel_events.py +61 -0
- scurrypy-0.8.5.1/scurrypy/events/gateway_events.py +32 -0
- scurrypy-0.8.5.1/scurrypy/events/guild_events.py +57 -0
- scurrypy-0.8.5.1/scurrypy/events/hello_event.py +10 -0
- scurrypy-0.8.5.1/scurrypy/events/interaction_events.py +188 -0
- scurrypy-0.8.5.1/scurrypy/events/message_events.py +45 -0
- scurrypy-0.8.5.1/scurrypy/events/reaction_events.py +101 -0
- scurrypy-0.8.5.1/scurrypy/events/ready_event.py +32 -0
- scurrypy-0.8.5.1/scurrypy/models/__init__.py +35 -0
- scurrypy-0.8.5.1/scurrypy/models/application.py +82 -0
- scurrypy-0.8.5.1/scurrypy/models/channel.py +75 -0
- scurrypy-0.8.5.1/scurrypy/models/emoji.py +51 -0
- scurrypy-0.8.5.1/scurrypy/models/guild.py +83 -0
- scurrypy-0.8.5.1/scurrypy/models/guild_member.py +36 -0
- scurrypy-0.8.5.1/scurrypy/models/integration.py +25 -0
- scurrypy-0.8.5.1/scurrypy/models/interaction.py +150 -0
- scurrypy-0.8.5.1/scurrypy/models/message.py +31 -0
- scurrypy-0.8.5.1/scurrypy/models/role.py +57 -0
- scurrypy-0.8.5.1/scurrypy/models/user.py +41 -0
- scurrypy-0.8.5.1/scurrypy/parts/__init__.py +81 -0
- scurrypy-0.8.5.1/scurrypy/parts/channel.py +43 -0
- scurrypy-0.8.5.1/scurrypy/parts/command.py +110 -0
- scurrypy-0.8.5.1/scurrypy/parts/component_types.py +56 -0
- scurrypy-0.8.5.1/scurrypy/parts/components.py +224 -0
- scurrypy-0.8.5.1/scurrypy/parts/components_v2.py +165 -0
- scurrypy-0.8.5.1/scurrypy/parts/embed.py +111 -0
- scurrypy-0.8.5.1/scurrypy/parts/message.py +153 -0
- scurrypy-0.8.5.1/scurrypy/parts/modal.py +17 -0
- scurrypy-0.8.5.1/scurrypy/parts/role.py +39 -0
- scurrypy-0.8.5.1/scurrypy/resources/__init__.py +36 -0
- scurrypy-0.8.5.1/scurrypy/resources/application.py +22 -0
- scurrypy-0.8.5.1/scurrypy/resources/base_resource.py +14 -0
- scurrypy-0.8.5.1/scurrypy/resources/bot_emojis.py +49 -0
- scurrypy-0.8.5.1/scurrypy/resources/channel.py +177 -0
- scurrypy-0.8.5.1/scurrypy/resources/guild.py +201 -0
- scurrypy-0.8.5.1/scurrypy/resources/interaction.py +214 -0
- scurrypy-0.8.5.1/scurrypy/resources/message.py +157 -0
- scurrypy-0.8.5.1/scurrypy/resources/user.py +78 -0
- scurrypy-0.8.5.1/scurrypy.egg-info/PKG-INFO +104 -0
- scurrypy-0.8.5.1/scurrypy.egg-info/SOURCES.txt +68 -0
- scurrypy-0.8.5.1/scurrypy.egg-info/dependency_links.txt +1 -0
- scurrypy-0.8.5.1/scurrypy.egg-info/requires.txt +2 -0
- scurrypy-0.8.5.1/scurrypy.egg-info/top_level.txt +1 -0
- scurrypy-0.8.5.1/setup.cfg +4 -0
scurrypy-0.8.5.1/LICENSE
ADDED
|
@@ -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
|
+
[](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
|
+
[](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,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
|
+
)
|