inconsistent timing in async discord bot - python-3.x

im trying to make a discord bot send a message every 30 miniutes, the only solution i could come up with gets very weird, it will start sending messages at seemingly random intervals and send multiple at once.
here is the affected code:
#client.event
async def on_ready():
await test()
async def test():
print("running test")
channel = client.get_channel(PLACEHOLDER)
await channel.send("i like " +words)
print(words)
await asyncio.sleep(1800)
await test()
i have tried replacing asyncio.sleep with time.sleep but that causes the bot to time out and run the test() function from both on_ready and itself causing it to send messages twice, i'll be it on a consistent basis. me and a couple friends have been messing with it for a while and can't fix it.

You can use discord.ext.task.loop:
from discord.ext import task
#client.event
async def on_ready():
print("Bot is ready")
await test.start()
#task.loop(minutes=30)
async def test():
print("30 minutes have passed")

Related

Discord.py V2 not recognizing command, mistaking for message event

Wanted to drop an odd issue i've been having.
It seems, despite having process_commands in my message event function, it is still processing any commands as simple messages. This is odd because the file was working before. What I end up with with this code and sending >helloworld is a print out of the message object from the message event function.
Here's my code, if anybody could tell me what they know that would be huge.
intents = discord.Intents.default()
bot = commands.Bot(command_prefix='>', intents=intents)
#bot.event
async def on_ready():
print(f'[*] bot connected.')
class Menu(discord.ui.View):
def __init__(self, args, *kwargs):
self.guild_id = kwargs.pop('guild_id')
super().__init__(timeout=None)
self.value = None
#discord.ui.button(label="Yes", custom_id="yes", style=discord.ButtonStyle.green)
async def button_yes(self, button: discord.ui.Button, interaction: discord.Interaction):
print(True)
#bot.event
async def on_message(message):
print(message)
do stuff here
await bot.process_commands(message)
#bot.command()
async def helloworld(ctx):
view = Menu()
await ctx.channel.send('test', view=view())

I want to change the discord bot status dynamically

This is the code im using
async def on_ready():
print(f'bots up')
await bot.change_presence(activity=discord.Activity(type=discord.ActivityType.listening, name='.help'))
like every minute the status changes ,
I tried but it doesnt allow me to use other commands , I put this code but it would give a error saying i cant put message argument in on_ready()
await bot.process_commands(message)
This is how I change the bots presence
async def status_task():
while True:
await bot.change_presence(activity=discord.Activity(type=discord.ActivityType.listening, name=f"listining status"))
await asyncio.sleep(10)# 10 as in 10seconds
await bot.change_presence(activity=discord.Game(name="playing status"))
await asyncio.sleep(10)
await bot.change_presence(activity=discord.Activity(type=discord.ActivityType.competing, name=f"competing status"))
await asyncio.sleep(10)
await bot.change_presence(activity=discord.Activity(type=discord.ActivityType.streaming, name=f"streaming status"))
await asyncio.sleep(10)
and then on_ready
#bot.event
async def on_ready():
print(f"bots up")
bot.loop.create_task(status_task())
hopefully this works for you,(for the status_task) change the 10 seconds in between each to lets say 60 , then every minute it will change
To periodically change your bot's presence, you can use a discord.ext.tasks.Loop. A basic blueprint could look something like this:
import discord
from discord.ext import commands
from discord.ext import tasks
bot = commands.Bot('.')
#tasks.loop(seconds=30)
async def switch_presence():
# list of all activities to switch between
activities = [
discord.Activity(type=discord.ActivityType.listening, name='First activity'),
discord.Activity(type=discord.ActivityType.listening, name='Another activity')
]
curr_activity = bot.activity
# default to the first activity if not set or invalid
if curr_activity not in activities:
await bot.change_presence(activity=activities[0])
return
# use modulo to start from the beginning once the list is exhausted
next_activity_index = (activities.index(curr_activity) + 1) % len(activities)
await bot.change_presence(activity=activities[next_activity_index])
#bot.event
async def on_ready():
switch_presence.start()
With some modifications, you can put this into a Cog as well. That would allow you to keep one static activity list instead of dynamically creating it (simply create it in the Cog's __init__ and store it as a class variable) and also store the index of the next activity centrally, eliminating the need to compute it every single time the loop is called

Discord.py Rewrite: Functions suddenly stopped working

I've been messing around with the discord bot python rewrite for the last few days. I've noticed that adding multiple functions tends to cause other functions to stop working. I added a looping task that sends a video from a random list of URLs and I initially thought that may be causing the other functions to stop working, but commenting that out still causes issues. It's pretty annoying when you have no error messages to go off of. Any help would be greatly appreciated!
import discord
from discord.ext import commands, tasks
import re
from random import randint
client = commands.Bot(command_prefix = "//")
#client.event
async def on_ready():
print("The bot is doing stuff.")
#client.event
async def on_message(message):
"""Deletes <specific> YT link"""
if <specific yt link> in message.content:
await message.delete()
print("video deleted")
#client.event
async def on_message(message):
"Sends a peeposalute whenever someone says 'goodnight'"
gn = re.compile('goodnight|good night|gn')
if gn.search(message.content.lower()):
await message.channel.send('<:peepoSalute:665687773407215637>')
print('peepo has saluted')
#client.event
async def on_message(message):
"""Checks the #new-uploads channel, reacts to any new messages and adds the video URL to the list"""
if message.channel.id == <channel id>:
with open('videos.txt', 'a') as f:
f.write(message.content + '\n')
print("New video added to list")
message.add_reaction('<:Wowee:592122719546638408>')
#tasks.loop(hours=24)
async def daily_video():
"""Sends a random video in #general daily"""
with open('videos.txt', 'r') as f:
videos = f.readlines()
target_general_id = <channel id>
general_id = client.get_channel(target_general_id)
await general_id.send(videos[randint(0, len(videos) - 1)])
print("Daily video sent")
#daily_video.before_loop
async def before():
await client.wait_until_ready()
print("Finished waiting")
daily_video.start()
client.run(<token>)

AttributeError: 'NoneType' object has no attribute 'send' Discord.py rewrite

I'm trying to send a message to a specific channel. I have still not been able to figure out how to do this. Help is greatly appreciated.
import keep_alive
import discord
client = discord.Client()
channel = client.get_channel('ID'`enter code here`)
#client.event
async def on_ready():
print('We have logged in as {0.user}'.format(client))
#client.event
async def on_message(message):
if message.author == client.user:
return
if message.content.startswith('$hello'):
await channel.send('hello')
keep_alive.keep_alive()
client.run('ID')
get_channel won't work where you have it because the bot hasn't connected to discord yet (that happens during run). When the bot connects, it will build internal caches of all the things it's aware of (members, guilds, channels, etc.). Those caches are what the various get methods use, but since the caches are empty those methods return None.
Instead, you can either get the channel in the on_message every time, or use a global variable in the on_ready:
#client.event
async def on_message(message):
if message.author == client.user:
return
if message.content.startswith('$hello'):
channel = client.get_channel(1234)
await channel.send('hello')

discord.py module how do i remove the command text afterwards?

from discord.ext.commands import Bot
import secrets
from time import sleep
discordBot = Bot(command_prefix = ".")
listStrings = ['add a reaction', 'adnd']
#discordBot.event
async def on_read():
print('Client logged in')
#discordBot.command()
async def s(*args):
return await discordBot.say (" ".join(args))
#discordBot.command()
async def close():
quit()
discordBot.run(secrets.token)
I wanted to say ".s (text)" and that the bot says the text(works already) but deletes your message, how can i do this? i got the part working of on_message:
#discordbot.event
async def on_message(message):
await discordBot.delete_message(message)
What is the best way to do this? Thanks in advance.
I'm sorry you haven't got an answer for 26 days. If you are still looking for an answer, I hope I can provide some help. So I ran your code, and the bot ran the command, my message deleted, then the bot's message also deleted. One way to fix this is to provide an if statement which means the bot only deletes the message if the author is not a bot.
#test_bot.event
async def on_message(message):
if not (message.author).bot:
await test_bot.delete_message(message)
await test_bot.process_commands(message)
Another way to remove only messages that are the commands is to use another if statement. The following code is specific, so you only delete commands, not just all user's messages if they aren't a bot. The following code uses message.content which returns the message as a string.
#test_bot.event
async def on_message(message):
if message.content.startswith('.s'):
await test_bot.delete_message(message)
await test_bot.process_commands(message)

Resources