Discord bot 无法使用线程,卡住错误:必需的位置参数:'ctx'

Posted

技术标签:

【中文标题】Discord bot 无法使用线程,卡住错误:必需的位置参数:\'ctx\'【英文标题】:Discord bot can't use threads, stuck error: required positional argument: 'ctx'Discord bot 无法使用线程,卡住错误:必需的位置参数:'ctx' 【发布时间】:2020-08-30 11:36:20 【问题描述】:

我试图让这个机器人有一个线程,以便它每 24 小时执行一次 almanax 协程而不使用任何命令,但是当我尝试在另一个线程中这样调用它时,我收到一个错误 (TypeError: almanax() missing 1 个必需的位置参数:'ctx')它需要 ctx,我已经尝试过,但我只是卡住了。我对此完全陌生。

import discord
from discord.ext import commands
import urllib.request
import re
import datetime
from bs4 import BeautifulSoup
import requests
import asyncio

bot = commands.Bot(command_prefix='-', description= "Este es un DuckBot")

sourceLinkAlmanax = 'http://www.krosmoz.com/es/almanax'
fechaexacta = '0:%d-%m-%Y'.format(datetime.datetime.now())

async def dailyAlmanax():
    while 1:
        await asyncio.sleep(5) #86400
        await almanax()

@bot.command()
async def almanax(ctx):
    print("Procesando almanax")

    source = requests.get(sourceLinkAlmanax).text

    soup = BeautifulSoup(source, 'lxml')

    mision = soup.find('div', class_='mid').p.text
    bonus = soup.find('div', class_='more').getText()
    ofrenda = soup.find('div', class_='more-infos-content').p.text
    bonus = bonus.replace(mision, "")
    bonus = bonus.replace(ofrenda, "")
    linkImagen = soup.find('div', "class": "more-infos").img['src']

    fechaexacta = '0:%d-%m-%Y'.format(datetime.datetime.now())

    mensaje = discord.Embed(title = "`Duckmanax del " + fechaexacta + "`", url=sourceLinkAlmanax, color=0xe5be01)
    mensaje.add_field(name="Mision: ", value=f"mision", inline=False)
    mensaje.add_field(name="Bonus: ", value=f"bonus.strip()", inline=False)
    mensaje.add_field(name="Ofrenda: ", value=f"ofrenda.strip()", inline=False)
    mensaje.set_image(url=linkImagen)
    await ctx.send(embed = mensaje)

    print("Almanax enviado")

@bot.command()
async def salmanax(ctx, busqueda: str):
    print("Procesando busqueda de almanax")
    fecha = datetime.datetime.now()
    año = fecha.year
    smes = fecha.month
    sdia = fecha.day

    for mes in range (smes,13):

        if mes > smes:
            sdia = 1

        for dia in range (sdia,32):

            print("Procesando Año:", año, "Mes:", mes, "Dia:", dia, "Buscando:", busqueda)

            if mes < 10:
                mes2 = "0" + str(mes)
            else:
                mes2 = mes
            if dia < 10:
                dia2 = "0" + str (dia)
            else:
                dia2 = dia

            link = "http://www.krosmoz.com/es/almanax/" + str(año) + "-" + str(mes2) + "-" + str(dia2)

            try:
                data = urllib.request.urlopen(link).read().decode('utf-8')
            except Exception as error:
                pass

            for linea in data.split("/n"):
                try:
                    if re.findall(busqueda, linea, re.IGNORECASE):
                        await ctx.send("Encontre esta coincidencia de " + busqueda + " " + link)
                except Exception as error2:
                    pass
    print("Busqueda de almanax finalizada")

@bot.event
async def on_message(ctx):
    if ctx.channel.name == 'almanax':
        await bot.process_commands(ctx)

@bot.event
async def on_ready():
    print("Bot listo")
    await bot.change_presence(activity=discord.Streaming(name="-almanax",url="https://www.twitch.tv/kerdrai"))

bot.loop.create_task(dailyAlmanax())
bot.run(token)

【问题讨论】:

您的 dailyAlmanax 函数在 almanax() 上等待。你调用这个函数时不带参数,但它需要一个,就像错误消息告诉你的那样。顺便说一句,您不是从另一个线程而是从另一个协程调用它。 【参考方案1】:

命令需要传递一个上下文对象,所以await mycommand() 是无效的,除非你传递一个有效的上下文。并且有效上下文是必要的,因为在你的almanax()命令中,它在await ctx.send(embed = mesaje)中使用,所以你不能只是组成一个新的上下文对象并将其传入并期望它工作。

可以实例化一个新的 Context 对象,该对象非常适合使调用有效,但这太变通了,有更好的方法来做到这一点。 (如果您希望这样做,请对具有 valid almanax 命令的消息使用 Bot.get_context() 方法,并将其作为参数传递给 await almanax()。这将导致每日消息从您选择的消息所在的频道发送。)

almanax 命令的整个部分

source = requests.get(sourceLinkAlmanax).text

mensaje.set_image(url=linkImagen)

可以外包给你可以在almanax()中调用的另一个函数,我将调用该函数get_almanax()(你应该将该函数设为async,因为它依赖于等待响应)但是,你可以命名随心所欲。此函数返回在 almanax() 中发送的嵌入。然后,您可以将dailyAlmanax()almanax() 都更改为如下内容:

async def dailyAlmanax():
    while 1:
        await asyncio.sleep(5) #86400
        mesaje = await get_almanax()
        channel = bot.get_channel(ID) #ID for the daily almanax channel
        await channel.send(embed = mesaje)
...

@bot.command()
async def almanax(ctx):
    print("Procesando almanax")

    mesaje = await get_almanax()
    await ctx.send(embed = mesaje)

get_almanax() 函数应该定义为我之前提到的行,以及您需要的任何输入(看起来没有任何必要,但以防万一),它应该返回所需的嵌入。

【讨论】:

以上是关于Discord bot 无法使用线程,卡住错误:必需的位置参数:'ctx'的主要内容,如果未能解决你的问题,请参考以下文章

Discord Bot 错误:无法向刚启动的协程发送非无值

Discord Bot 无法识别命令名称

即使没有错误,Discord Welcome Bot (Python) 也无法工作

Discord bot 无法访问 Google Sheets 获取错误请求缺少有效的 API 密钥

Discord bot 无法使用 Python 在 Heroku 上运行

Discord.py 从后台线程关闭 Bot