Cooldown on on_message event discord.py - discord.py

I'm trying to make a suggestion system with discord.py. A user DMs the bot a message and the bot sends that message in a specific channel. The code works, I wanted to understand if it is possible to add a cooldown in sending DMs to the bot and how to do it.
#client.event
async def on_message(message):
if not message.author.bot:
if isinstance(message.channel, DMChannel):
if len(message.content) > 700:
await message.channel.send("Suggerimento troppo lungo")
else:
embedMod= discord.Embed(title="Suggerimento:", description=message.content, colour=0xfc5a50, timestamp=datetime.utcnow())
embedMod.set_footer(icon_url="https://s3.us-west-2.amazonaws.com/cdn.lnk.bio/profilepics/-1230732_20210524863.jpg")
embedMod.set_author(name=f'{message.author}', icon_url=f'{message.author.avatar_url}')
mod = client.get_channel(900085945414582312)
await mod.send(embed=embedMod)
await message.channel.send('Suggerimento registrato con successo, grazie mille.')
Update, is correct?
#client.event # Suggerimenti
async def on_message(message):
bucket = cd_mapping.get_bucket(message)
retry_after = bucket.update_rate_limit()
if retry_after:
await message.channel.send("Scimmia")
else:
if not message.author.bot:
if isinstance(message.channel, DMChannel):
if len(message.content) > 700:
await message.channel.send("Suggerimento troppo lungo")
else:
embedMod= discord.Embed(title="Suggerimento:", description=message.content, colour=0xfc5a50, timestamp=datetime.utcnow())
embedMod.set_footer(icon_url="https://s3.us-west-2.amazonaws.com/cdn.lnk.bio/profilepics/-1230732_20210524863.jpg")
embedMod.set_author(name=f'{message.author}', icon_url=f'{message.author.avatar_url}')
mod = client.get_channel(900085945414582312)
await mod.send(embed=embedMod)
await message.channel.send('Suggerimento registrato con successo, grazie mille.')
else:
await client.process_commands(message)

You can do it with discord.py cooldowns:
from discord.ext import commands
cd_mapping = commands.CooldownMapping.from_cooldown(1, 60, commands.BucketType.user)
#client.event
async def on_message(message):
bucket = cd_mapping.get_bucket(message)
retry_after = bucket.update_rate_limit()
if retry_after:
# rate limited
else:
# not rate limited

Related

Discord py delete voicechannel if its empty

Well im trying to create a voice channel by command so i can join it.
And as soon i leave the channel its supposed to get deleted.
What i tried:
if message.content.startswith('/voice'):
guild = message.guild
voicechannel = await guild.create_voice_channel(f"{str(message.author)}")
await asyncio.sleep(5)
while True:
if len(voicechannel.voice_states) == 0:
await voicechannel.delete()
break
doesnt even work tho
I believe that your issue is that you are stuck in an infinite while True loop. I would first suggest that you switch to using discord.ext.commands, it simplifies the process of creating a Discord Bot by a great deal. If you were using discord.ext.commands.Bot, you would be able to use the wait_for() function to wait until the voice channel is empty.
from discord.ext.commands import Bot
client = Bot(command_prefix="/")
#client.command(name="voice")
async def voice(ctx):
guild = ctx.guild
voice_channel = await guild.create_voice_channel(f"{str(ctx.author)}")
def check(member, before, after):
return member == ctx.author and before.channel == voice_channel and after.channel is None
await client.wait_for("voice_state_update", check=check)
await voice_channel.delete()
client.run("TOKEN")
The only issue that I think could happen, is if the member never joins the voice channel. To counter this, we can set up another wait_for() function to determine if the member ever joins before waiting for the member to leave the voice channel.
from asyncio import TimeoutError
#client.command(name="voice")
async def voice(ctx):
guild = ctx.guild
voice_channel = await guild.create_voice_channel(f"{str(ctx.author)}")
def check(member, before, after):
return member == ctx.author and before.channel is None and after.channel == voice_channel
try:
await client.wait_for("voice_state_update", check=check, timeout=60)
except TimeoutError:
await voice_channel.delete()
return

Nextcord typing through discord bot

I would like to be able to asynchronously send inputs to my python terminal and have my bot output them, whilst also keeping my other event running.
import nextcord
import botToken #contains the string of my bot token
from nextcord.ext import commands
client = commands.Bot(command_prefix="!")
#client.event
async def on_ready():
general = client.get_channel(925388635304521859)
while True:
inp = input("->")
if len(inp) < 4001:
await general.send(inp)
else:
await general.send(inp[0: 1500])
#client.event
async def on_message(message): #its supposed to react to each message with a buffalo emoji
print(message.content)
channel = message.channel
if "<#!308022163330564099>" in message.content:
await message.delete()
await channel.send("🐃")
await message.add_reaction("🐃")
client.run(botToken.TOKEN)e
Currently the on_ready() event only loads when it starts which is good, but i would like it to be asyncronic if thats a possibility. I don't know much about nextcord so I have no ideas. I would love any ideas for this.
The tasks extension in Nextcord may help for what you are trying to do
https://nextcord.readthedocs.io/en/latest/ext/tasks/index.html
It allows you to execute code in the background using a loop.
from nextcord.ext import tasks
#tasks.loop(seconds=1.0)
async def my_task_loop():
print("Hello!")
#my_task_loop.before_loop
async def before_my_task_loop():
print('waiting for ready')
await self.bot.wait_until_ready()
my_task_loop.start()

How to make bot reply to a mention discord.py

I'm making a discord bot and a problem that has come up for me is that the bot won't reply to the user, here is the code
#Code Imports
import discord
import random
from discord import message
from discord import channel
from discord.embeds import Embed
from discord.ext import commands
from discord.ext.commands.bot import Bot
from discord.message import Message
from apikeys import *
from discord import guild
from discord import emoji
from discord import *
from discord import ContentFilter
from discord import channel
from discord import client
#intents
intents=discord.Intents.default()
intents.members=True
#prefix
client=commands.Bot(command_prefix='!',intents=intents)
#Start
#client.event
async def on_ready():
for emoji in client.emojis:
print("Name:", emoji.name + ",", "ID:", emoji.id)
print('Bot is Online {0.user}'.format(client))
print("--------------------------------------------------------------------------------------------------------------------------------------------------------")
client.remove_command('help')
#Commands
#client.command()
async def work(ctx):
await ctx.send('use !war to get up the war menu')
emojigood = '\N{THUMBS UP SIGN}'
emojibad="\N{THUMBS DOWN SIGN}"
#client.command()
async def help(ctx):
embed=discord.Embed(title='Help', description='!war is currently under testing please do not complain about it', color=0x00000)
await ctx.send(embed=embed)
#client.command()
async def war(ctx):
embed = discord.Embed(title='War', description='You are starting a war, do you want to continue?', color=0x00000)
msg = await ctx.send(embed=embed)
await msg.add_reaction(emojigood)
await msg.add_reaction(emojibad)
def check(r, user):
return (r.emoji == emojigood or r.emoji == emojibad) and r.message == msg
#Checks whether the message is the same, and the emoji is one of the accepted ones, and returns either True or False
r, user = await client.wait_for('reaction_add',timeout=10 ,check=check)
#this is equivalent to a event listener within your command, it will stop there until a reaction that meets the requirements has been found
#(This won't block other commands and functions)
if r.emoji == emojigood:
embed = discord.Embed(title='War', description='Please now choose a country', color=0x00000)
await ctx.send(embed=embed)
prefix = "!" #insert your prefix
async def on_message(message):
if message.author == client.user:
return
if message.content == f'{prefix}war': #dont need to use this string, just illustrating the point
await message.channel.send("What country do you want to start a war with?")
def check(msg):
return msg.author == message.author and len(msg.role_mentions) > 0
msg = await client.wait_for('message', check=check)
role = msg.role_mentions[0]
channel = client.get_channel(849230881994047508)
await channel.send(f"{role.mention} {message.author} has declared war on you.")
client.run(token)
What's meant to happen:
Bot: Which role would you like to start a war with
User:#something
Bot:Send information to UN, 'War on #something'
I don't know how to make it see the role mention
You have a couple of issues, the way to make the code you're using function decently is to replace message.content with message.clean_content, however, 1. That will react to any message starting with # or a mention, which is probably not what you want, and 2. any message not beginning with the mention wouldn't work.
You say in your description that you're looking for role mentions, which is a different attribute, and you're looking to send a message, and wait for a response, so here's a piece of sample code that would solve those issues, assuming I'm interpreting your question correctly:
def check(msg):
return msg.author == message.author and len(msg.role_mentions) > 0
msg = await client.wait_for('message', check=check)
role = msg.role_mentions[0]
channel = client.get_channel(ID of the channel)
await channel.send(f"{role.mention} {message.author} has declared war on you."
If I misinterpreted any of what you wanted or you're not sure how some of it works, shoot me a comment and I'll do my best to explain!
Docs reference for slightly more complex objects used:
role_mentions,
wait_for(),

how do i resolve this [ discord.py ]

how are you doing today i sure hope your doing great im sorry for the spam on other account i apologize. ok so my problem is that i switched from client to bot basically bot = commands.Bot i tried renaming all the commmands to bot.event or bot.command can someone pls help me pls i would appreciate it thank you here is the code :)
#bot.command()
async def ping(ctx):
await ctx.send(f'Pong!\n`{round(client.latency*1000)}ms`')
#bot.command(aliases=['8ball'])
async def _8ball(ctx, *, question):
responses = [ "It is certain.",
"As I see it, yes",
"Ask again later.",
"Better not tell you now.",
"Cannot predict now.",
"Concentrate and ask again.",
"Don't count it",
"It is certain.",
"It is decidedly so.",
"Most likely.",
"My reply is no."
"My sources say no.",
"Outlook not so good.",
"Outlook good.",
"Reply hazy, try again.",
"Signs point to yes.",
"Very doubtful.",
"Without a doubt.",
"Yes.",
"Yes – definitely.",
"You may rely on it." ]
await ctx.send(f'Question: {question}\nAnswer: {random.choice(responses)}')
#commands.has_permissions(ban_members=True)
#bot.command()
async def kick(ctx, user: discord.Member, *, reason="No reason provided"):
await user.ban(reason=reason)
kick = discord.Embed(title=f":boom: Kicked {user.name}!", description=f"Reason: {reason}\nBy: {ctx.author.mention}")
await ctx.message.delete()
await ctx.channel.send(embed=kick)
await user.send(embed=kick)
#commands.has_permissions(ban_members=True)
#bot.command()
async def ban(ctx, user: discord.Member, *, reason="No reason provided"):
await user.ban(reason=reason)
ban = discord.Embed(title=f":boom: Banned {user.name}!", description=f"Reason: {reason}\nBy: {ctx.author.mention}")
await ctx.message.delete()
await ctx.channel.send(embed=ban)
await user.send(embed=ban)
#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)
await ctx.channel.send(f"Unbanned: {user.mention}")
#bot.command(pass_context = True)
async def mute(ctx, user_id, userName: discord.User):
if ctx.message.author.server_permissions.administrator:
user = ctx.message.author
role = discord.utils.get(user.server.roles, name="Muted")
#bot.command()
async def serverinfo(ctx):
name = str(ctx.guild.name)
description = str(ctx.guild.description)
owner = str(ctx.guild.owner)
id = str(ctx.guild.id)
region = str(ctx.guild.region)
memberCount = str(ctx.guild.member_count)
icon = str(ctx.guild.icon_url)
embed = discord.Embed(
title=name + " Server Information",
description=description,
color=discord.Color.blue()
)
embed.set_thumbnail(url=icon)
embed.add_field(name="Owner", value=owner, inline=True)
embed.add_field(name="Server ID", value=id, inline=True)
embed.add_field(name="Region", value=region, inline=True)
embed.add_field(name="Member Count", value=memberCount, inline=True)
await ctx.send(embed=embed)
await client.add_roles(user, role)
#bot.command()
async def setdelay(ctx, seconds: int):
await ctx.channel.edit(slowmode_delay=seconds)
await ctx.send(f"Set the slowmode delay in this channel to {seconds} seconds!")
#bot.command()
async def afk(ctx, mins):
current_nick = ctx.author.nick
await ctx.send(f"{ctx.author.mention} has gone afk for {mins} minutes.")
await ctx.author.edit(nick=f"{ctx.author.name} [AFK]")
counter = 0
while counter <= int(mins):
counter += 1
await asyncio.sleep(60)
if counter == int(mins):
await ctx.author.edit(nick=current_nick)
await ctx.send(f"{ctx.author.mention} is no longer AFK")
break
def setup(bot):
bot.add_cog(Afk(bot))
def user_is_me(ctx):
return ctx.message.author.id == "Your ID"
def convert(time):
pos = ["s","m","h","d"]
time_dict = {"s" : 1, "m" : 60, "h" : 3600, "d": 3600*24}
unit = time[-1]
if unit not in pos:
return -1
try:
val = int(time[:-1])
except:
return -2
return val * time_dict[unit]
#bot.command()
#commands.has_permissions(kick_members=True)
async def giveaway(ctx):
await ctx.send("Let's start with this giveaway! Answer these questions within 15 seconds!")
questions = ["Which channel should it be hosted in?", "What should be the duration of the giveaway? (s|m|h|d)", "What is the prize of the giveaway?"]
answers = []
def check(m):
return m.author == ctx.author and m.channel == ctx.channel
for i in questions:
await ctx.send(i)
try:
msg = await bot.wait_for('messsage', timeout=15.0, check=check)
except asyncio.TimeoutError:
await ctx.send('You didn\'t answer in time, please be quicker next time!')
return
else:
answers.append(msg.content)
try:
c_id = int(answers[0][2:-1])
except:
await ctx.send(f"You didn't mention a channel properly. Do it like this {ctx.channel.mention} next time.")
return
channel = bot.get_channel(c_id)
time = convert(answers[1])
if time == -1:
await ctx.send(f"You didn't answer with a proper unit. Use (s|m|h|d) next time!")
return
elif time == -2:
await ctx.send(f"The time just be an integer. Please enter an integer next time.")
return
prize = answers[2]
await ctx.send(f"The giveaway will be in {channel.mention} and will last {answers[1]} seconds!")
embed = discord.embed(title = "Giveaway!", description = f"{prize}", color = ctx.author.color)
embed.add_field(name = "Hosted by:", value = ctx.author.mention)
embed.set_footer(text = f"Ends {answers[1]} from now!")
my_msg = await channel.send(embed = embed)
await my_msg.add_reaction("🎉")
await asyncio.sleep(time)
new_msg = await channel.fetch_message(my_msg.id)
users = await new_msg.reactions[0].users().flatten()
users.pop(users.index(bot.user))
winner = random.choice(users)
await channel.send(f"Congratulations! {winner.mention} won the prize: {prize}!")
#bot.command()
#commands.has_permissions(kick_members=True)
async def reroll(ctx, channel : discord.TextChannel, id_ : int):
try:
new_msg = await channel.fetch_message(id_)
except:
await ctx.send("The ID that was entered was incorrect, make sure you have entered the correct giveaway message ID.")
users = await new_msg.reactions[0].users().flatten()
users.pop(users.index(bot.user))
winner = random.choice(users)
await channel.send(f"Congratulations the new winner is: {winner.mention} for the giveaway rerolled!")
if you want me to answer anything to help you solve it feel free to comment thank you so much have a great day!
It seems like you copied most of the code from the internet and bashed it together to create a bot or a cog (based on your question I would guess a bot).
Assuming this is a snippet of your main bot file and not a cog there are a couple of things that could be different:
Put your utility functions in one place (peferably after your import statatements). It's good practise overall and makes more readeable code.
Unless you have a cog class in the same file as your bot instance (which is bad practise) you shouldn't need this:
def setup(bot):
bot.add_cog(Afk(bot))
If there is a cog class named Afk you should move it into a separate file (putting the cog class into the main bot file defeats the purpose of the cog)
In your mute command you have pass_context = True. This is from the old version of discord.py and is no longer needed.
I can't tell you much more since there's no point in trying to debug your code since you didn't give us any errors or stacktrace to work with.
It is very exhausting, so you can just leave client in every command, just write this client = commands.Bot(command_prefix = 'your prefix') it is the same bot, but it just has a different name.
If you meant that, because i didn't really understand what you need

How to get my bot to join a voice channel

I'm trying to get my discord bot to connect to a voice channel like this currently:
#client.event
async def on_message(message):
message.content = message.content.lower()
if message.author == client.user:
return
if '-skip' in message.content:
await message.author.channel.connect
await message.channel.send (f"-p scotland forever")
await disconnect
Basically I want it to join a voice channel from the message author when they send the message "-skip" and then my bot joins, says -p scotland forever in chat, and then leaves. I get an error message saying things like "channel" not defined or "connect" not defined, ive tried doing it a few different ways, I think i just havent imported a plugin or whatever and thats probably my issue, but idk what plugin thing to use. Any help would be appreciated.
Try this:
#client.event
async def on_message(message):
message.content = message.content.lower()
if message.author == client.user:
return
if '-skip' in message.content:
channel = message.author.voice.channel
if channel is not None:
await channel.connect()
await message.channel.send (f"-p scotland forever")
await client.voice_clients[0].disconnect()
else:
await message.channel.send ("You need to join to voice channel")
Try this
#commands.command()
async def join_voice(self, ctx):
connected = ctx.author.voice
if connected:
await connected.channel.connect(put vc id here)
It may work
I guess?

Resources