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))
Related
I am making a verification system where if you type !verify "1. John 2. Mr. Teacher 3. Somewhere 4. Freshman 5. The Cool Mascot" it will send an embed in a channel looking like this: https://gyazo.com/ab808bafcd4a5f3ed05f63e007da20c1.
If someone reacts with the checkmark I want to dm the user saying that they have been accepted and if they get denied it will send a dm saying they have been denied but I seem to not get a dm when reacting and they do not get the Member role right after, and there are no tracebacks.
Code:
#bot.command(pass_context=True)
async def verify(ctx, message):
logem = discord.Embed(color=discord.Color.red())
logem.set_author(name=f"Verification Request!")
logem.add_field(name="User", value=f"{ctx.author.mention}")
logem.add_field(name="Application", value=f"{message}")
logem.set_footer(text=f"React with ✅ to accept the application and ❌ to deny the application",
icon_url="https://upload.wikimedia.org/wikipedia/commons/thumb/2/2e/Exclamation_mark_red.png/50px-Exclamation_mark_red.png")
logemlog = bot.get_channel(820840787645956123)
msg = await logemlog.send(embed=logem)
await msg.add_reaction('✅')
await msg.add_reaction('❌')
async def on_raw_reaction_add(payload):
msgid = await ctx.fetch_message(msgID)
ourMessageID = msgid
if ourMessageID == payload.message_id:
member = payload.member
guild = member.guild
emoji = payload.emoji.name
if emoji == '✅':
role = discord.utils.get(guild.roles, name="Member")
print ('Accepted Someones Application')
em = discord.Embed(color=discord.Color.red())
em.set_author(name="Verified!")
em.set_footer(text=f"You Have Been Accepted Into The Official WHS Discord Server!",
icon_url="https://upload.wikimedia.org/wikipedia/commons/thumb/2/2e/Exclamation_mark_red.png/50px-Exclamation_mark_red.png")
await member.send("You have been accepted!")
await member.add_roles(role)
elif emoji == '❌':
em = discord.Embed(color=discord.Color.red())
em.add_field(name="Denied!", value=f"{message}")
em.set_footer(text=f"You Have Been Denied Access Into The Official WHS Discord Server!",
icon_url="https://upload.wikimedia.org/wikipedia/commons/thumb/2/2e/Exclamation_mark_red.png/50px-Exclamation_mark_red.png")
await ctx.member.send("You have been Denied!")
Use this instead of async def on_raw_reaction_add:
def check(reaction, user):
return reaction.emoji in ['✅', '❌'] and user == ctx.author
while True:
try:
reaction, user = await bot.wait_for('reaction_add', check=check)
except Exception as e:
print(e)
else:
if reaction.emoji == '✅':
role = discord.utils.get(guild.roles, name="Member")
print ('Accepted Someones Application')
em = discord.Embed(color=discord.Color.red())
em.set_author(name="Verified!")
em.set_footer(text=f"You Have Been Accepted Into The Official WHS Discord Server!",
icon_url="https://upload.wikimedia.org/wikipedia/commons/thumb/2/2e/Exclamation_mark_red.png/50px-Exclamation_mark_red.png")
await member.send("You have been accepted!")
await member.add_roles(role)
if reaction.emoji == '❌':
em = discord.Embed(color=discord.Color.red())
em.add_field(name="Denied!", value=f"{message}")
em.set_footer(text=f"You Have Been Denied Access Into The Official WHS Discord Server!",
icon_url="https://upload.wikimedia.org/wikipedia/commons/thumb/2/2e/Exclamation_mark_red.png/50px-Exclamation_mark_red.png")
await ctx.member.send("You have been Denied!")
Test it and let me know if it doesn't work.
So I am trying to make a discord.py echo/say command, but no response or errors are happening, if you know how to fix this please help me out!
import discord, os, keep_alive, asyncio, datetime, pytz, requests
from discord.ext import tasks, commands
client = commands.Bot(
command_prefix=':',
self_bot=True
)
async def on_ready():
client.remove_command('help')
await client.change_presence(status=discord.Status.online, activity=discord.Game("TEST"))
#client.command()
async def echo(ctx, *,args):
if ctx.message.author.id in [782258096210051102]:
await ctx.send(args)
await ctx.message.delete()
else:
await ctx.send("Bot developers only :<")
keep_alive.keep_alive()
client.run(os.getenv("TOKEN"), bot=False)
It's not working because the ctx.author is None, to fix that enable intents.members
intents = discord.Intents.default()
intents.members = True
client = commands.Bot(..., intents=intents)
Also make sure to enable them in the developer portal
Reference
Uhhhhhh it is better to do something like
#bot.command()
async def echo(ctx,*,arg):
#the star is required
if ctx.authir.id==782258096210051102:
await ctx.send(arg)
else:
await ctx.send("devs only :<")
You can use ' '.join(ctx.message.content.split()[1:]) to join all words after the first space. So something like:
#client.command()
async def echo(ctx, *args):
await ctx.send(' '.join(ctx.message.content.split()[1:]))
To See Where The Problem Is From First Try:
#client.command()
async def echo(ctx, *,args):
await ctx.send(args[0])
await ctx.message.delete()
Ok so actually you have need to do this:
#client.command(name='echo')
async def echo(ctx, *, what_bot_need_to_say: str):
if ctx.message.author.id == 782258096210051102:
await ctx.channel.purge(limit=1) # This delete an message in the channel
await ctx.send(what_bot_need_to_say) # This the echo
else:
await ctx.send("Bot developers only :<")
#bot.command()
async def say(ctx, *, msg):
await ctx.send(msg)
Just copy me it is the simplest and gives the correct format
import discord
from discord.ext import commands
bot = commands.Bot('?')
#bot.command()
async def repeat(ctx,*,repeat:str):
if ctx.author.id == 782258096210051102:
await ctx.send(f"{repeat}")
await ctx.message.delete()
return
else:
await ctx.send("Only devs")
return
#bot.event
async def on_ready():
print("bot online")
bot.run("YOUR_TOKEN_HERE")
try this:
import discord, os, keep_alive, asyncio, datetime, pytz, requests
from discord.ext import tasks, commands
client = commands.Bot(
command_prefix=':',
self_bot=True
)
async def on_ready():
client.remove_command('help')
await client.change_presence(status=discord.Status.online, activity=discord.Game("TEST"))
#client.command()
async def echo(ctx, *,args):
if ctx.author.id in [782258096210051102]:
await ctx.send(args)
# await ctx.message.delete() # i am not sure of delete you can add it if you want
else:
await ctx.send("Bot developers only :<")
keep_alive.keep_alive()
client.run(os.getenv("TOKEN"), bot=False)
I've tried 3 times to do this code, my plan is removing all roles from an user, writing the roles in an ctx.send() to send a message with the old roles in the channel, after that, send a message that says the user was imprisoned and the reason and give the prisoner role.
'BabaYaga' is the adm's role; 'D 001' is the prisoner role
Code 01:
# Detentos 3
#client.command()
#commands.has_any_role('BABAYAGA')
async def det(ctx, member: discord.Member = None, role = discord.Guild.roles, *, reason = None):
if member == None:
await ctx.send('Say the user')
return
if reason == None:
await ctx.send('Say the reason')
return
Roles = member.roles
for _ in Roles:
print(Roles)
await client.remove_roles(member, *Roles)
await member.add_role(ctx, member, role)
await ctx.send(f'{member} was arrested for {reason}')
Code 02:
# Detentos 2
#client.command()
#commands.has_any_role('BABAYAGA')
async def det(ctx, member: discord.Member, *,reason):
role = discord.utils.get(ctx.guild.roles, name = 'D 001')
await ctx.send(f'{member.roles}')
for _ in member.roles:
await member.remove_roles(member.top_role)
await ctx.message.add_reaction(emoji=self.tick)
await member.add_roles(role)
await ctx.send(f'{member} was arrested for {reason}')
Code 03:
# Detentos
#client.command()
#commands.has_any_role('BABAYAGA')
async def det(self, ctx, member: discord.Member, *, reason = None):
if reason == None:
await ctx.send('Say the reason!')
return
roles = discord.utils.get(member.guild.roles) # member's roles
role = discord.utils.get(ctx.guild.roles, name = 'D 001') # Det's role
await ctx.message.add_reaction(emoji=self.tick)
await member.edit(member.guild.roles)
await ctx.send(f'{discord.Member} preso por {reason}')
await ctx.send(f'cargos do {discord.Member}: {member.roles}')
Code 04:
# Detentos
#client.command()
#commands.has_any_role('BABAYAGA')
async def det(self, ctx, member: discord.Member = None, *, reason = None):
if reason == None:
await ctx.send('Say the reason! :angry: :angry:')
return
if member == None:
await ctx.send('Say the user')
return
rolesserver = ['D 001', 'D 002', 'D 003', 'D 004', 'testers']
await ctx.send(f'{member.roles}')
for roles in rolesserver:
await client.remove_roles(member, *roles)
await ctx.send(f'<#{member.id}> was arrested for {reason}')
I don't know what is my error there. Can anyone help me?
There are a lot of mistakes in your code snippets. Here's a correct way of doing it:
#client.command()
#commands.has_any_role('BABAYAGA')
async def det(ctx, member: discord.Member, *, reason):
await ctx.send(f'Removed ", ".join([role.name for role in member.roles])')
for role in member.roles:
await member.remove_roles(role)
await ctx.message.add_reaction(emoji=self.tick)
role = discord.utils.get(ctx.guild.roles, name = 'D 001')
await member.add_roles(role)
await ctx.send(f'{member} was arrested for {reason}')
Some advices:
The get method returns a single item from an iterable so writing get(member.guild.roles) won't work, you can just type roles = member.guild.roles
You must set a variable in your for loops or else, you can't cycle through your member's roles, so your for _ in member.roles must become for role in member.roles.
To have a nice message with all your member's roles, you can use the join method combined with list comprehension (eg. ', '.join([role.name for role in member.roles]))
remove_roles is a discord.Member method so you have to use it this way: member.remove_roles(role)
I just learned how to code a discord bot with python.
Ban command
#bot.command()
async def ban(ctx, member: Member = None, *, reason):
await member.ban(reason=reason)
Kick command
#bot.command()
async def kick(ctx, member: Member = None, *, reason):
await member.kick(reason=reason)
Unban command
#bot.command()
async def unban(ctx, *, member):
banned_users = await ctx.guild.bans()
member_name, member_discriminator = member.split('#')
for ban_entry in banned_users:
user = ban_entry.user
if (user.name, user.discriminator) == (member_name, member_discriminator):
await ctx.guild.unban(user)
But how can I use the User ID to kick,ban and unban someone?
If member is on server, you can normal ban/kick by ID
If member isn't on server, you must use await client.fetch_user(ID).ban
This is the code:
import asyncio
import discord
from discord.ext import commands
client = commands.Bot(command_prefix = ".")
Token=""
#client.command()
async def react(ctx):
message = await ctx.send("Test")
await message.add_reaction("<💯>")
await message.add_reaction("<👍>")
user=ctx.message.author
def check(reaction, user):
user == ctx.message.author and str(message.emoji) == '💯'
try:
reaction, user = await client.wait_for('reaction_add', timeout=60.0, check=check)
except asyncio.TimeoutError:
await channel.send('💯')
else:
await channel.send('👍')
client.run(Token)
The problem is that I always get an error "'await' outside async function", and the a of "reaction, user = a" get highlighted. Thank you for any help.