I want to change the discord bot status dynamically - python-3.x

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

Related

How to allow only one person at a time to use discord bot

So I have this line of code:
async def on_message(message):
if message.content == "!test":
await asyncio.sleep(15)
await message.channel.send("Hello world"!)
If I want this line of code to run ONLY to one person at a time (that is, if someone else is using the bot other people will not be able to use the bot), how should I code this?
I'm using discord.Client() instead of discord.Bot(), and I intend to keep it that way.
If you want to make that only 1 person can use it at a time so you can add an if statement as I have added below:
occupied = False
#client.event
async def on_message(message):
global occupied
if not occupied:
occupied = True
elif occupied:
await ctx.send("Someone is using command pls wait")
return
if message.content == "!test":
await asyncio.sleep(15)
await message.channel.send("Hello world"!)
I have added the if statement so if someone runs command var occupied will be true and then if someone else tries to run the command it will show someone is using it.

inconsistent timing in async discord bot

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")

Discord.py running an async function on demand

I want to run the following async function at a certain time.
async def test(ctx):
channel = bot.get_channel(730099302130516058)
await channel.send('hello')
I am testing it with
asyncio.run(test(bot.get_context)). But when I run it I get 'NoneType' object has no attribute 'send' And I have tested this and it means channel is equal to none so it cant send the message as channel = "None".
Now when I do the following it works. But of course I have to run the command test
#bot.command()
async def test(ctx):
channel = bot.get_channel(730099302130516058)
await channel.send('hello')
I plan to use schedule to run it at the times I required but will still call the function in a similar way.
Is there a way to call an async function and pass ctx correctly?
Entire Code:
import discord
from discord.ext import commands
import asyncio
TOKEN = "Token Would Be Here"
bot = commands.Bot(command_prefix='+')
async def test(ctx):
channel = bot.get_channel(730099302130516058)
await channel.send('hello')
asyncio.run(test(bot.get_context))
bot.run(TOKEN)
bot.get_channel() is returning None because the bot has not yet connected, meaning it cannot see any channels. You need to add await bot.wait_until_ready(), which will force the bot to wait until it is connected before continuing.
You also don't need to pass ctx as you never use it.
discord.py also already has it's own event loop that you can use. You can add the coroutine to the loop using bot.loop.create_task().
from discord.ext import commands
TOKEN = "Token Would Be Here"
bot = commands.Bot(command_prefix='+')
async def test():
await bot.wait_until_ready()
channel = bot.get_channel(370935329353367568)
await channel.send('hello')
bot.loop.create_task(test())
bot.run(TOKEN)

Add a reaction to a ctx.send message in discord.py

I am making a poll command, the bot will send a ctx message and will say the poll question. I want to make it so when the poll message is sent, the bot adds two reaction, a thumbs up and a thumbs down. I have tried several different ways but non of them work. Here is the code from my latest try (everything is already imported)
reactions = ["👍", "👎"]
#bot.command(pass_context=True)
async def poll(self, ctx, message,*, question):
poll_msg = f"Poll: {question} -{ctx.author}"
reply = await self.bot.say(poll_msg)
for emoji_id in reactions:
emoji = get(ctx.server.emojis, name=emoji_id)
await message.add_reaction(reply, emoji or emoji_id)
The code is all over the place because I tried putting different solutions together to see if it would work but it doesn't work at all.
It looks like you're operating from some old examples. You should read the official documentation to find examples of the modern interfaces.
from discord.ext import commands
from discord.utils import get
bot = commands.Bot("!")
reactions = ["👍", "👎"]
#bot.command()
async def poll(ctx, *, question):
m = await ctx.send(f"Poll: {question} -{ctx.author}")
for name in reactions:
emoji = get(ctx.guild.emojis, name=name)
await m.add_reaction(emoji or name)

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