sorry that this is probably rather easy to fix (I don't really understand the docs)
But, I want a channel to be opened, so only the user and mods can see it. It will be opened when the user adds a reaction to the message, the reaction will then be deleted (leaving just the bot's reaction)
Currently, my code is:
#commands.Cog.listener()
async def on_reaction_add(self, reaction, user):
if reaction.emoji == '📩':
if user.channel.id == 850622999577231370:
await message.remove_reaction("📩", user)
overwrites = {
guild.default_role: discord.PermissionOverwrite(read_messages=False),
guild.me: discord.PermissionOverwrite(read_messages=True)
}
n = random.randomint(1, 1000)
await guild.create_text_channel(f'Ticket {n}', overwrites=overwrites, categoty="Tickets")
else:
pass
else:
pass
It doesn't seem to run, since there is no error message, but no channels are created either
A few things I noticed:
random.randomint does not exist, it must be random.randrange.
You didn't define guild in the provided code, we'll just use user.guild instead.
To get the channel we use if reaction.message.channel.id and not if user.channel.id, that makes little sense here.
Here is a possible new code:
#commands.Cog.listener()
async def on_reaction_add(self, reaction, user):
if reaction.emoji == '📩':
print("Reaction")
if reaction.message.channel.id == Your_Channel_ID:
await reaction.message.remove_reaction("📩", user)
guild = user.guild # We get the guild
overwrites = {
guild.default_role: discord.PermissionOverwrite(read_messages=False),
guild.me: discord.PermissionOverwrite(read_messages=True)
}
n = random.randrange(1, 1000) # We choose a number from randrange 1-1000
await guild.create_text_channel(f'Ticket {n}', overwrites=overwrites, categoty="Tickets")
else:
pass
else:
pass
Related
I've been trying to work on a system where if you run the "AWM" command, the bot will check all further messages from anyone in a given server, if the message contains a key-phrase (in this case being 's') the bot will send "FlyingWiener go brrrrrrrrrrrrr" in the same channel as the message it found. But I don't know why my code isn't working, could I please have some help? Thanks!
def MessageContentDetection(): #on_message event definition where it detects "s" in a given message's content
#bot.event
def on_message(message):
if 's' in message.content:
await message.channel.send("FlyingWiener go brrrrrrrrrrrrr")
variables = {}
Messages = {}
#commands.command() #Activation Command
async def AWM(ctx):
User = ctx.author
Owner = ctx.guild.owner
if User == Owner:
var = variables.get(ctx.guild.id, 0)
if var == 0:
variables[ctx.guild.id] = 1
await ctx.send("WienerMode Now Active!")
Messages[ctx.guild.id] = 1
else:
await ctx.send("WienerMode is still active Sherlock")
else:
await ctx.send(f"Access Denied, No access granted to **{User}**")
#bot.event #Message Send Event
async def on_message(ctx):
MSG = Messages.get(ctx.guild.id, 0)
if MSG==1:
MessageContentDetection()
#commands.command() #Deactivation Command
async def DWM(ctx):
User = ctx.author
Owner = ctx.guild.owner
if User == Owner:
var = variables.get(ctx.guild.id, 0)
if var == 1:
variables[ctx.guild.id] = 0
await ctx.send("WienerMode Nolonger Active!")
Messages[ctx.guild.id] = 0
else:
await ctx.send("WienerMode is still off Idiot")
else:
await ctx.send(f"Access Denied, No access granted to **{User}**")```
You don't need the MessageContentDetection function, instead you should just check the condition inside the existing on_message event itself as the event is running either way. It can be done this way instead:
#bot.event
async def on_message(message):
if Messages.get(message.guid.id, 0) == 1:
if 's' in message.content:
await message.channel.send('FlyingWiener go brrrrrrrrrrrrr')
This way, if the condition isn't true, the on_message event will be passed and no code runs inside that.
What I've tried
StackOverflow articles
Need help to fix a certain bug in rock, scissor and paper.
discord.py documentation
How can I add reaction to a message
(checked plenty of articles, but I'm not going to add them in order to get into the point)
I've managed to retrieve the emoji from the user in the check method, but still the issue with timeouterror appears, so there is something I'm missing which I can't get a hold on.
In this senario im using Cog,
The issue
Even though the wait_for passes the check method, I'm not sure how to send it forward to the logical conditon. The result I get is passed in the exception.
bot.py
import os
from dotenv import load_dotenv
from discord import Intents
# lib
from lib.cog.miniGames import miniGames # Games
from lib.client.krigjo25 import krigjo25
# Importing .evn file
load_dotenv()
def botSetup ():
# necsessary values from .env
botKey = os.getenv('Token')
server = os.getenv('server')
# discord configs
intents= Intents.all()
#retrieving the module command prefix is created in the bot module
bot=krigjo25(intents=intents)
# adding cogs into the bot
bot.add_cog(miniGames(bot))
bot.run(botKey)
if __name__ == '__main__':
botSetup()
miniGames.py
class miniGames(Cog, name='miniGames module'):
def __init__(self, bot):
self.bot = bot
#command(name='rsp')
#Cog.listener()
# 1: Creating a game where the user has three choices to choose between from
# 2: The bot adds 3 reactions, where you have to choose one of them as an answer
# 3: The bot checks wheter the conditions is true or false, in order to send the correct messge:
async def RockscissorsPaper(self, message:Message):
# Declearing variables
# Rock, Scissors, Paper
rock,scissor, paper = '\U0001FAA8', '\U00002702','\U0001F4C4'
answer = { 0:'\U0001FAA8',
1:'\U00002702',
2:'\U0001F4C4'}
# Randomizing the answer and assign it to the variable
shuffle(answer)
x = randrange(0,2)
answer = '\U0001FAA8' #answer.get(x)
print(answer)
# Creating Embed message
embed = Embed(color = Color.blurple())
embed.title = 'Rock, Scissors & Paper'
embed.description = ' In order to play the game, please click one one of the following reactions'
# Sending & adding reactions
ch = await message.channel.send(embed=embed)
await ch.add_reaction(rock)
await ch.add_reaction(scissor)
await ch.add_reaction(paper)
# passes the check method
def check( user, reaction):
print('check function', reaction, user)
return user == message.author and reaction == str(reaction.emoji)
# Checks the user's input¨'
# Questions : Is it possible to use dictionaries in order to find the given emoji?
try :
# How does this work? If wait_for is a "asynico" function how can it work like this?
reaction, user = await self.bot.wait_for('reaction_add', timeout=30, check=check)
except TimeoutError as e:
print(e)
else:
reaction = str(reaction.emoji)
# Checking if its the bots reaction
if user == self.bot.user:
return None
else:
if reaction == '\U0001F4C4' and answer == '\U0001FAA8':
await message.channel.send(' you won')
Add this at the beginning of your code:
intents = discord.Intents.all()
Then add this into your discord.Bot's declaration:
bot = discord.commands.Bot(prefixes=['!'], intents=intents)
Then go to Discord Developer Portal and enable all the intents writing from the Application's "bot" page.
can u remove this line?
#command(name='rsp')
--> #Cog.listener()
# 1: Creating a game where the user has three choices to choose between from
What is this listener supposed to answer?
It appears that i had to change :
def check( user, reaction):
print('check function', reaction, user)
return user == message.author and reaction == str(reaction.emoji)
New
def emojiCheck(reaction, member):
reaction = str(reaction)
member == ctx.author.name
# Do not return the bot's last reaction
return member !=self.bot.user and reaction
--
I also had to add the code block in the try - except statement.
** OLD **
try :
# How does this work? If wait_for is a "asynico" function how can it work like this?
reaction, user = await self.bot.wait_for('reaction_add', timeout=30, check=check)
except TimeoutError as e:
print(e)
else:
reaction = str(reaction.emoji)
# Checking if its the bots reaction
if user == self.bot.user:
return None
else:
if reaction == '\U0001F4C4' and answer == '\U0001FAA8':
await message.channel.send(' you won')
New
try:
# Timer Check
reaction, member = await self.bot.wait_for('reaction_add', timeout=60.0, check=emojiCheck)
print(member, reaction, answer)
# Dictionaries
# Tie
tie = {
0:f'{self.bot.user} draws a **tie** for {member}',
1:'Sir, lets **tie** a **tie**',
2:'What did the **tie** say to the bowtie? You\'re a weirdo',
3:'lets have a wii-match',
}
reactionRock = {
}
# Randomize the dictionary
shuffle(tie)
x = randrange(0,3)
tie = tie.get(x)
# If the situation is a draw / tie
if str(reaction) == answer:
self.embed.description = tie
await ctx.send(embed = self.embed)
The point is if-elif or else statement has to be inside the try-except statement.
Hope this is for help for other developers which has the same issue.
Thanks for the assistance which I received. Its appreciated.
What i am specifically looking for is that i want is for the exception to be thrown on ("you must mention someone to x") and for the exception of if the person isn't in the guild to throw that message instead of using the cooldown.
#tasks.loop(count=1)
async def load_interaction_commands(self):
""" Load interaction commands. """
self.bot.interaction_commands = []
cooldown = commands.Cooldown(1, 600, commands.BucketType.user)
mapping = commands.CooldownMapping(cooldown)
for cmd, aliases in COMMANDS.items():
async def interaction_callback(cls, ctx, user: discord.Member):
if not user:
await ctx.send(f"You must mention someone to {ctx.command}.")
elif user == ctx.author:
await ctx.send("You can't {} yourself, silly!".format(ctx.command.name))
elif not discord.utils.find(lambda m: m.id == user.id, ctx.guild.members):
await ctx.send("you cant {} someone not in the server silly!")
else:
await cls.interact(ctx, user)
interaction_callback = commands.command(name=cmd, aliases=aliases)(interaction_callback)
interaction_callback._buckets = mapping
interaction_callback.__commands_cooldown__ = cooldown
interaction_callback.cog = self
self.bot.add_command(interaction_callback)
self.bot.interaction_commands.append(interaction_callback)
I currently have a function which is polling a message for reactions and adding users to a list based on that using Discord.py. Here is the code below:
#commands.Cog.listener()
async def on_message(self, message):
editMessage = message
tankBoosters = []
healBoosters = []
dpsBooster = []
boosters = []
# we do not want the bot to reply to itself
if message.author != self.bot.user:
return
if len(message.embeds) > 0:
for embed in message.embeds:
if "Boost is Ready" in embed.fields:
return
else:
pass
for x in message.embeds:
if '<:tank:801416324306829312>' and '<:healer:801416334243921971>' and '<:dps:801416343848615947>' in x.description:
await message.add_reaction('<:tank:801416324306829312>')
await message.add_reaction('<:healer:801416334243921971>')
await message.add_reaction('<:dps:801416343848615947>')
embedToEdit = x
def check(reaction, user):
return str(reaction.emoji) in ['<:tank:801416324306829312>', '<:healer:801416334243921971>', '<:dps:801416343848615947>'] and user != self.bot.user
boosters = tankBoosters + healBoosters + dpsBooster
while len(boosters) != 4:
if len(boosters) != 4:
reaction, user = await self.bot.wait_for('reaction_add', check=check)
print(message.reactions)
if reaction.emoji.name == 'tank' and len(tankBoosters) == 0:
tankBoosters.append(user)
if reaction.emoji.name == 'healer' and len(healBoosters) == 0:
healBoosters.append(user)
if reaction.emoji.name == 'dps' and len(dpsBooster) < 2:
dpsBooster.append(user)
if len(tankBoosters) == 1 and len(healBoosters) == 1 and len(dpsBooster) == 2:
message = f"<:tank:801416324306829312> {tankBoosters[0].mention} \n <:healer:801416334243921971> {healBoosters[0].mention} \n <:dps:801416343848615947> {dpsBooster[0].mention} \n <:dps:801416343848615947> {dpsBooster[1].mention}"
embedToEdit.add_field(name="Boost is Ready", value=message, inline=False)
await editMessage.edit(embed=embed)
This is working fine, but what I need to do be able to do is remove users from the respective lists (tank, heal and dps) when a reaction is removed from the message.
I.e. a message is posted and 3 tanks, 2 healers and 6 DPS "sign up" to the message by posting reactions to the message and they are appended to their respective lists. Then 1 tank and 2 DPS "unsign" by removing their reaction to the message. I need to remove those users from the list when they remove their reaction. I have looked into using message.reactions[0].users() but according to the VS Code debug terminal, message.reactions[0].users() is <discord.iterators.ReactionIterator object at 0x011B5DF0>
, which I unfortunately don't know enough about python or discord to understand!
I think you can try this:
#bot.event
async def on_raw_reaction_remove(payload):
reaction = str(payload.emoji)
msg_id = payload.message_id
user_id = payload.user_id
guild_id = payload.guild_id
exists = db.exists(msg_id)
When someone remove his reaction, you know what reaction, the user ID...
For those interested, or frustratedly searching for answers on how to do this, I ended up changing my approach slightly. Instead of doing all the logic inside the on_message function, I removed that and used on_raw_reaction_add and on_raw_reaction_remove instead, and I am tracking users by storing them in global arrays which are emptied once certain conditions are met.
This does mean that the code can only handle looking at one post at a time, but thats all I need it to do for now :)
If user add reaction :HotS_Tank: in a special message, the bot will need to give this role to user, but I do not have any idea how to do it...
That's what I have tried:
async def role_background_task():
await client.wait_until_ready()
roleChannel = discord.Object(id='411270826374070293')
roleMSG1 = client.get_message(roleChannel, id='411657109860515840')
roleMSG2 = client.get_message(roleChannel, id='411657144488689674')
while not client.is_closed:
reac1 = await client.wait_for_reaction(emoji=':HotS_Tank:411445724287598592',message=roleMSG1)
if reac1.reaction.emoji == ':HotS_Tank:411445724287598592':
await client.add_roles(reac1.user, roleHOTS_Tank)
client.loop.create_task(role_background_task())
If you check the documentation, there's an event called on_reaction_add here. You can simply use that.
#client.event
async def on_reaction_add(reaction, user):
roleChannelId = '411270826374070293'
if reaction.message.channel.id != roleChannelId:
return #So it only happens in the specified channel
if str(reaction.emoji) == "<:HotS_Tank:411445724287598592>":
await client.add_roles(user, roleHOTS_Tank)