{ ... }: { flake.homeManagerModules.wisdomDesktopScreenshot = { config, lib, pkgs, ... }: let root = config.chiasson.home; cfg = config.chiasson.home.desktop.screenshot; hyprlandHm = lib.attrByPath [ "wayland" "windowManager" "hyprland" ] { } config; hyprlandHmEnabled = hyprlandHm.enable or false; keyOk = cfg.swiftshareApiKeyFile != null && cfg.swiftshareApiKeyFile != ""; in { options.chiasson.home.desktop.screenshot.enable = lib.mkEnableOption '' grim/slurp/swappy + SwiftShare helpers; Hyprland binds if HM Hyprland is on. ''; options.chiasson.home.desktop.screenshot.swiftshareApiKeyFile = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; description = '' File with SwiftShare API key (sops path is fine). Required when screenshot module is on. ''; }; config = lib.mkMerge [ (lib.mkIf (root.enable && cfg.enable) { assertions = [ { assertion = keyOk; message = "chiasson.home.desktop.screenshot: set chiasson.home.desktop.screenshot.swiftshareApiKeyFile to your SwiftShare API key file path."; } ]; }) (lib.mkIf (root.enable && cfg.enable && keyOk) ( let apiKeyFile = cfg.swiftshareApiKeyFile; in lib.mkMerge [ { home.packages = with pkgs; [ grim slurp swappy wl-clipboard libnotify (writeShellScriptBin "swiftshare-upload" '' #!${pkgs.bash}/bin/bash set -euo pipefail COPY_URL=0 if [ "$#" -ge 1 ] && [ "$1" = "--copy-url" ]; then COPY_URL=1 shift fi APP_NAME="" if [ "$#" -ge 2 ] && [ "$1" = "--app-name" ]; then APP_NAME="$2" shift 2 fi API_KEY_FILE=${lib.escapeShellArg apiKeyFile} if [ -r "$API_KEY_FILE" ]; then SWIFTSHARE_API_KEY="$(tr -d '\n' < "$API_KEY_FILE")" fi if [ -z "''${SWIFTSHARE_API_KEY:-}" ]; then ${pkgs.libnotify}/bin/notify-send "SwiftShare upload" "SwiftShare API key missing (expected readable: $API_KEY_FILE)" echo "Error: SwiftShare API key missing (expected readable: $API_KEY_FILE)" >&2 exit 1 fi IMAGE_FILE="" RESPONSE_FILE="" cleanup() { if [ -n "$RESPONSE_FILE" ] && [ -f "$RESPONSE_FILE" ]; then rm -f "$RESPONSE_FILE" fi } trap cleanup EXIT if [ "$#" -ge 1 ] && [ "$1" != "-" ]; then IMAGE_FILE="$1" if [ "''${IMAGE_FILE#'/'}" = "''${IMAGE_FILE}" ]; then IMAGE_FILE="$(${pkgs.coreutils}/bin/readlink -f "''${IMAGE_FILE}")" fi if [ ! -f "$IMAGE_FILE" ]; then echo "Error: file not found: $IMAGE_FILE" >&2 exit 1 fi else APP_NAME="''${APP_NAME:-screenshot}" APP_NAME="''${APP_NAME%% *}" APP_NAME="''${APP_NAME//[^A-Za-z0-9]/}" APP_NAME="''${APP_NAME,,}" if [ -z "$APP_NAME" ]; then APP_NAME="screenshot" fi IMAGE_FILE="$(${pkgs.coreutils}/bin/mktemp --suffix=.png "''${TMPDIR:-/tmp}/''${APP_NAME}_XXXXXX")" cat > "$IMAGE_FILE" fi if [ ! -s "$IMAGE_FILE" ]; then ${pkgs.libnotify}/bin/notify-send "SwiftShare" "Empty capture (maybe canceled) – not uploading" echo "Empty image file, not uploading." >&2 exit 0 fi RESPONSE_FILE="$(mktemp)" set +e HTTP_STATUS="$(${pkgs.curl}/bin/curl -sS -o "''${RESPONSE_FILE}" -w '%{http_code}' \ -X POST "https://swiftshare.cloud/api/upload/sharex" \ -F "upload=@''${IMAGE_FILE}" \ -F "apiKey=''${SWIFTSHARE_API_KEY}")" CURL_EXIT=$? set -e RESPONSE="$(cat "''${RESPONSE_FILE}")" if [ "''${CURL_EXIT}" -ne 0 ]; then ${pkgs.libnotify}/bin/notify-send "SwiftShare upload failed" "Network or HTTP error (curl exit ''${CURL_EXIT})" echo "SwiftShare upload failed (curl exit ''${CURL_EXIT})." >&2 echo "Response body:" >&2 echo "''${RESPONSE}" >&2 exit 1 fi if ! echo "''${HTTP_STATUS}" | grep -qE '^2[0-9][0-9]$'; then ERROR_MSG="$(${pkgs.jq}/bin/jq -r '.error // empty' <<< "''${RESPONSE}")" if [ -z "''${ERROR_MSG}" ] || [ "''${ERROR_MSG}" = "null" ]; then ERROR_MSG="Failed to upload file" fi ${pkgs.libnotify}/bin/notify-send "SwiftShare upload failed (''${HTTP_STATUS})" "''${ERROR_MSG}" echo "SwiftShare upload failed (HTTP ''${HTTP_STATUS}): ''${ERROR_MSG}" >&2 exit 1 fi URL="$(${pkgs.jq}/bin/jq -r '.url // empty' <<< "''${RESPONSE}")" THUMBNAIL="$(${pkgs.jq}/bin/jq -r '.thumbnail // empty' <<< "''${RESPONSE}")" if [ -z "$URL" ] || [ "$URL" = "null" ]; then ${pkgs.libnotify}/bin/notify-send "SwiftShare upload failed" "Could not parse URL from response" echo "Upload failed. Raw response:" >&2 echo "''${RESPONSE}" >&2 exit 1 fi echo "$URL" if [ -n "$THUMBNAIL" ] && [ "$THUMBNAIL" != "null" ]; then echo "$THUMBNAIL" fi if [ "$COPY_URL" = "1" ]; then ${pkgs.wl-clipboard}/bin/wl-copy <<< "$URL" fi if [ -n "$IMAGE_FILE" ] && [ -f "$IMAGE_FILE" ]; then ${pkgs.libnotify}/bin/notify-send \ -a "SwiftShare" \ -i "$IMAGE_FILE" \ -h string:image-path:"$IMAGE_FILE" \ "SwiftShare upload" "Uploaded image: $URL" else ${pkgs.libnotify}/bin/notify-send "SwiftShare upload" "Uploaded image: $URL" fi '') (writeShellScriptBin "swiftshare-screenshot" '' #!${pkgs.bash}/bin/bash set -euo pipefail LOG_DIR="$HOME/.local/state/swiftshare" mkdir -p "$LOG_DIR" LOG_FILE="$LOG_DIR/screenshot.log" APP_CLASS="$(${pkgs.hyprland}/bin/hyprctl activewindow -j 2>/dev/null | ${pkgs.jq}/bin/jq -r '.class // .initialClass // empty' 2>/dev/null || true)" APP_CLASS="''${APP_CLASS%% *}" APP_CLASS="''${APP_CLASS//[^A-Za-z0-9]/}" APP_CLASS="''${APP_CLASS,,}" if [ -z "$APP_CLASS" ]; then APP_CLASS="screenshot" fi GEOM="$(${pkgs.slurp}/bin/slurp)" SLURP_EXIT=$? if [ "$SLURP_EXIT" -ne 0 ] || [ -z "$GEOM" ]; then ${pkgs.libnotify}/bin/notify-send "SwiftShare" "Capture canceled" { echo "==== $(date) ==== capture canceled (slurp exit $SLURP_EXIT, geom='$GEOM')" } >>"$LOG_FILE" 2>&1 exit 0 fi { echo "==== $(date) ====" echo "Geometry: $GEOM" ${pkgs.grim}/bin/grim -g "$GEOM" - | ${pkgs.swappy}/bin/swappy -f - -o - | swiftshare-upload --copy-url --app-name "$APP_CLASS" } >>"$LOG_FILE" 2>&1 '') ]; } (lib.mkIf hyprlandHmEnabled { wayland.windowManager.hyprland.settings = { bind = [ ", Print, exec, grim -g \"$(slurp)\" - | wl-copy" "Control, Print, exec, grim -g \"$(slurp)\" - | swappy -f -" "SUPER, Print, exec, swiftshare-screenshot" ]; windowrule = [ "float on, opacity 1.0 override, match:class ^(swappy)$" ]; }; }) ] )) ]; }; }