def idle_check(): global idle_thread global last_time global last_autosave global afk_state current_time = int(win32api.GetTickCount() / 1000) last_input = int(win32api.GetLastInputInfo() / 1000.0) if isAFK(last_input): # Did the state switch from not afk to afk? if not afk_state: afk_state = True # Add the window usage time prior to state switch usage_time = max(last_input - last_time, 0) print("You've become afk after %d seconds" % (usage_time)) updateLog(time_log, last_app, last_window, usage_time) else: # Did the state switch from afk to not afk? if afk_state: afk_state = False # Set the last_time pointer to the current time to "skip over" idle time last_time = current_time print("Welcome back!") # Autosave check if current_time - last_autosave > getSetting('autoSaveFrequencySeconds', 300): saveCurrentWindowToLog() writeData(time_log) last_autosave = current_time # Check if the date has changed and the time has exceeded a user-set threshold. This threshold ensures # that those who like to burn the midnight oil don't see their data reset before they go to sleep if time.strftime('%d') != current_date and time.strftime('%X') > getSetting('dayResetTime', '00:00:00'): onDateChange() # Restart the timer for another update cycle idle_thread = threading.Timer(0.1, idle_check) idle_thread.start()
def isIdle(self): if self.debug: return True current = (ctypes.c_ulong(win32api.GetTickCount()).value / 1000) idle = win32api.GetLastInputInfo() / 1000 print("IDLE {} {}".format((current - idle), self.idle)) return (current - idle) >= self.idle
def isAFK(last_input): # Does current window contain an afk-exluded keyword, like "YouTube"? for keyword in getSetting('afkExclude', []): if containsIgnoreCase(last_window, keyword): return False current_time = int(win32api.GetTickCount() / 1000) # Is the user afk? return current_time - last_input > getSetting("afkTimeoutSeconds", 120)
def onDateChange(): global time_log global last_time global current_date # Save currently active window to log saveCurrentWindowToLog() writeData(time_log) time_log = {} # Reset date, timer current_date = time.strftime('%d') last_time = int(win32api.GetTickCount() / 1000) updateDisplay(window,time_log)
def callback(hWinEventHook, event, hwnd, idObject, idChild, dwEventThread, dwmsEventTime): global last_app global last_window global last_time length = user32.GetWindowTextLengthW(hwnd) buff = ctypes.create_unicode_buffer(length + 1) status = user32.GetWindowTextW(hwnd, buff, length + 1) name = buff.value app_name = getAppName() if not afk_state and name != '' and name != last_window and name == win32gui.GetWindowText(win32gui.GetForegroundWindow()) and app_name not in getSetting("appExclude", {}): new_time = int(win32api.GetTickCount() / 1000) print(time.strftime('%X') + ' --> ' + name) saveCurrentWindowToLog() # Update state variables last_app = app_name last_time = new_time last_window = name # TCL can't display emojis so we need to clean up the window name last_window = ''.join([letter for letter in name if ord(letter) < 65536])
def saveCurrentWindowToLog(): global last_time if not afk_state: seconds = int(win32api.GetTickCount() / 1000) - last_time updateLog(time_log, last_app, last_window, seconds) last_time += seconds
# User settings settings = {} idle_thread = threading.Thread() # Thread to run the afk check afk_state = False # Has the system not received an input for longer than the timeout? # The day of the month at runtime start - used for end-of-day autosave current_date = time.strftime('%d') time_log = {} # The number of seconds spent on each window, using changes in window focus # State variables last_app = '' # The name of the application used prior to window switch last_window = win32gui.GetWindowText(win32gui.GetForegroundWindow()) # The name of the recently unfocused window last_time = int(win32api.GetTickCount() / 1000) # integer timestamp of the last change in focus last_autosave = last_time # The word(s) used to filter the table's contents window_filter = '' user32 = ctypes.windll.user32 ole32 = ctypes.windll.ole32 ole32.CoInitialize(0) WinEventProcType = ctypes.WINFUNCTYPE( None, ctypes.wintypes.HANDLE, ctypes.wintypes.DWORD, ctypes.wintypes.HWND,