How can I check when a mentioned user reacts? - discord.py

So I'm trying to check when a certain user reacts, but I'm not sure how.
#bot.command()
#commands.has_any_role("Franchise Owner", "General Manager", "Head Coach")
async def offer(ctx, member:discord.Member):
embed = discord.Embed(
)
embed.add_field(name="⌛ Incoming Offer", value=f"The <:DallasCowboys:788796627161710592> have offered {member}.")
offer_sent = await ctx.send(embed=embed)
await offer_sent.add_reaction("<a:CheckMark:768095274949935146>")
await offer_sent.add_reaction("<a:XMark:768095331555606528>")
await member.send("You have been offered to the <:DallasCowboys:788796627161710592>. You have 30 minutes to accept/decline.")
await asyncio.sleep(30)
await offer_sent.delete()

unrelated to to topic of this post, but when using asyncio.sleep it is in seconds not minutes meaning that the offer would only last 30 seconds.
You should change it to await asyncio.sleep(1800).
1800 seconds is 30 minutes

For this, you can add a #client.event decorator outside the offer command. Just like:
#bot.command()
#commands.has_any_role("Franchise Owner", "General Manager", "Head Coach")
async def offer(ctx, member:discord.Member):
embed = discord.Embed()
embed.add_field(name="⌛ Incoming Offer", value=f"The
<:DallasCowboys:788796627161710592> have offered {member}.")
offer_sent = await ctx.send(embed=embed)
await offer_sent.add_reaction("<a:CheckMark:768095274949935146>")
await offer_sent.add_reaction("<a:XMark:768095331555606528>")
await member.send("You have been offered to the <:DallasCowboys:788796627161710592>.
You have 30 minutes to accept/decline.")
await asyncio.sleep(1800) # Replace "30" with 1800, because 1800 in seconds is 30 min.
await offer_sent.delete()
# Reaction detector:
#client.event
async def on_reaction_add(reaction, user):
reaction1 = "<a:CheckMark:768095274949935146>"
reaction2 = "<a:XMark:768095331555606528>"
if reaction.emoji in [reaction1, reaction2]:
# Do anything after the user reacted
await reaction.message.channel.id.send(f'{user} reacted with {reaction}!')

Related

Discord bot disconnects before finishing music

I'm using DiscordUtils for this exact bot. The music plays somewhere around halfway (every song) and stops with the bot displaying information that there is no song playing. Here is my code (no errors show up).
I cannot seem to find any information regarding this that contains information regarding DiscordUtils. I only get results for YouTube-DL and sadly it works differently. Is there any exact solution to this problem, is this an FFMPEG error?
import discord
from discord.ext import commands
from discord.ext.commands import has_permissions
from discord import Client, Intents, Embed
from discord.ext.commands.core import command
from discord_slash import SlashCommand, SlashContext
from discord_slash.utils.manage_commands import create_choice, create_option
import DiscordUtils
import ffmpeg
music = DiscordUtils.Music()
activity = discord.Game(name="around. Use /help")
client = commands.Bot(command_prefix='?', activity=activity)
slash = SlashCommand(client, sync_commands=True)
#client.command()
async def join(ctx):
voicetrue = ctx.author.voice
if voicetrue is None:
return await ctx.send('You are not currently in a voice channel. :exclamation:')
await ctx.author.voice.channel.connect()
await ctx.send('Joined the voice chat you are in. :white_check_mark:')
#client.command()
async def leave(ctx):
voicetrue = ctx.author.voice
mevoicetrue = ctx.guild.me.voice
if voicetrue is None:
return await ctx.send('You are not currently in the same voice channel as I am.')
if mevoicetrue is None:
return await ctx.send('Im not currently in any voice channel!')
await ctx.voice_client.disconnect()
await ctx.send('I have disconnected from the voice channel.')
#client.command()
async def play(ctx, *, url):
player = music.get_player(guild_id=ctx.guild.id)
if not player:
player = music.create_player(ctx, ffmpeg_error_bettercix=True)
if not ctx.voice_client.is_playing():
await player.queue(url, search=True)
song = await player.play()
await ctx.send(f'Playing **{song.name}** :notes:')
else:
song = await player.queue(url, search=True)
await ctx.send(f'Ive added **{song.name}** to the queue!')
#client.command()
async def queue(ctx):
player = music.get_player(guild_id=ctx.guild.id)
await ctx.send(f"The music queue currently is: **{', '.join([song.name for song in player.current_queue()])}**")
#client.command()
async def pause(ctx):
player = music.get_player(guild_id=ctx.guild.id)
song = await player.pause()
await ctx.send(f'Paused **{song.name}** :pause_button:')
#client.command()
async def resume(ctx):
player = music.get_player(guild_id=ctx.guild.id)
song = await player.resume()
await ctx.send(f'Resumed **{song.name}** :arrow_forward:')
#client.command()
async def loop(ctx):
player = music.get_player(guild_id=ctx.guild.id)
song = await player.toggle_song_loop()
if song.is_looping:
return await ctx.send(f'{song.name} will now start looping. :repeat:')
else:
return await ctx.send(f'{song.name} will no longer loop. :no_entry:')
#client.command()
async def nowplaying(ctx):
player = music.get_player(guild_id=ctx.guild.id)
song = player.now_playing()
if song.name is None:
await ctx.send(song.name + ' is currently playing.')
#client.command()
async def remove(ctx, index):
player = music.get_player(guild_id=ctx.guild.id)
song = await player.remove_from_queue
await ctx.send(f'Removed {song.name} from the song queue!')
#slash.slash(
name="hello",
description="Hello there!",
guild_ids=[822512275331219517, 708384142978711582, 747869167889285180]
)
async def _hello(ctx:SlashContext):
await ctx.send("Hi! test command")
#slash.slash(
name="help",
description="Recieve help using Anix",
guild_ids=[822512275331219517, 708384142978711582, 747869167889285180]
)
async def _help(ctx:SlashContext):
embed=discord.Embed(title="Commands to get you going", description="", color=0xff131a)
embed.set_author(name="Anix Help")
embed.add_field(name="?play", value="use this command whilst in a voice channel to start music", inline=False)
embed.add_field(name="?join", value="make Anix join your voice channel", inline=False)
embed.add_field(name="?leave", value="make Anix leave your voice channel", inline=False)
embed.add_field(name="?queue", value="check the music queue", inline=False)
embed.add_field(name="?pause", value="pauses the current song that's playing", inline=False)
embed.add_field(name="?resume", value="resumes a paused song", inline=False)
embed.add_field(name="?loop", value="loops the current song (type again to stop loop)", inline=False)
embed.add_field(name="?nowplaying", value="check the song that's currently playing", inline=True)
embed.add_field(name="?remove", value="removes the currently playing song from the queue", inline=True)
await ctx.send(embeds=[embed])
client.run('token')
By removing import ffmpeg the disconnecting problem no longer occurs. All of the commands work with no problems whatsoever.

I want to improve my kick command in discord.py

I have made a bot in discord.py which has a kick command. But I want the bot to say "please tell me whom to kick" when someone uses the command without saying whom to kick. I mean if someone uses the kick command without mentioning whom to kick, the bot will say "please tell me whom to kick".
I am trying to make a good bot so please help me.
async def kick(ctx, member : discord.Member, *, reason=None):
if (ctx.message.author.permissions_in(ctx.message.channel).kick_members):
await member.kick(reason=reason)
await ctx.send(f"{member.mention} has successfully been kickded for {reason}")
if not (ctx.message.author.permissions_in(ctx.message.channel).kick_members):
await ctx.send("You don't perms to play football with Araforce and kick them. Sed")
if not user:
await ctx.message.delete()
msg = await ctx.send("You are a bit idiot, don't you know I can't kick anyone if you don't tell whom to kick? Tell me whom to kick and the go away.")
await sleep(4.7)
await msg.delete()
return
if not reason:
await ctx.message.delete()
msg2 = await ctx.send("Hmm.. Why I will kick him? Specify a reason please.")
await sleep(4.7)
await msg2.delete()
return```
async def kick(ctx, user: discord.User = None, *, reason=None):
if not user:
await ctx.message.delete()
msg = await ctx.send("You must specify a user.")
await sleep(4.7)
await msg.delete()
return
if not reason:
await ctx.message.delete()
msg2 = await ctx.send("You must specify a reason.")
await sleep(4.7)
await msg2.delete()
return
I changed ifs to the error handler, which is necessary because if you won't pass one of the arguments (user or reason) you would get an error.
Full code:
#client.command()
async def kick(ctx, member: discord.Member, *, reason): #if you will change "member" and "reason" to something else remember to also change it in error handler
await member.kick(reason=reason)
await ctx.send(f"{member.mention} has successfully been kicked for {reason}")
#kick.error #cool mini error handler
async def kick_error(ctx, error):
if isinstance(error, discord.ext.commands.errors.MissingRequiredArgument):
if str(error) == "member is a required argument that is missing.": #change this if you changed "member"
await ctx.message.delete()
await ctx.send("You are a bit idiot, don't you know I can't kick anyone if you don't tell whom to kick? Tell me whom to kick and then go away.", delete_after=4.7) #you don't have to use "await sleep" you can use "delete_after" parameter
elif str(error) == "reason is a required argument that is missing.": #change this if you changed "reason"
await ctx.message.delete()
await ctx.send("Hmm.. Why I will kick him? Specify a reason please.", delete_after=4.7)
elif isinstance(error, discord.ext.commands.errors.MissingPermissions):
await ctx.send("You don't have perms to play football with Araforce and kick them. Sed")
Discord error handling example

How to make multiple reaction roles

So I'm working on a reaction role cog, and the commands work so far. There's just one problem. When I create two different reaction roles, it only works for the second one. It's because I only have one dictionary and it updates that every time. I think I've seen people use a payload for reaction roles, but I have no idea what that does and if it would fix my problem. Is there a way to use payload to fix my problem? Thanks!! Here's my code:
import discord
from discord.ext import commands
from discord.ext.commands import BucketType, cooldown, CommandOnCooldown
import random
import json
reaction_title = ""
reactions = {}
reaction_message_id = ""
class ReactionRoles(commands.Cog):
"""Reaction roles!!\nYou need manage roles permissions to use these"""
def __init__(self, bot):
self.bot = bot
# Bot Commands
#commands.command(aliases=['rcp'])
async def reaction_create_post(self, ctx):
"""Creates an embed that shows all the reaction roles commands"""
embed = discord.Embed(title="Create Reaction Post", color=discord.Colour.dark_purple())
embed.set_author(name="Botpuns")
embed.add_field(name="Set Title", value=".rst [New Title]", inline=False)
embed.add_field(name="Add Role", value=".rar [#Role] [EMOJI]", inline=False)
embed.add_field(name="Remove Role", value=".rrr [#Role]", inline=False)
embed.add_field(name="Reaction Send Post", value=".rsp", inline=False)
await ctx.send(embed=embed)
await ctx.message.delete()
#commands.command(aliases=['rst'])
async def reaction_set_title(self, ctx, *, new_title):
global reaction_title
reaction_title = new_title
await ctx.send(f"The title for the message is now `{new_title}`")
await ctx.message.delete()
#commands.command(aliases=['rar'])
async def reaction_add_role(self, ctx, role: discord.Role, reaction):
global reactions
reactions[role.name] = reaction
await ctx.send(f"Role `{role.name}` has been added with the emoji {reaction}")
await ctx.message.delete()
print(reactions)
#commands.command(aliases=['rrr'])
async def reaction_remove_role(self, ctx, role: discord.Role):
if role.name in reactions:
del reactions[role.name]
await ctx.send(f"Role `{role.name}` has been deleted")
await ctx.message.delete()
else:
await ctx.send("That role wasn't even added smh")
print(reactions)
#commands.command(aliases=['rsp'])
async def reaction_send_post(self, ctx):
description = "React to add roles\n"
for role in reactions:
description += f"`{role}` - {reactions[role]}\n"
embed = discord.Embed(title=reaction_title, description=description, color=discord.Colour.purple())
embed.set_author(name="Botpuns")
message = await ctx.send(embed=embed)
global reaction_message_id
reaction_message_id = str(message.id)
for role in reactions:
await message.add_reaction(reactions[role])
await ctx.message.delete()
#commands.Cog.listener()
async def on_reaction_add(self, reaction, user):
if not user.bot:
message = reaction.message
if str(message.id) == reaction_message_id:
# Add roles to user
role_to_give = ""
for role in reactions:
if reactions[role] == reaction.emoji:
role_to_give = role
role_for_reaction = discord.utils.get(user.guild.roles, name=role_to_give)
await user.add_roles(role_for_reaction)
#commands.Cog.listener()
async def on_reaction_remove(self, reaction, user):
if not user.bot:
message = reaction.message
if str(message.id) == reaction_message_id:
# Add roles to user
role_to_remove = ""
for role in reactions:
if reactions[role] == reaction.emoji:
role_to_remove = role
role_for_reaction = discord.utils.get(user.guild.roles, name=role_to_remove)
await user.remove_roles(role_for_reaction)
def setup(bot):
bot.add_cog(ReactionRoles(bot))

How to make lockdown and unlock commands discord.py

Im trying to make a lockdown and unlock command using discord.py rewrite. I have the code but it doesn't work at all. Can someone help me?
#client.command()
#commands.has_permissions(manage_channels = True)
async def lockdown(ctx):
await ctx.channel.set_permissions(ctx.guild.default_role, send_messages=False)
await ctx.send( ctx.channel.mention + " ***is now in lockdown.***")
#client.command()
#commands.has_permissions(manage_channels=True)
async def unlock(ctx):
await ctx.channel.set_permissions(ctx.guild.default_role, send_messages=True)
await ctx.send(ctx.channel.mention + " ***has been unlocked.***")
I found out the issue. The commands work on every other server except for the one I'm testing it on. It turns out that That server makes everyone admin as soon as they join.
Try this, to enable the necessary bot permissions:
#client.command()
#has_permissions(manage_channels=True)
async def lockdown(ctx):
await ctx.channel.set_permissions(ctx.guild.default_role,send_messages=False)
await ctx.send( ctx.channel.mention + " ***is now in lockdown.***")
#client.command()
#has_permissions(manage_channels=True)
async def unlock(ctx):
await ctx.channel.set_permissions(ctx.guild.default_role, send_messages=True)
await ctx.send(ctx.channel.mention + " ***has been unlocked.***")
this is my unlock command hope it helps you
you have to use overwrites TextChannel.set_permissions
#client.command()
async def unlock(ctx, role:Optional[Role], channel:Optional[TextChannel]):
role = role or ctx.guild.default_role
channel = channel or ctx.channel
async with ctx.typing():
if ctx.author.permissions_in(channel).manage_permissions:
await ctx.channel.purge(limit=1)
overwrite = channel.overwrites_for(role)
overwrite.send_messages = True
await channel.set_permissions(role, overwrite=overwrite)
unlock_embed = discord.Embed(
title= ("UNLOCKED"),
description= (f"**{channel.mention}** HAS BEEN UNLOCKED FOR **{role}**"),
colour=0x00FFF5,
)
unlock_embed.set_footer(text=ctx.author.name, icon_url=ctx.author.avatar_url)
unlock_embed.set_author(name=client.user.name, icon_url=client.user.avatar_url)
unlock_embed.set_thumbnail(url=ctx.guild.icon_url)
await ctx.channel.send(embed=unlock_embed, delete_after=10)
print("unlock")
else:
error3_embed=discord.Embed(title="ERROR", description="YOU DONT HAVE PERMISSION", colour=0xff0000)
error3_embed.set_thumbnail(url='https://images.emojiterra.com/google/android-11/512px/274c.png')
error3_embed.set_footer(text=ctx.author.name, icon_url=ctx.author.avatar_url)
error3_embed.set_author(name=client.user.name, icon_url=client.user.avatar_url)
await ctx.channel.send(embed=error3_embed, delete_after=10)

How to make a bot delete its own message after 5 seconds

I can't get the bot to delete its own message.
I have tried await ctx.message.delete() and ctx.message.delete(embed)
#bot.command()
async def help(ctx):
embed=discord.Embed(title="List of commands.", description="", colour=discord.Color.orange(), url="")
await ctx.send(embed=embed)
await ctx.message.delete()
await asyncio.sleep(5)
await message.delete()
I'm wanting the bot to delete the command then send an embed: "A list of commands has been sent to your DM's" then wait 5 secs and delete the embed
ctx.message.delete() deletes the message from the user.
But to delete the bot's message you need the bot's message object
from the return of ctx.send() :
bot.remove_command('help') # Removes default help command
#bot.command()
async def help(ctx):
embed=discord.Embed(title="List of commands.", description="", colour=discord.Color.orange())
msg = await ctx.send(embed=embed) # Get bot's message
await ctx.message.delete() # Delete user's message
await asyncio.sleep(5)
await msg.delete() # Delete bot's message
EDIT:
You can use parameter delete_after=(float)
await ctx.send(embed=embed, delete_after=5.0)

Resources