trying to write an apple script that chimes every hour - applescript

I'm trying to write this script that chimes on every hour. I saved it as an application and selected the checkbox run after completion but it doesn't work. My code looks like this:
global chime
set chime to (path to resource "chime.mp3")
on idle
set currenthour to hours of (current date)
if currenthour = 0 then
set currenthour to 12
end if
if currenthour > 12 then
set currenthour to currenthour - 12
end if
set currentminute to minutes of (current date)
set currentsecond to seconds of (current date)
set currenttime to {currentminute, currentsecond} as text
if currenttime is "" then
repeat currenthour times
do shell script "afplay " & (quoted form of POSIX path of chime)
end repeat
end if
return 1
end idle

In a script app, the number you return from the on idle handler tells the system how long to sleep the app before the next idle invocation. You can use this set up a (loosely) accurate timer.
global chime, firstRun
on run
-- I'm not sure if this is necessary, but I always use explicit run handlers in script apps.
set chime to (path to resource "chime.mp3")
set firstRun to true
end run
on idle
set {currenthour, currentminute, currentsecond} to {hours, minutes, seconds} of (current date)
-- don't chime when the script app is activated
if not firstRun then
-- quick mathy way to retrieve the number of chimes.
set chimeCount to (currenthour + 11) mod 12 + 1
repeat chimeCount times
do shell script "afplay " & (quoted form of POSIX path of chime)
end repeat
else
set firstRun to true
end if
-- calculate the number of seconds until the next hour mark and tell app to sleep until then
return 60 * (60 - currentminute) + 60 - currentsecond
end idle

Related

Idle handler function is not running at the exact specified interval

The script uses idle handler that runs every 5 minutes and alerts me to perform the task. But the script always runs late by 10-40 seconds. I am not sure why that is happening.
global numberOfBeeps, beepcycle
on idle
if beepcycle is greater than 0 then
say "Update 5 minute data and watchlist " using "Serena"
set beepcycle to beepcycle - 1
else
say "Update 30 minute data and watchlist" using "Kate"
set beepcycle to 5
end if
return 300
end idle
on run
set beepcycle to 6
end run
The if statement in your script adds this 10-40 seconds to the on idle handler. So, you should correct the return time of on idle handler some way. For example, you can do something like this:
global numberOfBeeps, beepcycle
on idle
set currentDate to (get current date)
if beepcycle is greater than 0 then
say "Update 5 minute data and watchlist " using "Serena"
set beepcycle to beepcycle - 1
else
say "Update 30 minute data and watchlist" using "Kate"
set beepcycle to 5
end if
set timeElapsed to (get current date) - currentDate
return (300 - timeElapsed)
end idle
on run
set beepcycle to 6
end run

AppleScript Progress Bar with Reboot Button

I've recently been tasked with working on a project to switch antivirus software in the environment as we are changing to a new vendor. Naturally, this kind of effort will require a reboot on our endpoints once the old A/V software has been removed.
What I'm trying to do is create a reboot notification prompt for our Mac customers (since many are high up on the food chain) to let them know what we are doing.
This prompt will let them know they have 3 hours to reboot their Macs to complete the removal of the software if they are logged in. If they do not reboot within 3 hours, their workstation will automatically reboot.
Applescript has a great workflow that allows me to effectively communicate with our users, but I would like to change the Stop button to a reboot, so that our customers can reboot their Macs on demand.
I will work in logic later on to automatically reboot if they are not logged in.
I modified one of the scripts that I, "borrowed," from here
https://macscripter.net/viewtopic.php?id=46572
-- Progress Bar - Reboot Timer
progress_timer("03:00:00", "Reboot Timer") -- call the progress timer with an HMS time and timer label
return result
------------------------------------------
-- subroutines in alphabetical order --
------------------------------------------
-- getTimeConversion converts a time in HMS format (hh:mm:ss) to a time in seconds
on getTimeConversion(HMS_Time)
set HMSlist to the words of HMS_Time -- get {hh, mm, ss} from HMS time (p. 158 Rosenthal)
set theHours to item 1 of HMSlist
set theMinutes to item 2 of HMSlist
set theSeconds to item 3 of HMSlist
return round (theHours * (60 ^ 2) + theMinutes * 60 + theSeconds)
end getTimeConversion
-- progress_timer displays the elapsed time in a progress bar. For information on progress bars see: https://developer.apple.com/library/archive/documentation/LanguagesUtilities/Conceptual/MacAutomationScriptingGuide/DisplayProgress.html
on progress_timer(HMS_Time, timerLabel)
set theTimeSec to getTimeConversion(HMS_Time) -- convert the HMS format to seconds
set progress total steps to theTimeSec
set progress completed steps to 0
set startTime to (current date)
repeat with i from 0 to theTimeSec -- begin at i = 0 to start the timer at 00:00:00
set HMS_SoFar to TimetoText(i) -- convert the seconds so far to HMS format for display
set HMS_ToGo to TimetoText(theTimeSec - i) -- convert the seconds to go to HMS format for display
set progress completed steps to 0
set progress description to "
Your IT Department needs to make changes to your Mac.
Your workstation must be rebooted in order for these changes to take effect.
Your workstation will reboot in " & HMS_ToGo
set progress additional description to ¬
""
--"Time Elapsed: " & HMS_SoFar & return & ¬
--"Counting Down: " & HMS_ToGo
set progress completed steps to i
set elapsedTime to (current date) - startTime -- get actual elapsed time for adjusting delay
set lagAdjust to elapsedTime - i -- compute lag adjustment
delay 1 - lagAdjust -- delay 1 second minus any cumulative lag that needs removing
end repeat
--set HMS_Elapsed to TimetoText(elapsedTime) -- convert elapsedTime back to HMS format for display
set dialogText to null
--set dialogText to "Elapsed Time: " & return & ¬
-- "Nominal = " & HMS_Time & return & ¬
-- "Actual = " & HMS_Elapsed
tell me to activate
--display dialog dialogText with title timerLabel & " Timer"
return dialogText
end progress_timer
-- TimetoText converts a time in seconds to a time in HMS format (hh:mm:ss)
on TimetoText(theTime)
-- parameters - TheTime [integer]: the time in seconds
-- returns [text]: the time in the format hh:mm:ss
-- Nigel Garvey points out this script is only valid for parameter values up to 86399 seconds (23:59:59) and offers a solution for longer times here: https://macscripter.net/viewtopic.php?pid=134656#p134656
if (class of theTime) as text is "integer" then
set TimeString to 1000000 + 10000 * (theTime mod days div hours) -- hours
set TimeString to TimeString + 100 * (theTime mod hours div minutes) -- minutes
set TimeString to (TimeString + (theTime mod minutes)) as text -- seconds
tell TimeString to set theTime to (text -6 thru -5) & ":" & (text -4 thru -3) & ":" & (text -2 thru -1)
end if
return theTime
end TimetoText
Here's a screenshot of the resulting output.

Problems with variables working outside idle loops in apple script

I have a problem with variables not working outside an idle. What should I do to make it work? My code looks like this:
set currentdate to current date
set currentminute to currentdate's minutes
on idle
display dialog currentminute
if idle_time < 0 then set idle_time to days - (time of (current date))
return idle_time
end idle
on idle is not a loop, it's a handler having its own scope.
Mark currentminute as global or declare it as property for example. Both ways makes the variable available in handlers on lower levels.
property currentminute : 0
set currentdate to current date
set currentminute to currentdate's minutes
on idle
display dialog currentminute
if idle_time < 0 then set idle_time to days - (time of (current date))
return idle_time
end idle

VBscript loop - Tell time every 15 minutes

I just want a file I can double-click and have Windows verbally tell me the time every 15 minutes. (Until I kill the process)
I found this tutorial for a VBscript that tells the time every hour, on the hour:
https://www.nextofwindows.com/windows-trick-how-to-make-your-computer-to-speak-out-time-at-every-hour
I couldn't get the Windows scheduler working with it for my purposes (start only when double-clicked and run every 15 minutes), and honestly, I just want a 15-minute-interval loop programmed into the script itself. (perhaps by using a Do/While loop and Sleep()?)
Another issue:
I tried adding a minutes variable so Windows would announce the minutes as well:
Dim speaks, speech
speaks = “It is ” & hour(time) & minute(time)
Set speech = CreateObject(“sapi.spvoice”)
speech.Speak speaks
However, it announces the time in an odd format this way. For example, It's currently 5:01AM, and when I run the script, Windows says "It is fifty-one." Why would it interpret 5:01 as fifty plus one? Earlier when I tested it at 4:32, it said "four hundred and thirty-two." I'd like it to just state the time in a normal 12-hour fashion.
This does 5 secs. So 60 x 15 = 900.
You need spaces between numbers if you want them parsed as individual numbers.
Set speech = CreateObject("sapi.spvoice")
Do
If Hour(Now) < 12 then
Var = Hour(Now) & " AM"
else
Var = Hour(Now) - 12 & " PM"
End If
speech.Speak Var & " and " & Minute(Now) & " minutes and " & Second(Now) & " seconds"
wscript.sleep 5
Loop

Applescript: Getting week number from file name

I have lots of pics from my smartphone. The file name format for all of them is yyyy-mm-dd hh:mm:ss.jpg
I need to sort them into the folders according to the week number.
I have no problems moving files to folders with AppleScript :) I also have no problems defining a week number for a given date. I have a problem (as I think) with syntax or even data types but I cannot understand where the problem lies.
Here's what I'm using.
I have a function for defining a week number for a given date
I scan through my folder and get all the names into the list
I parse the names to get yyyy, mm and dd as variables
Then I try to call for my function with these variables - and here's where the problem starts.
Please take a look at this example of my code:
property DBFolder : "Macintosh HD:Users:lyubovberezina:Dropbox:DB"
property CUFolder : "Macintosh HD:Users:lyubovberezina:Dropbox:Camera Uploads"
on weekNumber(_inputDate)
script Week_Number_Extras
on dateOfFirstWeekOfYear(_year)
-- Get Monday of first week number
set _date to current date
set year of _date to _year
set month of _date to 1
set day of _date to 1
set time of _date to 0
-- Get the first Thursday of this year
repeat until weekday of _date is Thursday
set _date to _date + (24 * 60 * 60)
end repeat
-- Return the Monday before
set _date to _date - (3 * 24 * 60 * 60)
return _date
end dateOfFirstWeekOfYear
end script
-- Make a copy of the passed date object to avoid changes to the original
copy _inputDate to _targetDate
-- Reset the time and go back to Monday
set time of _targetDate to 0
repeat until weekday of _targetDate is Monday
set _targetDate to _targetDate - (24 * 60 * 60)
end repeat
-- Get the date of the first week for the current year and the next one
tell Week_Number_Extras
set _matchDate to dateOfFirstWeekOfYear(year of _targetDate)
set _nextYearsFirstWeekDate to dateOfFirstWeekOfYear((year of _targetDate) + 1)
end tell
-- Exit early, if the current week is the first one of next year
if _targetDate = _nextYearsFirstWeekDate then return 1
-- Count up until the target date is reached
set _weekNumber to 1
repeat until _targetDate = _matchDate
set _matchDate to _matchDate + (7 * 24 * 60 * 60)
set _weekNumber to _weekNumber + 1
end repeat
return _weekNumber
end weekNumber
tell application "Finder"
set this_folder to folder CUFolder
set this_list to every file of this_folder
repeat with i in this_list
set fileName to name of i
set fileYear to characters 1 thru 4 of fileName as string
set fileMonth to characters 6 thru 7 of fileName as string
set fileDay to characters 9 thru 10 of fileName as string
end repeat
end tell
set theNewDate to date (fileMonth & "/" & fileDay & "/" & fileYear)
weekNumber(theNewDate)
In this case the line
set theNewDate1 to date (fileMonth & "/" & fileDay & "/" & fileYear)
is working ok (I mean, no errors) but as it's outside the loop it gives the result for the last image in the loop only.
But if I move it to the loop then it gives an error:
property DBFolder : "Macintosh HD:Users:lyubovberezina:Dropbox:DB"
property CUFolder : "Macintosh HD:Users:lyubovberezina:Dropbox:Camera Uploads"
on weekNumber(_inputDate)
script Week_Number_Extras
on dateOfFirstWeekOfYear(_year)
-- Get Monday of first week number
set _date to current date
set year of _date to _year
set month of _date to 1
set day of _date to 1
set time of _date to 0
-- Get the first Thursday of this year
repeat until weekday of _date is Thursday
set _date to _date + (24 * 60 * 60)
end repeat
-- Return the Monday before
set _date to _date - (3 * 24 * 60 * 60)
return _date
end dateOfFirstWeekOfYear
end script
-- Make a copy of the passed date object to avoid changes to the original
copy _inputDate to _targetDate
-- Reset the time and go back to Monday
set time of _targetDate to 0
repeat until weekday of _targetDate is Monday
set _targetDate to _targetDate - (24 * 60 * 60)
end repeat
-- Get the date of the first week for the current year and the next one
tell Week_Number_Extras
set _matchDate to dateOfFirstWeekOfYear(year of _targetDate)
set _nextYearsFirstWeekDate to dateOfFirstWeekOfYear((year of _targetDate) + 1)
end tell
-- Exit early, if the current week is the first one of next year
if _targetDate = _nextYearsFirstWeekDate then return 1
-- Count up until the target date is reached
set _weekNumber to 1
repeat until _targetDate = _matchDate
set _matchDate to _matchDate + (7 * 24 * 60 * 60)
set _weekNumber to _weekNumber + 1
end repeat
return _weekNumber
end weekNumber
tell application "Finder"
set this_folder to folder CUFolder
set this_list to every file of this_folder
repeat with i in this_list
set fileName to name of i
set fileYear to characters 1 thru 4 of fileName as string
set fileMonth to characters 6 thru 7 of fileName as string
set fileDay to characters 9 thru 10 of fileName as string
set theNewDate to date (fileMonth & "/" & fileDay & "/" & fileYear)
weekNumber(theNewDate)
end repeat
end tell
The error is given fight after the first file is taken:
get name of document file "2013-01-02 02.43.21.jpg" of folder "Camera Uploads" of folder "Dropbox" of folder "lyubovberezina" of folder "Users" of startup disk
--> "2013-01-02 02.43.21.jpg"
get date "01/02/2013"
--> error number -1728 from date "01/02/2013"
Result:
error "Finder got an error: Can’t get date \"01/02/2013\"." number -1728 from date "Wednesday, January 2, 2013 12:00:00 AM"
I am an almost total newbie in Applescript so I cannot understand why the code is working outside the loop and not working inside the loop. I would appreciate any help with this matter.
Thanks a lot!
It might be easier to use a shell script at least for the week number part:
do shell script "date -jf %F 2013-07-19 +%V"
cd ~/Dropbox/Camera\ Uploads; for f in *; do d=../DB/$(date -jf %F ${f:0:10} +%Y-%V "$f"); mkdir -p $d; mv "$f" $d; done
You should stick to your original format of:
set theNewDate to current date
set theNewDate's year to fileYear
set theNewDate's month to fileMonth
set theNewDate's day to fileDay
Also:
set _date to _date + (24 * 60 * 60)
is the same as
set _date to _date + days
set _date to _date - (3 * 24 * 60 * 60)
is the same as
set _date to _date - (3 * days)
set _matchDate to _matchDate + (7 * 24 * 60 * 60)
is the same as
set _matchDate to _matchDate + weeks

Resources