I want to ensure my bot only responds to commands/messages and responds only in 1 specific channel is this possible I have tried multiple variations to no success. even better if I could define it for any event. Anyone got any ideas?
You can check message.channel in the on_message event and if it matches your criteria, in this case a specific channel, then do process_commands.
Below is an example where the !ping command will only work when channel.name is "general".
from discord.ext import commands
client = commands.Bot(command_prefix='!')
#client.command()
async def ping():
await client.say('Pong')
#client.event
async def on_message(message):
if message.channel.name == 'general':
await client.process_commands(message)
client.run('token')
Related
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()
So, what I want to do is stop a specific role from speaking in a channel on discord using discord.py.
Here's what I have so far.
import discord
import os
from keep_alive import keep_alive
client = discord.Client()
#client.event
async def on_ready():
print('We have logged in as {0.user}'.format(client))
#client.event
async def on_message(message):
countingBotGuildSave = ['test']
if any(word in message.content for word in countingBotGuildSave):
await message.channel.set_permissions(discord.utils.get(message.guild.members, name='Foo'), send_messages=False)
await message.channel.send('**An admin/moderator has locked this channel. Please wait for an admin to unlock this channel with `+unlock`.**')
print(f'{message.author} locked channel {message.channel}')
keep_alive()
client.run(os.getenv('TOKEN'))
This doesn't cause any errors when I run the bot, but when I say test in discord it says: target parameter must be either Member or Role. I don't understand because I made a role named Foo.
Can you pls help?
Tysm.
The error itself tells you what went wrong. Your await function does not make any sense in that case. You are looking for guild.members with the name Foo but what you want is the role.
Have a look at the following code:
#client.event
async def on_message(message):
countingBotGuildSave = ['test']
if any(word in message.content for word in countingBotGuildSave):
await message.channel.set_permissions(discord.utils.get(message.guild.roles, name='Foo'), send_messages=False) # Get the role
await message.channel.send('**An admin/moderator has locked this channel. Please wait for an admin to unlock this channel with `+unlock`.**')
print(f'{message.author} locked channel {message.channel}')
Here we are looking for a role in the guild named Foo. You can also just use the ID to change the name to whatever you want to without editing the code (id=RoleID).
The output:
This may be kinda dumb but I'm trying to make a purge command but theres always something wrong with it. Can anyone help please?
#client.event
async def on_message(message):
if message.author == client.user:
return
if message.content.startswith('p!purge'):
numberoftimes = input(int('How many times: '))
await message.channel.purge(limit=str(numberoftimes))
I'll start with answering your question, then I'll clarify on a better way to create a purge command. To answer your question, there is no need to make an input() statement. Rather, this is how you make an input prompt with a Discord bot:
#client.event
async def on_message(message):
if message.author == client.user:
return
if message.content.startswith('p!purge'):
await message.channel.send('How many messages do you want to purge?')
while True:
numberoftimes = client.wait_for('message') # This means, the client is waiting for a message
if numberoftimes.author == message.author: # Make sure that the person responding is the person who did the command
limit = int(numberoftimes.content) # If its a string, it will be treated as a word. You want to purge a "number" of messages
await message.channel.purge(limit=limit+1)
That's how you would purge messages in a channel. But, the way you are creating this command can be made simpler. You can use the command decorator, which is the "standard" way of doing things:
import discord
from discord.ext import commands
client = commands.Bot(command_prefix='p!')
#client.command()
#commands.has_permissions(manage_messages=True)
async def purge(ctx, limit):
limit = int(limit)
await ctx.channel.purge(limit=limit + 1)
lets say on_member_join event
#commands.Cog.listener()
async def on_member_join(self, member):
# On member joins we find a channel called general and if it exists,
# send an embed welcoming them to our guild
channel = discord.utils.get(member.guild.text_channels, name="welcome")
if channel:
embed = discord.Embed(
description="Welcome to our guild!",
color=random.choice(self.bot.color_list),
)
embed.set_thumbnail(url=member.avatar_url)
embed.set_author(name=member.name, icon_url=member.avatar_url)
embed.set_footer(text=member.guild, icon_url=member.guild.icon_url)
embed.timestamp = datetime.datetime.utcnow()
await channel.send(embed=embed)
This is my event (I know it works) how can I test it in any way to execute command to emit the event (not manually by adding and removing someone)?
[something like .emit on_member_join #user where arg1 is event and if needed arg2 is mention or id of channel ]
Any command for that ?
something like Discord.js: Manually triggering events but in discord.py not in JavaScript
Currently there isn't official support in the discord.py api to do something like that but you can always make a command in the cog like follows:
#commands.command()
async def test_join(self, ctx, member: discord.Member):
await self.on_member_join(member)
Technically there is a way to probably do it that isn't documented...
Line 131 in here. I will not offer addition support for that because it isn't documented.
Discord.py, how to set a command, without Prefix, only with certain word to which bot replies, and also bot replies to that command while Dm with the bot.
Remember about the errors for example, bot object has no attribute on_message, etc, errors.
You can write a function to pass to command_prefix that will check for one prefix in servers and another (or none) in private messages:
from discord.ext import commands
def command_prefix(bot, message):
if message.guild is None:
return ''
else:
return '$'
bot = commands.Bot(command_prefix=command_prefix)
#bot.command(name='hello')
async def hello(ctx):
await ctx.send("Hello")
bot.run("TOKEN")
If you are using this in a cog.
#commands.Cog.listener()
async def on_message(self,message):
await message.send("Hello!")
or in the main.py
#bot.event
async def on_message(message):
await message.send("Hello!")
Please reply back if you have an error with this.
message.guild will return None if the message is in dms.