I have been asking lots of questions lately about discord.py and this is one of them.
Sometimes there are those times when some people spam your discord server but kicking or banning them seems too harsh. I had the idea for a silence command which would delete every new message on a channel for a given amount of time.
My code so far is:
#BSL.command(pass_context = True)
async def silence(ctx, lenghth = None):
if ctx.message.author.server_permissions.administrator or ctx.message.author.id == ownerID:
global silentMode
global silentChannel
silentChannel = ctx.message.channel
silentMode = True
lenghth = int(lenghth)
if lenghth != '':
await asyncio.sleep(lenghth)
silentMode = False
else:
await asyncio.sleep(10)
silentMode = False
else:
await BSL.send_message(ctx.message.channel, 'Sorry, you do not have the permissions to do that #{}!'.format(ctx.message.author))
The code in my on_message section is:
if silentMode == True:
await BSL.delete_message(message)
if message.content.startswith('bsl;'):
await BSL.process_commands(message)
All the variables used are pre-defined at the top of the bot.
My problem is that the bot deletes all new messages in all channels which it has access to. I tried putting if silentChannel == ctx.message.channel in the on_message section but this made the command stop working completely.
Any suggestions as to why this is happening are much appreciated.
Something like
silent_channels = set()
#BSL.event
async def on_message(message):
if message.channel in silent_channels:
if not message.author.server_permissions.administrator and message.author.id != ownerID:
await BSL.delete_message(message)
return
await BSL.process_commands(message)
#BSL.command(pass_context=True)
async def silent(ctx, length=0): # Corrected spelling of length
if ctx.message.author.server_permissions.administrator or ctx.message.author.id == ownerID:
silent_channels.add(ctx.message.channel)
await BSL.say('Going silent.')
if length:
length = int(length)
await asyncio.sleep(length)
if ctx.message.channel not in silent_channels: # Woken manually
return
silent_channels.discard(ctx.message.channel)
await BSL.say('Waking up.')
#BSL.command(pass_context=True)
async def wake(ctx):
silent_channels.discard(ctx.message.channel)
Should work (I haven't tested it, testing bots is a pain). Searching through sets is fast, so doing it for every message shouldn't be a real burden on your resources.
Related
I have mostly rebuilt the code and made changes.
When I do !embed everything works as it should, the bot creates the embed, and reacts with the emojis set, it just doesn't give user the roles once they react with the emojis the bot reacts to the post with..
I decided to add in some random print statements to hit the console per step and found I can see up to while True as commented in my code but after that the print statements don't respond.
My error handler/trace back has been pretty good so far and picked up everything, so its like after while True nothing exists, I believe the problem lies within this line:
reaction = await bot.wait_for("reaction_add", check=lambda reaction, user: user == reaction.message.id == msg.id)
Any help would be greatly appreciated.
desc1 = ("React with the corresponding emoji to game specific channels you want\n"
"\nπ - Counter Strike\n"
"π - Warframe\n"
"π€ - Lost Ark\n"
"π - Chiller\n"
"πͺ - Warhammer")
#bot.command()
async def embed(ctx: commands.Context):
embed=discord.Embed(title="Create Your Profile", description=(desc1))
embed.set_footer(text="Jammys Bot")
msg = await ctx.send(embed=embed)
await msg.add_reaction('π')
await msg.add_reaction('π')
await msg.add_reaction('π€')
await msg.add_reaction('π')
await msg.add_reaction('πͺ')
print('it works here')
while True:
print('it works here 1') ## makes it up to here. Error handle/trace back isn't picking anything below up so its like its non-existent.
reaction = await bot.wait_for("reaction_add", check=lambda reaction, user: user == reaction.message.id == msg.id) # stops working here
print('it works here 2')
if reaction.emoji == 'π':
print('it works here 3')
CSGO = ctx.guild.get_role(780182144747569193)
print('it works here 4')
await bot.add_roles(CSGO)
print('it works here 5')
if reaction.emoji == 'π':
WF = ctx.guild.get_role(780244861130768395)
await ctx.add_roles(WF)
if reaction.emoji == 'π€':
LA = ctx.guild.get_role(947231964753170473)
await bot.add_roles(LA)
if reaction.emoji == 'π':
CHILL = ctx.guild.get_role(896853904384458772)
await bot.add_roles(CHILL)
if reaction.emoji == 'πͺ':
WH = ctx.guild.get_role(896882687816630293)
await bot.add_roles(WH)
To send it to a specific channel you can try this code
channel =client.get_channel(your channelid)
msg = await channel.send(embed = embed)
Wow... Hello, I'm back here after two days. (Thank you to the person who helped me last time..)
First of all, this code works in the direction I want.
However, there is a problem.
This bot's command is "!곡μ§". However, this bot sends me a message because the code works no matter what chat I write... I want to make it work only when I write "!곡μ§"
#client.event
async def on_message(message):
if message.author == client.user:
return
if message.content.startswith("!곡μ§"):
await message.channel.purge(limit=1)
i = (message.author.guild_permissions.send_messages)
if i is True:
notice = message.content[4:]
channel = client.get_channel(927233433489526904)
embed = discord.Embed(title="*λΈλ¦¬ν*", description="\nββββββββββββββββββββββββββββ\n\n{}\n\nββββββββββββββββββββββββββββ".format(notice), color=0x00ff00)
embed.set_footer(text="-C0de")
embed.set_thumbnail(url="https://i.imgur.com/UDJYlV3.png")
await channel.send (embed=embed)
if i is False:
await message.channel.send("{}, λΉμ μ κ΄λ¦¬μκ° μλλλ€".format(message.author.mention))
If you want the code to exit if the user's message doesn't start with "!곡μ§" then add
if message.content.startswith("!곡μ§"):
await message.channel.purge(limit=1)
else:
return
This will exit the function if the message does not start with those characters.
The problem lies in this:
i = (message.author.guild_permissions.send_messages)
if i is True:
Since anyone who writes something has that permission, i will always be true.
I guess what you want to do is to indent those two lines, so it is inside the if-block that checks the command.
Try moving your i = (message.author.guild_permissions.send_messages) line to the same indentation as the if conditional, while also initializing your i before the if-else statement:
i = False
if message.content.startswith("!곡μ§"):
await message.channel.purge(limit=1)
i = (message.author.guild_permissions.send_messages) # set only in condition.
else:
i = False
When inserted in code:
#client.event
async def on_message(message):
if message.author == client.user:
return
i = False # initialize i
if message.content.startswith("!곡μ§"):
await message.channel.purge(limit=1)
i = (message.author.guild_permissions.send_messages) # set only in condition.
else:
i = False
if i is True:
notice = message.content[4:]
channel = client.get_channel(927233433489526904)
embed = discord.Embed(title="*λΈλ¦¬ν*", description="\nββββββββββββββββββββββββββββ\n\n{}\n\nββββββββββββββββββββββββββββ".format(notice), color=0x00ff00)
embed.set_footer(text="-C0de")
embed.set_thumbnail(url="https://i.imgur.com/UDJYlV3.png")
await channel.send (embed=embed)
if i is False:
await message.channel.send("{}, λΉμ μ κ΄λ¦¬μκ° μλλλ€".format(message.author.mention))
This should let your code properly branch based on the command
I'm trying to make my discord bot have a higher or lower game where the player clicks an up or down arrow to guess, but I'm struggling to work out how check if the reaction is the first one or the second one.
Here is my code so far (its in a cog):
#commands.command()
async def highlow(self, ctx, limit:int = 100, *args):
num = random.randint(0, limit)
msg = await ctx.reply("The number is {num} \nWHould you like to go (h)igher or (l)ower")
await self.client.add_reaction(msg, emoji="<:arrow_up:>")
await self.client.add_reaction(msg, emoji="<:arrow_down:>")
def check(reaction, user):
return reaction.message == msg and str(reaction.emoji) == '<:arrow_down:>'
await self.client.wait_for('reaction_add', check=check)
(Also, I am aware that self.client.add_reaction will not work, its some old code I just quickly copied over to test out)
How do I make it so that I can check either reaction instead of just one?
To add a reaction we use msg.add_reaction("Your reaction") in your case.
If you want to check the reaction of a user we wait_for a reaction_add.
You can have a look at the following code:
try:
reaction, user = await client.wait_for('reaction_add')
while user == client.user:
reaction, user = await client.wait_for('reaction_add')
if str(reaction.emoji) == "YourEmoji": # First reaction
# Do what you want to do
if str(reaction.emoji) == "YourEmoji": # Second reaction
# Do what you want to do
except Exception: # Timeout can be added for example
return
Here we check that the bot reaction is not counting as a valid reaction but instead a user one. You can then add more if-statements in your code.
I have been making a Discord bot for one of my servers, and one of it's functions is to prevent curse words. I want it to toggle the censor mode when you type in a command. However, instead of switching the variable to 1 and back again, it just stays on 0, even though I get the "Bad words will now not work" output.
#client.event
async def on_message(message):
swareCensor: int = 0
if message.content == 'f! censor':
if swareCensor == 0:
await message.channel.send('Bad words will now not work')
swareCensor += 1
else:
await message.channel.send('The bad word filter is now off')
swareCensor *= 0
if swareCensor == 1:
if 'fuck' in message.content:
await message.delete()
await message.channel.send('Sware has been detected')
It wouldn't be ideal for swears to be censored all the time, especially if I want it on multiple servers
I would first of all strongly recommend using the actual command method instead of saying if message == "!command" in an onMessage event.
swearFilter = False
#client.command()
async def sensor(ctx):
swearFilter = not swearFilter
await ctx.send(f"Swear filter is now set to {swearFilter}")
#client.event()
async def on_message(message):
if swearFilter:
if "fuck" in message.content:
await message.delete()
await message.channel.send("Swear detected!")
so right now I'm trying to create a type of application bot and right now the check I used for the bot doesn't allow the user to move onto the next question. There is no traceback so it's something with the check I defined.
#commands.command()
#commands.has_role("Realm OP")
async def block(self, ctx, user: discord.User):
DMchannel = await ctx.author.create_dm()
channel = ctx.message.channel
author = ctx.message.author
mentions = [role.mention for role in ctx.message.author.roles if role.mentionable]
channel2 = str(channel.name)
channel = channel2.split('-')
if len(channel2) == 2: # #real-emoji
realm, emoji = channel
else: # #realm-name-emoji
realm, emoji = channel[0], channel[-1]
realmName = realm.replace("-" , " ")
realmName1 = realmName.lower()
rolelist = []
print(realmName1)
a = solve(realmName1)
print(a)
realmName2 = str(a) + " OP"
print(realmName2)
check_role = discord.utils.get(ctx.guild.roles, name= realmName2)
if check_role not in ctx.author.roles:
return await ctx.send('You do not own this channel')
else:
await ctx.send("You own this channel!")
def check(m):
return m.channel == channel and m.author != self.bot.user
await DMchannel.send("Please fill out the questions in order to block the user!")
await DMchannel.send("User's Gamertag: (If you don't know, try using the >search command to see if they have any previous records!) ")
blocka1 = await self.bot.wait_for('message', check=check)
await DMchannel.send("Reason for block:")
blocka2 = await self.bot.wait_for('message', check=check)
Right now the bot doesn't do anything after the user responds to the first question and there is no traceback.
Any help or suggestions would help greatly!
Your check isn't returning anything. It's supposed to return either True or False. This means your wait_for will never end (as the check never returns True), so it will never ask the next question.
def check(m):
return m.channel == channel and m.author != self.bot.user
EDIT:
Your channel is the ctx.channel, while your bot waits for answers in DM. Assuming you answer your bot in DM as well, this means your check will never pass, as m.channel never equals channel.
def check(m):
return m.guild is None and m.author == ctx.author
This checks if a message was sent in DM (Guild is None), and if it was a DM by the original author.