267 lines
7.9 KiB
Lua
267 lines
7.9 KiB
Lua
local obj = {}
|
|
obj.__index = obj
|
|
obj.__name = "seal_vpn"
|
|
|
|
function obj:commands()
|
|
return {vpn = {
|
|
cmd = "vpn",
|
|
fn = obj.choicesVPNCommand,
|
|
name = "VPN",
|
|
description = "Manage VPN connections",
|
|
plugin = obj.__name
|
|
}
|
|
}
|
|
end
|
|
|
|
function obj:bare()
|
|
return nil
|
|
end
|
|
|
|
function obj.getVPNConnections()
|
|
connections = {}
|
|
code, output, descriptor = hs.osascript.applescript([[
|
|
set output to ""
|
|
|
|
on join_list(the_list, delimiter)
|
|
set the_string to ""
|
|
set old_delims to AppleScript's text item delimiters
|
|
repeat with the_item in the_list
|
|
if the_string is equal to "" then
|
|
set the_string to the_string & the_item
|
|
else
|
|
set the_string to the_string & delimiter & the_item
|
|
end if
|
|
end repeat
|
|
set AppleScript's text item delimiters to old_delims
|
|
return the_string
|
|
end join_list
|
|
|
|
set vpn_connections to {}
|
|
|
|
tell application "Viscosity"
|
|
repeat with the_connection in connections
|
|
set the end of vpn_connections to (name of the_connection) & tab & (state of the_connection) & tab & "Viscosity"
|
|
end repeat
|
|
end tell
|
|
|
|
tell application "System Events"
|
|
tell current location of network preferences
|
|
repeat with vpn in (every service whose (kind is greater than 10 and kind is less than 17))
|
|
set state to "Disconnected"
|
|
if connected of current configuration of vpn is equal to true then
|
|
set state to "Connected"
|
|
end if
|
|
set the end of vpn_connections to (name of vpn) & tab & state & tab & "macOS"
|
|
end repeat
|
|
end tell
|
|
end tell
|
|
|
|
return my join_list(vpn_connections, linefeed)
|
|
]])
|
|
|
|
if code == false or output == nil or output == "" then
|
|
return connections
|
|
end
|
|
|
|
for line in output:gmatch("[^\r\n]+") do
|
|
parts = {}
|
|
for part in line:gmatch("%S+") do
|
|
table.insert(parts, part)
|
|
end
|
|
kind = parts[#parts]
|
|
table.remove(parts, #parts)
|
|
state = parts[#parts]
|
|
table.remove(parts, #parts)
|
|
name = table.concat(parts, " ")
|
|
table.insert(connections, {name=name, state=state, kind=kind})
|
|
end
|
|
return connections
|
|
end
|
|
|
|
function obj.disconnectVPN(name, kind)
|
|
if kind == "Viscosity" then
|
|
obj.disconnectViscosity(name)
|
|
elseif kind == "macOS" then
|
|
obj.disconnectMacOS(name)
|
|
end
|
|
end
|
|
|
|
function obj.disconnectViscosity(name)
|
|
code, output, descriptor = hs.osascript.applescript(string.format([[
|
|
-- Return true if VPN is active
|
|
on vpn_is_active(vpn_name)
|
|
tell application "Viscosity"
|
|
repeat with the_connection in connections
|
|
if (name of the_connection) is equal to vpn_name then
|
|
if (state of the_connection) is equal to "Connected" then
|
|
return true
|
|
else
|
|
return false
|
|
end if
|
|
end if
|
|
end repeat
|
|
end tell
|
|
return false
|
|
end vpn_is_active
|
|
|
|
on run argv
|
|
set vpn_name to "%s"
|
|
if my vpn_is_active(vpn_name) then
|
|
tell application "Viscosity"
|
|
disconnect vpn_name
|
|
end tell
|
|
end if
|
|
end run
|
|
]], name))
|
|
end
|
|
|
|
function obj.disconnectMacOS(name)
|
|
code, output, descriptor = hs.osascript.applescript(string.format([[
|
|
-- Return true if VPN is active
|
|
on vpn_is_active(vpn_name)
|
|
tell application "System Events"
|
|
tell current location of network preferences
|
|
return connected of current configuration of service vpn_name
|
|
end tell
|
|
end tell
|
|
end vpn_is_active
|
|
|
|
on connect_vpn(vpn_name)
|
|
tell application "System Events"
|
|
tell current location of network preferences
|
|
connect service vpn_name
|
|
end tell
|
|
end tell
|
|
end connect_vpn
|
|
|
|
on run argv
|
|
set vpn_name to "%s"
|
|
if my vpn_is_active(vpn_name) then
|
|
tell application "System Events"
|
|
tell current location of network preferences
|
|
disconnect service vpn_name
|
|
end tell
|
|
end tell
|
|
end if
|
|
end run
|
|
]], name))
|
|
end
|
|
|
|
function obj.connectVPN(name, kind)
|
|
if kind == "Viscosity" then
|
|
obj.connectViscosity(name)
|
|
elseif kind == "macOS" then
|
|
obj.connectMacOS(name)
|
|
end
|
|
end
|
|
|
|
function obj.connectViscosity(name)
|
|
code, output, descriptor = hs.osascript.applescript(string.format([[
|
|
-- Return true if VPN is active
|
|
on vpn_is_active(vpn_name)
|
|
tell application "Viscosity"
|
|
repeat with the_connection in connections
|
|
if (name of the_connection) is equal to vpn_name then
|
|
if (state of the_connection) is equal to "Connected" then
|
|
return true
|
|
else
|
|
return false
|
|
end if
|
|
end if
|
|
end repeat
|
|
end tell
|
|
return false
|
|
end vpn_is_active
|
|
|
|
-- Connect to specified VPN
|
|
on connect_vpn(vpn_name)
|
|
tell application "Viscosity"
|
|
connect vpn_name
|
|
end tell
|
|
end connect_vpn
|
|
|
|
on run argv
|
|
set vpn_name to "%s"
|
|
if my vpn_is_active(vpn_name) then
|
|
log "VPN " & quote & vpn_name & quote & " is already active."
|
|
return
|
|
end if
|
|
connect_vpn(vpn_name)
|
|
end run
|
|
]], name))
|
|
end
|
|
|
|
function obj.connectMacOS(name)
|
|
code, output, descriptor = hs.osascript.applescript(string.format([[
|
|
-- Return true if VPN is active
|
|
on vpn_is_active(vpn_name)
|
|
tell application "System Events"
|
|
tell current location of network preferences
|
|
return connected of current configuration of service vpn_name
|
|
end tell
|
|
end tell
|
|
end vpn_is_active
|
|
|
|
-- Connect to specified VPN
|
|
on connect_vpn(vpn_name)
|
|
tell application "System Events"
|
|
tell current location of network preferences
|
|
connect service vpn_name
|
|
end tell
|
|
end tell
|
|
end connect_vpn
|
|
|
|
on run argv
|
|
set vpn_name to "%s"
|
|
if my vpn_is_active(vpn_name) then
|
|
log "VPN " & quote & vpn_name & quote & " is already active."
|
|
return
|
|
end if
|
|
connect_vpn(vpn_name)
|
|
end run
|
|
]], name))
|
|
end
|
|
|
|
|
|
function obj.choicesVPNCommand(query)
|
|
local choices = {}
|
|
local connections = obj.getVPNConnections()
|
|
local img_connected = hs.image.imageFromPath(obj.seal.spoonPath.."/viscosity_locked.png")
|
|
local img_disconnected = hs.image.imageFromPath(obj.seal.spoonPath.."/viscosity_unlocked.png")
|
|
|
|
for k,v in pairs(connections) do
|
|
name = v["name"]
|
|
if string.match(name:lower(), query:lower()) then
|
|
state = v["state"]
|
|
kind = v["kind"]
|
|
local choice = {}
|
|
choice["text"] = name
|
|
choice["subText"] = state .. " (" .. kind .. ")"
|
|
if state == "Connected" then
|
|
choice["image"] = img_connected
|
|
else
|
|
choice["image"] = img_disconnected
|
|
end
|
|
choice["name"] = name
|
|
choice["state"] = state
|
|
choice["kind"] = kind
|
|
choice["plugin"] = obj.__name
|
|
choice["type"] = "toggle"
|
|
table.insert(choices, choice)
|
|
end
|
|
end
|
|
return choices
|
|
end
|
|
|
|
function obj.completionCallback(rowInfo)
|
|
if rowInfo["type"] == "toggle" then
|
|
if rowInfo["state"] == "Connected" then
|
|
obj.disconnectVPN(rowInfo["name"], rowInfo["kind"])
|
|
else
|
|
obj.connectVPN(rowInfo["name"], rowInfo["kind"])
|
|
end
|
|
end
|
|
end
|
|
|
|
return obj
|