@kystikmei
Недо-программист на Python

Как исправить TypeError: Object of type Button is not JSON serializable?

Недавно переписал своего бота под работу с командами и кнопками через библиотеки discord_slash и discord_components соответственно. Но случилась беда: при попытке отправки Embed'а с кнопками выскакивает ошибка:

An exception has occurred while executing command `embed`:
Traceback (most recent call last):
  File "C:\Users\K0w0Mei\AppData\Local\Programs\Python\Python39\lib\site-packages\discord_slash\client.py", line 1353, in invoke_command
    await func.invoke(ctx, **args)
  File "C:\Users\K0w0Mei\AppData\Local\Programs\Python\Python39\lib\site-packages\discord_slash\model.py", line 210, in invoke
    return await self.func(*args, **kwargs)
  File "C:\Users\K0w0Mei\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\core.py", line 374, in __call__
    return await self.callback(*args, **kwargs)
  File "c:\Users\K0w0Mei\Documents\VAYO\VAYO.py", line 469, in embed
    await channel.send(
  File "C:\Users\K0w0Mei\AppData\Local\Programs\Python\Python39\lib\site-packages\discord_slash\dpy_overrides.py", line 323, in send_override
    return await send(channel, *args, **kwargs)
  File "C:\Users\K0w0Mei\AppData\Local\Programs\Python\Python39\lib\site-packages\discord_slash\dpy_overrides.py", line 300, in send
    data = await state.http.send_message(
  File "C:\Users\K0w0Mei\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\http.py", line 156, in request
    kwargs['data'] = utils.to_json(kwargs.pop('json'))
  File "C:\Users\K0w0Mei\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\utils.py", line 328, in to_json
    return json.dumps(obj, separators=(',', ':'), ensure_ascii=True)
  File "C:\Users\luchk\AppData\Local\Programs\Python\Python39\lib\json\__init__.py", line 234, in dumps
    return cls(
  File "C:\Users\K0w0Mei\AppData\Local\Programs\Python\Python39\lib\json\encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "C:\Users\K0w0Mei\AppData\Local\Programs\Python\Python39\lib\json\encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "C:\Users\K0w0Mei\AppData\Local\Programs\Python\Python39\lib\json\encoder.py", line 179, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type Button is not JSON serializable

Проблема в том, что раньше такой же код, но в другом боте, работал адекватно. С чем связана проблема?

Вот нужные строчки кода:

from asyncio.tasks import sleep
from logging import error
from typing import Counter
import discord
import asyncio
import sqlite3
import config as cfg
from discord_components import DiscordComponents, Button, ButtonStyle
from discord_slash import SlashCommand,SlashContext
from discord_slash.utils.manage_commands import create_option
from discord.ext import commands

intents = discord.Intents().all()
bot = commands.Bot(command_prefix='/', intents=intents)  # Префикс для команд
slash = SlashCommand(bot, sync_commands=True)

@bot.event
async def on_ready():
    DiscordComponents(bot)
    print('VAYO заработал под профилем {0.user}'.format(bot)) 
@slash.slash(
    name = "embed", 
    description = "Обновить кол-во полученных заказов.",
    options = []
)
@bot.command(aliase = ["embed"])
async def embed(ctx):
    channel = bot.get_channel(cfg.Config[0])
    await channel.send(
    embed = discord.Embed(title = "VAYO", description = """Тестовый текст""", colour=1752220, timestamp = ctx.created_at),
    components = [Button(custom_id = "Order", label = 'Оформить текст')])

Замечу, что при удалении кнопки, Embed отправляется спокойно.
  • Вопрос задан
  • 339 просмотров
Решения вопроса 1
По хорошему - посмотрите в последнюю версию discord.py. Там есть и поддержка slash команд, и поддержка "гибридных" команд, которая в будущем будет в релизной версии. Код основанный на slash_commands и прочих библиотеках, с вероятностью в 99% на dpy2.0 придётся переписывать. discord_components уже архивирован и обновлений в будущем не предполагается

В целом - библиотека, насколько я вижу, не подразумевает использование slash-команд в совокупи со стандартными командами (обработка slash-команд отличается от обработки обычных команд слишком сильно).

В Вашем случае это скорее всего всё же конфликт декораторов. Если вам нужна только slash-команда - уберите декоратор @bot.command(aliase = ["embed"]) (и да, аргумент все же называется aliases)

Если вам нужна и slash-команда и текстовая команда - выведите код команды в отдельную функцию и вызывайте её из двух методов под каждый вид

# discord_slash имеет свои методы создания компонентов. Они не обязательно совместимы с discord_components.
from discord_slash.utils.manage_components import create_button, create_actionrow

...


async def send_embed(ctx, button_type):
    channel = bot.get_channel(cfg.Config[0])
    if button_type == "slash":
        components = create_row(create_button(label="Оформить текст"))
    elif button_type == "message":
        components = [Button(custom_id="Order", label="Оформить текст")]
    else:
        raise Exception("Кто-то забыл указать тип кнопки")
    await channel.send(
        embed=discord.Embed(
            title="VAYO",
            description="""Тестовый текст""",
            colour=0x1ABC9C,
            timestamp=ctx.created_at,
        ),
        components=components,
    )


@slash.slash(
    name="embed", description="Обновить кол-во полученных заказов.", options=[]
)
async def slash_embed(ctx):
    return await send_embed(ctx, button_type="slash")


@bot.command(
    name="embed"
)  # aliases используется для *дополнительных* имён команд. для названия самой команды - используйте аргумент "name"
async def message_embed(ctx):
    """Обновить кол-во полученных заказов."""  # показывается в [p]help
    return await send_embed(ctx, button_type="message")
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы