diff options
Diffstat (limited to 'users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/next-meeting.sh')
| -rwxr-xr-x | users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/next-meeting.sh | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/next-meeting.sh b/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/next-meeting.sh new file mode 100755 index 0000000..b8e13e5 --- /dev/null +++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/next-meeting.sh | |||
| @@ -0,0 +1,101 @@ | |||
| 1 | #!/bin/bash | ||
| 2 | # Get next meeting using icalBuddy (much faster than AppleScript, handles recurring events) | ||
| 3 | # Usage: next-meeting.sh [icalBuddyPath] [lookAheadHours] | ||
| 4 | |||
| 5 | # Configuration | ||
| 6 | MAX_IN_PROGRESS_MINUTES=15 # Stop showing "now" after meeting is 15 min in progress | ||
| 7 | LOOKAHEAD="${2:-12}" # How many hours ahead to look for meetings (default: 12) | ||
| 8 | MAX_EVENTS=10 # Fetch multiple events to skip stale in-progress ones | ||
| 9 | |||
| 10 | # Calculate end time (icalBuddy doesn't support now+Xh syntax) | ||
| 11 | END_TIME=$(date -v+${LOOKAHEAD}H "+%Y-%m-%d %H:%M") | ||
| 12 | |||
| 13 | # Use custom path if provided, otherwise auto-detect | ||
| 14 | CUSTOM_PATH="$1" | ||
| 15 | if [ -n "$CUSTOM_PATH" ] && [ -x "$CUSTOM_PATH" ]; then | ||
| 16 | ICALBUDDY="$CUSTOM_PATH" | ||
| 17 | else | ||
| 18 | ICALBUDDY=$(which icalBuddy 2>/dev/null) | ||
| 19 | if [ -z "$ICALBUDDY" ]; then | ||
| 20 | if [ -x "/opt/homebrew/bin/icalBuddy" ]; then | ||
| 21 | ICALBUDDY="/opt/homebrew/bin/icalBuddy" | ||
| 22 | elif [ -x "/usr/local/bin/icalBuddy" ]; then | ||
| 23 | ICALBUDDY="/usr/local/bin/icalBuddy" | ||
| 24 | else | ||
| 25 | echo "" | ||
| 26 | exit 0 | ||
| 27 | fi | ||
| 28 | fi | ||
| 29 | fi | ||
| 30 | |||
| 31 | now_epoch=$(date +%s) | ||
| 32 | |||
| 33 | # Fetch multiple events - each event bullet starts with <<<E>>> | ||
| 34 | # Using a unique prefix that won't appear in notes content | ||
| 35 | output=$("$ICALBUDDY" -n -nc -nrd -ea -eed -li "$MAX_EVENTS" \ | ||
| 36 | -b "<<<E>>>" -ss "" \ | ||
| 37 | -df "%Y-%m-%d" -tf "%H:%M" \ | ||
| 38 | -iep "title,datetime,notes" \ | ||
| 39 | eventsFrom:"now" to:"$END_TIME" 2>/dev/null) | ||
| 40 | |||
| 41 | if [ -z "$output" ]; then | ||
| 42 | echo "" | ||
| 43 | exit 0 | ||
| 44 | fi | ||
| 45 | |||
| 46 | # Write events to temp file for processing | ||
| 47 | tmpfile=$(mktemp) | ||
| 48 | echo "$output" > "$tmpfile" | ||
| 49 | |||
| 50 | # Extract individual events by splitting on <<<E>>> prefix | ||
| 51 | event_num=0 | ||
| 52 | while IFS= read -r line; do | ||
| 53 | if [[ "$line" == "<<<E>>>"* ]]; then | ||
| 54 | # Process previous event if we have one | ||
| 55 | if [ "$event_num" -gt 0 ] && [ -n "$cur_title" ] && [ -n "$cur_start_time" ] && [ -n "$cur_iso_date" ]; then | ||
| 56 | meeting_epoch=$(date -j -f "%Y-%m-%d %H:%M" "$cur_iso_date $cur_start_time" +%s 2>/dev/null) | ||
| 57 | if [ -n "$meeting_epoch" ]; then | ||
| 58 | minutes_until=$(( (meeting_epoch - now_epoch) / 60 )) | ||
| 59 | if [ "$minutes_until" -ge "-$MAX_IN_PROGRESS_MINUTES" ]; then | ||
| 60 | echo "${cur_title}|${cur_iso_date}T${cur_start_time}||${cur_notes}|${minutes_until}" | ||
| 61 | rm -f "$tmpfile" | ||
| 62 | exit 0 | ||
| 63 | fi | ||
| 64 | fi | ||
| 65 | fi | ||
| 66 | |||
| 67 | # Start new event | ||
| 68 | event_num=$((event_num + 1)) | ||
| 69 | cur_title="${line#<<<E>>>}" | ||
| 70 | cur_title=$(echo "$cur_title" | sed 's/ (Calendar)$//') | ||
| 71 | cur_iso_date="" | ||
| 72 | cur_start_time="" | ||
| 73 | cur_notes="" | ||
| 74 | in_notes=0 | ||
| 75 | elif [[ "$line" =~ ^[[:space:]]+[0-9]{4}-[0-9]{2}-[0-9]{2}" at "[0-9]{2}:[0-9]{2} ]]; then | ||
| 76 | cur_iso_date=$(echo "$line" | grep -oE '[0-9]{4}-[0-9]{2}-[0-9]{2}') | ||
| 77 | cur_start_time=$(echo "$line" | grep -oE 'at [0-9]{2}:[0-9]{2}' | head -1 | sed 's/at //') | ||
| 78 | in_notes=0 | ||
| 79 | elif [[ "$line" == *"notes:"* ]]; then | ||
| 80 | in_notes=1 | ||
| 81 | cur_notes="$line" | ||
| 82 | elif [ "$in_notes" -eq 1 ]; then | ||
| 83 | cur_notes="${cur_notes} $(echo "$line" | sed 's/|/¦/g')" | ||
| 84 | fi | ||
| 85 | done < "$tmpfile" | ||
| 86 | |||
| 87 | # Process the last event | ||
| 88 | if [ "$event_num" -gt 0 ] && [ -n "$cur_title" ] && [ -n "$cur_start_time" ] && [ -n "$cur_iso_date" ]; then | ||
| 89 | meeting_epoch=$(date -j -f "%Y-%m-%d %H:%M" "$cur_iso_date $cur_start_time" +%s 2>/dev/null) | ||
| 90 | if [ -n "$meeting_epoch" ]; then | ||
| 91 | minutes_until=$(( (meeting_epoch - now_epoch) / 60 )) | ||
| 92 | if [ "$minutes_until" -ge "-$MAX_IN_PROGRESS_MINUTES" ]; then | ||
| 93 | echo "${cur_title}|${cur_iso_date}T${cur_start_time}||${cur_notes}|${minutes_until}" | ||
| 94 | rm -f "$tmpfile" | ||
| 95 | exit 0 | ||
| 96 | fi | ||
| 97 | fi | ||
| 98 | fi | ||
| 99 | |||
| 100 | rm -f "$tmpfile" | ||
| 101 | echo "" | ||
