Приложение не отвечает discord.py @bot.slash_command

Рейтинг: 0Ответов: 1Опубликовано: 30.01.2023

Если использовать команду с несуществующим профилем, бот реагирует правильно, отвечает на команду и никаких проблем нет. Но если ввести команду с настоящим профилем, бот отвечает "Приложение не отвечает", но отправляет нужный embed отдельным сообщением позже. Помогите пожалуйста Вот мой код:

from webserver import keep_alive
from discord.ext import commands
import os
import psutil
import random
import asyncio
import discord
from datetime import datetime
import time
import requests
from bs4 import BeautifulSoup

intents = discord.Intents.all()
bot = commands.Bot(command_prefix='+', intents=intents)


@bot.event
async def on_ready():
    print(f'{bot.user} подключен к Discord!')


@bot.slash_command(guild_ids=[432921053493198859, 248124585189310475], description = "отправляет иконку вашего профиля Overwatch 2")
async def icon(ctx, username: str):
    username1 = username.replace('#', '-')
    url = f"https://overwatch.blizzard.com/ru-ru/career/{username1}"
    try:
        response = requests.get(url)
    except (requests.exceptions.ConnectionError, requests.exceptions.Timeout) as error:
        await ctx.send(f"Произошла ошибка подключения: {error}")
        return
    soup = BeautifulSoup(response.text, 'html.parser')
    element = soup.select_one('.Profile-player--portrait')
    if element:
        link = element['src']
        embed = discord.Embed(title=f'Иконка профиля: {username}', color=0x00ff00)
        embed.set_image(url=link)
        await ctx.send(embed=embed)
    else:
        await ctx.respond(f"Профиль {username} не найден")


keep_alive()
bot.run(os.getenv("123"))

Ответы

▲ 1Принят

Поскольку дискорд обрабатывает команды интерактивно,

1

необходимо что-то делать с контекстом выполнения команды.


Например, вы отправляете ответ (await ctx.respond()):

@bot.slash_command(name='test_slash_command', description='Отвечает "Успешный тест!"')
async def __test(ctx):
    await ctx.respond('Успешный тест!')

Результат:

3


Если не сделать что-то с контекстом сразу, то дискорд не дождавшись ответа от бота, выдаст ошибку.

@bot.slash_command(name='test_slash_command', description='Имитирует 5-секундное вычисление и выводит "Команда выполнена!"')
async def __test(ctx):
    await asyncio.sleep(5)
    await ctx.respond('Команда выполнена!')

4

Выглядит так, будто при выполнении произошла ошибка, но на деле это просто дискорд не получил ответа от бота в течение первых секунд. Поэтому, если идут какие-то долгие вычисления, дискорд может просто не дождаться ответа и команда не выполнится. В таких случаях контекст стоит либо удалять (await ctx.delete()), либо использовать метод контекста defer().

Из описания следует, что он нужен как раз для таких ситуаций: "Откладывает ответ на взаимодействие. Обычно это используется, когда взаимодействие подтверждено, а дополнительное действие будет выполнено позже."

import asyncio
. . .

@bot.slash_command(name='test_slash_command', description='Имитирует 5-секундное вычисление и выводит "Команда выполнена!"')
async def __test(ctx):
    await ctx.defer()
    await asyncio.sleep(5)
    await ctx.respond('Команда выполнена!')

Результат:

5

Разумеется, использовать метод await ctx.defer() имеет смысл только если вы собираетесь что-то отвечать на команду. Если же никакого ответа не подразумевается, то лучше просто удалять контекст. Иначе бот просто бесконечно будет "думать" как на скрине выше.


Источник