1#!/usr/bin/env zsh
2
3STATE_DIR="/tmp/have-to-go"
4PID_FILE="$STATE_DIR/pid"
5TIME_FILE="$STATE_DIR/target"
6GRACE_MINUTES=3
7
8mkdir -p "$STATE_DIR"
9
10# -------------------------
11# Print remaining time
12# -------------------------
13print_remaining() {
14 [[ -f "$TIME_FILE" ]] || { echo '{"text":"","msg":"no active timer"}'; return }
15
16 REMAIN=$(( $(cat "$TIME_FILE") - $(date +%s) ))
17
18 if (( REMAIN <= 0 )); then
19 echo "Timer expired."
20 return
21 fi
22
23 printf '{"text":"T-minus: %02d:%02d:%02d","tooltip":"Move your ass"}\n' \
24 $((REMAIN/3600)) $(( (REMAIN%3600)/60 )) $((REMAIN%60))
25}
26
27# -------------------------
28# Handle special commands
29# -------------------------
30case "$1" in
31 remaining)
32 print_remaining
33 exit 0
34 ;;
35 kill)
36 if [[ -f "$PID_FILE" ]]; then
37 PID=$(<"$PID_FILE")
38 kill -0 "$PID" 2>/dev/null && kill "$PID"
39 rm -f "$PID_FILE" "$TIME_FILE"
40 echo "Timer killed."
41 else
42 echo "No active timer."
43 fi
44 exit 0
45 ;;
46esac
47
48# -------------------------
49# Check existing timer
50# -------------------------
51if [[ -f "$PID_FILE" ]]; then
52 PID=$(<"$PID_FILE")
53 if kill -0 "$PID" 2>/dev/null; then
54 print_remaining
55 exit 0
56 else
57 rm -f "$PID_FILE" "$TIME_FILE"
58 fi
59fi
60
61if [[ -z "$1" ]]; then
62 if command -v rofi >/dev/null 2>&1; then
63 INPUT=$(echo "" | rofi -dmenu -p "Butt Out in:" -theme-str 'listview {lines:0;}')
64 else
65 echo "Usage: have-to-go <10m | 2h | 4:15>"
66 exit 1
67 fi
68
69 [[ -n "$INPUT" ]] || { echo "No input provided."; exit 1 }
70else
71 INPUT="$1"
72fi
73
74
75get_seconds() {
76 NOW=$(date +%s)
77
78 if [[ "$INPUT" == <->m ]]; then
79 echo $(( ${INPUT%m} * 60 ))
80 return
81 elif [[ "$INPUT" == <->h ]]; then
82 echo $(( ${INPUT%h} * 3600 ))
83 return
84 elif [[ "$INPUT" == <->:<-> ]]; then
85 hour=${INPUT%%:*}
86 min=${INPUT##*:}
87 candidates=()
88
89 for add in 0 12; do
90 h=$(( (hour % 12) + add ))
91 TARGET=$(date -d "today $h:$min" +%s 2>/dev/null) || continue
92 (( TARGET > NOW )) && candidates+=($TARGET)
93 done
94
95 if (( ${#candidates[@]} > 0 )); then
96 # Pick earliest future candidate
97 TARGET=$candidates[1]
98 for t in "${candidates[@]}"; (( t < TARGET )) && TARGET=$t
99 else
100 TARGET=$(date -d "tomorrow $((hour % 12)):$min" +%s)
101 fi
102
103 echo $(( TARGET - NOW ))
104 return
105 fi
106
107 return 1
108}
109
110SECONDS_TO_WAIT=$(get_seconds)
111[[ -n "$SECONDS_TO_WAIT" ]] || { echo "Invalid format. Use 10m | 2h | 4:15"; exit 1 }
112
113# -------------------------
114# Schedule timer
115# -------------------------
116TARGET_TIME=$(( $(date +%s) + SECONDS_TO_WAIT ))
117echo "$TARGET_TIME" > "$TIME_FILE"
118
119(
120 sleep "$SECONDS_TO_WAIT" || exit
121
122 shutdown now
123 # zenity --question \
124 # --title="Have To Go" \
125 # --text="Time's up.\n\nShutdown now?\n\nCancel = 3 min delay"
126 #
127 # if (( $? == 0 )); then
128 # shutdown now
129 # else
130 # shutdown +$GRACE_MINUTES &>/dev/null
131 # fi
132
133 rm -f "$PID_FILE" "$TIME_FILE"
134) &
135
136echo $! > "$PID_FILE"
137disown