|
|
@ -1,4 +1,4 @@
|
|
|
|
import cliutils, docopt, json, logging, os, re, random, sequtils,
|
|
|
|
import cliutils, docopt, json, logging, os, nre, random, sequtils,
|
|
|
|
times, timeutils
|
|
|
|
times, timeutils
|
|
|
|
|
|
|
|
|
|
|
|
from posix import SIGTERM, SIGHUP, signal, kill
|
|
|
|
from posix import SIGTERM, SIGHUP, signal, kill
|
|
|
@ -11,7 +11,7 @@ type
|
|
|
|
DPConfig = tuple[planDir, dateFmt, pidfile, logfile, errfile: string,
|
|
|
|
DPConfig = tuple[planDir, dateFmt, pidfile, logfile, errfile: string,
|
|
|
|
notificationSecs: int]
|
|
|
|
notificationSecs: int]
|
|
|
|
|
|
|
|
|
|
|
|
const VERSION = "0.3.0"
|
|
|
|
const VERSION = "0.3.2"
|
|
|
|
const NOTE_TITLE = "Daily Notifier v" & VERSION
|
|
|
|
const NOTE_TITLE = "Daily Notifier v" & VERSION
|
|
|
|
const timeFmt = "HH:mm"
|
|
|
|
const timeFmt = "HH:mm"
|
|
|
|
|
|
|
|
|
|
|
@ -19,12 +19,12 @@ var args: Table[string, Value]
|
|
|
|
var cfg: DPConfig
|
|
|
|
var cfg: DPConfig
|
|
|
|
let appName = getAppFilename()
|
|
|
|
let appName = getAppFilename()
|
|
|
|
let soundsDir: string = appName[0..(appName.len-15)] & "sounds/navi"
|
|
|
|
let soundsDir: string = appName[0..(appName.len-15)] & "sounds/navi"
|
|
|
|
let soundFiles = toSeq(walkFiles(soundsDir & "/*"))
|
|
|
|
let soundFiles = seqUtils.toSeq(walkFiles(soundsDir & "/*"))
|
|
|
|
randomize()
|
|
|
|
randomize()
|
|
|
|
|
|
|
|
|
|
|
|
proc parseDailyPlan(filename: string): seq[PlanItem] =
|
|
|
|
proc parseDailyPlan(filename: string): seq[PlanItem] =
|
|
|
|
|
|
|
|
|
|
|
|
debug "debug - Parsing daily plan file: " & filename
|
|
|
|
debug "Parsing daily plan file: " & filename
|
|
|
|
|
|
|
|
|
|
|
|
result = @[]
|
|
|
|
result = @[]
|
|
|
|
|
|
|
|
|
|
|
@ -40,37 +40,25 @@ proc parseDailyPlan(filename: string): seq[PlanItem] =
|
|
|
|
if line.strip.startsWith("## Timeline"): parseState = ReadingPlans
|
|
|
|
if line.strip.startsWith("## Timeline"): parseState = ReadingPlans
|
|
|
|
|
|
|
|
|
|
|
|
of ReadingPlans:
|
|
|
|
of ReadingPlans:
|
|
|
|
# TODO: This is the better code using the nre module:
|
|
|
|
let match = line.find(planItemRe)
|
|
|
|
# let match = line.find(planItemRe)
|
|
|
|
if match.isSome(): result.add((
|
|
|
|
# if match.isSome(): result.add((
|
|
|
|
time: parse(match.get().captures[0], timeFmt),
|
|
|
|
# time: parse(match.get().captures[0], timeFmt),
|
|
|
|
note: match.get().captures[1]))
|
|
|
|
# note: match.get().captures[1]))
|
|
|
|
|
|
|
|
# else: parseState = AfterPlans
|
|
|
|
|
|
|
|
#
|
|
|
|
|
|
|
|
# Curently there is an incompatibility between the os and nre modules
|
|
|
|
|
|
|
|
# (see https://github.com/nim-lang/Nim/issues/4996) so the following code
|
|
|
|
|
|
|
|
# is used to avoid using nre until the bug is fixed.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if line.match(planItemRe):
|
|
|
|
|
|
|
|
let stripped = line.strip
|
|
|
|
|
|
|
|
result.add((
|
|
|
|
|
|
|
|
time: parse(stripped[0..4], timeFmt),
|
|
|
|
|
|
|
|
note: stripped.substr(5)))
|
|
|
|
|
|
|
|
else: parseState = AfterPlans
|
|
|
|
else: parseState = AfterPlans
|
|
|
|
|
|
|
|
|
|
|
|
of AfterPlans: break
|
|
|
|
of AfterPlans: break
|
|
|
|
else: break
|
|
|
|
else: break
|
|
|
|
|
|
|
|
|
|
|
|
debug "debug - Found " & $result.len & " items."
|
|
|
|
debug "Found " & $result.len & " items."
|
|
|
|
|
|
|
|
|
|
|
|
proc doAndLog(cmd: string): void =
|
|
|
|
proc doAndLog(cmd: string): void =
|
|
|
|
debug "debug - Executing '" & cmd & "'"
|
|
|
|
debug "Executing '" & cmd & "'"
|
|
|
|
discard execShellCmd(cmd)
|
|
|
|
discard execShellCmd(cmd)
|
|
|
|
|
|
|
|
|
|
|
|
proc notifyDailyPlanItem(item: PlanItem): void =
|
|
|
|
proc notifyDailyPlanItem(item: PlanItem): void =
|
|
|
|
|
|
|
|
|
|
|
|
let desc = item.time.format(timeFmt) & " - " & item.note
|
|
|
|
let desc = item.time.format(timeFmt) & " - " & item.note
|
|
|
|
debug "debug - Notifying: " & desc
|
|
|
|
debug "Notifying: " & desc
|
|
|
|
|
|
|
|
|
|
|
|
let soundFile = soundFiles[random(soundFiles.len)]
|
|
|
|
let soundFile = soundFiles[random(soundFiles.len)]
|
|
|
|
case hostOS
|
|
|
|
case hostOS
|
|
|
@ -89,14 +77,14 @@ proc loadConfig(s: cint): void {. exportc, noconv .} =
|
|
|
|
|
|
|
|
|
|
|
|
# Find and parse the .dailynotificationrc file
|
|
|
|
# Find and parse the .dailynotificationrc file
|
|
|
|
let rcLocations = @[
|
|
|
|
let rcLocations = @[
|
|
|
|
if args["--config"]: $args["<cfgFile>"] else:"",
|
|
|
|
if args["--config"]: $args["--config"] else:"",
|
|
|
|
".dailynotificationrc", $getEnv("DAILY_NOTIFICATION_RC"),
|
|
|
|
".dailynotificationrc", $getEnv("DAILY_NOTIFICATION_RC"),
|
|
|
|
$getEnv("HOME") & "/.dailynotificationrc"]
|
|
|
|
$getEnv("HOME") & "/.dailynotificationrc"]
|
|
|
|
|
|
|
|
|
|
|
|
var rcFilename: string =
|
|
|
|
var rcFilename: string =
|
|
|
|
foldl(rcLocations, if len(a) > 0: a elif existsFile(b): b else: "")
|
|
|
|
foldl(rcLocations, if len(a) > 0: a elif existsFile(b): b else: "")
|
|
|
|
|
|
|
|
|
|
|
|
debug "debug - Reloading config file from " & rcFilename
|
|
|
|
debug "Reloading config file from " & rcFilename
|
|
|
|
|
|
|
|
|
|
|
|
var jsonCfg: JsonNode
|
|
|
|
var jsonCfg: JsonNode
|
|
|
|
try: jsonCfg = parseFile(rcFilename)
|
|
|
|
try: jsonCfg = parseFile(rcFilename)
|
|
|
@ -118,7 +106,7 @@ proc loadConfig(s: cint): void {. exportc, noconv .} =
|
|
|
|
|
|
|
|
|
|
|
|
proc mainLoop(args: Table[string, Value]): void =
|
|
|
|
proc mainLoop(args: Table[string, Value]): void =
|
|
|
|
|
|
|
|
|
|
|
|
debug "debug - Started daemon main loop."
|
|
|
|
debug "Started daemon main loop."
|
|
|
|
loadConfig(0)
|
|
|
|
loadConfig(0)
|
|
|
|
signal(SIGHUP, loadConfig)
|
|
|
|
signal(SIGHUP, loadConfig)
|
|
|
|
var curDay: TimeInfo = getLocalTime(fromSeconds(0))
|
|
|
|
var curDay: TimeInfo = getLocalTime(fromSeconds(0))
|
|
|
|