loopbot-discord-sdk 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- loopbot/__init__.py +60 -0
- loopbot/bot.py +584 -0
- loopbot/builders/__init__.py +30 -0
- loopbot/builders/action_row.py +40 -0
- loopbot/builders/button.py +58 -0
- loopbot/builders/container.py +61 -0
- loopbot/builders/embed.py +95 -0
- loopbot/builders/file.py +33 -0
- loopbot/builders/media_gallery.py +36 -0
- loopbot/builders/modal.py +67 -0
- loopbot/builders/section.py +52 -0
- loopbot/builders/select_menu.py +63 -0
- loopbot/builders/separator.py +31 -0
- loopbot/builders/text_display.py +24 -0
- loopbot/client.py +805 -0
- loopbot/context/__init__.py +17 -0
- loopbot/context/base.py +263 -0
- loopbot/context/button.py +28 -0
- loopbot/context/command.py +93 -0
- loopbot/context/modal.py +46 -0
- loopbot/context/select.py +34 -0
- loopbot/types.py +76 -0
- loopbot_discord_sdk-1.0.0.dist-info/METADATA +434 -0
- loopbot_discord_sdk-1.0.0.dist-info/RECORD +26 -0
- loopbot_discord_sdk-1.0.0.dist-info/WHEEL +5 -0
- loopbot_discord_sdk-1.0.0.dist-info/top_level.txt +1 -0
loopbot/__init__.py
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Loop Discord SDK for Python
|
|
3
|
+
Build Discord bots without websockets using HTTP Interactions
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from .bot import Bot
|
|
7
|
+
from .client import Client
|
|
8
|
+
from .builders import (
|
|
9
|
+
EmbedBuilder,
|
|
10
|
+
ButtonBuilder,
|
|
11
|
+
ButtonStyle,
|
|
12
|
+
ActionRowBuilder,
|
|
13
|
+
SelectMenuBuilder,
|
|
14
|
+
ModalBuilder,
|
|
15
|
+
ContainerBuilder,
|
|
16
|
+
SeparatorBuilder,
|
|
17
|
+
TextDisplayBuilder,
|
|
18
|
+
MediaGalleryBuilder,
|
|
19
|
+
SectionBuilder,
|
|
20
|
+
FileBuilder,
|
|
21
|
+
)
|
|
22
|
+
from .context import (
|
|
23
|
+
CommandContext,
|
|
24
|
+
ButtonContext,
|
|
25
|
+
ModalContext,
|
|
26
|
+
SelectContext,
|
|
27
|
+
)
|
|
28
|
+
from .types import (
|
|
29
|
+
InteractionType,
|
|
30
|
+
InteractionResponseType,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
__version__ = "1.0.0"
|
|
34
|
+
__all__ = [
|
|
35
|
+
# Core
|
|
36
|
+
"Bot",
|
|
37
|
+
"Client",
|
|
38
|
+
# Builders
|
|
39
|
+
"EmbedBuilder",
|
|
40
|
+
"ButtonBuilder",
|
|
41
|
+
"ButtonStyle",
|
|
42
|
+
"ActionRowBuilder",
|
|
43
|
+
"SelectMenuBuilder",
|
|
44
|
+
"ModalBuilder",
|
|
45
|
+
# Components V2
|
|
46
|
+
"ContainerBuilder",
|
|
47
|
+
"SeparatorBuilder",
|
|
48
|
+
"TextDisplayBuilder",
|
|
49
|
+
"MediaGalleryBuilder",
|
|
50
|
+
"SectionBuilder",
|
|
51
|
+
"FileBuilder",
|
|
52
|
+
# Context
|
|
53
|
+
"CommandContext",
|
|
54
|
+
"ButtonContext",
|
|
55
|
+
"ModalContext",
|
|
56
|
+
"SelectContext",
|
|
57
|
+
# Types
|
|
58
|
+
"InteractionType",
|
|
59
|
+
"InteractionResponseType",
|
|
60
|
+
]
|
loopbot/bot.py
ADDED
|
@@ -0,0 +1,584 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Bot class - Main entry point for the Loop Discord SDK
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import asyncio
|
|
6
|
+
import signal
|
|
7
|
+
from typing import Any, Callable, Dict, List, Optional, Union
|
|
8
|
+
|
|
9
|
+
from .client import Client
|
|
10
|
+
from .context.command import CommandContext
|
|
11
|
+
from .context.button import ButtonContext
|
|
12
|
+
from .context.modal import ModalContext
|
|
13
|
+
from .context.select import SelectContext
|
|
14
|
+
from .types import InteractionType
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
CommandHandler = Callable[[CommandContext], None]
|
|
18
|
+
ButtonHandler = Callable[[ButtonContext], None]
|
|
19
|
+
ModalHandler = Callable[[ModalContext], None]
|
|
20
|
+
SelectHandler = Callable[[SelectContext], None]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class Command:
|
|
24
|
+
"""Represents a slash command"""
|
|
25
|
+
|
|
26
|
+
def __init__(
|
|
27
|
+
self,
|
|
28
|
+
name: str,
|
|
29
|
+
description: str,
|
|
30
|
+
handler: CommandHandler,
|
|
31
|
+
options: Optional[List[Dict[str, Any]]] = None,
|
|
32
|
+
):
|
|
33
|
+
self.name = name
|
|
34
|
+
self.description = description
|
|
35
|
+
self.handler = handler
|
|
36
|
+
self.options = options or []
|
|
37
|
+
|
|
38
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
39
|
+
return {
|
|
40
|
+
"name": self.name,
|
|
41
|
+
"description": self.description,
|
|
42
|
+
"options": self.options,
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class Bot:
|
|
47
|
+
"""Main class for creating a Loop Discord bot"""
|
|
48
|
+
|
|
49
|
+
def __init__(
|
|
50
|
+
self,
|
|
51
|
+
token: str,
|
|
52
|
+
api_url: str = "https://api.loopbot.app",
|
|
53
|
+
):
|
|
54
|
+
self.token = token
|
|
55
|
+
self.api_url = api_url
|
|
56
|
+
self._client = Client(token, api_url)
|
|
57
|
+
self._commands: Dict[str, Command] = {}
|
|
58
|
+
self._button_handlers: Dict[str, ButtonHandler] = {}
|
|
59
|
+
self._modal_handlers: Dict[str, ModalHandler] = {}
|
|
60
|
+
self._select_handlers: Dict[str, SelectHandler] = {}
|
|
61
|
+
self._application_id: str = ""
|
|
62
|
+
self._running = False
|
|
63
|
+
|
|
64
|
+
def command(
|
|
65
|
+
self,
|
|
66
|
+
name: str,
|
|
67
|
+
description: str,
|
|
68
|
+
options: Optional[List[Dict[str, Any]]] = None,
|
|
69
|
+
) -> Callable[[CommandHandler], CommandHandler]:
|
|
70
|
+
"""Decorator to register a command handler"""
|
|
71
|
+
def decorator(func: CommandHandler) -> CommandHandler:
|
|
72
|
+
self._commands[name] = Command(name, description, func, options)
|
|
73
|
+
return func
|
|
74
|
+
return decorator
|
|
75
|
+
|
|
76
|
+
def on_button(self, custom_id: str) -> Callable[[ButtonHandler], ButtonHandler]:
|
|
77
|
+
"""Decorator to register a button handler"""
|
|
78
|
+
def decorator(func: ButtonHandler) -> ButtonHandler:
|
|
79
|
+
self._button_handlers[custom_id] = func
|
|
80
|
+
return func
|
|
81
|
+
return decorator
|
|
82
|
+
|
|
83
|
+
def on_modal(self, custom_id: str) -> Callable[[ModalHandler], ModalHandler]:
|
|
84
|
+
"""Decorator to register a modal handler"""
|
|
85
|
+
def decorator(func: ModalHandler) -> ModalHandler:
|
|
86
|
+
self._modal_handlers[custom_id] = func
|
|
87
|
+
return func
|
|
88
|
+
return decorator
|
|
89
|
+
|
|
90
|
+
def on_select(self, custom_id: str) -> Callable[[SelectHandler], SelectHandler]:
|
|
91
|
+
"""Decorator to register a select menu handler"""
|
|
92
|
+
def decorator(func: SelectHandler) -> SelectHandler:
|
|
93
|
+
self._select_handlers[custom_id] = func
|
|
94
|
+
return func
|
|
95
|
+
return decorator
|
|
96
|
+
|
|
97
|
+
def _handle_interaction(self, interaction: Dict[str, Any]) -> None:
|
|
98
|
+
"""Handle incoming interaction"""
|
|
99
|
+
interaction_type = interaction.get("type")
|
|
100
|
+
data = interaction.get("data", {})
|
|
101
|
+
|
|
102
|
+
response: Optional[Dict[str, Any]] = None
|
|
103
|
+
|
|
104
|
+
if interaction_type == InteractionType.APPLICATION_COMMAND:
|
|
105
|
+
command_name = data.get("name", "")
|
|
106
|
+
command = self._commands.get(command_name)
|
|
107
|
+
|
|
108
|
+
if command:
|
|
109
|
+
ctx = CommandContext(interaction, self._client, self._application_id)
|
|
110
|
+
command.handler(ctx)
|
|
111
|
+
response = ctx.response
|
|
112
|
+
|
|
113
|
+
elif interaction_type == InteractionType.MESSAGE_COMPONENT:
|
|
114
|
+
custom_id = data.get("custom_id", "")
|
|
115
|
+
component_type = data.get("component_type")
|
|
116
|
+
|
|
117
|
+
# Button (type 2)
|
|
118
|
+
if component_type == 2:
|
|
119
|
+
handler = self._button_handlers.get(custom_id)
|
|
120
|
+
if handler:
|
|
121
|
+
ctx = ButtonContext(interaction, self._client, self._application_id)
|
|
122
|
+
handler(ctx)
|
|
123
|
+
response = ctx.response
|
|
124
|
+
|
|
125
|
+
# Select Menu (type 3)
|
|
126
|
+
elif component_type == 3:
|
|
127
|
+
handler = self._select_handlers.get(custom_id)
|
|
128
|
+
if handler:
|
|
129
|
+
ctx = SelectContext(interaction, self._client, self._application_id)
|
|
130
|
+
handler(ctx)
|
|
131
|
+
response = ctx.response
|
|
132
|
+
|
|
133
|
+
elif interaction_type == InteractionType.MODAL_SUBMIT:
|
|
134
|
+
custom_id = data.get("custom_id", "")
|
|
135
|
+
handler = self._modal_handlers.get(custom_id)
|
|
136
|
+
|
|
137
|
+
if handler:
|
|
138
|
+
ctx = ModalContext(interaction, self._client, self._application_id)
|
|
139
|
+
handler(ctx)
|
|
140
|
+
response = ctx.response
|
|
141
|
+
|
|
142
|
+
# Send response
|
|
143
|
+
if response:
|
|
144
|
+
asyncio.create_task(
|
|
145
|
+
self._client.respond(interaction.get("id", ""), response)
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
async def _start_async(self) -> None:
|
|
149
|
+
"""Start the bot (async)"""
|
|
150
|
+
print("[Loop SDK] Starting bot...")
|
|
151
|
+
|
|
152
|
+
# Get command schemas
|
|
153
|
+
commands = [cmd.to_dict() for cmd in self._commands.values()]
|
|
154
|
+
|
|
155
|
+
# Connect to API
|
|
156
|
+
result = await self._client.connect(commands)
|
|
157
|
+
self._application_id = result.get("applicationId", "")
|
|
158
|
+
|
|
159
|
+
print(f"[Loop SDK] Connected to application {self._application_id}")
|
|
160
|
+
print(f"[Loop SDK] Deployed {len(commands)} commands")
|
|
161
|
+
print("[Loop SDK] Bot is running. Waiting for interactions...")
|
|
162
|
+
|
|
163
|
+
self._running = True
|
|
164
|
+
|
|
165
|
+
try:
|
|
166
|
+
# Start SSE connection
|
|
167
|
+
await self._client.connect_sse(self._handle_interaction)
|
|
168
|
+
except asyncio.CancelledError:
|
|
169
|
+
pass
|
|
170
|
+
finally:
|
|
171
|
+
await self.stop()
|
|
172
|
+
|
|
173
|
+
async def stop(self) -> None:
|
|
174
|
+
"""Stop the bot"""
|
|
175
|
+
if self._running:
|
|
176
|
+
print("[Loop SDK] Stopping bot...")
|
|
177
|
+
self._running = False
|
|
178
|
+
await self._client.disconnect()
|
|
179
|
+
|
|
180
|
+
def start(self) -> None:
|
|
181
|
+
"""Start the bot (blocking)"""
|
|
182
|
+
loop = asyncio.new_event_loop()
|
|
183
|
+
asyncio.set_event_loop(loop)
|
|
184
|
+
|
|
185
|
+
# Handle signals
|
|
186
|
+
def signal_handler() -> None:
|
|
187
|
+
loop.create_task(self.stop())
|
|
188
|
+
|
|
189
|
+
try:
|
|
190
|
+
loop.add_signal_handler(signal.SIGINT, signal_handler)
|
|
191
|
+
loop.add_signal_handler(signal.SIGTERM, signal_handler)
|
|
192
|
+
except NotImplementedError:
|
|
193
|
+
# Windows doesn't support add_signal_handler
|
|
194
|
+
pass
|
|
195
|
+
|
|
196
|
+
try:
|
|
197
|
+
loop.run_until_complete(self._start_async())
|
|
198
|
+
except KeyboardInterrupt:
|
|
199
|
+
loop.run_until_complete(self.stop())
|
|
200
|
+
finally:
|
|
201
|
+
loop.close()
|
|
202
|
+
|
|
203
|
+
def run(self) -> None:
|
|
204
|
+
"""Alias for start()"""
|
|
205
|
+
self.start()
|
|
206
|
+
|
|
207
|
+
# ==================== MESSAGING ====================
|
|
208
|
+
|
|
209
|
+
async def send(
|
|
210
|
+
self,
|
|
211
|
+
channel_id: str,
|
|
212
|
+
content: Optional[str] = None,
|
|
213
|
+
embeds: Optional[List[Dict[str, Any]]] = None,
|
|
214
|
+
components: Optional[List[Dict[str, Any]]] = None,
|
|
215
|
+
) -> Dict[str, Any]:
|
|
216
|
+
"""Send a message to a channel"""
|
|
217
|
+
return await self._client.send_message(
|
|
218
|
+
self._application_id, channel_id, content, embeds, components
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
async def edit_message(
|
|
222
|
+
self,
|
|
223
|
+
channel_id: str,
|
|
224
|
+
message_id: str,
|
|
225
|
+
content: Optional[str] = None,
|
|
226
|
+
embeds: Optional[List[Dict[str, Any]]] = None,
|
|
227
|
+
components: Optional[List[Dict[str, Any]]] = None,
|
|
228
|
+
) -> Dict[str, Any]:
|
|
229
|
+
"""Edit a message"""
|
|
230
|
+
return await self._client.edit_message(
|
|
231
|
+
self._application_id, channel_id, message_id, content, embeds, components
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
async def delete_message(self, channel_id: str, message_id: str) -> None:
|
|
235
|
+
"""Delete a message"""
|
|
236
|
+
await self._client.delete_message(self._application_id, channel_id, message_id)
|
|
237
|
+
|
|
238
|
+
async def get_messages(
|
|
239
|
+
self,
|
|
240
|
+
channel_id: str,
|
|
241
|
+
limit: Optional[int] = None,
|
|
242
|
+
before: Optional[str] = None,
|
|
243
|
+
after: Optional[str] = None,
|
|
244
|
+
) -> List[Dict[str, Any]]:
|
|
245
|
+
"""Get messages from a channel"""
|
|
246
|
+
return await self._client.get_messages(
|
|
247
|
+
self._application_id, channel_id, limit, before, after
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
async def get_message(self, channel_id: str, message_id: str) -> Dict[str, Any]:
|
|
251
|
+
"""Get a single message"""
|
|
252
|
+
return await self._client.get_message(
|
|
253
|
+
self._application_id, channel_id, message_id
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
# ==================== CHANNELS ====================
|
|
257
|
+
|
|
258
|
+
async def get_channel(self, channel_id: str) -> Dict[str, Any]:
|
|
259
|
+
"""Get a channel"""
|
|
260
|
+
return await self._client.get_channel(self._application_id, channel_id)
|
|
261
|
+
|
|
262
|
+
async def create_channel(
|
|
263
|
+
self,
|
|
264
|
+
guild_id: str,
|
|
265
|
+
name: str,
|
|
266
|
+
channel_type: Optional[int] = None,
|
|
267
|
+
topic: Optional[str] = None,
|
|
268
|
+
permission_overwrites: Optional[List[Dict[str, Any]]] = None,
|
|
269
|
+
parent_id: Optional[str] = None,
|
|
270
|
+
) -> Dict[str, Any]:
|
|
271
|
+
"""Create a channel in a guild"""
|
|
272
|
+
return await self._client.create_channel(
|
|
273
|
+
self._application_id, guild_id, name, channel_type, topic,
|
|
274
|
+
permission_overwrites, parent_id
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
async def modify_channel(
|
|
278
|
+
self,
|
|
279
|
+
channel_id: str,
|
|
280
|
+
name: Optional[str] = None,
|
|
281
|
+
topic: Optional[str] = None,
|
|
282
|
+
permission_overwrites: Optional[List[Dict[str, Any]]] = None,
|
|
283
|
+
) -> Dict[str, Any]:
|
|
284
|
+
"""Modify a channel"""
|
|
285
|
+
return await self._client.modify_channel(
|
|
286
|
+
self._application_id, channel_id, name, topic, permission_overwrites
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
async def delete_channel(self, channel_id: str) -> None:
|
|
290
|
+
"""Delete a channel"""
|
|
291
|
+
await self._client.delete_channel(self._application_id, channel_id)
|
|
292
|
+
|
|
293
|
+
# ==================== GUILDS ====================
|
|
294
|
+
|
|
295
|
+
async def get_guild(self, guild_id: str) -> Dict[str, Any]:
|
|
296
|
+
"""Get guild info"""
|
|
297
|
+
return await self._client.get_guild(self._application_id, guild_id)
|
|
298
|
+
|
|
299
|
+
async def get_guild_channels(self, guild_id: str) -> List[Dict[str, Any]]:
|
|
300
|
+
"""Get guild channels"""
|
|
301
|
+
return await self._client.get_guild_channels(self._application_id, guild_id)
|
|
302
|
+
|
|
303
|
+
async def get_guild_roles(self, guild_id: str) -> List[Dict[str, Any]]:
|
|
304
|
+
"""Get guild roles"""
|
|
305
|
+
return await self._client.get_guild_roles(self._application_id, guild_id)
|
|
306
|
+
|
|
307
|
+
# ==================== MEMBERS ====================
|
|
308
|
+
|
|
309
|
+
async def get_guild_member(self, guild_id: str, user_id: str) -> Dict[str, Any]:
|
|
310
|
+
"""Get a guild member"""
|
|
311
|
+
return await self._client.get_guild_member(
|
|
312
|
+
self._application_id, guild_id, user_id
|
|
313
|
+
)
|
|
314
|
+
|
|
315
|
+
async def list_guild_members(
|
|
316
|
+
self,
|
|
317
|
+
guild_id: str,
|
|
318
|
+
limit: Optional[int] = None,
|
|
319
|
+
after: Optional[str] = None,
|
|
320
|
+
) -> List[Dict[str, Any]]:
|
|
321
|
+
"""List guild members"""
|
|
322
|
+
return await self._client.list_guild_members(
|
|
323
|
+
self._application_id, guild_id, limit, after
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
async def add_member_role(
|
|
327
|
+
self, guild_id: str, user_id: str, role_id: str
|
|
328
|
+
) -> None:
|
|
329
|
+
"""Add role to member"""
|
|
330
|
+
await self._client.add_member_role(
|
|
331
|
+
self._application_id, guild_id, user_id, role_id
|
|
332
|
+
)
|
|
333
|
+
|
|
334
|
+
async def remove_member_role(
|
|
335
|
+
self, guild_id: str, user_id: str, role_id: str
|
|
336
|
+
) -> None:
|
|
337
|
+
"""Remove role from member"""
|
|
338
|
+
await self._client.remove_member_role(
|
|
339
|
+
self._application_id, guild_id, user_id, role_id
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
async def kick_member(self, guild_id: str, user_id: str) -> None:
|
|
343
|
+
"""Kick member"""
|
|
344
|
+
await self._client.kick_member(self._application_id, guild_id, user_id)
|
|
345
|
+
|
|
346
|
+
async def ban_member(
|
|
347
|
+
self,
|
|
348
|
+
guild_id: str,
|
|
349
|
+
user_id: str,
|
|
350
|
+
delete_message_seconds: Optional[int] = None,
|
|
351
|
+
) -> None:
|
|
352
|
+
"""Ban member"""
|
|
353
|
+
await self._client.ban_member(
|
|
354
|
+
self._application_id, guild_id, user_id, delete_message_seconds
|
|
355
|
+
)
|
|
356
|
+
|
|
357
|
+
async def unban_member(self, guild_id: str, user_id: str) -> None:
|
|
358
|
+
"""Unban member"""
|
|
359
|
+
await self._client.unban_member(self._application_id, guild_id, user_id)
|
|
360
|
+
|
|
361
|
+
# ==================== REACTIONS ====================
|
|
362
|
+
|
|
363
|
+
async def add_reaction(
|
|
364
|
+
self, channel_id: str, message_id: str, emoji: str
|
|
365
|
+
) -> None:
|
|
366
|
+
"""Add reaction to message"""
|
|
367
|
+
await self._client.add_reaction(
|
|
368
|
+
self._application_id, channel_id, message_id, emoji
|
|
369
|
+
)
|
|
370
|
+
|
|
371
|
+
async def remove_reaction(
|
|
372
|
+
self, channel_id: str, message_id: str, emoji: str
|
|
373
|
+
) -> None:
|
|
374
|
+
"""Remove reaction from message"""
|
|
375
|
+
await self._client.remove_reaction(
|
|
376
|
+
self._application_id, channel_id, message_id, emoji
|
|
377
|
+
)
|
|
378
|
+
|
|
379
|
+
# ==================== PINS ====================
|
|
380
|
+
|
|
381
|
+
async def pin_message(self, channel_id: str, message_id: str) -> None:
|
|
382
|
+
"""Pin a message"""
|
|
383
|
+
await self._client.pin_message(
|
|
384
|
+
self._application_id, channel_id, message_id
|
|
385
|
+
)
|
|
386
|
+
|
|
387
|
+
async def unpin_message(self, channel_id: str, message_id: str) -> None:
|
|
388
|
+
"""Unpin a message"""
|
|
389
|
+
await self._client.unpin_message(
|
|
390
|
+
self._application_id, channel_id, message_id
|
|
391
|
+
)
|
|
392
|
+
|
|
393
|
+
async def get_pinned_messages(self, channel_id: str) -> List[Dict[str, Any]]:
|
|
394
|
+
"""Get pinned messages"""
|
|
395
|
+
return await self._client.get_pinned_messages(
|
|
396
|
+
self._application_id, channel_id
|
|
397
|
+
)
|
|
398
|
+
|
|
399
|
+
# ==================== USERS ====================
|
|
400
|
+
|
|
401
|
+
async def get_user(self, user_id: str) -> Dict[str, Any]:
|
|
402
|
+
"""Get user info"""
|
|
403
|
+
return await self._client.get_user(self._application_id, user_id)
|
|
404
|
+
|
|
405
|
+
# ==================== THREADS ====================
|
|
406
|
+
|
|
407
|
+
async def create_thread(
|
|
408
|
+
self,
|
|
409
|
+
channel_id: str,
|
|
410
|
+
name: str,
|
|
411
|
+
message_id: Optional[str] = None,
|
|
412
|
+
thread_type: Optional[int] = None,
|
|
413
|
+
auto_archive_duration: Optional[int] = None,
|
|
414
|
+
) -> Dict[str, Any]:
|
|
415
|
+
"""Create a thread"""
|
|
416
|
+
return await self._client.create_thread(
|
|
417
|
+
self._application_id, channel_id, name, message_id,
|
|
418
|
+
thread_type, auto_archive_duration
|
|
419
|
+
)
|
|
420
|
+
|
|
421
|
+
# ==================== FORUM CHANNELS ====================
|
|
422
|
+
|
|
423
|
+
async def create_forum_post(
|
|
424
|
+
self,
|
|
425
|
+
channel_id: str,
|
|
426
|
+
name: str,
|
|
427
|
+
message: Dict[str, Any],
|
|
428
|
+
applied_tags: Optional[List[str]] = None,
|
|
429
|
+
) -> Dict[str, Any]:
|
|
430
|
+
"""Create a forum post"""
|
|
431
|
+
return await self._client.create_forum_post(
|
|
432
|
+
self._application_id, channel_id, name, message, applied_tags
|
|
433
|
+
)
|
|
434
|
+
|
|
435
|
+
async def get_forum_tags(self, channel_id: str) -> List[Dict[str, Any]]:
|
|
436
|
+
"""Get forum tags"""
|
|
437
|
+
return await self._client.get_forum_tags(self._application_id, channel_id)
|
|
438
|
+
|
|
439
|
+
async def modify_forum_tags(
|
|
440
|
+
self, channel_id: str, tags: List[Dict[str, Any]]
|
|
441
|
+
) -> Dict[str, Any]:
|
|
442
|
+
"""Modify forum tags"""
|
|
443
|
+
return await self._client.modify_forum_tags(
|
|
444
|
+
self._application_id, channel_id, tags
|
|
445
|
+
)
|
|
446
|
+
|
|
447
|
+
async def archive_thread(
|
|
448
|
+
self, thread_id: str, archived: bool = True
|
|
449
|
+
) -> Dict[str, Any]:
|
|
450
|
+
"""Archive thread"""
|
|
451
|
+
return await self._client.archive_thread(
|
|
452
|
+
self._application_id, thread_id, archived
|
|
453
|
+
)
|
|
454
|
+
|
|
455
|
+
async def lock_thread(
|
|
456
|
+
self, thread_id: str, locked: bool = True
|
|
457
|
+
) -> Dict[str, Any]:
|
|
458
|
+
"""Lock thread"""
|
|
459
|
+
return await self._client.lock_thread(
|
|
460
|
+
self._application_id, thread_id, locked
|
|
461
|
+
)
|
|
462
|
+
|
|
463
|
+
# ==================== ROLES ====================
|
|
464
|
+
|
|
465
|
+
async def get_roles(self, guild_id: str) -> List[Dict[str, Any]]:
|
|
466
|
+
"""Get roles"""
|
|
467
|
+
return await self._client.get_roles(self._application_id, guild_id)
|
|
468
|
+
|
|
469
|
+
async def create_role(
|
|
470
|
+
self,
|
|
471
|
+
guild_id: str,
|
|
472
|
+
name: Optional[str] = None,
|
|
473
|
+
permissions: Optional[str] = None,
|
|
474
|
+
color: Optional[int] = None,
|
|
475
|
+
hoist: Optional[bool] = None,
|
|
476
|
+
mentionable: Optional[bool] = None,
|
|
477
|
+
) -> Dict[str, Any]:
|
|
478
|
+
"""Create role"""
|
|
479
|
+
return await self._client.create_role(
|
|
480
|
+
self._application_id, guild_id, name, permissions, color, hoist, mentionable
|
|
481
|
+
)
|
|
482
|
+
|
|
483
|
+
async def modify_role(
|
|
484
|
+
self,
|
|
485
|
+
guild_id: str,
|
|
486
|
+
role_id: str,
|
|
487
|
+
name: Optional[str] = None,
|
|
488
|
+
permissions: Optional[str] = None,
|
|
489
|
+
color: Optional[int] = None,
|
|
490
|
+
hoist: Optional[bool] = None,
|
|
491
|
+
mentionable: Optional[bool] = None,
|
|
492
|
+
) -> Dict[str, Any]:
|
|
493
|
+
"""Modify role"""
|
|
494
|
+
return await self._client.modify_role(
|
|
495
|
+
self._application_id, guild_id, role_id, name, permissions, color, hoist, mentionable
|
|
496
|
+
)
|
|
497
|
+
|
|
498
|
+
async def delete_role(self, guild_id: str, role_id: str) -> None:
|
|
499
|
+
"""Delete role"""
|
|
500
|
+
await self._client.delete_role(self._application_id, guild_id, role_id)
|
|
501
|
+
|
|
502
|
+
async def reorder_roles(
|
|
503
|
+
self, guild_id: str, positions: List[Dict[str, Any]]
|
|
504
|
+
) -> List[Dict[str, Any]]:
|
|
505
|
+
"""Reorder roles"""
|
|
506
|
+
return await self._client.reorder_roles(
|
|
507
|
+
self._application_id, guild_id, positions
|
|
508
|
+
)
|
|
509
|
+
|
|
510
|
+
# ==================== WEBHOOKS ====================
|
|
511
|
+
|
|
512
|
+
async def create_webhook(
|
|
513
|
+
self, channel_id: str, name: str, avatar: Optional[str] = None
|
|
514
|
+
) -> Dict[str, Any]:
|
|
515
|
+
"""Create webhook"""
|
|
516
|
+
return await self._client.create_webhook(
|
|
517
|
+
self._application_id, channel_id, name, avatar
|
|
518
|
+
)
|
|
519
|
+
|
|
520
|
+
async def get_channel_webhooks(self, channel_id: str) -> List[Dict[str, Any]]:
|
|
521
|
+
"""Get channel webhooks"""
|
|
522
|
+
return await self._client.get_channel_webhooks(
|
|
523
|
+
self._application_id, channel_id
|
|
524
|
+
)
|
|
525
|
+
|
|
526
|
+
async def get_guild_webhooks(self, guild_id: str) -> List[Dict[str, Any]]:
|
|
527
|
+
"""Get guild webhooks"""
|
|
528
|
+
return await self._client.get_guild_webhooks(self._application_id, guild_id)
|
|
529
|
+
|
|
530
|
+
async def get_webhook(self, webhook_id: str) -> Dict[str, Any]:
|
|
531
|
+
"""Get webhook"""
|
|
532
|
+
return await self._client.get_webhook(self._application_id, webhook_id)
|
|
533
|
+
|
|
534
|
+
async def modify_webhook(
|
|
535
|
+
self,
|
|
536
|
+
webhook_id: str,
|
|
537
|
+
name: Optional[str] = None,
|
|
538
|
+
avatar: Optional[str] = None,
|
|
539
|
+
channel_id: Optional[str] = None,
|
|
540
|
+
) -> Dict[str, Any]:
|
|
541
|
+
"""Modify webhook"""
|
|
542
|
+
return await self._client.modify_webhook(
|
|
543
|
+
self._application_id, webhook_id, name, avatar, channel_id
|
|
544
|
+
)
|
|
545
|
+
|
|
546
|
+
async def delete_webhook(self, webhook_id: str) -> None:
|
|
547
|
+
"""Delete webhook"""
|
|
548
|
+
await self._client.delete_webhook(self._application_id, webhook_id)
|
|
549
|
+
|
|
550
|
+
async def execute_webhook(
|
|
551
|
+
self,
|
|
552
|
+
webhook_id: str,
|
|
553
|
+
webhook_token: str,
|
|
554
|
+
content: Optional[str] = None,
|
|
555
|
+
username: Optional[str] = None,
|
|
556
|
+
avatar_url: Optional[str] = None,
|
|
557
|
+
embeds: Optional[List[Dict[str, Any]]] = None,
|
|
558
|
+
wait: bool = False,
|
|
559
|
+
) -> Optional[Dict[str, Any]]:
|
|
560
|
+
"""Execute webhook (send message)"""
|
|
561
|
+
return await self._client.execute_webhook(
|
|
562
|
+
webhook_id, webhook_token, content, username, avatar_url, embeds, wait
|
|
563
|
+
)
|
|
564
|
+
|
|
565
|
+
async def edit_webhook_message(
|
|
566
|
+
self,
|
|
567
|
+
webhook_id: str,
|
|
568
|
+
webhook_token: str,
|
|
569
|
+
message_id: str,
|
|
570
|
+
content: Optional[str] = None,
|
|
571
|
+
embeds: Optional[List[Dict[str, Any]]] = None,
|
|
572
|
+
) -> Dict[str, Any]:
|
|
573
|
+
"""Edit webhook message"""
|
|
574
|
+
return await self._client.edit_webhook_message(
|
|
575
|
+
webhook_id, webhook_token, message_id, content, embeds
|
|
576
|
+
)
|
|
577
|
+
|
|
578
|
+
async def delete_webhook_message(
|
|
579
|
+
self, webhook_id: str, webhook_token: str, message_id: str
|
|
580
|
+
) -> None:
|
|
581
|
+
"""Delete webhook message"""
|
|
582
|
+
await self._client.delete_webhook_message(
|
|
583
|
+
webhook_id, webhook_token, message_id
|
|
584
|
+
)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Builders for Discord components
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from .embed import EmbedBuilder
|
|
6
|
+
from .button import ButtonBuilder, ButtonStyle
|
|
7
|
+
from .action_row import ActionRowBuilder
|
|
8
|
+
from .select_menu import SelectMenuBuilder
|
|
9
|
+
from .modal import ModalBuilder
|
|
10
|
+
from .container import ContainerBuilder
|
|
11
|
+
from .separator import SeparatorBuilder
|
|
12
|
+
from .text_display import TextDisplayBuilder
|
|
13
|
+
from .media_gallery import MediaGalleryBuilder
|
|
14
|
+
from .section import SectionBuilder
|
|
15
|
+
from .file import FileBuilder
|
|
16
|
+
|
|
17
|
+
__all__ = [
|
|
18
|
+
"EmbedBuilder",
|
|
19
|
+
"ButtonBuilder",
|
|
20
|
+
"ButtonStyle",
|
|
21
|
+
"ActionRowBuilder",
|
|
22
|
+
"SelectMenuBuilder",
|
|
23
|
+
"ModalBuilder",
|
|
24
|
+
"ContainerBuilder",
|
|
25
|
+
"SeparatorBuilder",
|
|
26
|
+
"TextDisplayBuilder",
|
|
27
|
+
"MediaGalleryBuilder",
|
|
28
|
+
"SectionBuilder",
|
|
29
|
+
"FileBuilder",
|
|
30
|
+
]
|