A lightweight Discord bot library built on the raw Discord API.
Project description
suneord
suneord - библиотека для Discord-ботов на Python, которая работает через сырой Discord API без discord.py, disnake, nextcord и других готовых Discord-обёрток.
Возможности
- Прямой Discord Gateway + REST.
- Prefix-команды.
- Slash-команды.
cogs.Embed,Color.MessageContext,SlashContext,ModalContext.- Модальные окна.
- Отдельный
IntentsAPI. - Moderation-хелперы.
Установка
pip install suneord
Требования:
- Python
3.12+ aiohttp
Быстрый старт
from suneord import Bot
bot = Bot(
prefix="!",
status="dnd",
activity="слежу за сервером",
case_insensitive=True,
)
@bot.event
async def on_ready():
print(f"{bot.username} успешно запущен и работает")
@bot.command("p", "пинг", description="Показывает пинг")
async def ping(ctx):
await ctx.send("Понг!")
@bot.slash_command(name="ping", description="Показывает задержку бота")
async def ping_slash(ctx):
await ctx.respond(f"Понг! {ctx.latency} мс")
bot.run("TOKEN")
Bot
Создание:
from suneord import Bot
bot = Bot(
prefix="!",
status="online",
activity="работаю",
case_insensitive=True,
strip_after_prefix=True,
)
Параметры:
prefix- префикс для обычных команд.status- Discord-статус бота.activity- текст активности.case_insensitive- команды без учёта регистра.strip_after_prefix- убирать лишние пробелы после префикса.intents-Intentsилиint.
Свойства:
bot.userbot.usernamebot.avatar_urlbot.mentionbot.latencybot.latency_msbot.commandsbot.slash_commandsbot.modalsbot.intents
Методы:
bot.run(token)bot.start(token)bot.close()bot.wait_until_ready()bot.sync_commands()bot.fetch_user(user_id)bot.fetch_member(guild_id, user_id)bot.get_command(name)bot.has_command(name)bot.remove_command(name)bot.add_cog(cog)await bot.add_cog_async(cog)bot.get_cog(name)bot.remove_cog(name)await bot.remove_cog_async(name)bot.add_modal(modal)bot.get_modal(custom_id)bot.remove_modal(custom_id)
Intents
Теперь интенты вынесены в отдельный файл suneord/intents.py.
Использование:
from suneord import Bot, Intents
bot = Bot(
prefix="!",
status="dnd",
activity="слежу за сервером",
case_insensitive=True,
intents=Intents.default().add(Intents.GUILD_MEMBERS),
)
Если intents не передать, библиотека сама возьмёт Intents.default(). Поэтому такой код тоже корректен:
bot = Bot(
prefix="!",
status="dnd",
activity="слежу за сервером",
case_insensitive=True,
)
Полезные методы:
Intents.default()Intents.all()Intents.none()Intents.from_names(...)intents.add(...)intents.remove(...)intents.has(...)
События
@bot.event
async def on_ready():
print(bot.username)
Примеры:
@bot.event
async def on_message(ctx):
print(ctx.content)
@bot.event
async def on_command(ctx):
print(ctx.command.name)
@bot.event
async def on_command_error(ctx, error):
await ctx.send_error(str(error))
@bot.event
async def on_slash_command_error(ctx, error):
await ctx.send_error(str(error))
@bot.event
async def on_modal_error(ctx, error):
await ctx.send_error(str(error))
Дополнительные lifecycle-события:
on_command_completionon_slash_command_completionon_modal_submiton_modal_completion
Prefix-команды
@bot.command(description="Пинг")
async def ping(ctx):
await ctx.send("Понг!")
С алиасами:
@bot.command("p", "пинг", description="Пинг")
async def ping(ctx):
await ctx.send("Понг!")
Или:
@bot.command(aliases=("p", "пинг"))
async def ping(ctx):
await ctx.send("Понг!")
Поддерживаемые параметры:
namedescriptionaliasesusagecooldowncheckshiddenenabled
Аргументы prefix-команд парсятся через shlex, поэтому строки в кавычках работают нормально:
!say "привет мир"
Slash-команды
from suneord import OptionType, SlashOption
@bot.slash_command(
name="avatar",
description="Показывает аватар",
options=[
SlashOption(
name="user",
description="Пользователь",
type=OptionType.USER,
required=True,
)
],
)
async def avatar(ctx):
user = ctx.option("user")
await ctx.respond(f"ID: {user['id']}")
Типы OptionType:
STRINGINTEGERBOOLEANUSERCHANNELROLEMENTIONABLENUMBERATTACHMENT
Context API
MessageContext
Свойства:
ctx.botctx.messagectx.guild_idctx.channel_idctx.message_idctx.authorctx.author_idctx.author_namectx.author_mentionctx.contentctx.argsctx.args_textctx.commandctx.invoked_withctx.latencyctx.jump_urlctx.channel_mention
Методы:
ctx.send(...)ctx.reply(...)ctx.typing()ctx.react("🔥")ctx.pin()ctx.unpin()ctx.edit(...)ctx.delete()ctx.send_success(...)ctx.send_error(...)
SlashContext
Свойства:
ctx.botctx.interactionctx.guild_idctx.channel_idctx.userctx.authorctx.author_idctx.author_namectx.author_mentionctx.commandctx.command_namectx.optionsctx.latencyctx.channel_mentionctx.respondedctx.deferred
Методы:
ctx.option("name")ctx.respond(...)ctx.send(...)ctx.defer(...)ctx.followup(...)ctx.edit_original_response(...)ctx.delete_original_response()ctx.send_success(...)ctx.send_error(...)ctx.show_modal(modal)
ModalContext
Свойства:
ctx.botctx.interactionctx.custom_idctx.optionsctx.userctx.authorctx.author_idctx.respondedctx.deferred
Методы:
ctx.value("field_id")ctx.respond(...)ctx.send(...)ctx.defer(...)ctx.followup(...)ctx.edit_original_response(...)ctx.delete_original_response()ctx.send_success(...)ctx.send_error(...)
Embed
from suneord import Color, Embed
embed = Embed(
title="Заголовок",
description="Описание",
color=Color.BLURPLE,
)
embed.set_author(name="Suneord")
embed.add_field(name="Поле", value="Значение", inline=False)
embed.set_thumbnail(url="https://example.com/avatar.png")
embed.set_image(url="https://example.com/banner.png")
embed.set_footer(text="Footer")
embed.set_timestamp()
Модальные окна
Библиотека поддерживает Discord modals.
Пример:
from suneord import Bot, Modal, TextInput, TextInputStyle
bot = Bot(prefix="!")
@bot.modal(
custom_id="feedback_modal",
title="Обратная связь",
components=[
TextInput(
custom_id="feedback_text",
label="Твой отзыв",
style=TextInputStyle.PARAGRAPH,
min_length=5,
max_length=400,
)
],
)
async def feedback_submit(ctx):
text = ctx.value("feedback_text")
await ctx.send_success(f"Спасибо за отзыв:\n{text}")
@bot.slash_command(name="feedback", description="Открыть форму отзыва")
async def feedback(ctx):
modal = Modal(
custom_id="feedback_modal",
title="Обратная связь",
components=(
TextInput(
custom_id="feedback_text",
label="Твой отзыв",
style=TextInputStyle.PARAGRAPH,
),
),
)
await ctx.show_modal(modal)
Для cogs доступен отдельный декоратор:
from suneord import Cog, modal, TextInput
class FeedbackCog(Cog):
@modal(
custom_id="report_modal",
title="Жалоба",
components=[TextInput(custom_id="reason", label="Причина")],
)
async def report_submit(self, ctx):
await ctx.respond(ctx.value("reason"), ephemeral=True)
Moderation API
В библиотеке есть готовые методы:
await bot.kick(guild_id, user_id, reason="Причина")
await bot.ban(guild_id, user_id, reason="Причина", delete_message_seconds=86400)
await bot.unban(guild_id, user_id, reason="Причина")
await bot.mute(guild_id, user_id, minutes=10, reason="Причина")
await bot.unmute(guild_id, user_id, reason="Причина")
await bot.set_nickname(guild_id, user_id, "Новый ник", reason="Причина")
await bot.set_slowmode(channel_id, 10)
deleted = await bot.purge_messages(channel_id, limit=25)
Проверка unmute:
bot.unmute(...)теперь сначала проверяет, есть ли у пользователя активный timeout.- Если тайм-аута нет, выбрасывается
MemberNotMuted.
Пример обработки:
from suneord import MemberNotMuted
@bot.event
async def on_slash_command_error(ctx, error):
if isinstance(error, MemberNotMuted):
await ctx.send_error("У этого пользователя нет активного мута.")
return
await ctx.send_error(str(error))
Checks и hooks
@bot.check
async def only_guild(ctx):
return ctx.guild_id is not None
@bot.before_invoke
async def before_any_command(ctx):
print("before", ctx.command.name)
@bot.after_invoke
async def after_any_command(ctx):
print("after", ctx.command.name)
Cogs
from suneord import Bot, Cog, command, slash_command
bot = Bot(prefix="!")
class Utility(Cog):
@Cog.listener()
async def on_ready(self):
print(f"{self.bot.username} готов")
@command("p", "пинг", description="Пинг")
async def ping(self, ctx):
await ctx.send("Понг!")
@slash_command(name="hello", description="Приветствие")
async def hello(self, ctx):
await ctx.respond("Привет из cog!")
bot.add_cog(Utility(bot))
bot.run("TOKEN")
Для cog lifecycle доступны:
cog_loadcog_unload
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file suneord-1.0.2.tar.gz.
File metadata
- Download URL: suneord-1.0.2.tar.gz
- Upload date:
- Size: 22.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3c03bc8ee30efae1994ad35115e051d470e46a1f5cd81dedd30546b6be2d7fcf
|
|
| MD5 |
9dd3f202372bbd46aaca9c5d663bd05c
|
|
| BLAKE2b-256 |
f67358575324131d13a85243305e979866ebacfde4c8c7d889a559d6232c1d1d
|
File details
Details for the file suneord-1.0.2-py3-none-any.whl.
File metadata
- Download URL: suneord-1.0.2-py3-none-any.whl
- Upload date:
- Size: 21.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bb0a61efdcdaf6dd0e2f4315d71368a0a4e065540cf149832661988f27324423
|
|
| MD5 |
b54340bc56e5650ffa9d27dc215a432a
|
|
| BLAKE2b-256 |
d27abd8dd4ecd00ce95ea6d312f78e71a3828e5ca51a51177b0e0cf2f03590af
|