How to use reaction as button in discord.py - 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)

Related

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

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```

How to change channel permissions without having a message sent first?

I have a program that changes what channel members can see at certain times of the day. To do this, I can either change the roles that every member has, or change the permissions of each channel. However, I have looked all over the web and all of the ways for either method require a message to be sent so that the data from that message can be read and put into the function, such as:
#client.command()
async def perm(ctx):
await ctx.channel.set_permissions(ctx.guild.default_role, send_messages=False
Change the permissions of a discord text channel with discord.py
or
async def addrole(ctx):
member = ctx.message.author
role = get(member.server.roles, name="Test")
await bot.add_roles(member, role)
Discord.py | add role to someone
My current program looks like this:
import discord
client = discord.Client()
import datetime
async def live_day(schedule):
current_place = "the void"
while True:
current_time = str((datetime.datetime.now() -datetime.timedelta(hours=7)).time())
int_time = int(current_time[:2] + current_time[3:5])
for x in range(len(schedule)):
try:
start_time = schedule[x][1]
end_time = schedule[x + 1][1]
except IndexError:
end_time = 2400
if current_place != schedule[x][0] and int_time >= start_time and int_time < end_time:
current_place = schedule[x][0]
#Change the channel permissions of the current place to allow viewing
#Change the channel permissions of the last channel to disallow viewing
#client.event
async def on_ready():
print("{0.user} has arrived for duty".format(client))
client.loop.create_task(live_day([
("Home", 0),
("Work", 900),
("Home", 1700),
("Nightclub", 2000),
("Home", 2200),
]))
client.run(my_secret)
Never mind the badly written code, how would I do this or where should I go to figure this out? Any help is appreciated. Thanks!
Edit: I could get the channels individually by using this,
channel1=client.get_channel(channelid)
discord.py, send message by channel id without on_message() event?
but then I can't use this for more than one server. How can I get channels by name?
Note on on_ready():
This function is not guaranteed to be the first event called. Likewise, this function is not guaranteed to only be called once. This library implements reconnection logic and thus will end up calling this event whenever a RESUME request fails.
Using this function may crash the bot.
Instead create background tasks and use wait_until_ready().
You can find examples in https://github.com/Rapptz/discord.py/blob/v1.7.3/examples/background_task.py
If you want to change only one channel's permissions (per guild) this might fit your needs:
#changing "Home" channel visibility, every day at 5 pm.
#client.event
async def on_ready():
while True:
await asyncio.sleep(1)
current_time = datetime.datetime.now()
five_pm = current_time.replace(hour=17, minute=0, second=0)
if current_time == five_pm:
for guild in client.guilds: #looping through all the guilds your bot is in
channel = discord.utils.get(client.get_all_channels(), name="Home") #getting channel by name by using "discord.utils"
await channel.set_permissions(guild.default_role, view_channel=True) #changing permissions
By using the on_ready() event you can loop through the time check without sending any message.
Remember to import discord.utils.

discord.py creating a bot that sends a specialized preset message in a text channel when specific users join a voice channel

for example when user1 connects to vc1 then "hello user1" is sent in text channel general but when user2 connects to vc1 then "hi user2" is sent in text channel general
im new to coding with discord.py and python in general what would be the easiest way to go about this
below is an example of what i have tried so far
#client.event
async def on_voice_state_update(member, before, after):
print(member)
vc = client.get_channel(id=channel id number)
vc1 = vc.members
if member in vc1[0] == "User#1234":
send msg in general text channel
Your event is well constructed from the point of view, but a little more structure would be good and also some things are completely wrong.
Have a look at the following code:
#client.event
async def on_voice_state_update(member, before, after):
channel = before.channel or after.channel
if channel.id == VoiceChannelID: # Insert voice channel ID
if before.channel is None and after.channel is not None: # Member joins the defined channel
channel1 = client.get_channel(GeneralTextChatID) # Define the general channel
await channel1.send(f"Welcome to the voice channel {member.mention}!") # Mention the member
What did we do?
Checked the channel before and after the user joined (channel=)
Checked if the joined channel matches the defined channel
Sent a message if the channel is correct
Used an f-string to mention the 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.

Resources