Skip to content

Instantly share code, notes, and snippets.

@JacksonChen666
Last active December 8, 2023 22:30
Show Gist options
  • Save JacksonChen666/ddeb6622634ddc2d0a9f74ce16812209 to your computer and use it in GitHub Desktop.
Save JacksonChen666/ddeb6622634ddc2d0a9f74ce16812209 to your computer and use it in GitHub Desktop.
Join zoom at the speed of computers (AppleScript)
# It is recommended that you save this script as an application, so you don't have to open Script editor.
(*
It all started when I wanted to join zoom faster than a human could do with no prompt like how I expected like this.
I first discovered zoom.us's URL scheme to join meeting, but when I found out it doesn't work, I started to make this program.
After this all of stuff, I finally have something that is constantly updated.
After this pandemic is over, development might slow down or become discontinued.
*)
global meetingNames, meetingIDs, meetingPwds, wname
# Compiling the app will reset all your saved meetings!
property meetingNames : {}
property meetingIDs : {}
property meetingPwds : {}
# Consistent setup example:
#set {meetingNames, meetingIDs, meetingPwds} to {{"Example without password", "Example with password"}, {"000000001", "000000002"}, {missing value, "P4ssw0rd!"}}
on joinMeeting(meetingID, meetingPwd)
tell application "System Events"
activate application "zoom.us"
if wname is "Login" then # both login and 2 buttons screen
try
my doWithTimeout("click UI element 2 of group 1 of window \"Login\" of application process \"zoom.us\"", 10)
on error errmsg number errnum
activate me
error "Error: " & errnum & ". " & errmsg & "\nUnable to click specified button"
end try
try
click text field 1 of window 1 of application process "zoom.us"
on error
my doWithTimeout("click UI element 2 of group 1 of window \"Login\" of application process \"zoom.us\"", 10)
click text field 1 of window 1 of application process "zoom.us"
end try
else if wname is "Zoom" then
my doWithTimeout("click UI Element 15 of window \"Zoom\" of application process \"zoom.us\"", 10)
click text field 1 of window 1 of application process "zoom.us"
else if wname contains "Zoom Meeting" or wname is "Window" then
activate me
display dialog "It seems like you are already in a meeting" buttons {"OK"} default button 1
return false
else
error "Please only use while logged out, or logged into zoom. I do not understand the window name, " & wname
return false
end if
tell process "zoom.us" to keystroke meetingID & return
if meetingPwd is not missing value then # yeah it's all pretty much the same
try
my doWithTimeout("click text field 1 of group 1 of window 1 of application process \"zoom.us\"", 10)
on error errmsg number errnum
if errmsg is "System Events got an error: Can’t get group 1 of window 1 of application process \"zoom.us\". Invalid index." or errmsg is "System Events got an error: Can’t get window 1 of application process \"zoom.us\". Invalid index." then error "Cannot get password window" number errnum
end try
tell process "zoom.us" to keystroke meetingPwd & return
end if
end tell
return true
end joinMeeting
on userPrompt()
lengthCheck()
getWinName()
set allowJoin to true
if wname contains "Zoom Meeting" or wname is "Window" or wname contains "Breakout Room" then
set allowJoin to false
activate me
display dialog "You are already in a meeting, so joining meeting is disabled." buttons {"OK"} default button 1
else if wname is "" then
set allowJoin to false
activate me
display dialog "I cannot figure which window it is, so I am unable to join for you." buttons {"OK"} default button 1
end if
set extras to {"Add meeting...", "Remove meeting...", "Change meeting info...", "Get Meeting ID and password...", "I DON'T HAVE TIME TO ADD, JUST JOIN"}
activate me
set choice to choose from list meetingNames & extras default items item 1 of (meetingNames & extras)
if choice is false then return # cancel
set choice to choice as text
if choice is "Add meeting..." then
addToList()
else if choice is "Remove meeting..." then
removeFromList()
else if choice is "Change meeting info..." then
changeInfo()
else if choice is "Get Meeting ID and password..." then
getIDPwd()
else if choice is "I DON'T HAVE TIME TO ADD, JUST JOIN" then
if allowJoin is true then
noTime()
else
display dialog "You can't join meetings because you are already in a meeting" buttons {"OK FINE"} default button 1
userPrompt()
end if
return
else
if allowJoin is false then
display dialog "You are still in the meeting" buttons {"OK"} default button 1
return
end if
repeat with a from 1 to length of meetingNames
if choice is item a of meetingNames then
joinMeeting(item a of meetingIDs, item a of meetingPwds)
exit repeat
end if
end repeat
end if
repeat with a from 1 to length of extras
if choice is item a of extras then
userPrompt()
return
end if
end repeat
end userPrompt
on emergencyMode() # incase something doesn't work
set extras to {"Add meeting...", "Remove meeting...", "Change meeting info..."}
activate me
set choice to choose from list meetingNames & extras default items item 1 of (meetingNames & extras) with prompt "What meeting info would you like to view?"
if choice is false then # cancel
return
end if
set choice to choice as text
if choice is "Add meeting..." then
addToList()
else if choice is "Remove meeting..." then
removeFromList()
else if choice is "Change meeting info..." then
changeInfo()
else
repeat with a from 1 to length of meetingNames
if choice is item a of meetingNames then
showIDPwd(item a of meetingNames, item a of meetingPwds)
exit repeat
end if
end repeat
end if
repeat with a from 1 to length of extras
if choice is item a of extras then
emergencyMode()
return
end if
end repeat
end emergencyMode
on lengthCheck()
if (length of meetingNames) ≠ (length of meetingIDs) or (length of meetingNames) ≠ (length of meetingPwds) then
display dialog "The lists are unequal in size, and all additional items will be removed.\nAmounts:\nMeeting Names: " & length of meetingNames & "\nMeeting IDs: " & length of meetingIDs & "\nMeeting passwords: " & length of meetingPwds buttons {"OK"} default button 1
set stuff to {meetingNames, meetingIDs, meetingPwds}
set minimum to 0
repeat with a from 1 to length of stuff
if minimum is 0 or (length of item a of stuff) is less than minimum then
set minimum to (length of item a of stuff)
end if
end repeat
set {meetingNames, meetingIDs, meetingPwds} to {items 1 thru minimum of meetingNames, items 1 thru minimum of meetingIDs, items 1 thru minimum of meetingPwds}
end if
end lengthCheck
on getWinName() # yes getting the window has been a too hard process
launch application "zoom.us"
try
tell application "System Events"
tell process "zoom.us" to set wname to name of front window
end tell
on error errmsg number errnum
if errnum is 600 or errmsg is "System Events got an error: Application isn’t running." then # System Events has stopped working
do shell script "pkill System Events"
delay 3
tell application "System Events"
tell process "zoom.us" to set wname to name of front window
end tell
else if errnum is -1719 and errmsg is not "System Events got an error: Can’t get window 1 of process \"zoom.us\". Invalid index." then
activate me
display dialog "Please enable accessibility access for me to join zoom for you\nError: " & errmsg & " " & errnum
tell application "System Preferences"
activate application "System Preferences"
reveal anchor "Privacy" of pane id "com.apple.preference.security"
authorize pane id "com.apple.preference.security"
end tell
set temp to getWinNameLoop((current date) + 60)
if length of temp is 3 and item 3 of temp is true then error item 1 of temp number item 2 of temp
else if errmsg is "System Events got an error: Can’t get window 1 of process \"zoom.us\". Invalid index." then
do shell script "pkill zoom.us"
launch application "zoom.us"
set temp to getWinNameLoop((current date) + 30)
if length of temp is 3 and item 3 of temp is true then error item 1 of temp number item 2 of temp
else
display dialog "Error: " & errnum & ". " & errmsg & "\nPress OK to continue"
emergencyMode()
return
end if
end try
return wname
end getWinName
on getWinNameLoop(timeOutTime)
repeat
try
tell application "System Events"
tell process "zoom.us" to set wname to name of front window
end tell
exit repeat
on error errmsg number errnum
if (current date) > timeOutTime then return {errmsg, errnum, true}
end try
end repeat
return wname
end getWinNameLoop
on getIDPwd()
if length of meetingNames is 0 then error "There's nothing to see..." number -2573
set choice to (choose from list meetingNames default items item 1 of meetingNames with prompt "What meeting info would you like to view?") as text
repeat with a from 1 to length of meetingNames
if choice is (item a of meetingNames as text) then
showIDPwd(item a of meetingNames, item a of meetingIDs, item a of meetingPwds)
exit repeat
end if
end repeat
return choice
end getIDPwd
on showIDPwd(meetingName, meetingID, meetingPwd)
set tempText to ("Meeting Name: " & meetingName & "\nMeeting ID: " & meetingID & "\nMeeting link: https://zoom.us/j/" & meetingID)
if meetingPwd is not missing value then set tempText to (tempText & "?pwd=" & meetingPwd)
display dialog tempText buttons {"OK"} default button 1
return
end showIDPwd
on addToList()
copy repeatUntilAnswered("What meeting name to use?") to the end of meetingNames
repeat
set mID to text returned of (display dialog "What is the meeting ID?" default answer "")
if length of regexMatch(mID, "/^\\d{9,11}$/") is less than 1 then
display dialog "Meeting IDs can only contain numbers, and must be between 9 and 11 characters." with icon caution
else
exit repeat
end if
end repeat
copy mID to the end of meetingIDs
set mPwd to text returned of (display dialog "What is the meeting password? (Required if set)" default answer "") as string
if mPwd is "" then set mPwd to missing value
copy mPwd to the end of meetingPwds
return
end addToList
on changeInfo()
if length of meetingNames is 0 then error "There's nothing to see..." number -2573
set rename to choose from list meetingNames with prompt "Which meeting would you like to change?" default items item 1 of meetingNames
if rename is false then return
set changeChoice to choose from list {"Name", "Meeting ID", "Meeting Password"} with prompt "Which info do you want to change?" default items {"Name"}
if changeChoice is false then return
set rename to rename as text
repeat with a from 1 to length of meetingNames
if (item a of meetingNames as text) is rename then
set changeChoice to changeChoice as text
set mn to item a of meetingNames
if changeChoice is "Name" then
set item a of meetingNames to text returned of (display dialog "What would you like to rename " & mn & " to?" default answer (mn))
exit repeat
else if changeChoice is "Meeting ID" then
repeat
set temp to text returned of (display dialog "What meeting ID would you like to change to on " & mn & "?" default answer (item a of meetingIDs))
if length of regexMatch(temp, "/^\\d{9,11}$/") is less than 1 then
display dialog "Meeting IDs can only contain numbers, and must be between 9 and 11 cahracters." with icon caution
else
exit repeat
end if
end repeat
set item a of meetingIDs to temp
else if changeChoice is "Meeting Password" then
set temp to text returned of (display dialog "What meeting password would you like to change to on " & mn & "?" default answer "")
if temp is "" then set temp to missing value
set item a of meetingPwds to temp
end if
exit repeat
end if
end repeat
return
end changeInfo
on removeFromList()
if length of meetingNames is 0 then error "There's nothing to see..." number -2573
set {toRemove, cleanList, cleanList2, cleanList3} to {(choose from list meetingNames with prompt "Remove meeting from list:" default items item 1 of meetingNames) as text, {}, {}, {}}
repeat with a from 1 to length of meetingNames
if (item a of meetingNames as text) is not toRemove then
set {cleanList, cleanList2, cleanList3} to {cleanList & (item a of meetingNames), cleanList2 & (item a of meetingIDs), cleanList3 & (item a of meetingPwds)}
end if
end repeat
set {meetingNames, meetingIDs, meetingPwds} to {cleanList, cleanList2, cleanList3}
return {cleanList, cleanList2, cleanList3}
end removeFromList
on versionCheck()
set {appVersion, supportedVersions, supported, maxTime} to {version of application "zoom.us", {"5.2.1"}, false, (current date) + 10}
repeat with a from 1 to length of supportedVersions
try
if appVersion contains (item a of supportedVersions as text) then
set supported to true
exit repeat
end if
on error errmsg number errnum
if ((current date) > maxTime) then error errmsg number errnum
end try
end repeat
if supported is false then display dialog "Zoom.us version unsupported! You may need to do it manually"
userPrompt()
return
end versionCheck
on repeatUntilAnswered(prompt)
repeat
set temp to text returned of (display dialog prompt default answer "")
if temp is not "" then exit repeat
end repeat
return temp
end repeatUntilAnswered
on doWithTimeout(uiScript, timeoutSeconds)
set endDate to (current date) + timeoutSeconds
repeat
try
run script "tell application \"System Events\"\n" & uiScript & "\nend tell"
exit repeat
on error errorMessage number errnum
if ((current date) > endDate) then error errorMessage number errnum
end try
end repeat
end doWithTimeout
on noTime()
repeat
set ids to text returned of (display dialog "Meeting ID" default answer "")
if length of regexMatch(ids, "/^\\d{9,11}$/") is less than 1 then
display dialog "Invalid. Meeting IDs must be between 9 to 11 characters long." with icon caution
else
exit repeat
end if
end repeat
set pwd to text returned of (display dialog "Meeting password (Required if set)" default answer "")
if pwd is "" then set pwd to missing value
joinMeeting(ids, pwd)
return
end noTime
on regexMatch(_subject, _regex)
set _js to "(new String(`" & _subject & "`)).match(" & _regex & ")"
set _result to run script _js in "JavaScript"
if _result is null or _result is missing value then return {}
return _result
end regexMatch
versionCheck()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment