Ask for channel ID through a command in Discord.py? - discord

I'm new to Discord py and trying to make my bot get the channel ID using a command like >sending [numbers] but it's not actually working. The error I get is
TypeError: get_channel() missing 1 required positional argument: 'id'
This is how I'm trying to make it:
from discord import Client
from discord import channel
from discord.ext import commands
id_chnl = ''
#bot.command()
async def sending(ctx, *, chnl):
global id_chnl
id_chnl = cnhl
global channel
channel = Client.get_channel(str(id_chnl))
await ctx.send("Saving your ID")

I don't know what your trying to but getting channel object is easy using command by converters.
All you have to do is,
#bot.command()
async def sending(ctx, channel: discord.TextChannel):
channel_id = channel.id
Note: There are different types of channels - text, voice, stage, category and store. Each of the uses different converters and you can find them in the docs.
If you want to get any one of the channel regardless of the type,
channel: typing.Union[discord.TextChannel, discord.VoiceChannel, discord.StoreChannel, discord.StageChannel, discord.CategoryChannel]```

been a bit, but try:
channel = Client.get_channel(id=str(id_chnl))

The easist way to get the channel the bot is in is:
#bot.command()
async def sending(ctx):
channel_id = ctx.channel.id
The easist way to get the channel by using #:
#bot.command()
async def sending(ctx, channel: discord.TextChannel):
channel_id = channel.id
To fetch the channel:
#bot.command()
async def sending(ctx, channel: discord.TextChannel):
channel_id = await bot.fetch_channel(channel.id)
Alternative way might be using name:
#bot.command()
async def sending(ctx, channel: discord.TextChannel):
channel = discord.utils.get(ctx.guild.channels, name=channel) #or instead of name it would be id

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}!")

Making my discord bot listen for specific messages and answer back when it identifies one

So, I'm new to python and even more to coding bots on discord. At the moment I'm using discord.py and red-bot (https://docs.discord.red/en/stable/index.html).
At the moment I'm trying to make the bot listen to a new message and print something in response to it, but I just can't figure it out. Since I'm using red-bot I didn't go through the steps of using client = discord.Client() and setting a token on the code itself so using #client.event() doesn't seem to work, nor #bot.event(), and I can't really find any other way to make the bot listen for an on_message() event.
Edit with part of my code:
import discord
from discord.ext import commands
from redbot.core import commands
class MyCog(commands.Cog):
client = discord.Client()
def __init__(self, bot):
self.bot = bot
#bot.event()
async def on_message(self, message):
if 'test' in message.content:
await self.send_message(message.channel, 'it works!')
Console returns that bot in #bot.event() is not defined.
Also a separate initialization file, it's done this way to follow Red's guide of how to make a cog.
from .remind import MyCog
def setup(bot):
bot.add_cog(MyCog(bot))
Here is an example of a cog that replies to a specific word mentioned. It also has a cooldown to prevent the bot spamming which I find absolutely neccesary to include.
from curses.panel import bottom_panel
import discord
from discord.ext import commands
class brilliant(commands.Cog):
def __init__(self, bot):
self.bot = bot
self._cd = commands.CooldownMapping.from_cooldown(1, 60.0, commands.BucketType.member) # Change accordingly
# rate, per, BucketType
def ratelimit_check(self, message):
"""Returns the ratelimit left"""
bucket = self._cd.get_bucket(message)
return bucket.update_rate_limit()
#commands.Cog.listener()
async def on_message(self, message):
if message.author == self.bot.user:
return
msg = message.content.lower()
brilliant = ['brilliant', 'Brilliant', 'brilliant!', 'Brilliant!']
if any(word in msg for word in brilliant):
retry_after = self.ratelimit_check(message)
if retry_after is None:
await message.channel.send("Brilliant!")
await self.bot.process_commands(message)
else:
return
async def setup(bot):
await bot.add_cog(brilliant(bot))
If you want it in the main file, you can put something a lot simpler:
brilliant = ['brilliant', 'Brilliant', 'brilliant!', 'Brilliant!']
#bot.event
async def on_message(message):
if message.author == bot.user:
return
msg = message.content.lower()
if any(word in msg for word in brilliant):
await message.channel.send("Brilliant!")
await bot.process_commands(message)
Hope it helps.

How can I put discord.py events to another file?

I need to log many events on my Discord server and i am trying add logging feature to my bot. But it looks like this:
#bot.event
async def on_message_delete(m):
created_at = m.created_at.strftime('%d-%m-%Y %H:%M:%S')
log_content = f'{m.author} deleted message.\n[{created_at}] "{m.content}"'
await Logging().write_log(1, log_content)
#bot.event
async def on_message_edit(m_before, m_after):
created_at = m_after.created_at.strftime('%d-%m-%Y %H:%M:%S')
edited_at = m_after.edited_at.strftime('%d-%m-%Y %H:%M:%S')
log_content = f'{m_after.author} edited message.\n[{created_at}] "{m_before.content}"\n[{edited_at}] "{m_after.content}"'
await Logging().write_log(1, log_content)
#bot.event
async def on_raw_reaction_add(payload):
channel = bot.get_channel(payload.channel_id)
message = await channel.fetch_message(payload.message_id)
created_at = message.created_at.strftime('%d-%m-%Y %H:%M:%S')
log_content = f'{payload.member} addded reaction {payload.emoji} to message from {message.author}.\n[{created_at}] "{message.content}"'
await Logging().write_log(2, log_content)
#bot.event
async def on_raw_reaction_remove(payload):
channel = bot.get_channel(payload.channel_id)
message = await channel.fetch_message(payload.message_id)
created_at = message.created_at.strftime('%d-%m-%Y %H:%M:%S')
log_content = f'{payload.member} removed reaction {payload.emoji} from message by {message.author}.\n[{created_at}] "{message.content}"'
await Logging().write_log(2, log_content)
# and more
How can I put this to another file? Or something like that
What you are looking for is dpy's Cogs
There comes a point in your bot’s development when you want to organize a collection of commands, listeners, and some state into one class. Cogs allow you to do just that.
A quick example here would be :
class Logging(commands.Cog):
def __init__(self, bot):
self.bot = bot
#commands.Cog.listener()
async def on_member_join(self, member):
# Do your logging stuff here
...
More details on adding and removing Cogs have been detailed in the documentation which you can read here
NOTE: In some versions of dpy add_cog, setup are coroutine functions and needs to be awaited. Be sure to crosscheck your version :D

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()

Welcome message Discord.py

I don't have much experience in discord.py, but I'm making a bot. Right now I added the welcoming message:
#client.event
async def on_member_join(member):
channel=client.get_channel(channel_ID)
emb=discord.Embed(title="NEW MEMBER",description=f"Thanks {member.name} for joining!")
await channel.send(embed=emb)
but I want to mention the user who joined as this picture
May you help me doing this? Thanks!
Use member.mention
This returns a string which allows you to mention the member.
#client.event
async def on_member_join(member):
channel=client.get_channel(channel_ID)
emb=discord.Embed(title="NEW MEMBER",description=f"Thanks {member.mention} for joining!")
await channel.send(embed=emb)
You should however keep in mind that because of caching, the mention will most likely look something like this <#!123456789>.
You need the code to look like this:
#client.event
async def on_member_join(member):
if member.guild.id !=Guild.id:
return
channel = client.get_channel(channel_id) # replace id with the welcome channel's id
await channel.send(f"{member.mention} has arrived!, check out our announcments channel for server and bot announcements!")
await member.send(f"Thank you for joining {member.guild.name}!")
This line right here is you only want people that join YOUR server to send a msg, if you don't have any server with your bot in it, will say the msg still
if member.guild.id !=Guild.id:
return
{member.mention} is what mentions the user if you are using {} in the sending part you need the f function
Next code will make the code call the {}
await channel.send(f"{member.mention}")
This calls the guild name:
{member.guild.name}
I am not sure about client.get_channel, but you sure can try this:
#client.event
async def on_member_join(member):
guild = client.get_guild(serverID)
channel = guild.get_channel(channelID)
emb = discord.Embed(title="NEW MEMBER",description=f"Thanks {member.name} for joining!")
await channel.send(member.mention, embed=emb)

Resources