I'm currently trying to make a bot in Discord using python (something almost brand new for me). I was trying to make an AFK function (similar to Dyno's). This is my code:
afkdict = {}
#client.command(name = "afk", brief = "Away From Keyboard",
description = "I'll give you the afk status and if someone pings you before you come back, I'll tell "
"them that you are not available. You can add your own afk message!")
async def afk(ctx, message = "They didn't leave a message!"):
global afkdict
if ctx.message.author in afkdict:
afkdict.pop(ctx.message.author)
await ctx.send('Welcome back! You are no longer afk.')
else:
afkdict[ctx.message.author] = message
await ctx.send("You are now afk. Beware of the real world!")
#client.event
async def on_message(message):
global afkdict
for member in message.mentions:
if member != message.author:
if member in afkdict:
afkmsg = afkdict[member]
await message.channel.send(f"Oh noes! {member} is afk. {afkmsg}")
await client.process_commands(message)
My issue here is that the user that uses this function will be AFK until they write again >afk. My intention was to make the bot able to remove the AFK status whenever the user talked again in the server, regardless they used a bot function or not. I know it's possible because other bots do so, but I'm lost and can't think of a way to do so.
Thanks in advance!
async def on_message(message):
global afkdict
if message.author in afkdict:
afkdict.pop(message.author)
for member in message.mentions:
if member != message.author:
if member in afkdict:
afkmsg = afkdict[member]
await message.channel.send(f"Oh noes! {member} is afk. {afkmsg}")
await client.process_commands(message)
I think that should do it, but you could as well pass the ctx again or save ctx as an parameter to access.
But this version does not notify the user, that they are not afk anymore
Related
I need help making a afk command for my discord server. When the afk command is triggered, my bot doesn't respond with a reasoning when you ping the person whos afk. Also, when you return from being afk and type, the bot doesn't send a message saying "(user) is no longer afk". Please help me and tell me what i'm doing wrong and how can I fix this?
afkdict = {User: "their reason"} # somewhere in the code
#bot.command("afk")
async def afk(ctx, reason=None):
afkdict[ctx.user] = reason
await ctx.send("You are now afk. Beware of the real world!")
#bot.event
async def on_message(message):
afkdict = {user: "their reason"}
# some other checks here
for user, reason in afkdict.items():
if user in message.mentions:
if reason is None:
reason = ""
embed = discord.Embed(title=f"{user} is AFK", color=0xFF0000, description=reason[:2500])
await message.reply()
I was expecting this to work, the way dyno works. When i ran the command i got a message back saying user has no context. I dont know what to do anymore.
I think there's a couple of issues. Firstly, you are redefining afkdict in your on_message function it doesn't matter that you're adding users to it in the afk command. Secondly, when you're doing await message.reply(), you're not actually sending the created embed along with it.
I've resolved those problems and changed the logic slightly. Instead of iterating over the users in the afk_dict and checking if they're mentioned, we're iterating over the mentions and seeing if they're in the afk_dict. I'm also using user.id rather user objects as keys.
# defined somewhere
afk_dict = {}
#bot.command()
async def afk(ctx, reason=None):
afk_dict[ctx.user.id] = reason
await ctx.send("You are now afk. Beware of the real world!")
#bot.event
async def on_message(message):
# do whatever else you're doing here
for user in message.mentions:
if user.id not in afk_dict:
continue
# mentioned used is "afk"
reason = afk_dict[user.id] or ""
embed = discord.Embed(title=f"{user.mention} is AFK", color=0xFF0000, description=reason[:2500])
await message.reply(embed=embed)
It looks like you are missing some pieces in your code. Here is an updated version of the code:
afkdict = {}
#bot.command("afk")
async def afk(ctx, reason=None):
user = ctx.message.author
afkdict[user] = reason
await ctx.send(f"You are now AFK. {'Reason: ' + reason if reason else ''}")
#bot.event
async def on_message(message):
for user, reason in afkdict.items():
if user in message.mentions:
if reason is None:
reason = ""
embed = discord.Embed(title=f"{user} is AFK", color=0xFF0000, description=reason[:2500])
await message.channel.send(embed=embed)
if message.author in afkdict:
afkdict.pop(message.author)
await message.channel.send(f"{message.author} is no longer AFK")
In this code, the afk command will add the user who runs the command to the afkdict dictionary along with the reason for being AFK. The on_message event handler will then check if any of the mentioned users are in the afkdict and if so, it will send an embed with the AFK status and reason. Finally, if the author of the message is in the afkdict, it will remove them from the dictionary and send a message indicating that they are no longer AFK.
I need help making a afk command for my discord server. When the afk command is triggered, my bot doesn't respond with a reasoning when you ping the person whos afk. Also, when you return from being afk and type, the bot doesn't send a message saying "(user) is no longer afk". Please help me and tell me what im doing wrong and how can i fix this?
afkdict = {}
#bot.command(name = "afk", brief = "Away From Keyboard",
description = "I'll give you the afk status and if someone pings you before you come back, I'll tell "
"them that you are not available. You can add your own afk message!")
async def afk(ctx, message = "They didn't leave a message!"):
global afkdict
if ctx.message.author in afkdict:
afkdict.pop(ctx.message.author)
await ctx.send('Welcome back! You are no longer afk.')
else:
afkdict[ctx.message.author] = message
await ctx.send("You are now afk. Beware of the real world!")
I expected this to run a afk command like the one dyno bot has, but instead its a timer. Please help me code an afk command where if someones afk and gets pinged the bot tells them theyre afk with reasoning and when someone comes back from being afk the bot says welcome back
You can use the on_message event and check if the message mentions an afk user. While you can use a command to "set" a user AFK
afkdict = {} # somewhere in the code
#bot.event
async def on_message(self, message):
# some other checks here
for user, reason in afkdict.items():
if user in message.mentions:
if reason is None:
reason = ""
embed = discord.Embed(title=f"{user} is AFK", color=0xFF0000, description=reason[:2500])
await message.reply(embed=embed)
#bot.command("afk")
async def afk(self, ctx: commands.Context, reason=None):
afkdict[ctx.author] = reason
await ctx.send("You are now afk. Beware of the real world!")
Read more about the on_message event: https://discordpy.readthedocs.io/en/latest/api.html#discord.on_message
Reading the docs about the Message object might also help: https://discordpy.readthedocs.io/en/latest/api.html#discord.Message
I am triying to develop a game using a discord bot. Im having trouble dealing with the onmessage routine.. I need it only to "listen" one specific channel, not all the server.. by now I did the following:
#client.event
async def on_message(message):
global rojo
global IDS
canal = IDS['C_Juego']
if message.author == client.user or str(message.channel) != IDS['C_Juego']:
return
else:
if(rojo == 1):
autor = message.author
await message.add_reaction("🔴")
await message.channel.send("Player: " + str(autor) + " removed!")
role = get(message.guild.roles, name="Jugador")
await message.author.remove_roles(role)
elif(str(message.channel) == IDS['C_Juego']):
await message.add_reaction("🟢")
print("verde")
What's going on? when I enable this function .. the rest of my commands stop having effect (in any channel of the server) in addition to the fact that this function is called by each message sent....
I explain the context: It is a game in which while listening to a song the players must place different words under a theme, when the music stops, if someone writes they are eliminated.
Commands definitios:
I have plenty command definitios... which works fine until I add this problematic function.. I add as example two of them:
#client.command()
#commands.has_role("Owner")
async def clear(ctx):
await ctx.channel.purge()
#client.command()
#commands.has_role("Owner")
async def swipe(ctx, role: discord.Role):
print(role.members)
for member in role.members:
await member.remove_roles(role)
await ctx.send(f"Successfully removed all members from {role.mention}.")
Overriding the default provided on_message forbids any extra commands from running. To fix this, add a bot.process_commands(message) line at the end of your on_message.
#client.event
async def on_message(message):
# do what you want to do here
await client.process_commands(message)
https://discordpy.readthedocs.io/en/latest/faq.html#why-does-on-message-make-my-commands-stop-working
Ive seen a lot of questions about this and none of them worked for me, I don't understand why something that sounds this simple is that complicated, alredy spent more than 4 hours on this, I want to make a basic bot to make new users accept the rules:
Not much to explain, just a basic bot that when you say accept in a special channel it should add you a role.
import discord
from discord.utils import get
client = discord.Client()
TOKEN = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXX'
#client.event
async def on_ready():
#creates a message for users to react to
guild = client.guilds
channel = client.get_channel(836583535981608530)
Text= "Type accept below if you understand and `accept` ALL the rules in <#836600011484785843>, in order to gain access to the server:"
await channel.send(Text)
#client.event
async def on_message(message):
if message.author == client.user:
return
channel = message.channel
if channel.id == 836593532981608530 and message.content.lower() == ('accept'):
await message.delete()
user_role = discord.utils.get(message.guild.roles, name = "role name")
new_member = message.author
new_member.add_role(user_role, reason = "new member")
elif channel.id == 836593532981608530:
await message.delete()
The problem here in your command is that you have not awaited statement(s) that had to be awaited for library to work.
So, let's start.
The statement(s) that needs to be awaited:
new_member.add_role(user_role, reason = "new member")
How to fix this error?
You need to await it just like you have awaited other statements in your code.
Just change the line to:
await new_member.add_roles(user_role, reason="new member")
This would solve the problem you have facing.
Why do you need to await some statements?
Read the docs from the following link to see why some statements are needed to be awaited. This would help you to figure out what commands has to be awaited in future.
Hope it helps. If still you have any problem, feel free to ask me in the comments. :)
Thank You! :D
I made a working AFK code, but i need it to slice (delete) '[AFK]' if the user sends a message. The code is:
#client.command()
async def afk(ctx, *, message="Dind't specify a message."):
global afk_dict
if ctx.author in afk_dict:
afkdict.pop(ctx.author)
await ctx.send('Welcome back! You are no longer afk.')
await ctx.author.edit(nick=ctx.author.display_name(slice[-6]))
else:
afk_dict[ctx.author] = message
await ctx.author.edit(nick=f'[AFK] {ctx.author.display_name}')
await ctx.send(f"{ctx.author.mention}, You're now AFK.")
I got no errors. i only need await ctx.author.edit(nick=ctx.author.display_name(slice[-6])) to be working and i'll be happy.
You need to have a on_message event. Something like this should work.
#client.event
async def on_message(message):
if message.author in afk_dict.keys():
afk_dict.pop(message.author.id, None)
nick = message.author.display_name.split('[AFK]')[1].strip()
await message.author.edit(nick=nick)
I also recomend you to store user id's instead of usernames.
To do that you just have to use member.id instead of member.