#!/bin/bash # Colors for output GREEN='\033[0;32m' BLUE='\033[0;34m' CYAN='\033[0;36m' NC='\033[0m' # No Color # Configuration CONFIG_FILE="config.json" OUR_PUBKEY="" RELAYS=() show_usage() { echo "Superball Relay Watcher - Simple JSON Display" echo "" echo "Usage:" echo " $0 [options]" echo "" echo "Options:" echo " -c, --config Config file path (default: config.json)" echo " -h, --help Show this help message" echo "" echo "Watches all relays from config.json for:" echo " - All events from our thrower (pubkey from config.json)" echo " - Kind 0 (Metadata), Kind 10002 (Relay List)" echo " - Kind 12222 (Thrower Info), Kind 22222 (Routing)" } while [[ $# -gt 0 ]]; do case $1 in -c|--config) CONFIG_FILE="$2" shift 2 ;; -h|--help) show_usage exit 0 ;; *) echo "Unknown option: $1" show_usage exit 1 ;; esac done # Check if nak is installed if ! command -v nak &> /dev/null; then echo "Error: 'nak' command not found" echo "Please install nak: https://github.com/fiatjaf/nak" exit 1 fi # Check if jq is installed if ! command -v jq &> /dev/null; then echo "Error: 'jq' command not found" exit 1 fi # Load config.json if it exists if [[ -f "$CONFIG_FILE" ]]; then echo -e "${BLUE}Loading configuration from $CONFIG_FILE...${NC}" # Extract private key and derive public key PRIVATE_KEY=$(jq -r '.thrower.privateKey // empty' "$CONFIG_FILE") if [[ -n "$PRIVATE_KEY" ]]; then OUR_PUBKEY=$(echo "$PRIVATE_KEY" | nak key public) if [[ -n "$OUR_PUBKEY" ]]; then echo -e "${GREEN}✓ Our thrower pubkey: ${OUR_PUBKEY:0:16}...${NC}" fi fi # Get all relays from config mapfile -t RELAYS < <(jq -r '.relays[].url' "$CONFIG_FILE") if [[ ${#RELAYS[@]} -gt 0 ]]; then echo -e "${GREEN}✓ Loaded ${#RELAYS[@]} relay(s) from config${NC}" for relay in "${RELAYS[@]}"; do echo -e " - $relay" done fi echo "" fi if [[ ${#RELAYS[@]} -eq 0 ]]; then echo "Error: No relays found in config.json" exit 1 fi if [[ -z "$OUR_PUBKEY" ]]; then echo "Warning: Could not derive pubkey from config.json" echo "Will only show kinds 0, 10002, 12222, 22222" echo "" fi echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" if [[ -n "$OUR_PUBKEY" ]]; then echo -e "${BLUE}Watching:${NC} Events from ${OUR_PUBKEY:0:16}... + kinds 0, 10002, 12222, 22222" else echo -e "${BLUE}Watching:${NC} Kinds 0, 10002, 12222, 22222" fi echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" echo "" echo -e "${GREEN}Listening for events... (Press Ctrl+C to stop)${NC}" echo "" # Build two separate nak commands: # 1. Watch for kinds 12222 and 22222 from anyone NAK_CMD1="nak req --stream -k 12222 -k 22222" for relay in "${RELAYS[@]}"; do NAK_CMD1="$NAK_CMD1 $relay" done # 2. Watch for all events from our thrower (if we have the pubkey) NAK_CMD2="" if [[ -n "$OUR_PUBKEY" ]]; then NAK_CMD2="nak req --stream -a $OUR_PUBKEY" for relay in "${RELAYS[@]}"; do NAK_CMD2="$NAK_CMD2 $relay" done fi # Combine both subscriptions and stream events { if [[ -n "$NAK_CMD2" ]]; then # Run both subscriptions in parallel, merge output eval "$NAK_CMD1" 2>/dev/null & eval "$NAK_CMD2" 2>/dev/null else # Only run the first subscription eval "$NAK_CMD1" 2>/dev/null fi } | while IFS= read -r line; do # Skip non-JSON lines if echo "$line" | jq empty 2>/dev/null; then # Check if it's an event array ["EVENT", "sub_id", {...}] if echo "$line" | jq -e '.[0] == "EVENT"' > /dev/null 2>&1; then event=$(echo "$line" | jq '.[2]') # Get event details kind=$(echo "$event" | jq -r '.kind') pubkey=$(echo "$event" | jq -r '.pubkey') id=$(echo "$event" | jq -r '.id') # Check if it's from our thrower is_ours="" if [[ -n "$OUR_PUBKEY" && "$pubkey" == "$OUR_PUBKEY" ]]; then is_ours=" ${GREEN}[OUR THROWER]${NC}" fi # Display separator and event info echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" echo -e "${BLUE}Kind ${kind} | ID: ${id:0:16}...${is_ours}${NC}" echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" # Display formatted JSON echo "$event" | jq '.' echo "" # Or if it's a direct event object elif echo "$line" | jq -e '.kind' > /dev/null 2>&1; then kind=$(echo "$line" | jq -r '.kind') pubkey=$(echo "$line" | jq -r '.pubkey') id=$(echo "$line" | jq -r '.id') # Check if it's from our thrower is_ours="" if [[ -n "$OUR_PUBKEY" && "$pubkey" == "$OUR_PUBKEY" ]]; then is_ours=" ${GREEN}[OUR THROWER]${NC}" fi # Display separator and event info echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" echo -e "${BLUE}Kind ${kind} | ID: ${id:0:16}...${is_ours}${NC}" echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" # Display formatted JSON echo "$line" | jq '.' echo "" fi fi done