How do i remove a specific user's reaction from a message? - python

I am making a command that will randomly pick a user from a message's reaction (similar to giveaway command). I tried to add a feature that will remove the chosen user's reaction once the user is chosen by the bot but it didn't work. I am new to the world of discord bot, please help me.
Here are the codes:
#client.command()
async def king(ctx):
time = 10
embed = nextcord.Embed(title="King's Game", description="React to join.")
embed.set_footer(text=f"Ends in {time}s")
kmsg = await ctx.send(embed=embed)
await kmsg.add_reaction("πŸ‘‘")
await asyncio.sleep(time)
new_msg = await ctx.channel.fetch_message(kmsg.id)
players = await new_msg.reactions[0].users().flatten()
players.pop(players.index(client.user))
print (players)
king = random.choice(players)
tembed = nextcord.Embed(title="Time is up!", description="Get ready to obey the king.")
kembed = nextcord.Embed(title="King", description=f"{king.mention} is the king!")
await ctx.send(embed=tembed)
ktime = 2
await asyncio.sleep(ktime)
await ctx.send(embed=kembed)
kingid = get(king.user.id)
await kmsg.remove_reaction(kingid)

You should read about await remove_reaction(emoji, member) from the official documentation.
You have to simply specify the member of which remove the reaction.

Related

How do I check which reaction inthe message is higher in Discord.py?

So basicly, I'm creating a command that let you vote for something and after 5 min it will check which is higher.
But the problem is I don't know how to do that.
Here is my code so far:
#client.command()
async def strongy_boi(ctx, boi):
if boi == "copper-golem-allay":
mess = await ctx.send(":heart: = copper golem :blue_heart: = allay")
await mess.add_reaction('❀️')
await mess.add_reaction('πŸ’™')
await asyncio.sleep(5)
#do code that check which is higher
One way you can do this is to access the message reactions through discord.Message.reactions and iterate through them, checking the discord.Reaction.count and comparing with the current highest. To check for reactions, however, a message needs to be cached, which can be done through await fetch_message(). Do view the revised code and further explanations below.
#client.command()
async def strongy_boi(ctx, boi):
if boi == "copper-golem-allay":
mess = await ctx.send("❀️ = copper golem πŸ’™ = allay")
await mess.add_reaction('❀️')
await mess.add_reaction('πŸ’™')
await asyncio.sleep(5)
# new code starts here #
msg = await ctx.channel.fetch_message(mess.id) # 'Cache' the message
# create variables to save the highest reactions
highest_reaction = ""
highest_reaction_number = 0
# msg.reactions format:
# [<Reaction emoji='❀️' me=True count=2>, <Reaction emoji='πŸ’™' me=True count=1>]
for reaction in msg.reactions: # iterate through every reaction in the message
if (reaction.count-1) > highest_reaction_number:
# (reaction.count-1) discounts the bot's reaction
highest_reaction = reaction.emoji
highest_reaction_count = reaction.count-1
await ctx.send(f"{highest_reaction} wins with {highest_reaction_count} votes!")
Other Links:
Count reactions on a message - Stackoverflow
How do I count reactions on a message in discord py? - Stackoverflow
Reactions counting - Stackoverflow
Get a List of Reactions on a Message - Stackoverflow

How Can You Turn Off An Event Through A Command? Discord.py

Im currently trying to make the reaction in the bot response to turn off an moderation event which listens to messages being deleted. This will work as a filter so if the user dont want to log deleted messages they can turn it off by reacting. I've heard of the wait for and the dispatch function but i currently dont know how it works and couldnt find a tutorial. Any feedback would be amazing as i am a bit stuck and willing to listen to anyone.
Current Code;
import discord
from discord.ext import commands
import datetime
class log(commands.Cog):
def __init__(self,bot):
self.bot = bot
mess = False
#commands.Cog.listener()
async def on_reaction_add(self, reaction, user):
channel = reaction.message.channel
guild = channel.guild
message = reaction.message
if user != self.bot.user:
if reaction.emoji == '1️⃣':
check = discord.utils.get(guild.categories, name="Chilly Logs") # Find the Category
if not check: # If category doesnt exist create the logs
cat = await channel.guild.create_category_channel('Chilly Logs')
await channel.guild.create_text_channel("Message Logs", category=cat) # Message Logs
await channel.guild.create_text_channel("Other Logs", category=cat) # Other Logs
await channel.send('**Log Channels Were Succesfully Added!**')
await message.remove_reaction('1️⃣', user)
return
else:
await channel.send('**Log Channel Already Exists**')
await message.remove_reaction('1️⃣', user)
if reaction.emoji == '2️⃣':
channel1 = discord.utils.get(guild.channels, name="other-logs") # Other Logs
channel2 = discord.utils.get(guild.channels, name="message-logs") # Message Logs
category = discord.utils.get(guild.categories, name="Chilly Logs") # Category/Parent
if category is not None: # Deletes All The Channels
await channel1.delete()
await channel2.delete()
await category.delete()
await channel.send('**Logging Channels Have Been Removed**')
await message.remove_reaction('2️⃣', user)
else:
await channel.send('**Channels Either Dont Exist Or Have Been Renamed**')
await message.remove_reaction('2️⃣', user)
if reaction.emoji == '❗':
#commands.command()
async def test(self, ctx):
embed = discord.Embed(title = "Chilly Logging", description = "Chilly Will Log Any Edited, Deleted Messages. More Features & Flexibility Coming Soon", colour = discord.Color.blurple())
embed.add_field(name="β€Žβ€Žβ€ŽLogging Commands β€Žβ€Žβ€Ž", value="1️⃣ - Turn On Server Logging", inline=True)
embed.add_field(name="β€Ž β€Ž", value= "2️⃣ - Delete & Turn Off Logging", inline=False)
msg = await ctx.send(embed=embed)
emoji = ['1️⃣', '2️⃣', '❗']
response = 3
for i in range(response):
await msg.add_reaction(emoji[i])
#commands.Cog.listener()
async def on_message_delete(self, message):
if x == True:
if not message.author.bot: # Checks for bot message
channel = message.channel.name # Channel the deleted message is from
logchannel = discord.utils.get(message.guild.channels, name='message-logs') # Finds the log channel
embed = discord.Embed(title="Message Log", description="", color= discord.Color.red()) # Embeds
embed.add_field(name="Message sent by {} has been deleted in `{}`" .format(message.author.display_name, channel), value=message.content, inline=True,)
embed.set_footer(text='User ID: {} | Message ID: {}' .format(message.author.id, message.id))
await logchannel.send(embed=embed) # Finally sends the embed to log channel
#commands.Cog.listener()
async def on_message_edit(self, before, after):
if not after.author.bot:
if before.content != after.content:
channel = after.channel.name # Channel the edited message is from
logchannel = discord.utils.get(after.guild.channels, name='message-logs') # Finds the log channel
embed = discord.Embed(title="Message Log", description="Message edited in `{}` by {}" .format(channel, after.author.display_name), color= discord.Color.red()) # Embeds
embed.add_field(name="Before", value=before.content, inline=True,)
embed.add_field(name="After", value=after.content, inline=False,)
embed.set_footer(text='User ID: {} | Message ID: {}' .format(after.author.id, before.id))
await logchannel.send(embed=embed) # Finally sends the embed to log channel
def setup(bot):
bot.add_cog(log(bot))```
You could use a global variable. Simply:
Toggle = True
#bot.command()
async def toggle(ctx):
global Toggle
# Toggles the variable.
Toggle = !Toggle
# Example event
#bot.event
async def on_message(message):
if Toggle:
# Event's code
else:
await message.channel.send("Function disabled")

How do I get the content from an old message/command with my discord bot?

I am currently trying to edit an embed with a command. The edited embed has a clear structure. It is supposed to be an evaluation of the suggestion. For this I need the author and his suggestion from the previous command. Is it possible to take the content of the old embed and transfer it to the edited embed if you have two commands? In addition, it would be good to still count and insert the reactions at the message.
Here are my working approaches, except for the missing parts:
##commands.cooldown(1, 100, BucketType.user)
#commands.command(usage="<text>")
async def suggest(self, ctx, *, text: str = None):
"""This is the command for suggestions."""
if text is None:
await ctx.send("**You need to insert a text.**")
return self.suggest.reset_cooldown(ctx)
channel1 = self.bot.get_channel(812284187427864616)
if channel1 == ctx.channel:
channel = self.bot.get_channel(812283430707920906)
e = discord.Embed(color=discord.Colour.green())
e.description = f "**__submitter:__**\n {ctx.author}"
e.add_field(name="__Suggestion:__", value=f"{text}")
e.set_thumbnail(url=ctx.message.author.avatar_url)
e.timestamp = datetime.utcnow()
e.set_footer(text=f "UID: {ctx.author.id}")
feedback = await channel.send(embed=e)
await feedback.add_reaction("βœ…")
await feedback.add_reaction("❌")
await ctx.message.add_reaction("βœ…")
The approve command which actually edits the old embed and should insert "Suggestion", "Submitter" and count the reactions.
#commands.command()
async def approve(self, ctx, msg_id: int = None, channel: discord.TextChannel = None):
if not msg_id:
channel = self.bot.get_channel(812283430707920906) # the message's channel
msg_id = 998877665544332211 # the message's id
elif not channel:
channel = ctx.channel
msg = await channel.fetch_message(msg_id)
embed = discord.Embed()
embed.title = "Suggestion accepted"
embed.description = "*Here are all the important information*"
embed.add_field(name="Results", value="βœ…: MISSING COUNT / ❌: MISSING COUNT")
embed.add_field(name="Suggestion", value=f"MISSING SUGGESTION TEXT")
embed.add_field(name="Submitter:", value=f"MISSING SUBMITTER")
embed.add_field(name="Approved by:", value=f"{ctx.author.mention}")
await msg.edit(embed=embed)
await msg.clear_reactions()
To count the reactions I would use something like:
total_count = 0
for r in message.reactions:
total_count += r.count
EDIT:
This is the embed right now with showing Suggestion two times in different ways.
#commands.command()
async def approve(self, ctx, channel: discord.TextChannel, msgID: int):
try:
msg = await channel.fetch_message(msgID)
embed = msg.embeds[0]
submitter = embed.description[embed.description.find('\n'):]
suggestion = embed.fields[0].value
embed.title = "Suggestion accepted"
embed.description = "*Here are all the important information*"
embed.add_field(name="Results", value="βœ…: Test/ ❌: Test", inline=False)
embed.add_field(name="Suggestion", value=f"{suggestion}", inline=False)
embed.add_field(name="Submitter", value=f"{submitter}", inline=False)
embed.add_field(name="Approved by", value=f"{ctx.author.mention}", inline=False)
await msg.edit(embed=embed, reference=msgID)
await msg.clear_reactions()
except:
pass
msg = await channel.fetch_message(msg_id)
You can use the fetched message to get details about it.
try:
msg = await channel.fetch_message(msg_id)
embed = msg.embeds[0]
submitter = embed.description[embed.description.find('/n'):] # get submitter name
suggestion = embed.fields[0].value
# other stuff
except:
pass
# possible exceptions message not found, list index out of range(if wrong msg id with no embeds passed as arg)
References:
fetch_message
embeds
message

send questions in dm, and post answers in embed to a channel discord.py

I am trying to make it where when the user initiates the command $createprofile the bot will dm the user with the questions provided in the list, one after the other then post the answers in an embed to a specified channel. Now I have already built the list, but I am unsure of how to build in asking each question one after another, I am possibly thinking of using asyncio wait_for
import discord
from discord.ext import commands
import platform
import cogs._json
class Profile(commands.Cog):
def __init__(self, bot):
self.bot = bot
#commands.Cog.listener()
async def on_ready(self):
print("Profile Cog has been loaded\n-----")
# #commands.command(aliases=['pm'])
# async def dm(self, ctx, user: discord.User, *, message=None):
# message = message or "This message is sent via dm"
# await user.send(message)
# await ctx.message.delete()
#commands.command()
async def createprofile(ctx, member: discord.Member = None):
userName = ""
userAge = ""
questions = [
"Please input your name/nickname:",
"Please input your age:"
]
dmChannel = await ctx.author.send(
"You will be receiving two questions. One involving your name and the other your age.")
def check(message):
return message.author == ctx.author and message.channel == dmChannel.channel
async def askQuestion(question):
await ctx.author.send(question)
print("Waiting for reply...")
userReply = await client.wait_for('message', check=check)
print("User replied")
return userReply.content
userName = await askQuestion(questions[0])
userAge = await askQuestion(questions[1])
e = discord.Embed(title=str(userName) + "'s Profile", description=f"""
Age: `{str(userAge)}`
""")
await ctx.send(embed=e)
def setup(bot):
bot.add_cog(Profile(bot))
#client.command()
async def createprofile(self, ctx, member: discord.Member = None):
userName = ""
userAge = ""
questions = [
"Please input your name/nickname:",
"Please input your age:"
]
dmChannel = await ctx.author.send(
"Yo will be receiving two questions. One involving your name and the other your age.")
def check(message):
return message.author == ctx.author and message.channel == dmChannel.channel
async def askQuestion(question):
await ctx.author.send(question)
print("Waiting for reply...")
userReply = await client.wait_for('message', check=check)
print("User replied")
return userReply.content
userName = await askQuestion(questions[0])
userAge = await askQuestion(questions[1])
e = discord.Embed(title=str(userName) + "'s Profile", description=f"""
Age: `{str(userAge)}`
""")
await ctx.send(embed=e)
First, you need to send the user a question, so how you do that is through await ctx.author.send("this is a question"). You then store that message into a variable. You then create a check function that makes sure that the user who replied is in fact the user who sent the $createprofile message in the first place. You will also need to check if the message's channel is the dm channel. So that's where the message you stored earlier takes action. It will make sure that the channel of the message is the same as the channel of the dm message you sent to the user earlier. After that, you create an async function to ask a question. From there on it's pretty straightforward. Feel free to optimize your code using for loops. Hope this helps.

Discord.py Listening for a Message after a Command

I've been trying to create a bot command that listens for a message after the command is sent. This is meant to be used to create a profile of the command author to later store in a JSON file.
#client.command() #creates player profile
async def create(ctx):
await ctx.send("You will be asked a series of questions to create your Profile. If you accidentally typed this wait 15 seconds for it to cancel.")
message = await client.wait_for('message',check=None,timeout=15)
await ctx.send(message) #used to check what message is holding
While the code above works, it doesn't work as I want it to. It sends back the id's of the server, member, channel, message, and the author, along with other information, instead of holding the reply by the command author.
So, what you want is to store the user's input data and append them as like an interview form:
It takes the user's input messages and appends them to the message they answered like:
q_list = [
'Your question 1',
'Your question 2',
'Your question 3']
a_list = []
#client.command()
async def create(ctx):
await ctx.send("You will be asked a series of questions to create your Profile. If you accidentally typed this wait 15 seconds for it to cancel.")
a_list = []
submit_channel = client.get_channel(CHANNEL_ID_FOR_SUBMISSIONS)
channel = await ctx.author.create_dm()
def check(m):
return m.content is not None and m.channel == channel
for question in q_list:
await asyncio.sleep(3)
await channel.send(question)
msg = await client.wait_for('message', check=check)
a_list.append(msg.content)
submit_wait = True
while submit_wait:
await channel.send(
'You have completed the interview, type ``submit`` to confirm')
msg = await client.wait_for('message', check=check)
if "submit" in msg.content.lower():
submit_wait = False
answers = "\n".join(f'{a}. {b}' for a, b in enumerate(a_list, 1))
submit_msg = f'''**Submission - Created by {msg.author.mention}** \n{answers}'''
await submit_channel.send(submit_msg)

Categories

Resources