Discord Bot Python send a message every hour - python

I have a problem with discord's bot.
I have done a script which calculate the weather every hour and I want to send the result to discord with bot:
import Secret
import discord
result = "temp is ...."
TOKEN = Secret.BOT_TOKEN
client = discord.Client()
client.send(result)
client.run(TOKEN)
I have searched on google but I have not found an answer to send the result automatically.
Can you help me?

If you're using python just put it in a while loop and have it send the message and sleep for an hour.
for sleep you can import time
Something like:
while true:
client.send(result)
sleep(3600)
Important:
Your bot will be 100% inactive while you sleep it, so if you use it for more than just weather this might not be the solution you're looking for.

Using the time module prevents your bot from doing anything else during the time that it is sleeping.
Use tasks. Just put what you want executed in the task() function:
from discord.ext import tasks
#tasks.loop(seconds=60) # repeat once every 60 seconds
async def task():
pass
mytask.start()

Related

How to send a message using discord.py into a channel without input but on true condition

here is my code i'm trying to integrate with a script that runs 24/7
import discord
client = discord.Client(intents=discord.Intents.default())
#client.event
async def on_ready():
channel = client.get_channel(3534536365654654)
await channel.send("Bot is ready")
#client.event
async def background_task():
channel = client.get_channel(3534536365654654)
embed = discord.Embed(title="Testing")
embed.add_field(name="Req Amount", value="100")
embed.add_field(name="Return Amount", value="120")
await channel.send(embed=embed)
client.run(token)
basically every time my condition sets to true in the main code i want to run background_task()
in the main file but right now while running just this code only the on_ready() function is sending an output.
My bot is not supposed to take any inputs or commands just send the message each time the condition is true in code.
I've also tested all previous solutions and they have been rendered useless after the async update to discord.py
Any help would be appreciated
Use tasks and just have it run every few minutes (or hours/whatever) and check that the condition you want is True - if it is then send the message you want to send.
The #client.event syntax is usually reserved for actual client events - so background_task is never going to be executed.
Have a look in to discord.ext.tasks
Here's a simple example which executes every 5 seconds. With every loop you can check on a value and perform the actions accordingly.
from discord.ext import tasks, commands
#tasks.loop(seconds=5.0)
async def bg_task(self):
if value:
// Do something on True
else:
// Do something on False
Then start the task like this:
bg_task.start()

pycord bot quits slash command too quick

When my bot is very busy, it sometimes takes a few seconds to respond to the slash commands. However, before he can reply, Discord sends the message "The application did not respond". How can I make Discord wait longer for a message from the bot?
Have you tried using Interaction.defer()? Here's a quick example on how to use that:
#bot_instance.slash_command(name="hi")
async def hi(ctx):
await ctx.defer()
# fairly long task?
await ctx.followup.send( # Whatever you want to send...
For more information check out the API Reference: https://docs.pycord.dev/en/master/api.html#discord.Interaction
Also see a GitHub issue related to this question: https://github.com/Pycord-Development/pycord/issues/264
There is something called defer, you can do that to increase waiting time of the function
#bot_instance.command(description="Description of the command"
async def command(ctx:discord.Interaction,keyword:str)#Keyword if any
await ctx.response.defer(ephemeral=True)#This line defers the function
#Do your process here
await ctx.followup("Followup message")#This is the confirmation message

How to count the number of times a discord.py bot outputs a message to a text channel

import os
import discord
from datetime import datetime, time, timedelta
from discord.ext import commands, tasks
from datetime import datetime, time, timedelta
import asyncio
client = discord.Client()
msg = f"<#{some number}>", 'some number that increases every time the message is outputted' ,"days: still waiting for ____ to post -`д´-"
#client.event
async def on_ready():
msg1.start()
#tasks.loop(hours=24)
async def msg1():
channel = client.get_channel(some number)
await channel.send(msg)
my_secret = os.environ['TOKEN']
client.run(my_secret)
This code works fine and does what I want, but I want the output message to read "#person 13 days and counting: still waiting for (their name) to post -`д´-
the next day would be 14 etc. How do you implement this? I am currently pulling my hair out trying to code it, but I have no idea how to make a counting function or whatever without getting some kind of error like "name counter is not defined."
If you do not restart the bot inbetween, you can simply count up in the function itself.
number = 1
#tasks.loop(hours=24)
async def msg1():
global number
channel = client.get_channel(some number)
msg = f"<#{some number}>, {number} days: still waiting for ____ to post -`д´"
await channel.send(msg)
number += 1
If you restart the bot inbetween and want the bot to keep counting up you have to store your number somewhere like a .json file or a database.

Keep bot alive even a function is looping

Im developing a discord covid tracker bot and the information is scraped from a facebook page. I successfully scrape the info and store it to a list, however when I run the bot the bot will work at first but for every 5 minute the bot will be disconnect and not responding because def scrape will be refresh every 5min. So my question is how can I keep the bot to work even the scrape function is looping?
My code:
import discord
import random
import time
import asyncio
from facebook_scraper import get_posts
from discord.ext import commands, tasks
listposts = []
token = 'xxxx'
client = discord.Client()
listposts = []
#tasks.loop(minutes=5)
async def scrape():
wanted = "Pecahan setiap negeri (Kumulatif)" # wanted post
for post in get_posts("myhealthkkm", pages=5):
if post.get("text") is not None and wanted in post.get("text"):
# print("Found", t)
listposts.append(post.get("text"))
else:
pass
# print("Not found")
print(listposts)
#client.event
async def on_message(message):
if message.content.startswith("-malaysiacase"):
await message.channel.send(listposts)
#client.event
async def on_ready():
print("RUN")
scrape.start()
client.run(token)
Result:
After 5 minutes (the scrape function reload), the bot couldn't respond to user request anymore until the scraping process completed
facebook_scraper module is not asynchronous therefore blocking, which will make your bot freeze till it has completed and miss heartbeats which causes disconnect.
Do not use time module inside a discord bot either you have to use asyncio.sleep for the same reason.
Some alternatives you can do are: use BS4 in conjunction with AIOHTTP.
Or look at running your sync function in loop.run_in_executor.
There are some examples here: Python lib beautiful soup using aiohttp

trying to list the most "voted on" messages with a specific reaction emoji on them

Trying to do a thing where you enter a command and get a list of the top 5 messages with a reaction emoji called :goldmedal: . when entered into the bot, everything is fine, but when executing the command it starts a infinite loop of responses to every message it can find. and doesn't show the "goldmedal" value, but rather all the reactions on that specific message. https://cdn.discordapp.com/attachments/511938736594878478/512733361819746314/unknown.png
import discord
from discord import Game
from discord.ext.commands import Bot
from discord import Channel
from discord.utils import get
from discord.ext import commands
bot = Bot(command_prefix='!')
def num_reactions(message):
return sum(react_count for react in message.reactions)
#bot.command(pass_context=True)
async def most_reacted(ctx, channel: Channel):
most_reactions = most_reactions_message = None
goldmedal_emoji = get(ctx.message.server.emojis, name="goldmedal_emoji")
async for message in bot.logs_from(channel):
num_reactions_message = ([goldmedal_emoji])
num_reactions_message = num_reactions(message)
if not most_reactions or num_reactions_message > most_reactions:
most_reactions = num_reactions_message
most_reactions_message = message
await bot.say(f"{most_reactions_message.content} has the most Gold Medals with {most_reactions}")
Your function here:
def num_reactions(message):
return sum(react_count for react in message.reactions)
only fetches the number of different reactions to a message instead of the count of reactions with the goldmedal emoji. You would probably want something like this instead:
def num_reactions(message):
for react in message.reactions:
if react.emoji.name === "goldmedal_emoji":
return react.count
There are also many long term issues with your approach being:
It only obtains the last 100 messages from the log as the default limit of logs_from() is 100 (unless this is exactly what you want)
The bot has to search the channel every single time the command is ran which will be SLOW
May I suggest a different approach that stores the highest 5 in memory (hopefully not RAM but a database, or other persistent storages such as text files, in case your bot ever crashes), replacing them instead when a new message has a higher count of "goldmedal_emoji" reactions.

Categories

Resources