# fish_greeting — show a random library image as the shell greeting. # # Updated for the J621 Docker/REST rewrite: the API answers with JSON that # carries a signed URL instead of streaming the image, so this function asks # for one random png/jpg/gif (fastfetch mode), downloads the signed link and # hands the file to fastfetch. Based on the original script from # J621-Django/extras/fish_greeting system/fish_greeting.fish. # # Requires: curl (or wget) and fastfetch; gifsicle is used for animated GIFs # (without it, the GIF is shown as-is). # # Rating modes (same file as the original script): # ~/.config/fish/greeting_mode 0 = NSFW (explicit), 1 = SFW (safe), # 2 = Questionable (default) # # Configuration, any of these (all optional): # ~/.config/j621Greeting/config.fish with `set -g VAR value` lines, or # universal variables, e.g. `set -Ux J621_BASE https://j621.example.ts.net` # J621_BASE API origin (default https://j621.rainbow-herring.ts.net) # J621_TOKEN API token, sent as `Authorization: Token …`; needed for # signed URLs and for hidden-from-guests items (optional) # J621_WEB Web origin used in the printed link (defaults to J621_BASE) # J621_FASTFETCH_CONFIG fastfetch config name (default "jake") function __j621_json_field --argument-names json field if command -v jq >/dev/null 2>&1 printf '%s' "$json" | jq -r --arg field "$field" '.[$field] // empty' else if command -v python3 >/dev/null 2>&1 printf '%s' "$json" | python3 -c "import json,sys; value = json.load(sys.stdin).get(sys.argv[1], ''); print(value if value is not None else '')" $field else printf '%s' "$json" | grep -o "\"$field\"[[:space:]]*:[[:space:]]*\"[^\"]*\"" | head -1 | sed -E 's/.*:[[:space:]]*"//; s/"$//' end end function __j621_fetch_random --argument-names rating set base (string trim --right --chars=/ "$J621_BASE") set api_url "$base/api/random/?fastfetch=1&rating=$rating" set curl_args -s -L --max-time 20 if set -q J621_TOKEN; and test -n "$J621_TOKEN" set -a curl_args -H "Authorization: Token $J621_TOKEN" end if command -v curl >/dev/null 2>&1 curl $curl_args "$api_url" | string collect else if command -v wget >/dev/null 2>&1 wget -qO- "$api_url" | string collect end end function fish_greeting --argument-names depth # Initialize depth to 0 if not provided or empty if not set -q depth; or test -z "$depth" set depth 0 end set MAX_DEPTH 3 # --- Configuration --- set config_file ~/.config/j621Greeting/config.fish if test -f $config_file source $config_file end set -q J621_BASE; or set -g J621_BASE https://j621.rainbow-herring.ts.net set -q J621_WEB; or set -g J621_WEB $J621_BASE set -q J621_FASTFETCH_CONFIG; or set -g J621_FASTFETCH_CONFIG jake set web_base (string trim --right --chars=/ "$J621_WEB") # --- Setup logging --- set log_dir ~/.config/j621Logos if not test -d $log_dir mkdir -p $log_dir end set log_file $log_dir/logs.log # --- Mode selection --- if test -f ~/.config/fish/greeting_mode set mode (cat ~/.config/fish/greeting_mode | string trim) else set mode 2 end switch $mode case "0" set rating e set modename "NSFW" case "1" set rating s set modename "SFW" case "2" set rating q set modename "Questionable" case "*" echo "Unknown mode, using default NSFW" set rating e set modename "NSFW" end # --- Ask the API for a random image (JSON with a signed URL) --- set json (__j621_fetch_random $rating) set image_url (__j621_json_field "$json" url) set j_id (__j621_json_field "$json" j_id) set md5 (__j621_json_field "$json" md5) set filename (__j621_json_field "$json" filename) if test -z "$image_url" set detail (__j621_json_field "$json" detail) fastfetch --config "$J621_FASTFETCH_CONFIG" if test -n "$detail" printf '\e[4;2;38;2;138;0;222;49mNo logo (%s)\e[0m\n' "$detail" else printf '\e[4;2;38;2;138;0;222;49mNo logo (API error)\e[0m\n' end echo "$(date '+%Y-%m-%d %H:%M:%S') No logo for rating=$rating: $detail" >> "$log_file" return end # --- Download the signed image --- set tempfile (mktemp /tmp/fastfetch_logo_XXXXXX) set download_success 0 if command -v curl >/dev/null 2>&1 curl -s -L --max-time 60 -o "$tempfile" "$image_url" if test $status -eq 0 -a -s "$tempfile" set download_success 1 end else if command -v wget >/dev/null 2>&1 wget -q -O "$tempfile" "$image_url" if test $status -eq 0 -a -s "$tempfile" set download_success 1 end end if test $download_success -ne 1 fastfetch --config "$J621_FASTFETCH_CONFIG" printf '\e[4;2;38;2;138;0;222;49mNo logo (download failed)\e[0m\n' echo "$(date '+%Y-%m-%d %H:%M:%S') Download failed for $j_id" >> "$log_file" rm -f "$tempfile" return end # --- Determine MIME type --- set mime (file --mime-type -b "$tempfile" 2>/dev/null | string trim | string collect) # --- Accept only PNG, JPEG, GIF; everything else causes one more roll --- if not string match -q "image/png" "$mime"; and not string match -q "image/jpeg" "$mime"; and not string match -q "image/gif" "$mime" if test $depth -lt $MAX_DEPTH fish_greeting (math $depth + 1) else printf '\e[31mMax recursion depth reached, skipping unsupported file type: %s\e[0m\n' "$mime" end if test $depth -eq 0 printf '\e[31mForked (Got unsupported type: %s - %s)\e[0m\n' "$mime" "$filename" if test -n "$md5" echo "Link: $web_base/view/$md5" end end rm -f "$tempfile" "$tempfile.tmp" 2>/dev/null return end # --- Process the file (only PNG, JPEG, GIF reach here) --- set logo_type "kitty" set processing_success 1 switch "$mime" case "image/png" "image/jpeg" set logo_type "kitty" case "image/gif" set processed_ok 0 set simple_file (mktemp /tmp/fastfetch_simple_XXXXXX) set gif_err (mktemp) if command -v gifsicle >/dev/null 2>&1 gifsicle --colors 255 "$tempfile" > "$simple_file" 2> "$gif_err" set gif_exit $status if test $gif_exit -eq 0 -a -s "$simple_file" gifsicle --unoptimize --resize-fit 360x360 "$simple_file" > "$tempfile.tmp" 2> "$gif_err" set final_exit $status set gif_warnings (cat "$gif_err" | string trim) if test $final_exit -eq 0 -a -s "$tempfile.tmp" -a -z "$gif_warnings" mv "$tempfile.tmp" "$tempfile" set processed_ok 1 set logo_type "kitty-icat" echo "$(date '+%Y-%m-%d %H:%M:%S') GIF processed with gifsicle" >> "$log_file" else echo "$(date '+%Y-%m-%d %H:%M:%S') gifsicle final failed: $gif_warnings" >> "$log_file" end else echo "$(date '+%Y-%m-%d %H:%M:%S') gifsicle --colors failed" >> "$log_file" end end rm -f "$simple_file" "$gif_err" if test $processed_ok -eq 0 set logo_type "kitty-icat" echo "$(date '+%Y-%m-%d %H:%M:%S') Using original GIF (processing failed)" >> "$log_file" end end # --- Display result --- if test $processing_success -eq 1 fastfetch --config "$J621_FASTFETCH_CONFIG" --logo-type "$logo_type" --logo "$tempfile" --logo-width 35 set timestamp (date '+%Y-%m-%d %H:%M:%S') echo "$timestamp Downloaded: $j_id $filename [$modename]" >> "$log_file" if test -n "$filename" printf '\e[4;2;38;2;138;0;222;49mLogo from API: %s (%s, %s)\e[0m\n' "$filename" "$modename" "$j_id" echo "Link: $web_base/detail/$j_id" else printf '\e[4;2;38;2;138;0;222;49mLogo from API (%s)\e[0m\n' "$modename" end else fastfetch --config "$J621_FASTFETCH_CONFIG" printf '\e[4;2;38;2;138;0;222;49mNo logo (Image processing error)\e[0m\n' end # --- Keep only the last 1000 lines of the log --- set log_tmp (mktemp) tail -n 1000 "$log_file" > "$log_tmp" 2>/dev/null mv "$log_tmp" "$log_file" # --- Cleanup --- rm -f "$tempfile" "$tempfile.tmp" 2>/dev/null end