Last active
December 8, 2023 22:30
-
-
Save JacksonChen666/ddeb6622634ddc2d0a9f74ce16812209 to your computer and use it in GitHub Desktop.
Join zoom at the speed of computers (AppleScript)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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