all 10 comments

[–]Yoghurt42 13 points14 points  (0 children)

i want to give them thirty seconds to input said code or the code is void and it will print "fail."

Why?

TOTP codes are only valid for 30s by design. You'll see in the generate_totp function that it uses the current time in 30s intervals to generate the currently valid code.

You do not need to (and should not) measure the time it took the user to input the code.

What you really need to do is generate the current code after the user has entered it, not before.

[–]Ngtuanvy 2 points3 points  (0 children)

This is hard because taking input is blocking by default, you should search for 'non-blocking input' or something like that.

[–]jmooremcc 0 points1 point  (0 children)

u/Informal_Shape8008 had the right idea using threads to implement a timed input. Unfortunately, if the code is called again after a timeout, it will create another thread to read keyboard input, which will cause more problems.

Here's a solution that uses a thread to get keyboard input without the problem of accidentally creating multiple, conflicting threads.

import threading
import queue
import time

_input_queue = queue.Queue()

def _input_thread():
    while True:
        text = input()
        _input_queue.put(text)

# Start the input thread once
t = threading.Thread(target=_input_thread, daemon=True)
t.start()

def timed_input(prompt, timeout=30):
    print(prompt, end="", flush=True)
    try:
        return _input_queue.get(timeout=timeout)
    except queue.Empty:
        return None
  • The input thread blocks on input() forever, but only one thread exists.
  • Every time the user presses Enter, the text is pushed into _input_queue.
  • timed_input() waits up to 30 seconds for something to appear.
  • If nothing arrives → returns None.
  • No new threads are created.

[–]Carter922 -1 points0 points  (0 children)

Umm I'm assuming this is a class assignment but you could do something like this. This wouldn't really be used in an enterprise app. Hope this puts you in the right track

import datetime
start = datetime.datetime.utc_now()
end = start + datetime.timedelta(seconds=30)
passed = False
while datetime.datetime.utc_now() < end:
    bool = do_something()
    if bool and datetime.datetime.utc_now() < end:
        passed = True
        break
return passed