Issue wit checking for time on check - python-3.x

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.

Related

Ensure a Callback is Complete in Mongo Node Driver

I am a bit new to JavaScript web dev, and so am still getting my head around the flow of asynchronous functions, which can be a bit unexpected to the uninitiated. In my particular use case, I want execute a routine on the list of available databases before moving into the main code. Specifically, in order to ensure that a test environment is always properly initialized, I am dropping a database if it already exists, and then building it from configuration files.
The basic flow I have looks like this:
let dbAdmin = client.db("admin").admin();
dbAdmin.listDatabases(function(err, dbs){/*Loop through DBs and drop relevant one if present.*/});
return await buildRelevantDB();
By peppering some console.log() items throughout, I have determined that the listDatabases() call basically puts the callback into a queue of sorts. I actually enter buildRelevantDB() before entering the callback passed to listDatabases. In this particular example, it seems to work anyway, I think because the call that reads the configuration file is also asynchronous and so puts items into the same queue but later, but I find this to be brittle and sloppy. There must be some way to ensure that the listDatabases portion resolves before moving forward.
The closest solution I found is here, but I still don't know how to get the callback I pass to listDatabases to be like a then as in that solution.
Mixing callbacks and promises is a bit more advanced technique, so if you are new to javascript try to avoid it. In fact, try to avoid it even if you already learned everything and became a js ninja.
Dcumentation for listDatabases says it is async, so you can just await it without messing up with callbacks:
const dbs = await dbAdmin.listDatabases();
/*Loop through DBs and drop relevant one if present.*/
The next thing, there is no need to await before return. If you can await within a function, it is async and returns a promise anyway, so just return the promise from buildRelevantDB:
return buildRelevantDB();
Finally, you can drop database directly. No need to iterate over all databases to pick one you want to drop:
await client.db(<db name to drop>).dropDatabase();

My Discord.js bot uses a command handler. How can I then create play/skip/pause/resume/etc commands in different files?

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

Discord Bot cannot access text files

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

webdriver-sync running asynchronously?

I'm trying to create selenium tests that run each step synchronously, without using .then(), or async/await. The reason for this is that I want to create a set of functions that allow pretty much anyone on our test team, almost regardless of tech skills to write easy to read automated tests. It looks to me like webdriver-sync should give me exactly what I want. However, the following dummy code is producing problems:
var wd = require('webdriver-sync');
var By = wd.By;
var Chromedriver = wd.Chromedriver;
var driver = new Chromedriver;
driver.get('https://my.test.url');
var myButton = driver.findElement(By.cssSelector('[id*=CLICK_ME]'));
myButton.click();
It tries to run - browser is launched, and page starts to load... but the steps are not executed synchronously - it goes on and tries to find and click "myButton" before the page has finished loading, throwing a "no such element" error... which to me kinda defeats the point of webdriver-sync?! Can someone tell me where I am going wrong?
FWIW, I have webdriver-sync 1.0.0, node v7.10.0, java 1.8.0_74, all running on CentOS 7.
Thanks in advance!
You need to put double-quotes around "CLICK_ME" as it's a string value.
Generally, though, it's a good idea to Wait for specific elements because dynamic pages are often "ready" before all their elements have been created.

Why seems my object to become NULL from one line to the next? - Could it be a hardware thing?

First thing to say: I program in a relatively unknown language: Blitzmax, which is a object oriented Basic dialect.
My problem is the following:
I wrote a debugmanager which runs in an own thread. So from every position in the program (it will be a game) you can add debug- or errormessages to the manager's queue.
In its own thread, it will fetch the messages from the queue and process them by writing them into a file and (if the message has the current chosen Debuglevel, Debugcategory and outputcategory, which are just enums) write it to the console.
Now I tested the program on three systems: My desktop PC which has Windows 8 as OS, my own laptop which has Windows 7 and the laptop of a friend which also has windows 7.
On my PC and my friend's laptop everything is fine.
But on my own laptop I get, nearly everytime, an "EXCEPTION_ACCESS_VIOLATION" Error while the manager is processing the messages.
Sometimes the program just runs fine, but most of the time it breaks down with this error.
Even in debugmode no line or stacktrace is shown which made it very hard to debug.
I broke all needed classes down to a minimum of attributes and functionality to make it easier to find the problem.
Now the queue is just a list (which is natively build in in Blitzmax) and the message just has one attribute which is a string.
Also the debugmanager only writes the message into the console without passing it to the process method which would write it to a file etc.
So the code which is actually needed is the following.
This is the message:
Type TThreadsafeMessage
Field complete_String:String
Method New_ThreadsafeMessage:TThreadsafeMessage(actual_Message:String, from_File:String, debugCategory:TDebugCategory_Enum, ..
debugLevel:TDebugLevel_Enum, outputCategory:TOutputCategory_Enum, from_Class:String = "", from_Method:String = "")
'Just create the string from the parameters.
Self.complete_String = actual_Message + " | " + from_File + "/" + from_Class + "/" + from_Method
Return Self
End Method
Method ToString:String()
'Just return the string attribute:
Return Self.complete_String' out_String
End Method
Method toString_Formatted_For_File:String()
Return Self.ToString()
End Method
Method toString_Formatted_For_Console:String()
Return Self.ToString()
End Method
End Type
This is the queue:
Type TThreadsafeQueue
'Predefined list.
Field list:TList
Method New()
Self.list = New TList
End Method
Method isEmpty:Byte()
Return Self.list.IsEmpty()
End Method
Method enqueue(to_Enqueue:Object)
'Add object to list
Self.list.AddLast(to_Enqueue)
End Method
Method dequeue:Object()
Return Self.list.RemoveFirst()
End Method
End Type
Here is the method which adds messages to the debugmanager:
Function enqueueMessage(message_To_Enqueue:TThreadsafeMessage)
'Test message for null pointer.
If(message_To_Enqueue = Null) Then
Throw New TNullpointer_Exception.NewException("'message_To_Enqueue' is NULL.", "TDebugmanager.bmx", ..
"TDebugmanager", "enqueueMessage")
EndIf
'Lock mutex for threadsafety.
LockMutex(TDebugmanager.getSingleton_Instance().queue_Mutex)
'Enqeue message in the queue
TDebugmanager.getSingleton_Instance().message_Queue.enqueue(message_To_Enqueue)
'Tell the update thread there is a message
SignalCondVar(TDebugmanager.getSingleton_Instance().sleep_ConditionVariable)
'Free the mutex for update thread.
UnlockMutex(TDebugmanager.getSingleton_Instance().queue_Mutex)
End Function
Now here is the (currently smaller) update function of the debugmanager:
Function _update:Object(thread_Object:Object)
'Do this over and over till the queue is empty AND the debugmanager is shut down
Repeat
Local message_To_Process:TThreadsafeMessage = Null
'Lock mutex for thread safety
LockMutex(TDebugmanager.getSingleton_Instance().queue_Mutex)
'Queue epmty...
If(TDebugmanager.getSingleton_Instance().message_Queue.isEmpty()) Then
'... Wait for a signal from the main thread
WaitCondVar(TDebugmanager.getSingleton_Instance().sleep_ConditionVariable, ..
TDebugmanager.getSingleton_Instance().queue_Mutex)
Else
'...Get the next message from the queue.
message_To_Process = TThreadsafeMessage(TDebugmanager.getSingleton_Instance().message_Queue.dequeue())
EndIf
'Unlock the mutex.
UnlockMutex(TDebugmanager.getSingleton_Instance().queue_Mutex)
'Check if the message is NULL.
If(message_To_Process = Null) Then
Throw "Got null message from queue."
EndIf
'Actually the _processMessage method is used. But for debugging
'it is commented out.
' TDebugmanager.getSingleton_Instance()._processMessage(message_To_Process)
'Write the message to the console.
'HERE is the error.
'See in the following description under the code section.
DebugLog("Message processed: " + message_To_Process.complete_String)
Until TDebugmanager.isFinished()
End Function
So at the position where it says in the update function 'HERE is the error.' the problem is the following: If this line is commented out or deleted, the program runs fine on my laptop and no error occures.
But if this line is there, the error occures most of the times.
An "EXCEPTION_ACCESS_VIOLATION" is thrown for example when: A stackoverflow occures somewhere. Or when you try to access to a NULL object.
Actually everything which tries to read or write from forbidden memory.
The really strange thing is: Only a few lines earlier, I check if the message which I got from the queue is NULL.
It should throw an error, as you can see.
But it never does.
Has anyone seen such a behaviour before?
I cannot explain that.
As I said: Debugging is really hard in this case. I could just break it down to smaller classes and finally the code you see here.
I also cannot just go step for step through the program with the debugger because then no error occures.
Can someone maybe think of something which can cause the error in this moment?
I know, this is much code, but I could not make it any shorter.
You are basically writing concurrently to a stream. If DebugLog is not reentrant (eg. there's some static buffer used internally), you will get random access violation. On faster machine, that could be perhaps avoided because contention will happen at the message queue, hence each thread will have the time to do a full loop on its own.
The solution is to lock the use of that function (you may want to make a function wrapper which implement that locking independently of the queue processing).
The problem was the following:
When I tried to debug the program a little bit more, sometimes the debugger kicked in and showed me where the debugger thought the error occured. It didn't occure there, but I was able to use the step-In function of the debugger.
The result was: It jumed into a library which is used for network methods. I do not use this library anywhere in the project.
So I tried a little bit further and the actual solution was: Deinstall Blitzmax and reinstall it. Now everything works fine.
Seems as if the linker was broken somehow.

Resources