zynko 0.1.0__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.
zynko-0.1.0/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ .venv*/
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ dist/
6
+ build/
7
+ .pytest_cache/
8
+ .mypy_cache/
9
+ .ruff_cache/
zynko-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,67 @@
1
+ Metadata-Version: 2.4
2
+ Name: zynko
3
+ Version: 0.1.0
4
+ Summary: Biblioteca oficial para bots do Zynko: API, gateway e voz.
5
+ Project-URL: Documentation, https://docs.zynko.org/bots/python
6
+ Project-URL: Homepage, https://zynko.org
7
+ License-Expression: MIT
8
+ Keywords: asyncio,bot,chat,voice,zynko
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Framework :: AsyncIO
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Programming Language :: Python :: 3.14
18
+ Classifier: Typing :: Typed
19
+ Requires-Python: >=3.10
20
+ Requires-Dist: aiohttp<4,>=3.11
21
+ Provides-Extra: dev
22
+ Requires-Dist: mypy>=1.13; extra == 'dev'
23
+ Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
24
+ Requires-Dist: pytest>=8.3; extra == 'dev'
25
+ Provides-Extra: voice
26
+ Requires-Dist: livekit==1.2.1; extra == 'voice'
27
+ Description-Content-Type: text/markdown
28
+
29
+ # zynko
30
+
31
+ A biblioteca oficial para bots do [Zynko](https://zynko.org) em Python: gateway com
32
+ reconexão, cache de servidores, canais e membros, a API inteira, comandos com "/", cartões e
33
+ botões, e voz (tocar e ouvir áudio nas salas). Feita com asyncio.
34
+
35
+ ```sh
36
+ pip install zynko
37
+ pip install "zynko[voice]" # com voz
38
+ ```
39
+
40
+ ```python
41
+ import os
42
+ import zynko
43
+
44
+ client = zynko.Client(intents=zynko.Intents.GUILDS | zynko.Intents.MESSAGES)
45
+
46
+ @client.on("message_create")
47
+ async def ping(msg: zynko.Message):
48
+ if not msg.mine and msg.content == "!ping":
49
+ await msg.reply("pong")
50
+
51
+ client.run(os.environ["ZYNKO_TOKEN"])
52
+ ```
53
+
54
+ Voz:
55
+
56
+ ```python
57
+ voice = await client.join_voice(channel_id)
58
+ voice.player.enqueue("https://exemplo.com/musica.mp3")
59
+ ```
60
+
61
+ Python 3.10 ou mais novo. Para tocar arquivos e links, o ffmpeg precisa estar instalado.
62
+ Exemplos em [`examples/`](examples): `ping.py`, `dado.py` (comandos, cartão e botões) e
63
+ `musica.py`.
64
+
65
+ Documentação: https://docs.zynko.org/bots/python · Crie seu bot: https://dev.zynko.org
66
+
67
+ Licença MIT.
zynko-0.1.0/README.md ADDED
@@ -0,0 +1,39 @@
1
+ # zynko
2
+
3
+ A biblioteca oficial para bots do [Zynko](https://zynko.org) em Python: gateway com
4
+ reconexão, cache de servidores, canais e membros, a API inteira, comandos com "/", cartões e
5
+ botões, e voz (tocar e ouvir áudio nas salas). Feita com asyncio.
6
+
7
+ ```sh
8
+ pip install zynko
9
+ pip install "zynko[voice]" # com voz
10
+ ```
11
+
12
+ ```python
13
+ import os
14
+ import zynko
15
+
16
+ client = zynko.Client(intents=zynko.Intents.GUILDS | zynko.Intents.MESSAGES)
17
+
18
+ @client.on("message_create")
19
+ async def ping(msg: zynko.Message):
20
+ if not msg.mine and msg.content == "!ping":
21
+ await msg.reply("pong")
22
+
23
+ client.run(os.environ["ZYNKO_TOKEN"])
24
+ ```
25
+
26
+ Voz:
27
+
28
+ ```python
29
+ voice = await client.join_voice(channel_id)
30
+ voice.player.enqueue("https://exemplo.com/musica.mp3")
31
+ ```
32
+
33
+ Python 3.10 ou mais novo. Para tocar arquivos e links, o ffmpeg precisa estar instalado.
34
+ Exemplos em [`examples/`](examples): `ping.py`, `dado.py` (comandos, cartão e botões) e
35
+ `musica.py`.
36
+
37
+ Documentação: https://docs.zynko.org/bots/python · Crie seu bot: https://dev.zynko.org
38
+
39
+ Licença MIT.
@@ -0,0 +1,70 @@
1
+ """Slash commands, a card and buttons: /dado rolls a die and offers to roll again.
2
+
3
+ ZYNKO_TOKEN=bot_... python dado.py
4
+ """
5
+
6
+ import os
7
+ import random
8
+
9
+ import zynko
10
+
11
+ LAVENDER = 0xA594F9
12
+
13
+ client = zynko.Client(intents=zynko.Intents.GUILDS, api=os.environ.get("ZYNKO_API"))
14
+
15
+ COMMANDS: list[zynko.Command] = [
16
+ {
17
+ "name": "dado",
18
+ "description": "Rola um dado",
19
+ "options": [{"name": "lados", "description": "Quantos lados", "type": "integer", "min_value": 2, "max_value": 100}],
20
+ },
21
+ {"name": "ping", "description": "Responde pong"},
22
+ ]
23
+
24
+
25
+ def roll(sides: int, who: str) -> tuple[list[zynko.Card], zynko.Components]:
26
+ """The card with a roll, and the buttons under it."""
27
+ card: zynko.Card = {
28
+ "title": f"🎲 {random.randint(1, sides)}",
29
+ "description": f"Dado de {sides} lados, rolado por **{who}**.",
30
+ "color": LAVENDER,
31
+ }
32
+ buttons: zynko.Components = [
33
+ [
34
+ {"style": "primary", "emoji": "🎲", "label": "De novo", "custom_id": f"dado:{sides}"},
35
+ {"style": "secondary", "label": "Pronto", "custom_id": "dado:fim"},
36
+ ]
37
+ ]
38
+ return [card], buttons
39
+
40
+
41
+ @client.event
42
+ async def on_ready(user: zynko.User) -> None:
43
+ await client.set_commands(COMMANDS)
44
+ print(f"{user.display_name} pronto, com {len(COMMANDS)} comandos")
45
+
46
+
47
+ @client.event
48
+ async def on_interaction(i: zynko.Interaction) -> None:
49
+ who = i.member.name if i.member else i.user.display_name
50
+ if i.type == "command":
51
+ if i.command == "ping":
52
+ await i.reply("pong", ephemeral=True)
53
+ elif i.command == "dado":
54
+ cards, buttons = roll(int(i.option("lados", 6)), who)
55
+ await i.reply(cards=cards, components=buttons)
56
+ return
57
+ # A click on one of the buttons.
58
+ if i.custom_id == "dado:fim":
59
+ await i.update(components=[])
60
+ elif i.custom_id and i.custom_id.startswith("dado:"):
61
+ cards, buttons = roll(int(i.custom_id.split(":")[1]), who)
62
+ await i.update(cards=cards, components=buttons)
63
+
64
+
65
+ @client.event
66
+ async def on_error(error: Exception) -> None:
67
+ print("erro:", error)
68
+
69
+
70
+ client.run(os.environ["ZYNKO_TOKEN"])
@@ -0,0 +1,293 @@
1
+ """A small music bot: joins your voice room and plays links (mp3, ogg, radio streams, anything
2
+ ffmpeg opens), with a queue. Use it with "/" commands (/tocar, /fila...) or the "!" ones
3
+ (!tocar <link>...); what is playing shows as a card with buttons.
4
+
5
+ pip install "zynko[voice]"
6
+ ZYNKO_TOKEN=bot_... python musica.py
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import asyncio
12
+ import os
13
+ import re
14
+ from collections.abc import Awaitable, Callable
15
+ from dataclasses import dataclass
16
+ from typing import Any
17
+ from urllib.parse import unquote, urlparse
18
+
19
+ import zynko
20
+ from zynko import Intents, Permissions
21
+
22
+ PREFIX = os.environ.get("PREFIX", "!")
23
+ LAVENDER = 0xA594F9
24
+
25
+ client = zynko.Client(
26
+ intents=Intents.GUILDS | Intents.MESSAGES | Intents.VOICE_STATES,
27
+ api=os.environ.get("ZYNKO_API"),
28
+ )
29
+
30
+
31
+ @dataclass
32
+ class Song:
33
+ url: str
34
+ title: str
35
+ #: Who asked for it, and where to talk about it.
36
+ by: str
37
+ channel_id: str
38
+
39
+
40
+ @dataclass
41
+ class Ctx:
42
+ """Where a command came from: a "!" message or a "/" command, answered the same way."""
43
+
44
+ user_id: str
45
+ name: str
46
+ guild_id: str | None
47
+ channel_id: str
48
+ #: Answers; ``quiet`` ones only the person sees, when the command came by "/".
49
+ say: Callable[..., Awaitable[Any]]
50
+
51
+
52
+ def title_of(url: str) -> str:
53
+ """A title for the queue: the link's last part."""
54
+ u = urlparse(url)
55
+ last = [p for p in u.path.split("/") if p]
56
+ return unquote(last[-1]) if last else u.netloc or url
57
+
58
+
59
+ def now_playing() -> dict[str, Any]:
60
+ """The "Tocando agora" card, with the queue's next ones and the buttons."""
61
+ p = client.voice.player if client.voice else None
62
+ song: Song | None = p.current.meta if p and p.current else None
63
+ if not p or not song:
64
+ return {"cards": [{"title": "Nada tocando", "color": LAVENDER}], "components": []}
65
+ nxt = [f"{n}. {t.meta.title if t.meta else '?'}" for n, t in enumerate(p.queue[:5], 1)]
66
+ fields: list[zynko.CardField] = [
67
+ {"name": "Pedido por", "value": song.by, "inline": True},
68
+ {"name": "Volume", "value": f"{round(p.volume * 100)}%", "inline": True},
69
+ ]
70
+ if nxt:
71
+ fields.append({"name": f"Próximas ({len(p.queue)})", "value": "\n".join(nxt)})
72
+ card: zynko.Card = {
73
+ "author": {"name": "Pausado" if p.paused else "Tocando agora"},
74
+ "title": song.title,
75
+ "color": LAVENDER,
76
+ "fields": fields,
77
+ }
78
+ if song.url:
79
+ card["url"] = song.url
80
+ buttons: zynko.Components = [
81
+ [
82
+ {
83
+ "style": "secondary",
84
+ "emoji": "▶️" if p.paused else "⏸️",
85
+ "label": "Continuar" if p.paused else "Pausar",
86
+ "custom_id": "pausar",
87
+ },
88
+ {"style": "primary", "emoji": "⏭️", "label": "Pular", "custom_id": "pular"},
89
+ {"style": "danger", "emoji": "⏹️", "label": "Parar", "custom_id": "parar"},
90
+ ]
91
+ ]
92
+ return {"cards": [card], "components": buttons}
93
+
94
+
95
+ async def voice_for(ctx: Ctx) -> Any:
96
+ """Joins the author's voice room, or says why not."""
97
+ state = client.voice_states.get(ctx.user_id)
98
+ where = state.channel_id if state else None
99
+ room = client.channels.get(where) if where else None
100
+ if not where or not room or room.guild_id != ctx.guild_id:
101
+ await ctx.say("Entre numa sala de voz deste servidor primeiro.", True)
102
+ return None
103
+ if client.voice and client.voice.channel_id == where:
104
+ return client.voice
105
+ assert client.user is not None
106
+ if not client.can(where, client.user.id, Permissions.CONNECT | Permissions.SPEAK):
107
+ await ctx.say("Não tenho permissão para entrar e falar nessa sala.", True)
108
+ return None
109
+ voice = await client.join_voice(where)
110
+
111
+ @voice.player.on("start")
112
+ async def started(track: zynko.Track[Song]) -> None:
113
+ if track.meta:
114
+ await client.send(track.meta.channel_id, **now_playing())
115
+
116
+ @voice.player.on("error")
117
+ async def failed(error: Exception, track: zynko.Track[Song]) -> None:
118
+ if track.meta:
119
+ await client.send(track.meta.channel_id, f"Não consegui tocar **{track.meta.title}**: {error}")
120
+
121
+ voice.on("disconnect", lambda reason: print(f"saiu da voz: {reason}"))
122
+ return voice
123
+
124
+
125
+ async def tocar(ctx: Ctx, arg: str) -> Any:
126
+ if not re.fullmatch(r"https?://\S+", arg, re.I):
127
+ return await ctx.say(f"Use: {PREFIX}tocar <link de áudio>", True)
128
+ voice = await voice_for(ctx)
129
+ if not voice:
130
+ return None
131
+ song = Song(arg, title_of(arg), ctx.name, ctx.channel_id)
132
+ playing = voice.player.current is not None
133
+ voice.player.enqueue(arg, song)
134
+ if playing:
135
+ return await ctx.say(f"Na fila ({len(voice.player.queue)}): **{song.title}**")
136
+ return await ctx.say(f"Vai tocar: **{song.title}**", True)
137
+
138
+
139
+ async def teste(ctx: Ctx, arg: str) -> Any:
140
+ voice = await voice_for(ctx)
141
+ if voice:
142
+ voice.player.play(zynko.tone(440, 3), Song("", "um lá de 440 Hz", ctx.name, ctx.channel_id))
143
+ return await ctx.say("Tocando um tom de 3 segundos.", True)
144
+ return None
145
+
146
+
147
+ async def pular(ctx: Ctx, arg: str) -> Any:
148
+ if not client.voice or not client.voice.player.current:
149
+ return await ctx.say("Nada tocando.", True)
150
+ client.voice.player.skip()
151
+ return await ctx.say("⏭️ Pulei.", True)
152
+
153
+
154
+ async def parar(ctx: Ctx, arg: str) -> Any:
155
+ if client.voice:
156
+ client.voice.player.stop()
157
+ return await ctx.say("⏹️ Parei e esvaziei a fila.", True)
158
+
159
+
160
+ async def pausar(ctx: Ctx, arg: str) -> Any:
161
+ if client.voice:
162
+ client.voice.player.pause()
163
+ return await ctx.say("⏸️ Pausado.", True)
164
+
165
+
166
+ async def continuar(ctx: Ctx, arg: str) -> Any:
167
+ if client.voice:
168
+ client.voice.player.resume()
169
+ return await ctx.say("▶️ Continuando.", True)
170
+
171
+
172
+ async def fila(ctx: Ctx, arg: str) -> Any:
173
+ return await ctx.say(now_playing())
174
+
175
+
176
+ async def volume(ctx: Ctx, arg: str) -> Any:
177
+ if not client.voice:
178
+ return await ctx.say("Não estou em nenhuma sala.", True)
179
+ p = client.voice.player
180
+ try:
181
+ v = float(arg)
182
+ except ValueError:
183
+ v = -1
184
+ if not 0 <= v <= 200:
185
+ return await ctx.say(f"Volume atual: {round(p.volume * 100)}%.", True)
186
+ p.volume = v / 100
187
+ return await ctx.say(f"🔊 Volume em {v:g}%.", True)
188
+
189
+
190
+ async def sair(ctx: Ctx, arg: str) -> Any:
191
+ if client.voice:
192
+ await client.voice.leave()
193
+ return await ctx.say("👋 Saí da sala.", True)
194
+
195
+
196
+ COMMANDS: dict[str, Callable[[Ctx, str], Awaitable[Any]]] = {
197
+ "tocar": tocar,
198
+ "teste": teste,
199
+ "pular": pular,
200
+ "parar": parar,
201
+ "pausar": pausar,
202
+ "continuar": continuar,
203
+ "fila": fila,
204
+ "volume": volume,
205
+ "sair": sair,
206
+ }
207
+
208
+ #: The "/" commands, as the apps show them.
209
+ SLASH: list[zynko.Command] = [
210
+ {
211
+ "name": "tocar",
212
+ "description": "Toca um link, ou põe na fila",
213
+ "options": [{"name": "link", "description": "Link de áudio (mp3, ogg, rádio...)", "type": "string", "required": True}],
214
+ },
215
+ {"name": "pular", "description": "Vai para a próxima da fila"},
216
+ {"name": "parar", "description": "Para e esvazia a fila"},
217
+ {"name": "pausar", "description": "Pausa a música"},
218
+ {"name": "continuar", "description": "Continua a música pausada"},
219
+ {"name": "fila", "description": "O que está tocando e as próximas"},
220
+ {
221
+ "name": "volume",
222
+ "description": "Muda o volume",
223
+ "options": [{"name": "porcentagem", "description": "0 a 200", "type": "integer", "min_value": 0, "max_value": 200}],
224
+ },
225
+ {"name": "sair", "description": "Sai da sala de voz"},
226
+ {"name": "teste", "description": "Toca um tom de 3 segundos"},
227
+ ]
228
+
229
+
230
+ @client.event
231
+ async def on_message_create(msg: zynko.Message) -> None:
232
+ if msg.mine or msg.author.bot or not msg.guild_id or not msg.content.startswith(PREFIX):
233
+ return
234
+ name, _, arg = msg.content[len(PREFIX) :].strip().partition(" ")
235
+ command = COMMANDS.get(name.lower())
236
+ if not command:
237
+ return
238
+ member = msg.member
239
+
240
+ async def say(answer: str | dict[str, Any], quiet: bool = False) -> Any:
241
+ return await (msg.reply(answer) if isinstance(answer, str) else msg.reply(**answer))
242
+
243
+ await command(Ctx(msg.author.id, member.name if member else msg.author.display_name, msg.guild_id, msg.channel_id, say), arg.strip())
244
+
245
+
246
+ @client.event
247
+ async def on_interaction(i: zynko.Interaction) -> None:
248
+ # The buttons on the "Tocando agora" card: act, then refresh that card.
249
+ if i.type == "button":
250
+ p = client.voice.player if client.voice else None
251
+ if p and i.custom_id == "pausar":
252
+ p.resume() if p.paused else p.pause()
253
+ elif p and i.custom_id == "pular":
254
+ p.skip()
255
+ elif p and i.custom_id == "parar":
256
+ p.stop()
257
+ if i.custom_id != "pausar":
258
+ await asyncio.sleep(0.3) # a skip only shows the next song once it starts
259
+ await i.update(**now_playing())
260
+ return
261
+
262
+ async def say(answer: str | dict[str, Any], quiet: bool = False) -> Any:
263
+ if isinstance(answer, str):
264
+ return await i.reply(answer, ephemeral=quiet)
265
+ return await i.reply(**answer, ephemeral=quiet)
266
+
267
+ command = COMMANDS.get(i.command or "")
268
+ if not command:
269
+ await i.reply("Não conheço esse comando.", ephemeral=True)
270
+ return
271
+ who = i.member.name if i.member else i.user.display_name
272
+ value = i.option("link", i.option("porcentagem"))
273
+ arg = "" if value is None else str(value)
274
+ await command(Ctx(i.user.id, who, i.guild_id, i.channel_id, say), arg)
275
+
276
+
277
+ @client.event
278
+ async def on_ready(user: zynko.User) -> None:
279
+ await client.set_commands(SLASH)
280
+ print(f"{user.display_name} conectado em {len(client.guilds)} servidores, com {len(SLASH)} comandos")
281
+
282
+
283
+ @client.event
284
+ async def on_reconnecting(info: dict[str, Any]) -> None:
285
+ print(f"gateway caiu, reconectando em {info['wait']:.0f}s")
286
+
287
+
288
+ @client.event
289
+ async def on_error(error: Exception) -> None:
290
+ print("erro:", repr(error))
291
+
292
+
293
+ client.run(os.environ["ZYNKO_TOKEN"])
@@ -0,0 +1,29 @@
1
+ """The smallest bot: answers !ping with pong.
2
+
3
+ ZYNKO_TOKEN=bot_... python ping.py
4
+ """
5
+
6
+ import os
7
+
8
+ import zynko
9
+
10
+ client = zynko.Client(
11
+ intents=zynko.Intents.GUILDS | zynko.Intents.MESSAGES,
12
+ api=os.environ.get("ZYNKO_API"), # another server; https://zynko.org/api by default
13
+ )
14
+
15
+
16
+ @client.event
17
+ async def on_ready(user: zynko.User) -> None:
18
+ print(f"{user.display_name} conectado em {len(client.guilds)} servidores")
19
+
20
+
21
+ @client.event
22
+ async def on_message_create(msg: zynko.Message) -> None:
23
+ if msg.mine:
24
+ return
25
+ if msg.content == "!ping":
26
+ await msg.reply("pong")
27
+
28
+
29
+ client.run(os.environ["ZYNKO_TOKEN"])
@@ -0,0 +1,49 @@
1
+ [build-system]
2
+ requires = ["hatchling==1.29.0"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "zynko"
7
+ version = "0.1.0"
8
+ description = "Biblioteca oficial para bots do Zynko: API, gateway e voz."
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.10"
12
+ keywords = ["zynko", "bot", "chat", "voice", "asyncio"]
13
+ classifiers = [
14
+ "Development Status :: 4 - Beta",
15
+ "Framework :: AsyncIO",
16
+ "Intended Audience :: Developers",
17
+ "Programming Language :: Python :: 3",
18
+ "Programming Language :: Python :: 3.10",
19
+ "Programming Language :: Python :: 3.11",
20
+ "Programming Language :: Python :: 3.12",
21
+ "Programming Language :: Python :: 3.13",
22
+ "Programming Language :: Python :: 3.14",
23
+ "Typing :: Typed",
24
+ ]
25
+ dependencies = ["aiohttp>=3.11,<4"]
26
+
27
+ [project.optional-dependencies]
28
+ voice = ["livekit==1.2.1"]
29
+ dev = ["pytest>=8.3", "pytest-asyncio>=0.24", "mypy>=1.13"]
30
+
31
+ [project.urls]
32
+ Documentation = "https://docs.zynko.org/bots/python"
33
+ Homepage = "https://zynko.org"
34
+
35
+ [tool.hatch.build.targets.wheel]
36
+ packages = ["src/zynko"]
37
+
38
+ [tool.hatch.build.targets.sdist]
39
+ include = ["src/zynko", "README.md", "tests", "examples"]
40
+
41
+ [tool.pytest.ini_options]
42
+ testpaths = ["tests"]
43
+ asyncio_mode = "auto"
44
+ asyncio_default_fixture_loop_scope = "function"
45
+
46
+ [tool.mypy]
47
+ python_version = "3.10"
48
+ strict = true
49
+ ignore_missing_imports = true
@@ -0,0 +1,74 @@
1
+ """zynko: the official library for Zynko bots (docs.zynko.org/bots).
2
+
3
+ API and gateway on asyncio and aiohttp; voice through the ``livekit`` package, installed with
4
+ ``pip install "zynko[voice]"`` and loaded only when a bot joins a voice room.
5
+ """
6
+
7
+ from .bits import ALL_PERMISSIONS, Intents, Permissions, id_time
8
+ from .client import Client
9
+ from .gateway import GatewayClosed
10
+ from .interaction import Interaction
11
+ from .message import Message
12
+ from .models import (
13
+ Attachment,
14
+ Button,
15
+ ButtonStyle,
16
+ Card,
17
+ CardField,
18
+ Channel,
19
+ ChannelType,
20
+ Command,
21
+ CommandOption,
22
+ Components,
23
+ Emoji,
24
+ Guild,
25
+ Member,
26
+ Overwrite,
27
+ Role,
28
+ User,
29
+ VoiceState,
30
+ )
31
+ from .permissions import compute_permissions
32
+ from .player import PCM, AudioInput, AudioPlayer, Stream, Track, tone
33
+ from .rest import File, Rest, ZynkoError
34
+
35
+ __version__ = "0.1.0"
36
+
37
+ __all__ = [
38
+ "ALL_PERMISSIONS",
39
+ "Attachment",
40
+ "AudioInput",
41
+ "AudioPlayer",
42
+ "Button",
43
+ "ButtonStyle",
44
+ "Card",
45
+ "CardField",
46
+ "Channel",
47
+ "ChannelType",
48
+ "Client",
49
+ "Command",
50
+ "CommandOption",
51
+ "Components",
52
+ "Emoji",
53
+ "File",
54
+ "GatewayClosed",
55
+ "Guild",
56
+ "Intents",
57
+ "Interaction",
58
+ "Member",
59
+ "Message",
60
+ "Overwrite",
61
+ "PCM",
62
+ "Permissions",
63
+ "Rest",
64
+ "Role",
65
+ "Stream",
66
+ "Track",
67
+ "User",
68
+ "VoiceState",
69
+ "ZynkoError",
70
+ "compute_permissions",
71
+ "id_time",
72
+ "tone",
73
+ "__version__",
74
+ ]