From 3f17fea0afa2a7d2c49f6a9cbd16e5a7b2324f65 Mon Sep 17 00:00:00 2001 From: ItsDrike Date: Fri, 21 Jun 2024 15:54:02 +0200 Subject: [PATCH] Add gh-notify script --- home/packages/cli/scripts/default.nix | 1 + .../packages/cli/scripts/packages/default.nix | 1 + .../scripts/packages/gh-notify/default.nix | 16 + .../scripts/packages/gh-notify/gh-notify.sh | 330 ++++++++++++++++++ home/programs/terminal/tools/git/gh.nix | 2 +- 5 files changed, 349 insertions(+), 1 deletion(-) create mode 100644 home/packages/cli/scripts/packages/gh-notify/default.nix create mode 100644 home/packages/cli/scripts/packages/gh-notify/gh-notify.sh diff --git a/home/packages/cli/scripts/default.nix b/home/packages/cli/scripts/default.nix index 307edbb..1149e67 100644 --- a/home/packages/cli/scripts/default.nix +++ b/home/packages/cli/scripts/default.nix @@ -10,5 +10,6 @@ in { cheatsh colors256 unix + gh-notify ]; } diff --git a/home/packages/cli/scripts/packages/default.nix b/home/packages/cli/scripts/packages/default.nix index 2d9e5d7..d4c4f7f 100644 --- a/home/packages/cli/scripts/packages/default.nix +++ b/home/packages/cli/scripts/packages/default.nix @@ -7,6 +7,7 @@ cheatsh = pkgs.callPackage ./cheatsh {}; colors256 = pkgs.callPackage ./colors256 {}; unix = pkgs.callPackage ./unix {}; + gh-notify = pkgs.callPackage ./gh-notify {}; }; in packages diff --git a/home/packages/cli/scripts/packages/gh-notify/default.nix b/home/packages/cli/scripts/packages/gh-notify/default.nix new file mode 100644 index 0000000..cd35398 --- /dev/null +++ b/home/packages/cli/scripts/packages/gh-notify/default.nix @@ -0,0 +1,16 @@ +{pkgs, ...}: +(pkgs.writeShellApplication { + name = "gh-notify"; + runtimeInputs = with pkgs; [ + coreutils + findutils + gawk + libnotify + gh # we also need gh-notify plugin, this assumes it's installed + ]; + text = '' + ${builtins.readFile ./gh-notify.sh} + ''; +}) + + diff --git a/home/packages/cli/scripts/packages/gh-notify/gh-notify.sh b/home/packages/cli/scripts/packages/gh-notify/gh-notify.sh new file mode 100644 index 0000000..206cfc8 --- /dev/null +++ b/home/packages/cli/scripts/packages/gh-notify/gh-notify.sh @@ -0,0 +1,330 @@ +#!/bin/sh + +# Parse arguments +# ------------------------------------------------------------------------------------ +ALL=0 +VERBOSE=0 +VERY_VERBOSE=0 +VERY_VERY_VERBOSE=0 +TEMP_SHOW=0 +DRY_RUN=0 +NO_CACHE=0 +NO_DISPLAY=0 +MAX_AMOUNT=0 +URGENCY="normal" +RESET=0 +while [ "${1-}" ]; do + case "$1" in + -h | --help) + cat </dev/null; then + printf "%s\n" "$file_name" >>"$fail_files_file" + fi + else + [ $VERY_VERY_VERBOSE -eq 1 ] && echo "Tempfile removal skipped (dry-run)" + fi + + # Add a new-line separator on very very verbose to group prints from each iteration + [ $VERY_VERY_VERBOSE -eq 1 ] && echo "" + done + + # Recover failed files from the temporary file + failed_files="$(cat "$fail_files_file")" + failed="$(printf "%s" "$fail_files_file" | wc -l)" + rm "$fail_files_file" + + if [ $VERBOSE -eq 1 ]; then + echo "Notification cache was reset." + removed_count="$(("$total" - "$failed"))" + if [ $DRY_RUN -eq 1 ]; then + echo "Removed $removed_count files (dry-run: no files were actually removed)" + else + echo "Removed $removed_count files" + fi + fi + + # If some cache files were'nt removed successfully, inform the user about it + # regardless of verbosity, this shouldn't go silent, even though it may be fine + if [ "$failed" -gt 0 ]; then + echo "WARNING: Failed to remove $failed files." + echo "You probably don't have permission to remove these." + echo "Perhaps these were made by someone else? If so, you can ignore this warning." + if [ $VERBOSE -eq 0 ]; then + echo "Run with --verbose to show exactly which files weren't removed." + else + echo "These are:" + echo "$failed_files" + fi + fi + else + [ $VERBOSE -eq 1 ] && echo "No cache files found, nothing to reset" + fi + exit 0 +fi + +# Helper functins +# ------------------------------------------------------------------------------------ +# This runs notify-send, and if NO_DISPLAY is set and we're running in headless +# mode, this will still try to send the notification by manually setting DISPLAY +# This also has a special handle that checks if dunst is the notification daemon +# in which case instead of using notify-send, we use dunstify to send the +# notification, with which we can also specify some more values. +send_notify() { + if [ $NO_DISPLAY -eq 1 ]; then + XDG_RUNTIME_DIR="/run/user/$(id -u)" \ + DISPLAY=:0 \ + notify-send -i "$HOME/.local/share/icons/hicolor/64x64/apps/github-notification.png" --app-name=github-notification --urgency="$URGENCY" "$1" "$2" + else + notify-send -i "$HOME/.local/share/icons/hicolor/64x64/apps/github-notification.png" --app-name=github-notification --urgency="$URGENCY" "$1" "$2" + fi +} + +# Obtain notifications and show them, if they weren't showed (aren't in cache) already +# ------------------------------------------------------------------------------------ +# Request unread notifications with gh-notify extension for github-cli +[ "$ALL" -eq 1 ] && out="$(gh notify -s -a -n "$MAX_AMOUNT" 2>/dev/null)" || out="$(gh notify -s -n "$MAX_AMOUNT" 2>/dev/null)" + +# When no notifications were found, set output to empty string, to avoid 'All caught up!' line +# being treated as notification +if [ "$out" == "All caught up!" ]; then + out="" +fi + +total="$(printf "%s\n" "$out" | wc -l)" +# Since we always end with a newline (to count the last entry as a line), we always get +# at least 1 as a total here, even if $out is empty. If we didn't use the \n, we'd always +# get 0, even if there was a single line, since it wasn't ended with a newline. To figure +# out whether there really is a line or not when we get a total of 1, we run character +# amount check as well +[ "$total" -eq 1 ] && [ "$(printf "%s" "$out" | wc -c)" -eq 0 ] && total=0 + +# Only run if we actually found some notifications +if [ "$total" -gt 0 ]; then + # Since the loop is running in a pipe, it can't modify variables, but we need to know + # how many notifications were sent, so to ge that information, we store it in a + # temporary file + sent_count_file="$(mktemp)" + printf "0" >"$sent_count_file" + + # Go through each notification, one by one + printf "%s\n" "$out" | while read -r line; do + + [ $VERY_VERY_VERBOSE -eq 1 ] && echo "gh-notify output line: $line" + + # Parse out the data from given output lines + issue_type="$(echo "$line" | awk '{print $4}' | sed 's/\x1b\[[0-9;]*m//g')" + repo_id="$(echo "$line" | awk '{print $3}' | sed 's/\x1b\[[0-9;]*m//g')" + + if [ "$issue_type" == "PullRequest" ]; then + issue_id="$(echo "$line" | awk '{print $5}' | sed 's/\x1b\[[0-9;]*m//g' | cut -c2-)" + description="$(echo "$line" | awk '{for (i=6; i"$temp_file" + hashsum="$(sum <"$temp_file" | cut -f 1 -d ' ')" + rm "$temp_file" + + tmpname="/tmp/gh-notification-$hashsum" + [ $TEMP_SHOW -eq 1 ] && echo "Tempfile: $tmpname" + + # If the temporary file is already present, this notification was already + # send and we don't want to re-send it + + # Only sent the notification if it wasn't already cached (doesn't have temp file) + # this avoids resending the same notifications + if [ ! -e "$tmpname" ] || [ $NO_CACHE -eq 1 ]; then + if [ $DRY_RUN -eq 1 ]; then + [ $VERY_VERBOSE -eq 1 ] && echo "Sending notification (dry-run, no actual notification was sent)" + else + [ $VERY_VERBOSE -eq 1 ] && echo "Sending notification" + send_notify "$name" "$description <$url>" + # Create the tempfile so that in the next run, we won't resend this notification again + # NOTE: We're storing the name and description into this file to make it easier + # to figure out what notification the tempfile belongs to, with ~@~ separator + printf "%s~@~%s" "$name" "$description" >"$tmpname" + fi + # Keep track of how many notifications were sent (didn't have a cache file) + sent="$(cat "$sent_count_file")" + sent="$(("$sent" + 1))" + printf "%s" "$sent" >"$sent_count_file" + else + [ $VERY_VERBOSE -eq 1 ] && echo "Skipping (cached) - notification already sent" + fi + + # Add a new-line separator on very verbose to group prints from each iteration + [ $VERY_VERBOSE -eq 1 ] && echo "" + done + + # Recover amount of sent notifications from the temporary file + sent="$(cat "$sent_count_file")" + rm "$sent_count_file" + + if [ $VERBOSE -eq 1 ]; then + unsent="$(("$total" - "$sent"))" + if [ "$sent" -eq "$total" ]; then + echo "Found and sent $total new notifications" + elif [ "$unsent" -eq "$total" ]; then + echo "Found $total notifications, all of which were already sent (no new notifications to send)" + else + echo "Found $total notifications, of which $sent were new and sent ($unsent were skipped - cached/already sent)" + fi + fi +else + [ $VERBOSE -eq 1 ] && echo "No new notifications" +fi diff --git a/home/programs/terminal/tools/git/gh.nix b/home/programs/terminal/tools/git/gh.nix index f10dc7f..05e2e69 100644 --- a/home/programs/terminal/tools/git/gh.nix +++ b/home/programs/terminal/tools/git/gh.nix @@ -6,7 +6,7 @@ gh-dash # dashboard with pull requess and issues gh-eco # explore the ecosystem gh-cal # contributions calendar terminal viewer - # TODO: Include meiji163/gh-notify + gh-notify # access and manage github notifications ]; settings = { git_protocol = "ssh";