#!/usr/bin/env bash # nf (netfinger): A netcat-based finger client. # Features: user@domain and finger:// URL support, HTML rendering, smart # wrapping, blocklists, custom shortcuts, CR/LF detection, error handling # and protocol validation. # 3.6 : 2025-12-04 : Filename changed to "nf", various improvements # 3.5 : 2025-12-01 : HTML renderer: better URL detection, punctuation handling # 3.0 : 2025-11-28 : added --wrap and --render flags # 2.0 : 2025-11-27 : multi-location weather support; per server blocklist # 1.0 : 2025-11-24 : initial release # Copyright (c) 2025 (https://640kb.neocities.org) # Licensed under the Blue Oak Model License 1.0.0 if [ $# -eq 1 ] && [[ "$1" =~ ^(-h|--help|/\?|-\?)$ ]]; then echo echo " .-----------------------------------------------------------." echo " | nf (netfinger): A finger client using netcat. |" echo " '-----------------------------------------------------------'" echo " .-----------------------------------------------------------." echo " | Usage: nf user@domain.com (OR) |" echo " | nf finger://domain.com/user |" echo " '-----------------------------------------------------------'" echo " .-----------------------------------------------------------." echo " | Examples: nf @example.com | head -n 20 |" echo " | nf user@example.com |" echo " | |" echo " | nf finger://example.com/user | less |" echo " | |" echo " | nf -r user@domain.com |" echo " | nf -w finger://domain.com/user |" echo " '-----------------------------------------------------------'" echo " .-----------------------------------------------------------." echo " | Options: -l --list Displays shortcuts (see code) |" echo " | |" echo " | -w --wrap Smart wrap using fold & less |" echo " | -r --render Output HTML; clickable links |" echo " | |" echo " | blocklist edit --hnb and --plan sections of code |" echo " | wrap width edit the function wrap_text() |" echo " '-----------------------------------------------------------'" echo exit 0 fi # --------------------------------------------------------------------------- # Shortcuts section: Examples below. Adjust for personal use (no arrays, no # config files - just easy to edit case statements) or you can delete this # entire section without affecting the script's core function. case "$1" in --ansi) "$0" ansi@happynetbox.com | head -n -2 | echo -e "$(cat)" exit 0 ;; --verse) "$0" fingerverse@happynetbox.com | less exit 0 ;; --text) "$0" textfile@typed-hole.org | less exit 0 ;; --weather) { echo "================================================================================" echo "$0" ^'New York, New York'@graph.no echo echo "================================================================================" echo "$0" ^'Death Valley, California'@graph.no echo echo "================================================================================" echo "$0" ^'Moscow, Russia'@graph.no echo echo "================================================================================" echo "$0" ^'Beijing, China'@graph.no echo echo "================================================================================" echo "$0" ^"roswell, new mexico"@graph.no echo echo "================================================================================" echo "$0" ^"Easter Island, Chile"@graph.no echo echo "================================================================================" echo "$0" ^'Beaver Creek, Yukon'@graph.no echo echo "================================================================================" echo } | less exit 0 ;; --say) "$0" say@happynetbox.com | head -n 25 exit 0 ;; # Blocklist: Edit the grep -v lines to add/remove usernames from your blocklist --hnb) "$0" @happynetbox.com \ | tail -n +5 | head -n -7 \ | grep -v -i -w trollacct1 \ | grep -v -i -w spammer1 \ | grep -v -i -w trollacct2 exit 0 ;; # Blocklist: Edit the grep -v lines to add/remove usernames from your blocklist --plan) "$0" @plan.cat \ | head -n 20 \ | grep -v -i -w trollacct1 \ | grep -v -i -w spammer1 \ | grep -v -i -w trollacct2 exit 0 ;; -l|--list) printf "%s\n" --ansi --verse --text --weather --say --hnb --plan --list exit 0 ;; esac # Shortcuts section: END # --------------------------------------------------------------------------- # Process flags WRAP_MODE=false RENDER_MODE=false FINGER_TARGET="" # Parse flags while [[ $# -gt 0 ]]; do case "$1" in -w|--wrap) WRAP_MODE=true shift ;; -r|--render) RENDER_MODE=true shift ;; -*) echo "Error: Unknown flag $1" >&2 exit 1 ;; *) if [ -z "$FINGER_TARGET" ]; then FINGER_TARGET="$1" shift else echo "Error: Multiple finger targets specified" >&2 exit 1 fi ;; esac done if [ -z "$FINGER_TARGET" ]; then echo echo " Error: Missing finger target" >&2 echo " Use 'nf -h' for help" >&2 echo exit 1 fi input="$FINGER_TARGET" if [[ "$input" == finger://* ]]; then path="${input#finger://}" if [[ "$path" == */* ]]; then host="${path%%/*}" user="${path#*/}" else host="$path" user="" fi if [ -n "$user" ]; then input="$user@$host" else input="@$host" fi fi if [[ "$input" == *://* ]]; then protocol="${input%%://*}" echo "Error: Only finger protocol is supported (got $protocol:// instead)" >&2 exit 1 fi # Edit "80" to change wrap width when using the "-w" option. Default is 80. wrap_text() { fold -s -w "${1:-80}" | less } render_html() { awk '{ while(match($0, /(https?|gemini|finger|spartan|gopher):\/\/[^[:space:]<>"'"'"']*/)) { url = substr($0, RSTART, RLENGTH) after = substr($0, RSTART + RLENGTH) # Strip trailing punctuation from all URLs EXCEPT Wikipedia if (url ~ /[.,;:!?)]$/ && !(url ~ /wikipedia\.org/)) { # Remove the trailing punctuation character after = substr(url, length(url)) after url = substr(url, 1, length(url) - 1) } printf "%s%s", substr($0, 1, RSTART - 1), url, url $0 = after } print }' } if [[ "$input" == @* ]]; then host="${input#@}" output=$(printf '\r\n' | nc -w 3 "$host" 79 2>/dev/null || echo | nc -w 3 "$host" 79 2>/dev/null) elif [[ "$input" == *@* ]]; then user="${input%@*}" host="${input#*@}" output=$(printf '%s\r\n' "$user" | nc -w 3 "$host" 79 2>/dev/null || echo "$user" | nc -w 3 "$host" 79 2>/dev/null) else echo "Error: Input must be in format user@host or finger://host/user" >&2 exit 1 fi # Process output based on flags (-r, -w or normal request) if $RENDER_MODE; then echo "
"
echo "$output" | render_html
echo ""
elif $WRAP_MODE; then
echo "$output" | wrap_text 80
else
echo "$output"
echo # optional: added a blank line for improved readability of finger query
fi