Reputation: 1
I try to make this bot have a thread so that every 24 hours it executes the almanax coroutine without any command, but when I try to call it like this in another thread, I get an error (TypeError: almanax() missing 1 required positional argument: 'ctx') that it needs ctx and I have tried but I just get stuck. I'm new to this completely.
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)
Upvotes: 0
Views: 358
Reputation: 169
Commands require a Context object to be passed, so await mycommand()
isn't valid unless you pass a valid context. And a valid context is necessary, because in your almanax()
command, it is used in await ctx.send(embed = mesaje)
, so you can't just make up a new Context object and pass it in and expect it to work.
You could instance a new Context object that is just perfect to make the call valid, but that would be too workaround-ish, and there is a better way to do this. (If you wish to go that way, use the Bot.get_context()
method on a message that has a valid almanax command, and pass that as argument in await almanax()
. This would cause the daily message to be sent from the channel the message you picked was in.)
The entire part of the almanax command that goes from
source = requests.get(sourceLinkAlmanax).text
to
mensaje.set_image(url=linkImagen)
can be outsourced into another function that you can call in almanax()
, I'll call that function get_almanax()
(you should make that function async
as it relies on waiting for a response) but, you can name it whatever you want. This function returns the embed that is sent in almanax(). Then, you could change both dailyAlmanax()
and almanax()
to something like this:
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)
The get_almanax()
function should be defined as the lines I mentioned before, along with whatever input you need (doesn't look like any is necessary, but just in case), and it should return the desired embed.
Upvotes: 2