You want a bot like voicemaster. but it doesn't work. Deleting a channel doesn't work as expected - discord.py

There is an error in the channel deletion part. I want to create a new dedicated channel when I enter a certain channel and delete that channel when I leave that channel. However, the function to be deleted when entering and exiting a voice room is applied to all voice channels. I'm sorry for my lack of English skills.
async def on_voice_state_update(member, before, after):
guild = bot.get_guild(guildid)
category = get(guild.categories, name="╭──── 🎮 gameroom 🎮 ────╮")
try:
if after.channel.id == 1015799007995510868:
global channel
channel = await guild.create_voice_channel(str(member).split("#")[0] + "'s channel", category = category, overwrites = {member: discord.PermissionOverwrite(manage_channels=True)})
await member.move_to(channel)
except:
if len(before.channel.members) == 0:
try: await bot.get_channel(before.channel.id).delete()
except: pass```

Related

I want to my discord bot to forward the message to another channel after a user reacts to it Discord.py

I know next to nothing about coding in Python but I created this bot from tutorials I found online and it does little things in my private server.
One thing we'd love to do is to react to certain messages so they will be collected in a specific channel. I've seen a few servers do this, like a highlights kind of thing.
I found something promising here in Stackoverflow but it's in javascript :<
Edit: 2023-01-19 08:53 GMT+8
#client.event
async def on_reaction_add(reaction, member):
if str(reaction.emoji) == "⭐":
channel = await bot.get_channel(channel_id)
await channel.send(reaction.message.content)
Final code
edited: 2023-01-20 17:14 GMT+8
#bot.event
async def on_reaction_add(reaction, user):
if reaction.emoji == "⭐":
astrometrics = bot.get_channel(channel id here)
embed = discord.Embed(color = 0xFEE75C)
embed.set_author(name = reaction.message.author.name, icon_url = reaction.message.author.display_avatar)
embed.add_field(name = "Message Content", value = reaction.message.content)
if len(reaction.message.attachments) > 0:
embed.set_image(url = reaction.message.attachments[0].url)
embed.add_field(name = "Go to message", value = reaction.message.jump_url, inline = False)
await astrometrics.send(embed = embed)
You can check certain messages in on_message event. And for getting a specific channel in your server, you need to have the channel id. link
Something like this:
#bot.event
async def on_message(message):
if message.content == 'the certain message':
specific_channel = await bot.get_channel(channel_id)
await specific_channel.send(message.content)
But this might have some rate-limited consequence if the 'certain message' was too much and sent at a high rate. (If yes, then there's nothing you can do since rate-limited is a discord limitation).

How to use reaction as button in discord.py

If we have a message with ⬇️ and ⬆️ Reaction.
How can we get all users reacted in particular emojis and how to use as button.
Like,
If a user reacts his name will be added in message along with the emoji which he reached.
Here is a simple example this is not the best method since this will be active on all bot messages when someone reacts with ⬆️. The best is save the message id that you want then do a check here to make sure it is the wanted message.
If message.id is not an option then make a dedicated channel for this and hard code the id of that channel, this is not the best practice but it will work.
#bot.event
async def on_raw_reaction_add(payload):
channel = bot.get_channel(payload.channel_id)
message = channel.get_message(payload.message_id)
# guild = bot.get_guild(payload.guild_id)
emoji = payload.emoji.name
# skip DM messages
if isinstance(channel, discord.DMChannel):
return
# only work if in bot is the author
# skip messages not by bot
# skip reactions by the bot
if message.author.id != bot.user.id or payload.member.id == bot.user.id:
return
if emoji == '⬆️':
up_users = f"{message.content} \n {user.name}"
await message.edit(up_users)
# remove user reaction
reaction = discord.utils.get(message.reactions, emoji=emoji)
await reaction.remove(payload.member)

how to make a discord.py bot that send embedded message in particular channel when user join a particular voice channel

I am learning discord.py and I want to make bot that sends embedded message like.(#user has joined!) joined in particular text channel only eg.(#music-cnsole) when users join particular voice channel eg.(music.vc)
like this
when user joins
also
when user leaves
#client.event
async def on_voice_state_update(member, before, after):
channelId = 1234567891011 # Your text channel id here
voiceChannelId = 1234567891011 # Your voice channel id here
#bot.event
async def on_voice_state_update(member, before, after):
if ((before.channel != None and before.channel.id == voiceChannelId) or (after.channel != None and after.channel.id == voiceChannelId)): # if connected/disconected to voiceChannelId channel
channel = bot.get_channel(channelId) # gets channel object
if (before.channel == None and after.channel != None): # if user connect
channel.send(f"{member.mention} connected to voice {after.channel.name}") # send message to channel
elif (before.channel != None and after.channel == None): # if user disconnect
channel.send(f"{member.mention} disconnect from voice {before.channel.name}") # send message to channel
on_voice_state_update event in docs
Pardon for many edits.

get channel name and send a message over at that channel

So I am working on a little project here, and pretty much, I want to have one of those "Please type the name of a channel in this server" feature.
So pretty much, the bot asks for a channel name, and I put in for example "#changelog" - and then it will ask for what it should write in that channel, etc etc.
So need to get the channel id (I am guessing), but I don't want users to write the ID, instead only writing the #server-name. And then whenever I have done that, the bot shall write in that channel.
Here is my current code!
class Changelog(commands.Cog):
def __init__(self, client):
self.client = client
#commands.Cog.listener()
async def on_ready(self):
print('Changelog is loaded')
#commands.command()
async def clhook(self, ctx):
await ctx.send('Write text-channel: ')
text_channel = await self.client.wait_for("message", check=lambda message: message.author == ctx.author, timeout=300)
clhook = self.client.get_channel(text_channel)
def setup(client):
client.add_cog(Changelog(client))
Edit:
The channel ID shall be saved "forever", meaning that I do not have to re-write the channel name where the message should go!
You can use discord.utils.get() with this example:
text_channel = await self.client.wait_for("message", check=lambda message: message.author == ctx.author, timeout=300)
channel = discord.utils.get(ctx.guild.text_channels, name=text_channel)
await channel.send('Bla Bla')
So when you type (prefix)clhook then only the channel name, for example general, it will send Bla Bla to the channel named general .
There is another way to do this and I think it's simple than the first option, here it is:
#commands.command()
async def clhook(self, ctx, channel: discord.TextChannel):
await channel.send('Bla Bla')
So in this command, usage is changed. You can use that with this: (prefix)clhook #general(mention the channel). I suggest this solution and I think it's more useful.
You can use message.channel_mentions. This will return a list of all channels that were mentioned using the #channel-name notation. That way, you can just use channel.id to get the id of the channel they mentioned.
Don't forget, however, to check if the user did in fact tag a channel (which you can also put in your check). I put it in a separate function to make it a bit more readable for the sake of this reply, but you can fit that in your lambda if you really want to.
Also, make sure to check if it's a Text Channel and not a Voice Channel or Category Channel.
#commands.command()
async def clhook(self, ctx):
def check(self, message):
author_ok = message.author == ctx.author # Sent by the same author
mentioned_channel = len(message.channel_mentions) == 1 and isinstance(message.channel_mentions[0], discord.TextChannel)
return author_ok and mentioned_channel
await ctx.send("Write text-channel: ")
text_channel = await self.client.wait_for("message", check=check)
chlhook = text_channel.channel_mentions[0]
I put two conditions on the mentioned_channel line, because if the first one fails, the second one could cause an IndexError. Alternatively you can also use an if-statement to return sooner at that place to solve the same issue.

I've got a problem where I want to create a voice channel every time 2 people use the same dedicated command, which I managed to do but

the problem is I can't connect the 2 users to it because I don't have the ID of the channel that has been created
Look at this code
async def join(ctx,i=[0],c=[0]):
author = ctx.author
guild = ctx.guild
if i[0] == 0:
channel = await guild.create_voice_channel(f"""Voice chat # {c[0]}""")
i[0] = 0
c[0]+=1
i[0] += 1
if i[0] == 2:
i[0] = 0
print(i[0])
return i[0]
Could anyone potentially help me with this?
For some elaboration - What happens here is, if the user types !join It will create a voice channel, in which i want the user to be sent into immediately, then a different user also uses !join and gets sent into the same channel (which I also covered by counting the number of people joining), so essentially if 2 people use the command, I want them to be sent into a dedicated voice channel, if other 2 users do the same, they also get sent into their own dedicated voice chat on the server. Thanks <3
If a user isn't connected to a voice channel, you can't make him join one.
The only thing you can do is moving someone to another channel with the move_to function.
To track which user is connected to a channel, you could have a dict which takes a channel id as a key and the two users as a value:
channels = {}
async def join(ctx, i=[0], c=[0]):
author = ctx.author
guild = ctx.guild
if i[0] == 0:
channel = await guild.create_voice_channel(f"""Voice chat # {c[0]}""")
channels[channel.id] = [#Your two users]
i[0] = 0
c[0]+=1
i[0] += 1
if i[0] == 2:
i[0] = 0
print(i[0])
return i[0]
A example of how to use move_to:
#commands.command()
async def move(ctx):
channel = bot.get_channel(ID) #ID must be an INT
await ctx.author.move_to(channel)
If you want to change the channel's user limit:
channel = await guild.create_voice_channel(f"""Voice chat # {c[0]}""")
await channel.edit(user_limit=2)
If you want to check how many members are connected:
async def check_channels(ctx):
for channel_id in self.channels.keys():
channel = bot.get_channel(int(channel_id))
if len(channel.members) == 0:
await channel.delete()

Resources