0

I am trying to create a timer that increments at a certain time (in this case, whenever the time is xx:03:24) and sends a notification when it reaches a user-inputted value. Once it does so, it resets the increment and repeats until manually quit.

However, this code is not reliably triggering when it is supposed to. Does anyone have a guess as to why?

on quit
    continue quit
end quit
tell application "Notifications Scripting"
    set event handlers script path to (path to me)
end tell

global actions, newActions

using terms from application "Notifications Scripting"
    on notification activated
        tell application "Safari"
            activate
            set winlist to every window
            repeat with win in winlist
                set numtabs to 0
                try
                    set tablist to every tab of win
                    set numtabs to length of tablist
                end try
                if numtabs is greater than 0 then
                    repeat with t in tablist

                        if "fallenlondon.storynexus.com" is in (URL of t as string) then
                            tell application "System Events"
                                tell window id (id of win as integer) of application "Safari" to set current tab to tab (index of t as integer)
                            end tell
                        end if
                    end repeat
                end if
            end repeat
        end tell
    end notification activated
end using terms from

display dialog "How many actions do you want to build up before being notified?" default answer "1"

set actions to (text returned of result) as number
set newActions to 0

on idle
    if ((seconds of (current date)) = 24) and ((minutes of (current date)) mod 10 = 3) then
        set newActions to (newActions + 1)
        set delayTime to 540
    else
        set delayTime to 0.5
    end if

    if newActions ≥ actions then
        if newActions = 1 then
            tell application "Notifications Scripting" to display notification "Fallen London" message "You have " & newActions & " new action!" sound name "Glass"
        else
            tell application "Notifications Scripting" to display notification "Fallen London" message "You have " & newActions & " new actions!" sound name "Glass"
        end if
        set newActions to 0
    end if
    return delayTime
end idle
Saklad5
  • 3
  • 2

2 Answers2

0

I think you have a few things working against you with your code.

First thing to note is that only the code within the idle handler will be called on each idle event. In other words, if you're expecting the main body of your script to run with each idle process, it will not.

try this as an example...

on run
    display dialog "hello!" giving up after 3
end run

on idle
    display dialog "Idle test!" giving up after 3
    return 5
on idle

When you save the code above as a stay open script, you'll get one dialog that says "hello" then you'll get the "Idle test!" message several times, until you quit the script. Remember to save it as "Stay Open"

To fix this, if you expect all the code outside of the idle handler to run, create a custom function from it that you call from your idle handler.

 on yourCustomFunction()
     -- All the code you want to run prior when the idle function is called
 end yourCustomFunction

 on idle
    yourCustomFunction()
    -- any other additional code you want to run here
    return 5
 end idle

Another thing I'd like to point out. You don't need to tell application "Notifications Scripting", you can just display notification as shown below.

on idle
    if ((seconds of (current date)) = 24) and ((minutes of (current date)) mod 10 = 3) then
        set newActions to (newActions + 1)
        set delayTime to 540
    else
        set delayTime to 0.5
    end if

    if newActions ≥ actions then
        if newActions = 1 then
            display notification "You have " & newActions & " new action!" with title "Fallen London" sound name "Glass"
        else
            display notification "You have " & newActions & " new actions!" with title "Fallen London" sound name "Glass"
        end if
        set newActions to 0
    end if
    return delayTime
end idle

Lastly, I would recommend adding an on run handler rather than just writing your code in the script without it.

ThrowBackDewd
  • 1,737
  • 2
  • 13
  • 16
  • Notifications Scripting is a special application that allows me to run a handler when a notification is clicked. That behavior is impossible without it. – Saklad5 Jul 19 '16 at 20:19
  • The code outside of the idle handler is intended to run on launch and never again. – Saklad5 Jul 19 '16 at 20:20
  • @Saklad5 - Ok, the syntax of the "Notifications Scripting" is very similar to that of display notifcations that I thought you were intending to use that. As for the code outside the idle handler, I would just make sure to wrap it in an `on run` to make that clearer. – ThrowBackDewd Jul 19 '16 at 20:26
0

I would not expect your idle implementation to work reliably. It is not a precision timing mechanism; therefore the following assumption is unsound:

if ((seconds of (current date)) = 24) and ((minutes of (current date)) mod 10 = 3) then

You're attempting to hit a 1-second window in a 10-minute loop here, and if you miss that window it'll be another 10 minutes till you get to try again.

A reliable way to do it is to store a date representing the time upon which to next trigger, then periodically check if the current date is now after that date and trigger if it does:

to nextTriggerDate() -- returns next xx:x3:23 date
    set d to current date
    set {d's minutes, d's seconds} to {((d's minutes) div 10 * 10) + 3, 23}
    if d < (current date) then set d to d + 10 * minutes
    d
end nextTriggerDate

property _triggerDate : nextTriggerDate()


on idle
    if (current date) > _triggerDate then
        set _triggerDate to nextTriggerDate()
        -- DO STUFF HERE...
    end if
    return 1
end idle

Alternatively, you could use NSTimer via the AppleScript-ObjC bridge, which is designed specifically for this type of task, or set up a launchd script to run an AppleScript on the specified times if you don't want to be tied to a stay-open applet.

foo
  • 3,171
  • 17
  • 18