How to do a server/guild level - discord.py

I am doing a command which logs info from one server to a main one, and I would like to count how many times a server has done a log after the "yes" confirmation, and then display it on the embed. How can I do that?
My script:
#bot.command(name="log")
async def log(ctx, name: str, where: str, too: str, time: str, info: str):
embed = discord.Embed(
colour=discord.Colour.red(), title="Confirm Log?")
embed.add_field(name="Name:", value=name, inline=True)
embed.add_field(name="From:", value=where, inline=True)
embed.add_field(name="Too:", value=too, inline=True)
embed.add_field(name="Time:", value=time, inline=True)
embed.add_field(name="Information:", value=info, inline=False)
await ctx.send("Confirm log? (yes/no)")
await ctx.send(embed=embed)
msg = await bot.wait_for('message', check=lambda message: message.author == ctx.author)
if msg.content.lower() == "yes":
await ctx.send("Sent!")
server = ctx.message.guild.name
channel = bot.get_channel(794856521100034060)
embed = discord.Embed(colour=discord.Colour.green(), title="New Log!", description=f'From {server}')
embed.add_field(name="Name:", value=name, inline=True)
embed.add_field(name="From:", value=where, inline=True)
embed.add_field(name="Too:", value=too, inline=True)
embed.add_field(name="Time:", value=time, inline=True)
embed.add_field(name="Information:", value=info, inline=False)
await channel.send(embed=embed)

if msg.content.lower() == "yes":
some value in a txt/json/db += 1
...
p.s there's no problem in sending both normal text and an embed in one message:
await ctx.send("Confirm log? (yes/no)")
await ctx.send(embed=embed)
# could just be
await ctx.send(content='Confirm log? (yes/no)', embed=embed)

Related

How do I combine 3 on_message functions into 1 on_message function

Basically I need to combine these 3 on_message functions into 1 on_message function cause you can't have more than 1 on_message function in a discord.py bot. Here's my code:
#client.event
async def on_message(message):
if message.content.startswith('Jason derulo'):
await message.channel.send('Wiggle wiggle wiggle')
await client.process_commands(message)
#client.event
async def on_message(message):
if message.content.startswith('fast'):
await message.channel.send('She a runner she a track star')
await client.process_commands(message)
#client.event
async def on_message(message):
await client.process_commands(message)
if message.author.bot:
return
for badword in file:
if badword in message.content.lower():
await message.delete()
warnMessage = f"Hey {message.author.mention}! Don't say that!"
await message.channel.send(warnMessage, delete_after=5.0)
print(f"{message.author.name} tried saying: {badword}")
channel = client.get_channel(836232733126426666)
embed = discord.Embed(title=f"Someone tried to swear!", colour=0x2D2D2D)
embed.add_field(name="Person who tried to swear:", value=f"{message.author.name}", inline=False)
embed.add_field(name="What they tried to say:", value=f"{badword}", inline=False)
await channel.send(embed=embed)
return
await client.process_commands(message)
You just add all the if together, but only use one await client.process_commands(message) at the bottom:
#client.event
async def on_message(message):
if message.author.bot:
return
for badword in file:
if badword in message.content.lower():
await message.delete()
warnMessage = f"Hey {message.author.mention}! Don't say that!"
await message.channel.send(warnMessage, delete_after=5.0)
print(f"{message.author.name} tried saying: {badword}")
channel = client.get_channel(836232733126426666)
embed = discord.Embed(title=f"Someone tried to swear!", colour=0x2D2D2D)
embed.add_field(name="Person who tried to swear:", value=f"{message.author.name}", inline=False)
embed.add_field(name="What they tried to say:", value=f"{badword}", inline=False)
await channel.send(embed=embed)
return
await client.process_commands(message)
if message.content.startswith('Jason derulo'):
await message.channel.send('Wiggle wiggle wiggle')
if message.content.startswith('fast'):
await message.channel.send('She a runner she a track star')
await client.process_commands(message)

Deleting the command after embed has been executed

I'm trying to make it to where when the embed for example below is executed, the ?ra1 message from the user is deleted. Thanks for any help.
#client.command()
async def ra1(ctx):
embed = discord.Embed(
colour=discord.Colour.blue(),
title="RIDEALONG 1 REQUEST",
description=str(ctx.author.mention) + " IS REQUESTING THEIR FIRST RIDEALONG IN SERVER !"
)
embed.add_field(name="For CDTOs", value="Please message the user to accept their RA request. Please delete their message once the ridealong has been completed.", inline=False)
embed.timestamp = datetime.utcnow()
await ctx.send(embed=embed, delete_after=7200)
You can use await ctx.message.delete() in order to delete the message that triggered the command.
#client.command()
async def ra1(ctx):
embed = discord.Embed(
colour=discord.Colour.blue(),
title="RIDEALONG 1 REQUEST",
description=str(ctx.author.mention) + " IS REQUESTING THEIR FIRST RIDEALONG IN SERVER !"
)
embed.add_field(name="For CDTOs", value="Please message the user to accept their RA request. Please delete their message once the ridealong has been completed.", inline=False)
embed.timestamp = datetime.utcnow()
await ctx.send(embed=embed, delete_after=7200)
await ctx.message.delete()
References
discord.Message.delete
Context.message
Context has the attribute message which you can delete
await ctx.message.delete()
This is quite simple infact its just using await ctx.message.delete()
Implemented inside of your code:
#client.command()
async def ra1(ctx):
await ctx.message.delete()
embed = discord.Embed(
colour=discord.Colour.blue(),
title="RIDEALONG 1 REQUEST",
description=str(ctx.author.mention) + " IS REQUESTING THEIR FIRST RIDEALONG IN SERVER !"
)
embed.add_field(name="For CDTOs", value="Please message the user to accept their RA request. Please delete their message once the ridealong has been completed.", inline=False)
embed.timestamp = datetime.utcnow()
await ctx.send(embed=embed, delete_after=7200)

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 send a message when a command is not found?

I am trying to send a message when a command is not found but it is not working:
#client.event
async def on_ready():
change_status.start()
print("----------------------")
print("Logged In As")
print("Username: %s" % client.user.name)
print("ID: %s" % client.user.id)
print("----------------------")
async def on_message(ctx, error):
if isinstance(error, commands.CommandNotFound):
text = ('Sorry {}, this command does not exist check $help for a more detailed list of').format(ctx.author.mention)
msg = await ctx.send(text)
await ctx.message.delete()
await asyncio.sleep(5)
await msg.delete()
else:
pass
raise error
You're looking for on_command_error event
#client.event
async def on_command_error(ctx, error):
if isinstance(error, commands.CommandNotFound):
await ctx.send("Command does not exist.")
Reference:
on_command_error
I have found an answer to my issue instead of running it through a client.event decorator, I have ran it through a client.listen, decorator:
#client.event
async def on_ready():
change_status.start()
print("----------------------")
print("Logged In As")
print("Username: %s" % client.user.name)
print("ID: %s" % client.user.id)
print("----------------------")
#client.listen()
async def on_command_error(ctx, error):
if isinstance(error, commands.CommandNotFound):
text = ('Sorry {}, this command does not exist check $help for a more detailed list of').format(ctx.author.mention)
msg = await ctx.send(text)
await ctx.message.delete()
await asyncio.sleep(5)
await msg.delete()
The on_command_error event is called when an error happens on any command.
and inside the on_command_error event you can check whether the error is an instance of CommandNotFound, which is thrown when the typed command is not found, or it doesn't exist. And if so, you can send a message to the channel, where the command was used.
#client.event
async def on_command_error(ctx, error):
"""Command error handler"""
embed = discord.Embed(color=discord.Color.red())
if isinstance(error, commands.CommandNotFound):
embed.title = "Command not Found"
embed.description = "Recheck what you've typed."
#await ctx.send(embed=embed)

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