Discord Python Rewrite - Broadcast - discord

Is it possible to make the bot sends 1 message on every server that the bot is in without sending the message to every channel? I have a working code but it sends to all channel
#client.command()
async def broadcast(ctx, *, message):
for guild in client.guilds:
for channel in guild.channels:
if guild.name == ctx.author.guild.name:
pass
else:
try:
await channel.send(message)
await ctx.send(
'Sent to {} (ID: {}, Owner: {}#{} With {} Members)'.format(
guild.name,
guild.id,
guild.owner.name,
guild.owner.discriminator,
guild.member_count
))
except:
await ctx.send(
'Could not send at {} (Channel ID: {}). (Owner: {}#{})'.format(
guild.name,
channel.id,
guild.owner.name,
guild.owner.discriminator,
))
return
else:
break
please help

If you use
for guild in client.guilds:
channel = discord.utils.get(guild.text_channels, name="general")
if channel != None:
#do something
you could get the #general channel from each guild. That would be just one channel (Discord allows multiple channels to share names but most people won't do this, and .get() will return the first only, anyway).
This is much better than looping over all channels and slightly better than picking random channels but I still would consider letting guilds set their own broadcast reception channels.
Tested and it works, albeit my bot exists only in one server, I don't know if there are unknown consequences for trying to do this over 100+ servers.

Related

get the number of users in a voice channel with my discord bot in python

I'm looking for a way to get the number of users in a voice channel and to get their username to use it in one of my discord bot command, I found that I can use ctx.guild.member to get the members of users in the server, but not in a specific channel, is there a method to do that ?
I tried this
from discord.ext import commands
bot = commands.Bot(intents=discord.Intents.all(),command_prefix = "/")
#bot.command()
async def teamup(ctx):
channel = ctx.author.VoiceChannel
Or this
bot = commands.Bot(intents=discord.Intents.all(),command_prefix = "/")
#bot.command()
async def teamup(ctx):
channel = ctx.message.author.voice.channel
None of them works, the first tells me that member objects has no attribute VoiceChannel
and the second one tells me that ctx.message.author.voice is a NoneType object and has no attribute channel
You're very close.
#bot.command()
async def teamup(ctx):
channel = ctx.message.author.voice.channel
ctx has an author property; this returns the user/member object for the individual that invoked the command. The user/member has a voice property that returns the VoiceState object of the user. This has a channel property which will return the voice channel that the user is in. Importantly, this will be None if the user isn't in a voice channel. So, putting it together:
#bot.command()
async def teamup(ctx):
voice = ctx.author.voice
if not voice.channel:
await ctx.send("You are not currently in a voice channel")
return
channel = voice.channel
# do what you want with the channel here
await ctx.send(f"You're in {channel.name}!")

discord.py sending message to channel name instead of ID

I am a beginner to this programming stuff, and I have a quick question. I am trying to make a logs channel for multiple servers, and I want to be able to look for a channel that has the word “logs” in it, so can you help me?
Code:
#client.event
async def on_command_completion(ctx):
channel = client.get_channel('829067962316750898')
embed = discord.Embed(colour=discord.Color.green(),
title="Command Executed")
embed.add_field(name="Command:", value=f"`,{ctx.command}`")
embed.add_field(name="User:", value=f"{ctx.author.mention}", inline=False)
embed.add_field(name="Channel:",
value=f"{ctx.channel} **( <#{ctx.channel.id}> )**")
await channel.send(embed=embed)
You need to get the channel. I suggest using discord.utils.get.
Also, try using {ctx.channel.mention} to mention the channel instead.
#client.event
async def on_command_completion(ctx):
channel = discord.utils.get(ctx.guild.text_channels, name='logs')
if channel is None:
return # If there is no logs channel, do nothing (or what you want to do)
embed = discord.Embed(colour=discord.Color.green(),
title="Command Executed")
embed.add_field(name="Command:", value=f"`,{ctx.command}`")
embed.add_field(name="User:", value=f"{ctx.author.mention}", inline=False)
embed.add_field(name="Channel:",
value=f"{channel.name} **( {channel.mention} )**")
await channel.send(embed=embed)
See the discord.TextChannel docs and discord.utils.get()

I cannot understand how to use this code in discord.py

It regards user imput, so like I was commissioned to do a prompt but I've never done this so like this is what i found online
playerChoice = await bot.wait_for('message', check=check(ctx.author), timeout=30)
I get some of it, but I don't get the 'message' part and the 'check = check'.
Here's my full code
#client.command()
async def event(ctx):
await ctx.send("Prompt will continue in DMs.")
embed = discord.Embed(title="Event Prompt", description="Please specify the type of event.")
embed.set_footer("Prompt will expire in ## seconds")
await ctx.author.send(embed=embed)
eventType = await bot.wait_for('message', check=check(ctx.author), timeout=30) # I want it to send the event type.
await ctx.send(eventType)
I'd like an explaination and a possible way to improve that and make it work. Thanks in advance
https://discordpy.readthedocs.io/en/stable/api.html?highlight=wait_for#discord.Client.wait_for
#client.event
async def on_message(message):
if message.content.startswith('$greet'):
channel = message.channel
await channel.send('Say hello!')
def check(m):
return m.content == 'hello' and m.channel == channel
msg = await client.wait_for('message', check=check)
await channel.send('Hello {.author}!'.format(msg))
await client.wait_for('message', check=check)
message refers to the event. You could have also do it for the event reaction_add, voice_state_update, etc.
So this means you are waiting for a message. The check defines what you are waiting for exactly. It is a method and returns a True or False.
In my case I am waiting for a message event which is posted in the same channel and has the message content "hello".
If you didn't have such check it would pick up a message that might have been send by a different author, in a different channel, in a different guild.

discord.py bot repeating messages

hi i am trying to make a discord.py bot so i can have a gif chat channel but when someone types a message in that channel then my bot starts repeating his message, pls help if u know.
my code:
#client.event
async def on_message(message):
with open("gif_chater.json", "r+") as file:
data=json.load(file)
if str(message.channel.id) in data:
if message.content.startswith("https://tenor.com/"):
print("wOw")
if not message.content.startswith("https://tenor.com/") and not message.author.id == "760083241133932544":
await message.channel.send("lol pls use gifs in this channel : )")
await message.delete()
exit
The on_message event
The issue is that the bot is constantly responding to itself, and it's because the on_message event triggers not just when users send a message but also when the bot sends a message. As such, once it tells the user that they must only post tenor gifs, it reacts to its own message and goes into an infinite loop, posting and deleting its responses.
Preventing the bot from responding to itself
To prevent the bot from responding to it's own messages, you should add a check at the start of the event like in the discord.py docs:
#client.event
async def on_message(message):
if message.author == client.user:
return
...
Also, the ID check at the end
The last condition in your code before it decides to send a message is checking the ID of the messenger (not message.author.id == "760083241133932544"). I don't know whether it's meant to avoid deleting you or the bot's messages but regardless, the check itself is bugged. message.author.id returns an integer but is then being compared to a string, and due to the conflicting types, will always return False.
To fix it, change your ID to an integer by removing the quotes: not message.author.id == 760083241133932544. As well, you should use the not-equals operator != instead of not to improve readability: message.author.id != 760083241133932544.
Also, since you already checked if the message starts with the website link, you can use an elif statement instead of rechecking the condition, since else/elif guarantees that the previous condition was false (aka, that the message didn't start with the website link):
if message.content.startswith("https://tenor.com/"):
print("wOw")
elif message.author.id != 760083241133932544:
await message.channel.send("lol pls use gifs in this channel : )")
await message.delete()
Fixes combined
With the new changes, your function could look something like this:
#client.event
async def on_message(message):
# Don't respond to the bot's own messages
if message.author == client.user:
return
with open("gif_chater.json") as file:
data = json.load(file)
if str(message.channel.id) in data:
if message.content.startswith("https://tenor.com/"):
print("wOw")
elif message.author.id != 760083241133932544:
await message.channel.send("lol pls use gifs in this channel : )")
await message.delete()

Discord.py welcome bot on_member_join event not getting callded

I've been interested in working with discord bots lately, and from what I'm seeing this code should work but it is not...
I'm simply just playing around with the API because it's fun so I'm pretty new with this. I just want the bot to welcome someone when they join.
import discord
client = discord.Client()
#client.event
async def on_ready():
print('We have logged in as {0.user}'.format(client))
channel = client.guilds[0].get_channel(CHANNEL ID)
await channel.send("Bot online")
#client.event
async def on_message(message):
if message.author == client.user:
return
if message.content.startswith('$hello'):
await message.channel.send('Hello!')
#client.event
async def on_member_join(member):
print(f'{member.name} has joined the server')
channel = client.guilds[0].get_channel(CHANNEL ID)
print(channel)
await channel.send(f'{member.name} has joined the server')
#client.event
async def on_member_remove(member):
print(f'{member.name} has left the server')
channel = client.guilds[0].get_channel(CHANNEL ID)
print(channel)
await channel.send(f'{member.name} has left the server')
client.run('TOKEN HERE')
instead of member.name use member and if that dosnt work add this where you have your variables intents = discord.Intents(messages = True, guilds = True, reactions = True, members = True, presences = True)
client = commands.Bot(command_prefix = '*', intents = intents)
FOR discord.py >= 1.5
1.5 adds support for Gateway Intents, by default your bot doesn't have access to guild members like it did in previous versions. If your bot is in less than 100 servers then you can enable these intents without verification. You should see these settings at the bottom of your Bot page on the Discord Developer Portal. If you enable both, then you need to change your Client (or commands.Bot) instantiation as such:
intents = discord.Intents.all()
client = discord.Client(intents=intents)
When I test this, the event is firing, but I'll bet your issue lies in the line:
channel = client.guilds[0].get_channel(CHANNEL ID)
It will be far more reliable to just use use client.get_channel to ensure you are actually grabbing the intended channel, all channel IDs on discord are unique so you do not need to use a guild object. Also CHANNEL ID will not be a valid variable, but I am guessing you just redacted it.
You forgot the brackets for the decorators.
#client.event
should be
#client.event()
EDIT: Not it, apparently. Will update this answer when OP replies with more information.

Resources