'RawReactionActionEvent' object has no attribute 'author Issue with adding a cooldown on event - discord.py

I'm trying to add a cooldown to a on_raw_reaction_add event in discord.py. I'm trying to do this by using cooldown mapping. The result should be to limit how many times this message
embed.description = f"It looks like you're joining us on a newly registered account. Verification requires accounts to be atleast a day old so please stick around and try again at {test_time.time().strftime(format)}."
is sent to a user if they don't meet the account age upon adding a reaction, which should be one reaction before the cooldown kicks in.
The error I get is 'RawReactionActionEvent' object has no attribute 'author not sure why this is happening.
Here is the full code I'm working with:
#commands.Cog.listener()
async def on_raw_reaction_add(self, payload): # Will be dispatched every time a user adds a reaction to a message the bot can se
general = self.bot.get_channel(701547632354525249)
introductions = self.bot.get_channel(705068046267580566)
botroom = self.bot.get_channel(706610280032894996)
if not payload.guild_id:
# In this case, the reaction was added in a DM channel with the bot
return
guild = self.bot.get_guild(payload.guild_id)
author = guild.get_member(payload.user_id)
bucket = self._cd.get_bucket(payload)
retry_after = bucket.update_rate_limit()
seconds = bucket.update_rate_limit()
seconds = round(seconds, 2)
hours, remainder = divmod(int(seconds), 3600)
minutes, seconds = divmod(remainder, 60)
if retry_after:
verification_error = f"You can do that again in **{minutes}m {seconds}s**."
embed = discord.Embed(title="You have already verified.", description=verification_error, colour=discord.Colour(0xff8100))
await message.channel.send(embed=embed)
pass
if payload.message_id != 743841858727444550:
return
else:
guild = self.bot.get_guild(payload.guild_id) # You need the guild to get the member who reacted
member = guild.get_member(payload.user_id) # Now you have the key part, the member who should receive the role
if payload.emoji.id != 743077610115956816:
reaction = payload.emoji.id
role = discord.utils.get(guild.roles, name="Members")
newbies = discord.utils.get(guild.roles, name="Newbies")
restricted_role = discord.utils.get(guild.roles, name="Restricted")
role = discord.Object(743840972068356116) # Pass the role's ID here
else:
return
if restricted_role in member.roles:
return
if member.created_at + dt.timedelta(days=30) <= dt.datetime.today():
await member.add_roles(role, reason='New member verified') # Finally add the role to the member
await member.add_roles(newbies, reason='New member verified') # Finally add the role to the member
welcome = f'Welcome {member.mention}! feel free to get started with adding some <#706648361196978177>'
intros = f'Hey {member.mention}! now that you\'re a member of our group, maybe you\'d like to tell us a bit about yourself. Tell us an interesting fact about yourself and so on... As always keep it sensible and fun.'
await general.send(welcome)
sent = await introductions.send(intros)
await asyncio.sleep(900)
await sent.delete()
else:
format = '%I:%M%p'
member1 = member.created_at.strftime("%I:%M%p")
dt3 = dt.datetime.strptime(member1, format)
test_time = dt3 + dt.timedelta(minutes = 1500)
embed = discord.Embed(colour=discord.Color(0x7289DA))
embed.title = f"Hey there {member.display_name}!"
embed.description = f"It looks like you're joining us on a newly registered account. Verification requires accounts to be atleast a day old so please stick around and try again at {test_time.time().strftime(format)}."
await member.send(embed=embed)
Help would be appreciated.

Under your #client.command statement just add
#commands.cooldown(1, 30, commands.BucketType.user)
This example will give a single user a cool down of 30 seconds for 1 use. You can configure BuckType to channel and server as well.

Related

How to rig a bot's command to only a certain user

I've been making this pp size machine, which is somewhat like dank memer's one
#client.command()
async def pp(ctx,member : discord.Member):
size=random.randint(1,10)
message = "8"
for x in range (size):
message= message + "="
if x == size-1:
message = message + "D"
if member == "PROTATO#6826":
message = "8D"
ppsize = discord.Embed(color=discord.Colour.orange(), title=f"PP size",description=f"""{member}'s penis
{message} """)
await ctx.send(embed = ppsize)
But i want to rig the command for a certain user to only show "8D" instead of the random lengths.
But no matter what it is the
if member == "PROTATO#6826":
message = "8D"
code doesnt run or gets over looked?
Can someone help me out with this?
You can check if the member mentioned has the same id as a specific user. You can either enable developer mode on discord, or you can print the member.id at the very beginning. Do view a code example below.
#client.command()
async def pp(ctx, member: discord.Member):
print(member.id) # this would print a user's unique id
message = "Hey!"
if member.id == 394506589350002688: # replace this id with what was printed at the start
message = "Hello!"
await ctx.send(message)
Similar Questions:
How to check if message was sent by certain user? - SO
How do I detect if the message is sent by a specific user id? - SO

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.

Is there a way to record the specific user of a command for future use without a database?

So I'm working on a discord bot using discord.py and I'm trying to create a bot for the moderation team in a server, the bot will swap the 'Moderator' role with a 'Leave of absence' role for when they're not active, however the code I have come up with has a slight loopholing problem that I just can't figure out, the code for the commands is this
...
#client.command()
#commands.has_role('Moderator')
async def sl(ctx, member: discord.Member = None):
if not member:
member = ctx.author
loa = ctx.guild.get_role(848032714715561985)
mod = ctx.guild.get_role(848032880709074944)
await member.add_roles(loa)
await member.remove_roles(mod)
await ctx.send("I have filed your Leave, take care, we look forward to your return!")
#client.command()
async def sr(ctx, member: discord.Member = None):
if not member:
member = ctx.author
mod = ctx.guild.get_role(848032880709074944)
loa = ctx.guild.get_role(848032714715561985)
await member.add_roles(mod)
await member.remove_roles(loa)
await ctx.send("Welcome back!")
...
as you can see anyone could use the second command to just give themselves a moderator role, I can't set the second command to be moderator only use as the moderator will no longer have said role from using the first command, I'm racking my brain to think of a work around i.e. logging the command users id to a whitelist and having only those whitelisted id's be able to use the second command, I've done many googlesearches for this but have come back with no results, any suggestions would be appreciated, please forgive that this question is a bit lengthy and I'm still very new to coding in general so any help at all, even if you don't fully understand what I'm blabbering on about would be very appreciated, thank you.
Check for the loa role in the command (ex):
mod = None
for role in ctx.author.roles:
if role.id == 848032714715561985: mod = True
if mod:
#your code here
So from your question, I'm guessing that you would like to code basically a "storage" file and make sure the person on the leave of absence was previously a moderator.
What you could do is create a csv file, for example records.csv (in the same folder as your main .py file of course), and every time someone calls the sl command, the program will record the user that used it.
import csv
#client.command()
#commands.has_role('Moderator')
async def sl(ctx, member: discord.Member = None):
if not member:
member = ctx.author
loa = ctx.guild.get_role(848032714715561985)
mod = ctx.guild.get_role(848032880709074944)
await member.add_roles(loa)
await member.remove_roles(mod)
file = open("records.csv", "w")
file.writelines(str(ctx.author.id))
file.close()
await ctx.send("I have filed your Leave, take care, we look forward to your return!")
#client.command()
async def sr(ctx, member: discord.Member = None):
if not member:
member = ctx.author
mod = ctx.guild.get_role(848032880709074944)
loa = ctx.guild.get_role(848032714715561985)
found = False
with open('records.csv', 'r') as file:
reader = csv.reader(file)
for row in reader:
if row[0] == str(ctx.author.id):
found = True
break
if found = False:
await member.add_roles(mod)
await member.remove_roles(loa)
await ctx.send("Welcome back!")
else:
await ctx.send("We do not have history of you having a moderator role.")
Are you running the program through an online environment like Repl.it? If so, this may not be the best way to approach this problem since people would have access to your this records.csv file (which you may not care about but just in case). If you are running the program through your desktop file directories, then there should be no privacy concerns.

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

Problem with (AttributeError) client.logs_from

i was creating bot for discord channel. But I don't understand where i have wronged or errored in my code
I was do from tutorial but in video this wrong not present. Then I search this problem in another tutorial, but i don't have result pls help
#client.command(pass_context=True, name='clear', aliases=['purgemessages'], no_pm=True)
async def clear(ctx, number):
number = int(number)
if number > 99 or number < 1:
await ctx.send("Sorry comrade>-< \n But i can deleted message within a range of 1 - 99")
else:
author = ctx.message.author
authorID = author.id
mgs = []
number = int(number)
channel = ctx.message.channel
async for x in client.logs_from((channel), limit = int(number)):
mgs.append
await ctx.message.channel.delete_messages(ctx, member, mgs)
await ctx.send("This was deleted ^^")
I want a bot to delete messages
You should use client.purge() to do it.
It seems that you're looking for a way to delete the command caller's messages (a.k.a author).
Here's a quick example using purge() method :
author = ctx.message.author
# check function
def is_caller(message):
if(message.author.id == author.id):
return(True)
else:
return(False)
# delete the author's messages
# the purge method returns a list of deleted messages
deleted_message = await client.purge(
limit = number,
check = is_caller
)
await ctx.send(f"{len(deleted_message)} messages deleted.")
The limit is represented by the number parameter of your command.
Hope it helped !

Resources