Skip to content

Instantly share code, notes, and snippets.

@TitusRobyK
Last active June 3, 2024 21:13
Show Gist options
  • Save TitusRobyK/c5de7affae99360cc54d737d3f03ac34 to your computer and use it in GitHub Desktop.
Save TitusRobyK/c5de7affae99360cc54d737d3f03ac34 to your computer and use it in GitHub Desktop.
This Hammerspoon script automates periodic keystroke simulation within a specified application ("Citrix Viewer") to prevent it from logging out due to inactivity. The script is designed with robust logging and error handling to ensure reliability and ease of debugging. Additionally, it reloads the Hammerspoon configuration after a set number of …
-- Overview:
-- This Hammerspoon script is designed to prevent the Citrix Viewer application from logging out due to inactivity.
-- It simulates user keystrokes periodically to keep the session active.
-- The script performs the following tasks:
-- 1. Configures Hammerspoon to use Spotlight for application name searches.
-- 2. Clears the console and logs the initiation of a fresh session.
-- 3. Defines constants for the application name, time interval between keystrokes, and session limit for reload.
-- 4. Implements a logging function that timestamps messages for better traceability.
-- 5. Implements a function to simulate keystrokes (right arrow and 'h') in the Citrix Viewer application.
-- 6. Implements a function to reload Hammerspoon configuration.
-- 7. Sets up a timer that triggers the keystroke simulation every specified time interval.
-- 8. Includes a mechanism to reload Hammerspoon after a specified number of sessions (20).
-- 9. Adds a path watcher to monitor changes in the Hammerspoon configuration directory and reloads the configuration if changes are detected.
-- 10. Adds a secondary timer to check if the primary timer is running and recreates it if it stops.
-- Enable Spotlight support for application searches
hs.application.enableSpotlightForNameSearches(true)
-- Clear the console and start a fresh session
hs.console.clearConsole()
print("Fresh Session Initiated...")
-- Constants
local appName = "Citrix Viewer" -- Exact name of your Citrix Viewer application
local timeInterval = 30 -- Interval in seconds
local sessionLimit = 20 -- Number of sessions before reloading
local maxAppNotFoundCount = 5 -- Maximum number of times the application can be not found
-- Variables
local index = 0
local appNotFoundCount = 1
local timer = nil
local monitorTimer = nil
-- Function to log messages to the console with timestamps
local function log(message)
print(os.date("%Y-%m-%d %H:%M:%S") .. ": " .. message)
end
-- Function to simulate keystrokes in the Citrix Viewer
local function simulateKeystrokes(app)
log("simulateKeystrokes function start")
local keys = { hs.keycodes.map.right, hs.keycodes.map.left }
for _, key in ipairs(keys) do
local success, err = pcall(function()
hs.eventtap.event.newKeyEvent(key, true):post(app)
hs.eventtap.event.newKeyEvent(key, false):post(app)
log("Simulating " .. hs.keycodes.map[key] .. " keystroke")
end)
if not success then
log("Error simulating keystroke: " .. err)
end
end
log("simulateKeystrokes function end")
end
-- Function to reload Hammerspoon
local function reloadHammerspoon()
log("Reloading Hammerspoon...")
hs.reload()
end
-- Function to stop all timers and exit the script
local function stopAllTimers()
log("Stopping all timers and exiting script...")
if timer then timer:stop() end
if monitorTimer then monitorTimer:stop() end
hs.application.enableSpotlightForNameSearches(false) -- Disable Spotlight support
log("Timers stopped and script exited.")
end
-- Timer to execute the function every timeInterval seconds
local function timerCallback()
local success, err = pcall(function()
index = index + 1
log("Session " .. index)
local app = hs.application.find(appName)
log("Searching for application: " .. appName)
if app then
log("Application found: " .. appName)
simulateKeystrokes(app)
appNotFoundCount = 0 -- Reset the counter if the application is found
else
log("Application not found: " .. appName)
appNotFoundCount = appNotFoundCount + 1
end
if index >= sessionLimit then
log("Session limit reached, reloading Hammerspoon")
reloadHammerspoon()
elseif appNotFoundCount > maxAppNotFoundCount then
log("Application not found for " .. appNotFoundCount-1 .. " consecutive times, stopping script.")
stopAllTimers()
end
end)
if not success then
log("Error occurred in timer function: " .. err)
reloadHammerspoon()
end
end
local function createTimer()
return hs.timer.doEvery(timeInterval, timerCallback)
end
-- Initial Timer Setup
timer = createTimer()
-- Monitor Hammerspoon reload
hs.pathwatcher.new(os.getenv("HOME") .. "/.hammerspoon/", function(files)
for _, file in pairs(files) do
if file:sub(-9) == ".hammerspoon" then
log("Hammerspoon configuration change detected")
hs.reload()
end
end
end):start()
log("Pathwatcher started to monitor changes in .hammerspoon directory")
-- Watcher to check if the timer is running and recreate it if it stops
monitorTimer = hs.timer.doEvery(timeInterval * 2, function()
if not timer:running() then
log("Timer stopped, recreating timer...")
timer = createTimer()
end
end)
log("Script initialization complete")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment