Discord.js Foreach loop add/removing roles - discord.js

I'm trying to create a simple command that quickly adds a certain role to all server members (or remove, depending on the command used), but I'm having a bit of an issue.
Current code:
try {
message.guild.members.filter(m => !m.user.bot).forEach((member) => {
member.removeRole(role)
});
console.log(`Role ${role.name} taken from everyone!`)
} catch {
error => console.log(error)
}
This works, but I get a lot. And I mean A LOT of errors. Mostly time errors, such as timeout: error removing role.
It says in the start that there's too much listeners, so I went online to find this .setMaxListeners(0);
But it doesn't do anything
Any help would be appreciated! Thank you

All of the behavior you described is because Discord.js needs to make so many calls to the same API endpoint concurrently, and only a certain amount can be processed at once. The loop is going through each member and calling your method again and again, and Discord.js winds up putting all these requests into a queue. When it has to wait too long to add the role, the error you see is returned. And about having too many listeners attached and the possible memory leak warning, Discord.js attaches a listener for when Discord says the role is actually removed. Because your code isn't waiting for the role to be removed for each member, a lot are attached at once.
Even if you wanted to await the member.removeRole() call, it wouldn't work in a forEach() loop because of the way it's built. It doesn't wait for your function to finish, so it just keeps going and then moves on. A for...of loop would fix this issue.
The best solution in this case might actually be to clone and then delete the role. By deleting it, it's automatically removed from every member, and you don't have to make all those calls to the API or wait for all of them. To "clone" it, you can create a new role using the old role instance as the data, adding 1 to the position (assuming the old role is there).
Also, just as a side note, the catch block of a try...catch statement doesn't use a callback function. The code inside of it is read and executed just like in the try block (only if there's an error of course). And, if you're not awaiting promises, your catch block won't actually catch rejections because everything may have already moved on (the promise is pending, so it just continues).

Related

Is there a way to refresh the channel cache in Discord.Net

I am currently writing a Discord bot.
If it doesn't exist, it is supposed to create a thread in a given channel and write some messages there.
My current way of checking is
private SocketThreadChannel ThreadIfExists(string id, SocketGuildChannel channel)
{
return Context.Guild.ThreadChannels.Where(t => t.ParentChannel == channel)
.FirstOrDefault(t => t.Name.Contains(id));
}
where id is a unique id given to each thread.
Most of the time, it works fine; if the thread doesn't exist, the function returns null, and I can create the thread myself later, and if it does, it just gets returned to me.
My problem is that if I manually delete one of said threads in discord later, the bot has them saved in cache, and it will still try to write in an unexistent thread.
The only function I could find to refresh the cache is Context.Client.PurgeChannelCache();, but it throws Object reference not set to an instance of an object, even if I check the client for null.
Restarting the bot does fix it, but that's clearly not viable after it gets released.
Is there something else I could try?
For now, I have just made a workaround with a try/catch, where I check if sending the message throws an Unknown Channel error and force the creation once again.
I am pretty sure that this is one of the worst ways of doing it, but it does work, I guess

Custom status using discord.py rewrite

This is my code
activity=discord.Game(name="Padamine", type=1)
Don’t worry, I put it in a #bot.event function. The problem is that my bot don’t put the custom status in his status. Can you help me?
Use change_presence() method to change bot status:
await bot.change_presence(activity=discord.Game("Padamine"))
If it's a static status (a status that won't change), it is recommended to use the activity keyword argument inside the bot constructor. If you want to make a dynamic status (a status that changes every now and then), use #tasks.loop of discord.ext.tasks (you can find more about tasks here)
# depending on what you name your variable, client/bot
client/bot = commands.Bot(command_prefix="yourprefix", activity=discord.Game("Padamine")) # removed type because there is no such key word argument
Also, it is recommended to not use await bot.change_presence() inside your on_ready event, I am mentioning this because many people do it and it's not good:
Discord has a high chance to completely disconnect you during the READY or GUILD_CREATE events (1006 close code) and there is nothing you can do to prevent it. As noted in the docs, on_ready is also triggered multiple times, not just once.
Basically: don't do anything in on_ready. (except printing that it came online obviously)

Error: There was a problem getting the Conversation associated with this room

I'm trying to implement this project: https://github.com/twilio/twilio-video-app-react
I got error "There was a problem getting the Conversation associated with this room." when the ChatProvider did mount. Seem like chatClient can't find the conversation with room.sid but I can't figure out how to create conversation when it doesn't exist and add participants when conversation existed. Does anyone know this issue? Thanks!
Update: the server code: https://gist.github.com/qngnud/c9910afada625a9a4eceb3ad3a67d3b7
Twilio developer evangelist here.
It appears that you are using similar code to the original app in your server, however you have missed a crucial keyword.
The part of the code where you try to fetch a conversation by the room.sid is surrounded by a try/catch, however it is called in promise form, so any failures will be picked up by a chained .catch() function.
In the original code, the calls are made using the await keyword which turns promises into code that appears synchronous and, most importantly, in which errors can be caught by a try/catch block.
So, you should either move your catch blocks to .catch() promise chains, or declare the whole function async and use await before the asynchronous function calls.
I fixed this issue by adding member in the channel before joining the twilio room.
To add member in the channel, I used the api provided by twilio => Click here.
After adding the member in the channel, ChatClient will find the conversation with roomSid.
And I used chatClient.getConversationBySid('CHXXXXXXXXXXXXXXXXXXXXXX') instead chatClient.getConversationByUniqueName(room.sid).
Happy Coding!

Overlapping Toastbar messages

I'm using the ToastBar messages with timeout 6 seconds. If I click another button within 6 seconds which will display another toastbar message, second one will overlap with first one in some instances. How can a dispose first message and display second message without overlapping if the button is clicked before timeout occurs. Please advise.
ToastBar.showErrorMessage("Test Message", 6000);
Thanks
Make sure you are always invoking this method from the EDT and not from a separate thread e.g. the network thread. Use the edt error detection tool in the simulator to try and track such issues.
I have the same issue. First I tried to make sure that I do not call each message using the same object reference, but also use local variable instances to allow the Garbage Collector (GC) dispose them since the instance is discarded when the task is done.
However, this may take some time and the message still appears overlapping or even worse, it repeats itself with out a trigger, but less likely (infrequent) now because the GC collects the object.
It may be tempting to call the GC manually if possible, but then you need to assess performance impact.
I have not attempted yet the approach I am about to suggest, but let me know what you think.
Making it so, that ToastBar messages appear one on top of the other when triggered. Maybe a List<ToastBar> object or other similar may prove useful. This may be described as a ToastBar "buffer".
The other way around is to clear() the message but then if it is too long it will not allow the user the necessary time to read the feedback.
I have this in my TODO list but will follow up when I make some additional progress.

SqlConnection.OpenAsync() hangs when there are no active connections

When I run this:
using(SqlConnection connection = new SqlConnection(connectionString)){
await connection.OpenAsync();
}
It hangs on the connection.OpenAsync() line.
If I look in Sql Server Management Studio how many connections are active for the database, there's only one: probably the one that this code uses. So, I'm not sure it is that I'm running out of connections from the app pool.
What am I doing wrong?
The problem was not the connection at all. The problem was that I shot myself in the foot with a deadlock on my threads. I was trying to make a synchronous call to the method containing the connection.OpenAsync(), like this:
Task task = MyAsyncMethod();
task.Wait();
By calling task.Wait() I was blocking the thread. When await connection.OpenAsync() returns, the rest of the method wants to run on the same thread I just blocked, so the task never finishes and task.Wait() never returns.
The solution:
Because in my async method I had nothing requiring me to stick to the same thread that called it, I simply used await connection.OpenAsync().ConfigureAwait(false), to make it run the remainder of the method in a different thread other than the one I block with task.Wait().
Another reason it could hang is because the implementation is bad. OpenAsync(CancellationToken) doesn't even use the cancellation token for the Open operation, so you can't actually cancel it. You have to wait for it to timeout. All it does is return a cancelled task if the cancellationToken was already set when you called the method, something you could check yourself without any special implementation. So this "async" overload is actually useless.

Resources