Long story short, I have been working in a bot for the past month but I had all of my commands on on_message listeners instead of context and command decorators, so I decided to do it properly, in the process of transferring my commands numerous changes have been needed, but this one has me puzzled.
The way I store user information is in text files, unfortunately on the new way of doing things it seems that I cannot access text files anymore, I looked at this code over and over and tried to troubleshoot it by making sure strings aren't empty and such, the more I looked into it the more I realized that there isn't anything wrong with it, based on other information i've looked up online, the only reason I could think of is because code is inside an async function which causes it to not work. It does not throw any exceptions for anyone wondering
If this is indeed the case, what would I have to do to fix it?
Current code:
userid = 'userfiles/' + ctx.message.server.id + '/' + ctx.message.author.id + '.txt' #get path based on user ID
try:
userfile = open(userid, 'a') #open the file from
userfile.write(i)
userfile.close()
except IOError:
await client.send_message(ctx.message.channel, 'Irrecovarable exception encountered')
return
Related
I'm trying to have my bot keep track of items that are being spawned by another bot (Mee6).
The following code gives me a None output.
#client.event
async def on_message(message:discord.Message):
if message.author.bot:
print(message.content)
The command the other bot is responding to is:
/spawn-item member={member} item={item} amount={amount}
I would like to retrieve these values.
Any help would be welcome!
Your code doesn't work, because you want to get an interaction, not a message.
Unfortunately, there is no way to get the interaction of another client. At most you can have a MessageInteraction, which gives you the name of the command used.
But in your case you can make it work since MEE6 still accepts the old command format. If you use the prefix of MEE6 instead of the / command, your code should work (with a bit of reworking: you would need to look at the message right before MEE6's response, or look if a message starts with the MEE6's prefix)
Hi I'm currently having an issue getting the time allocated for the user which is saved on a postgres database. What I'm trying to achieve is when the users duration expires a role is removed I'm wanting to get the time from the database when the check runs but this doesn't seem to be working,
My console is not outputting an error but the check doesn't seem to be running.
Here is what I'm working with:
#tasks.loop(seconds=5.0)
async def check_mute(self):
guild = self.bot.get_guild(750744359632121661)
restricted = discord.utils.get(member.guild.roles, name="Restricted")
members = discord.utils.get(member.guild.roles, name="Members")
for member in list(guild.members):
conn = psycopg2.connect(DATABASE_URL, sslmode='require')
cursor = conn.cursor()
cursor.execute("SELECT time FROM blacklist WHERE username=%s", (member.id, ))
restricted_role = get(ctx.guild.roles, name="Restricted")
muted_time = cursor.fetchone()
current_time = dt.datetime.now()
mute_elapsed_time = current_time - muted_time
if member.id:
await member.add_roles(members)
await member.remove_roles(restricted, reason=f'Restricted role removed by {author.name}')
You're not getting errors because tasks don't throw any errors by default. In order to get some info out of them, you need to write a custom error handler for them.
With that said, I do see a few issues that might cause your loop to break.
First of all, the variables ctx and author are never defined anywhere in your code fragment, but you're using them. This will throw errors & interrupt the loop.
Are you starting your loop using check_mute.start()? Tasks need to be started before they run, and your code fragment doesn't have this.
the check doesn't seem to be running
I don't see you checking the time difference anywhere. You said the check didn't happen, but it just isn't there in the first place. You're defining mute_elapsed_time, but never using it to check if enough time has elapsed or not.
After fixing those, could you put some debug prints in your task to see where it gets & when it stops? If something else is wrong, that might help identify it.
PS. This is unrelated, but you're get'ing restricted_role in the loop for every member, while you can just do that once above the loop (and you already did do it above the loop, so it's really unnecessary). You're not even using it as far as I can see so consider removing it ^^. That's also the line where the ctx is (which doesn't exist) so removing it all together might be a good idea.
I had made a discord bot a while back for a purpose involving message embeds that my friends and I needed. Long story short the bot went offline for like a year because the host (a raspberry pi) died. Fast forwarding today, we needed it again so I tried it firing it up, but noticed that most of my code doesn't work anymore, because the async branch of discord.py has been updated to v1.0 which brings major changes and requiers migration in code to comply with the new library. Looking at the documentation, I was able to figure everything out, except the embed part of my bot. Which is the most important.
This is the code I will focus on, there is more after, but it's irrelevant to this part, because if I can sucessfully store the values I am aiming for in the string, then the rest should work.
async def on_message(message):
serverid = message.guild.id
channel = message.channel
messagecontent = message.content
if message.embeds:
try:
charaname = message.embeds[0]['author']['name']
charaseries = message.embeds[0]['description']
except AttributeError:
return
What I am basically trying to do, is if a message has an embed, then I need to store the name and description values in seperate strings, for later on use in the code. But I get this trying to do so:
Ignoring exception in on_message
Traceback (most recent call last):
File "C:\discord\client.py", line 270, in _run_event
await coro(*args, **kwargs)
File "C:\path_to_script", line 35, in on_message
charaseries = message.embeds[0]['description']
TypeError: 'Embed' object is not subscriptable
Some research showed to me that 'subscriptable' means when an object can contain multiple other objects, such as lists. It's explained here better. If it's not subscriptable, then I am guessing the new library has a whole new way of handling this, which I cannot seem to figure out. So I need help understanding what exactly is going on here, so I can adapt my code and get this part working again.
Help is appreciated alot, thank you!
TypeError: 'Embed' object is not subscriptable as you can see Embed is a object and it is not subscriptable.
One of the examples of the subscriptable object is a standard dictionary. This means it's atribbutes can be accessed with ["key_name"].
For other objects to be subscriptable they need to implement the __getitem__() dunder method. Since you're getting object not subscriptable error it means that your Embed object does not implement this method.
You used to be able to access them in that way but if you look at d.py migrating page you will see that they state:
Message.embeds is now a list of Embed instead of dict objects.
So it's a list of Embed objects and if you look at current Embed documentation you will see how to access it's atributtes - for your case:
charaname = message.embeds[0].author.name
charaseries = message.embeds[0].description
So for clarification message.embeds is a list of Embed objects so with [0] we get the first element from that list, which is a Embed object.
As you can see from the documentation we can access it's description with description attribute, simple isn't it?
And if we do .author ,as seen from the documentation, we will access it's author EmbedProxy object. Now what can we access from this? If you look up the previous documentation link it states See set_author() for possible values you can access.
So let's see the documentation for set_author() , as we can see it's parameters are
name (str)
url (str)
icon_url (str)
So going by previous statement from the docs we know we can access those 3.
So this is all valid:
message.embeds[0].author.name
message.embeds[0].author.url
message.embeds[0].author.icon_url
If any of those are not set it will return Embed.Empty as seen from the docs
So if they are not set you will get Embed.Empty , one example of such embed is:
embed = discord.Embed(title="Test embed #1", description="Some description")
await ctx.send(embed=embed)
As you see the author is not set so if you fetch message.embeds[0].author.name you will get Embed.Empty while for message.embeds[0].description you will get Some description because it was set.
One example for setting author in embed:
embed = discord.Embed(title="Test embed #2", description="Some description").set_author(name=ctx.author.name)
await ctx.send(embed=embed)
(we used set_author()) - this will get us string for author name since it is set during Embed initialization.
I set up the command handler for my bot using the Discord.js guide (I am relatively new to Discord.js, as well as JavaScript itself, I'd say). However, as all my commands are in different files, is there a way that I can share variables between the files? I've tried experimenting with exporting modules, but sadly could not get it to work.
For example (I think it's somewhat understandable, but still), to skip a song you must first check if there is actually any audio streaming (which is all done in the play file), then end the current stream and move on to the next one in the queue (the variable for which is also in the play file).
I have gotten a separate music bot up and running, but all the code is in one file, linked together by if/else if/else chains. Perhaps I could just copy this code into the main file for my other bot instead of using the command handler for those specific commands?
I assume that there is a way to do this that is quite obvious, and I apologize if I am wasting peoples' time.
Also, I don't believe code is required for this question but if I'm wrong, please let me know.
Thank you in advance.
EDIT:
I have also read this question multiple times beforehand and have tried the solution, although I haven't gotten it to work.
A simple way to "carry over" variables without exporting anything is to assign them to a property of your client. That way, wherever you have your client (or bot) variable, you also have access to the needed information without requiring a file.
For example...
ready.js (assuming you have an event handler; otherwise your ready event)
client.queue = {};
for (guild of client.guilds) client.queue[guild.id] = [];
play.js
const queue = client.queue[message.guild.id];
queue.push({ song: 'Old Town Road', requester: message.author.id });
queue.js
const queue = client.queue[message.guild.id];
message.channel.send(`**${queue.length}** song${queue.length !== 1 ? 's' : ''} queued.`)
.catch(console.error);
so I'm creating a bot using Node.JS / Discord.JS and I have a question.
On some servers, when you mention a user, it returns in the console as <#!userid> and on other it returns as <#userid>.
My bot has a simple points / level system, and it saves in a JSON file as <#!userid>, so on some servers when trying to look at a users points by mentioning them will work, and on others it won't.
Does anyone have any idea how to fix this? I've tried to find an answer many times, and I don't want to have it save twice, once as <#!userid> and then <#userid>. If this is the only way to fix it then I understand.
Thanks for your help!
The exclamation mark in the <#!userID> means they have a nickname set in that server. Using it without the exclamation mark is more reliable as it works anywhere. Furthermore, you should save users with their id, not the whole mention (the "<#userid>"). Parse out the extra symbols using regex.
var user = "<#!123456789>" //Just assuming that's their user id.
var userID = user.replace(/[<#!>]/g, '');
Which would give us 123456789. Their user id. Of course, you can easily obtain the user object (you most likely would to get their username) in two ways, if they're in the server where you're using the command, you can just
var member = message.guild.member(userID);
OR if they're not in the server and you still want to access their user object, then;
client.fetchUser(userID)
.then(user => {
//Do some stuff with the user object.
}, rejection => {
//Handle the error in case one happens (that is, it could not find the user.)
});
You can ALSO simply access the member object directly from the tag (if they tagged them in the message).
var member = message.mentions.members.first();
And just like that, without any regex, you can get the full member object and save their id.
var memberID = member.id;