Compare commits
	
		
			9 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 68692bdc83 | ||
|  | f3d4421af2 | ||
|  | efe856c0fe | ||
|  | 3e430f8ff2 | ||
|  | ddf9ab7fd1 | ||
|  | 0e1b8fe987 | ||
|  | 1861a2fcd7 | ||
|  | c717e7eeb4 | ||
| b2d1007c09 | 
| @@ -1,5 +1,7 @@ | ||||
| import daemonize, docopt, json, os, nre, sequtils, times, timeutils | ||||
| from posix import SIGTERM, SIGHUP, signal, kill | ||||
| import cliutils, docopt, json, logging, os, nre, random, sequtils, | ||||
|   times, timeutils | ||||
|  | ||||
| from posix import SIGTERM, SIGHUP, signal, kill, Pid | ||||
| import strutils except toUpper | ||||
| from unicode import toUpper | ||||
|  | ||||
| @@ -9,30 +11,21 @@ type | ||||
|   DPConfig = tuple[planDir, dateFmt, pidfile, logfile, errfile: string, | ||||
|     notificationSecs: int] | ||||
|  | ||||
|   CombinedConfig = object | ||||
|     docopt: Table[string, Value] | ||||
|     json: JsonNode | ||||
|  | ||||
| proc getVal(cfg: CombinedConfig, key, default: string): string = | ||||
|   let argKey = "--" & key | ||||
|   let envKey = key.replace('-', '_').toUpper | ||||
|   let jsonKey = key.replace(re"(-\w)", proc (m: RegexMatch): string = ($m)[1..1].toUpper) | ||||
|  | ||||
|   if cfg.docopt[argKey]: return $cfg.docopt[argKey] | ||||
|   elif existsEnv(envKey): return getEnv(envKey) | ||||
|   elif cfg.json.hasKey(jsonKey): return cfg.json[jsonKey].getStr | ||||
|   else: return default | ||||
|  | ||||
| const VERSION = "0.2.2" | ||||
| const VERSION = "0.3.3" | ||||
| const NOTE_TITLE = "Daily Notifier v" & VERSION | ||||
| const timeFmt = "HH:mm" | ||||
|  | ||||
| var args: Table[string, Value] | ||||
| var cfg: DPConfig | ||||
| let appName = getAppFilename() | ||||
| let soundFile = appName[0..(appName.len-15)] & "sounds/notify1.ogg" | ||||
| let soundsDir: string = appName[0..(appName.len-15)] & "sounds/navi" | ||||
| let soundFiles = seqUtils.toSeq(walkFiles(soundsDir & "/*")) | ||||
| randomize() | ||||
|  | ||||
| proc parseDailyPlan(filename: string): seq[PlanItem] = | ||||
|  | ||||
|   debug "Parsing daily plan file: " & filename | ||||
|  | ||||
|   result = @[] | ||||
|  | ||||
|   var parseState = BeforeHeading | ||||
| @@ -56,18 +49,27 @@ proc parseDailyPlan(filename: string): seq[PlanItem] = | ||||
|     of AfterPlans: break | ||||
|     else: break | ||||
|  | ||||
|   debug "Found " & $result.len & " items." | ||||
|  | ||||
| proc doAndLog(cmd: string): void = | ||||
|   debug "Executing '" & cmd & "'" | ||||
|   discard execShellCmd(cmd) | ||||
|  | ||||
| proc notifyDailyPlanItem(item: PlanItem): void = | ||||
|  | ||||
|   let desc = item.time.format(timeFmt) & " - " & item.note | ||||
|   debug "Notifying: " & desc | ||||
|  | ||||
|   let soundFile = soundFiles[random(soundFiles.len)] | ||||
|   case hostOS | ||||
|   of "macosx": | ||||
|     discard execShellCmd("osascript -e 'display notification \"" & | ||||
|       item.time.format(timeFmt) & " - " & item.note & | ||||
|       "\" with title \"Daily Notifier v" & VERSION & | ||||
|       "\" sound name \"default\"'") | ||||
|     doAndLog "osascript -e 'display notification \"" & | ||||
|        desc & "\" with title \"" & NOTE_TITLE & "\"'" | ||||
|     doAndLog "ogg123 \"" & soundFile & "\"" | ||||
|  | ||||
|   of "linux": | ||||
|     discard execShellCmd("notify-send 'Daily Notifier v" & VERSION & "' '" & item.note & "'") | ||||
|     discard execShellCmd("paplay \"" & soundFile & "\"") | ||||
|     echo "paplay \"" & soundFile & "\"" | ||||
|     doAndLog "notify-send '" & NOTE_TITLE & "' '" & desc & "'" | ||||
|     doAndLog "paplay \"" & soundFile & "\"" | ||||
|  | ||||
|   else: quit("Unsupported host OS: '" & hostOS & "'.") | ||||
|  | ||||
| @@ -75,13 +77,15 @@ proc loadConfig(s: cint): void {. exportc, noconv .} = | ||||
|  | ||||
|   # Find and parse the .dailynotificationrc file | ||||
|   let rcLocations = @[ | ||||
|     if args["--config"]: $args["<cfgFile>"] else:"", | ||||
|     if args["--config"]: $args["--config"] else:"", | ||||
|     ".dailynotificationrc", $getEnv("DAILY_NOTIFICATION_RC"), | ||||
|     $getEnv("HOME") & "/.dailynotificationrc"] | ||||
|  | ||||
|   var rcFilename: string = | ||||
|     foldl(rcLocations, if len(a) > 0: a elif existsFile(b): b else: "") | ||||
|  | ||||
|   debug "Reloading config file from " & rcFilename | ||||
|  | ||||
|   var jsonCfg: JsonNode | ||||
|   try: jsonCfg = parseFile(rcFilename) | ||||
|   except: jsonCfg = newJObject() | ||||
| @@ -102,6 +106,7 @@ proc loadConfig(s: cint): void {. exportc, noconv .} = | ||||
|  | ||||
| proc mainLoop(args: Table[string, Value]): void = | ||||
|    | ||||
|   debug "Started daemon main loop." | ||||
|   loadConfig(0) | ||||
|   signal(SIGHUP, loadConfig) | ||||
|   var curDay: TimeInfo = getLocalTime(fromSeconds(0)) | ||||
| @@ -169,6 +174,7 @@ Options: | ||||
|   -h --help                   Print this usage information. | ||||
|  | ||||
|   -s --notification-seconds <sec> | ||||
|   -v --verbose                Enable verbose output. | ||||
|  | ||||
|     Notification period for plan items. | ||||
|      | ||||
| @@ -182,18 +188,25 @@ Options: | ||||
|  | ||||
|   loadConfig(0) | ||||
|  | ||||
|   addHandler(newConsoleLogger( | ||||
|     if args["--verbose"]: lvlAll | ||||
|     else: lvlInfo)) | ||||
|  | ||||
|   if args["start"]: | ||||
|     # Start our daemon process (if needed) | ||||
|     daemonize(cfg.pidfile, "/dev/null", cfg.logfile, cfg.errfile): | ||||
|       mainLoop(args) | ||||
|     info "daily_notifier: Starting daemon." | ||||
|     let childPid = daemonize(cfg.pidfile, "/dev/null", cfg.logfile, cfg.errfile, proc(): void = mainLoop(args)) | ||||
|     if childPid == 0: quit(QuitSuccess) # We are the child... don't need to do anything else. | ||||
|     info "daily_notifier: Started, pid: " & $childPid | ||||
|  | ||||
|   elif args["stop"] or args["reconfigure"]: | ||||
|  | ||||
|     if not fileExists(cfg.pidfile): | ||||
|       echo "daily_notifier is not running" | ||||
|       info "daily_notifier: not running" | ||||
|       quit(QuitSuccess) | ||||
|  | ||||
|     let pid = parseInt(readFile(cfg.pidfile).strip) | ||||
|     let pid: Pid = cast[Pid] (parseInt(readFile(cfg.pidfile).strip)) | ||||
|     info "daily_notifier: Killing process " & $pid | ||||
|  | ||||
|     if args["stop"]: discard kill(pid, SIGTERM) | ||||
|     else: discard kill(pid, SIGHUP) | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| # Package | ||||
|  | ||||
| version       = "0.2.2" | ||||
| version       = "0.3.3" | ||||
| author        = "Jonathan Bernard" | ||||
| description   = "Little programs that reads my daily plan and notifies me of upcoming events." | ||||
| license       = "MIT" | ||||
| @@ -8,5 +8,5 @@ bin           = @["daily_notifier", "deploy_plans_via_ftp"] | ||||
|  | ||||
| # Dependencies | ||||
|  | ||||
| requires @["nim >= 0.15.0", "docopt", "timeutils", "tempfile", "daemonize"] | ||||
| requires @["nim >= 0.18.0", "docopt", "timeutils", "tempfile", "cliutils"] | ||||
|  | ||||
|   | ||||
							
								
								
									
										
											BIN
										
									
								
								sounds/navi/hello.ogg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								sounds/navi/hello.ogg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								sounds/navi/hey.ogg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								sounds/navi/hey.ogg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								sounds/navi/listen.ogg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								sounds/navi/listen.ogg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								sounds/navi/look.ogg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								sounds/navi/look.ogg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								sounds/navi/watch-out.ogg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								sounds/navi/watch-out.ogg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
		Reference in New Issue
	
	Block a user