Discord Bot, Sending A Message Every 24 Hours - python

I would like to ask anyone who knows Python. I plan to make my discord bot send a certain message at a certain time. I was planning on making it remind me and other people for a certain occasion. On my end, I would like the bot to send that message every 24 hours. My code works when looping the message however, it only works when I use minutes or seconds. If I try to input days or hours, it won't work. I also tried to input the number of minutes/seconds for 24 hours and it wouldn't work as well. Below this text would be my code. Does anyone here know how to solve this, or at least find an alternate solution? I'm quite unsure of how to work with tasks and loops. I give you my thanks in advance.
#tasks.loop(hours=24)
async def e():
await client.get_channel(channel id here).send("#everyone It's A New Day!")
#e.before_loop
async def before_e():
await client.wait_until_ready()
e.start()

You can use Advanced Python Scheduler for doing it in a better way.
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from apscheduler.triggers.cron import CronTrigger
async def sendNewDayMessage():
await client.get_channel(channel_id).send("#everyone It's A New Day!")
sched = AsyncIOScheduler()
sched.start()
sched.add_job(sendNewDayMessage, CronTrigger(hour=0, minute=0, second=0)) #on 00:00

Related

Displaying Cooldown In Seconds in On_Message in Discord.py

EDIT:
I solved it, I just simply looped the asyncio.sleep and set a variable for the cooldown in seconds. :)
I'm new to discord.py and I just started developing a bot.
Most bots like Dank Memer has cooldowns after the on_message events happens. (I don't know if Dank Memer is in discord.py or not)
So I want to do the same, but I do not know how to display the cooldown in seconds. (Before you can enter another on_message event)
This is part of my code so far: (This is the cooldown)
import discord,asyncio #and some other modules
cooldown = []
async def on_message(message):
# Some Code
cooldown.append(message.author.id)
await asyncio.sleep(60)
cooldown.remove(message.author.id)
This code works, it doesn't show how many seconds you have before you can enter another command again.
My code is actually pretty long, so I don't want to rewrite it.
Is there a way to display how many seconds you have got left if the user enters the same command within the cooldown?
Ok, I solve it myself.
At the start you do:
cooldown = []
cooldownSec = 60 # How many seconds
cooldowntime = 0
Then, after the events from the on_message:
cooldown.append(message.author.id)
for i in range(cooldownSec,-1,-1):
if i == 0:
cooldown.remove(message.author.id)
break
cooldowntime = i
asyncio.sleep(1)
Put this line of code at the start of the on_message function:
global cooldowntime
Then, at the start of a message event happens:
if message.content.lower().startswith('!test'):
if message.author.id in cooldown:
await message.reply(f'You have to wait for {cooldowntime} more seconds before you can use the commands again!')
It should work.

Discord.py Bot send messages at certain times

I host a discord.py bot on a server for me and some friends, and have been trying to get a certain 'feature', where the bot will send a message every day, twice daily, once in the morning, once in the night, just saying general "good morning" and "good night!" I have spent hours looking through other peoples codes, and similar questions, and this is the best I can find/have gotten (It's taken from another user's 'python alarm', and I tried to hook it up to the bot.
from datetime import datetime
from threading import Timer
x = datetime.today()
y = x.replace(hour=21, minute=45, second=40, microsecond=0)
delta_t = y - x
secs = delta_t.seconds + 1
channel = client.get_channel(806702411808768023)
async def Goodnight():
await channel.send("Good night! Make sure to go to sleep early, and get enough sleep!")
print("Night Working")
t = Timer(secs, Goodnight)
t.start()
I keep getting the same error(s), usually about the message not being async or await-'able' (?). I am fairly new to coding/python, sorry if anything is obvious. I really do not know what to do, and I have found some promising solutions, though those make the whole bot the alarm, and force it to 'sleep' while waiting, while I want mine to still function normally (run other commands), if possible? Any help appreciated
This can be done using the tasks extension:
import datetime
import discord
from discord.ext import tasks
client = discord.Client()
goodNightTime = datetime.time(hour=21, minute=45, second=40) #Create the time on which the task should always run
#tasks.loop(time=goodNightTime) #Create the task
async def Goodnight():
channel = client.get_channel(806702411808768023)
await channel.send("Good night! Make sure to go to sleep early, and get enough sleep!")
print("Night Working")
#client.event
async def on_ready():
if not Goodnight.is_running():
Goodnight.start() #If the task is not already running, start it.
print("Good night task started")
client.run(TOKEN)
Note that for that to work you need to have the latest version of either discord.py or a fork which supports version 2.0. If you don't have it yet, you can install it via
pip install -U git+https://github.com/Rapptz/discord.py

Cooldowns in discord.py with on_message

So, I basically messed up. This is the first time I've ever tried a discord bot and I've done all my code in on_message with it checking the content of the message to see if it matches with the command name (example below). I've added a few commands, which are quite long, and I don't really want to rewrite it. Is there any way around this or do I have to rewrite it?
if message.content.lower().startswith("!test"):
await message.channel.send(db[str(message.author.id)])
Simple example of what I'm doing, just a test command.
I have tried looking inside other questions but I either: don't want to do that or don't understand what people are saying.
Any help would be appreciated and since I'm new to discord.py; I might need it explained in bit easier terms please.
You can do something like this:
import asyncio
users_on_cooldown = [] # Consider renaming this if you are going to have multiple commands with cooldowns.
def on_message(msg):
if msg.content.lower().startswith("!test") and not msg.author.id in users_on_cooldown:
await msg.channel.send(db[str(msg.author.id)])
users_on_cooldown.append(msg.author.id)
await asyncio.sleep(20) # time in seconds
users_on_cooldown.remove(msg.author.id)
Since you said you are a beginner, please note that if you make another command with a separate cooldown, use another variable that users_on_cooldown, maybe something like ban_cmd_cooldown and test_cmd_cooldown.
How It Works When the command is used, the user is added to a list, and after a certain amount of seconds, they are removed. When the command is run, it is checked if the user is on the list.
Note: When the bot is reset, cooldowns will be reset too.
If you have any questions about this, feel free to ask in the comments below.
Here how to use
#client.command()
#commands.cooldown(1, 60, commands.BucketType.user)
async def test(ctx):
await ctx.send(db[str(message.author.id)])
(1, 60, commands.BucketType.user) means 1 msg per 60sec or a 60sec cooldown.
I would recommend you rewrite your bot. It may take some time but it'll be worth it.

discord.py 8ball command but without bot prefix

I'm coding a bot for a friend and they have asked me to make an 8ball command. You think it seems easy.. but they don't want the prefix included the command. So it would be like this:
BotName, do you think today will be a good day?
I've tried using #client.event but I don't know how to make it so that the user can say their own question, but have the bots name at the front of the question.
So like this:
BotName, do you think today will be a good day?
The BotName part will need to be included to trigger the event. Then they can say what they want. Like this (example was already given above):
BotName, do you think today will be a good day?
Here is some code I tried:
import discord
from discord.ext import commands
import random
class eightball(commands.Cog):
def __init__(self, client):
self.client = client
#commands.Cog.listener()
async def on_message(self,message):
#botname = [f"BotName, {message}?"] #tried this too
# if message.content in botname: #tried this too
if f'BotName, {message.author.content}?' in message.content:
responses = ['Responses here.']
await message.channel.send(f'{random.choice(responses)}')
await self.client.process_commands(message)
def setup(client):
client.add_cog(eightball(client))
If it's not possible then do not worry! (Sorry if I didn't explain as well as I could and if I sound dumb or something.)
I guess you can make it work with a bit more logic.
if message.content.startswith('BotName,'):
#rest of the code
Consider that if they # your bot, the string would be <#1235574931>, do you think today will be a good day?
So, it'll only work if they add specifically whatever BotName would be.
Also, cog listeners doesn't need await self.client.process_commands(message)
You might use events for your bot. Try to do this.
#command.Cog.listener()
async def on_message(self, message, question):
if message.content.startswith("8ball"):
answers=["yes", "no", "maybe"]
await message.channel.send(random.choice(answers)
Don’t forget to import random like this:
import random

Running multiple commands with discord.py

Using discord.py and python:
Ok so basically I have this bot that updates the best prices for a certain game every minute. However, while I am doing that, other people cannot access the bot. For example, lets just say I have a command called "hello" that when called prints hello out in the chat. Since the code always runs, the user cant call the command hello because the code is too busy running the code that updates every minute. Is there any way to like make it so that the updateminute code runs while others can input commands as well?
import discord
import asyncio
import bazaar
from discord.ext import commands, tasks
client = commands.Bot(command_prefix = '.')
#client.command()
async def calculate(ctx):
while True:
await ctx.send(file2.calculate())
await asyncio.sleep(210)
#client.command()
async def hello(ctx):
await ctx.send("Hello")
client.run(token)
In file2.py:
def updateminute():
for product in product_list:
#Grab Api and stuff
#check to see whether it is profitable
time.sleep(0.3) #cause if i don't i will get a key error
#calculate the stuff
#return the result
To sum up, since the bot is too busy calculating updateminute and waiting, other people cannot access the bot. Is there any way I can try to fix this so that the bot calculates its stuff and so people can use the bots commands? Thanks!
You can look into threading! Basically, run two separate threads: one for taking requests and one for updating the prices.
You could also look into turning it into an async function, essentially making it easier to run things concurrently.
So your standard def will become async def and then to call the function you simply add an await before it so await file2.calculate()
Hope it helps and is also somewhat easier to understand

Categories