how to send messages all channel - python

i want send messages to all channel that bot has joined
def check(cnt):
while 1:
if hash_origin != str(subprocess.check_output(["md5sum",filename])[:-len(filename)-3])[2:-1] :
print("file destroyed alert!")
alert = 1
sleep(0.5)
i want send message to all discord channel that bot joined when specific file's hash result is different from original.
i know how to send respond message to channel
#client.event
async def on_message(message):
using this code, right?
but i want to send message to all of the channel that bot has joined when some event has happens.

In order to send a message to every channel that the bot is in, you must do:
#client.event
async def foo(bar): # change this to the event in which you wish to call it from
for guild in client.guilds:
for channel in guild.channels:
await channel.send(messagedata) # change messagedata to whatever it is you want to send.

#client.event
async def foo(bar): # change this to the event in which you wish to call it from
for guild in client.guilds:
for channel in guild.channels:
await channel.send(messagedata) # change messagedata to whatever it is you want to send.
when using this code directly, error has occurred
AttributeError: 'CategoryChannel' object has no attribute 'send'
because "guild.channels" object have list of "all channels"(including text,voice,etc..) that bot has joined.
so, if i want send text message to channel, using "guild.text_channels" instead.
anyway, thanks to Tylerr !!

Related

how to make a discord.py bot not accepts commands from dms

How do I make a discord.py bot not react to commands from the bot's DMs? I only want the bot to respond to messages if they are on a specific channel on a specific server.
If you wanted to only respond to messages on a specific channel and you know the name of the channel, you could do this:
channel = discord.utils.get(ctx.guild.channels, name="channel name")
channel_id = channel.id
Then you would check if the id matched the one channel you wanted it to be in. To get a channel or server's id, you need to enable discord developer mode. After than you could just right click on the server or channel and copy the id.
To get a server's id you need to add this piece of code as a command:
#client.command(pass_context=True)
async def getguild(ctx):
id = ctx.message.guild.id # the guild is the server
# do something with the id (print it out)
After you get the server id, you can delete the method.
And to check if a message is sent by a person or a bot, you could do this in the on_message method:
def on_message(self, message):
if (message.author.bot):
# is a bot
pass
You Can Use Simplest And Best Way
#bot.command()
async def check(ctx):
if not isinstance(ctx.channel, discord.channel.DMChannel):
Your Work...
So just to make the bot not respond to DMs, add this code after each command:
if message.guild:
# Message comes from a server.
else:
# Message comes from a DM.
This makes it better to separate DM from server messages. You just now have to move the "await message.channel.send" function.
I assume that you are asking for a bot that only listens to your commands. Well, in that case, you can create a check to see if the message is sent by you or not. It can be done using,
#client.event
async def on_message(message):
if message.author.id == <#your user id>:
await message.channel.send('message detected')
...#your code

How do you send a message in TwitchIO that's not a response to a command?

I'm setting up a python TwitchIO chat bot. The getting started example has this:
async def event_message(self, message):
print(message.content)
await self.handle_commands(message)
#commands.command(name='test')
async def my_command(self, ctx):
await ctx.send(f'Hello {ctx.author.name}!')
If the incoming message is a command (e.g. !test), a message is sent back to the channel with ctx.send().
I'd like the option to send a message back to the channel (based on come criteria) whenever any message is received, not just commands. For example:
async def event_message(self, message):
print(message.content)
if SOMETHING:
SEND_MESSAGE_HERE
await self.handle_commands(message)
I can't figure out how to do some type of .send to make that happen. This answer: TwitchIO: How to send a chat message? show this:
chan = bot.get_channel("channelname")
loop = asyncio.get_event_loop()
loop.create_task(chan.send("Send this message"))
I tried that and the bot sent a ton of messages instantly and got timed out for an hour.
So, the question is: How do you send a message back to the channel inside event_message
A command passes you a Context (an instance of of Messageable, which defines send()). A Channel is also a Messageable, thus it has a send(). So if your Bot instance is bot:
await bot.connected_channels[0].send('...')
Will send a message to the first channel the bot is connected to.
This is the answer I came up with:
bot_account_name = "BOT_ACCOUNT_NAME"
async def event_message(self, message):
print(message.content)
if message.author.name.lower() != bot_account_name.lower():
ws = self._ws
await ws.send_privmsg('CHANNEL_NAME', 'Message To Send')
await self.handle_commands(message)
You can do other checks, but it's important to do the check against the bot account user name. If you don't the bot will see its own messages and reply to them creating a loop. This is one of the issues I ran into where it send a bunch in no time and got timed out by twitch
I found an alternative. I replace the message with a command that I invented for the purpose. The name of the command is "z" but it could have been anything
async def event_message(self, message):
if message.echo:
return
message.content = f"#z {message.content}" # add command name before message
await self.handle_commands(message)
#commands.command()
async def z(self, ctx: commands.Context):
print(f"Original message is {ctx.message.content[3:]}\n")

guild.text_channels return just the top channel instead of all channels

I'm making a discord bot and I want it to send a message whenever it joins a new guild.
However, I only want it to send the message in the #general channel of the guild it joins:
#client.event
async def on_guild_join(guild):
chans = guild.text_channels
for channel in chans:
if channel.name == 'general':
await channel.send('hi')
break
The problem that I have noticed is that guild.text_channels only returns the name of the very first channel of the server. I want to iterate through all channels and finally send message only on the #general channel.
What's the workaround for it?
There are a couple ways you can do this.
Here's an example using utils.get():
import discord # To access utils.get
#client.event
async def on_guild_join(guild):
channel = discord.utils.get(guild.text_channels, name="general")
await channel.send("Hi!")
Or if the guild has a system_channel set up, you can send a message there:
#client.event
async def on_guild_join(guild):
await guild.system_channel.send("Hi!")
You can create checks for both of these, but bear in mind that some servers might not have a text channel called general or a system channel set up, so you may receive some attribute errors complaining about NoneType not having a .send() attribute.
These errors can be avoided with either an error handler or a try/except.
References:
Guild.system_channel
utils.get()

How to get the message content/embed from the message id?

I want to know how to get a message content (specifically the embeds) from the message id? Just like you can get the member using a member id
on_raw_reaction_add() example:
#bot.event
async def on_raw_reaction_add(payload):
channel = bot.get_channel(payload.channel_id)
msg = await channel.fetch_message(payload.message_id)
embed = msg.embeds[0]
# do something you want to
Command example:
#bot.command()
async def getmsg(ctx, channel: discord.TextChannel, msgID: int):
msg = await channel.fetch_message(msgID)
await ctx.send(msg.embeds[0].description)
In the command I'm passing in channel and msgID, so a sample command execution would like !getmsg #general 112233445566778899 - the channel must be in the same server that you're executing the command in!
Then I'm getting the message object using the fetch_message() coroutine, which allows me to get a list of embeds in said message. I then choose the first, and only, embed by choosing position index 0.
After that, the bot then sends the description (or whatever attribute you'd like) of the embed.
References:
discord.TextChannel
TextChannel.fetch_message()
Message.embeds
discord.Embed - This is where you can find the different attributes of the embed
commands.command() - Command decorator
on_raw_reaction_add()
discord.RawReactionActionEvent - The payload returned from the reaction event
RawReactionActionEvent.message_id - The ID of the message which was reacted to
RawReactionActionEvent.channel_id - The text channel that the reaction was added in

Discord: How to get channel object where new member joined?

I want to make a bot that send a message to new comer at the channel.
I'm using discord.py.
------------next day-------------------
Firstly, Thank you three people!(sorry for bad English). I studied a lot.
But unfortunately, I've found "member.server.defaul_channel"(which must have been this question's answer) no longer exist with this url:
Discord.py Invalid arguments inside member.server_default_channel
Then, how to send a mention to the channel where new comer appears now?
1, I know a way that is to specity the channel name.
#client.event
async def on_member_join(member):
server = member.server
channel = [channel for channel in client.get_all_channels() if channel.name == 'WRITE_YOUR_CHANNEL_NAME!!'][0]
message = 'hello {}, welcome to {}'.format(member.mention, server.name)
await client.send_message(channel, message)
2, but I would like to know more universal way. Such as to use "default_channel". Is there a way?
You can use the on_member_join event.
The following will send a message to the "general" channel every time a member joins a server.
#client.event
async def on_member_join(member):
for channel in member.server.channels:
if channel.name == 'general':
await client.send_message(channel, 'Message to send when member joins')
If you want to check some other channel property instead of the name, then check the following documentation.
http://discordpy.readthedocs.io/en/latest/api.html#discord.Channel
Note that I've tried using channel.is_default but this always returns False.
Members don't really join channels, they join servers. Something like
#client.event
async def on_server_join(member):
server = member.server
default channel = server.default_channel
message = ''Hello {}, welcome to {}'.format(member.mention, server.name)'
await client.send_message(default_channel, message)
Would send a message on the default channel of the server whenever someone joins.
The API has changed a little. This should work now:
#client.event
async def on_member_join(member):
for channel in client.get_all_channels():
if channel.name == 'general':
await channel.send(
f'Hi {member.mention}, Message to send when member joins')

Categories