#!/bin/bash # Persistent Subscription Test Script # Subscribes to all events in the relay and prints them as they arrive in real-time # This tests the persistent subscription functionality of the C-Relay set -e # Exit on any error # Color constants RED='\033[31m' GREEN='\033[32m' YELLOW='\033[33m' BLUE='\033[34m' BOLD='\033[1m' RESET='\033[0m' # Test configuration RELAY_URL="ws://127.0.0.1:8888" SUBSCRIPTION_ID="persistent_test_$(date +%s)" # Print functions print_header() { echo -e "${BLUE}${BOLD}=== $1 ===${RESET}" } print_info() { echo -e "${BLUE}[INFO]${RESET} $1" } print_success() { echo -e "${GREEN}✓${RESET} $1" } print_error() { echo -e "${RED}✗${RESET} $1" } print_warning() { echo -e "${YELLOW}[WARNING]${RESET} $1" } print_event() { echo -e "${GREEN}[EVENT]${RESET} $1" } # Cleanup function cleanup() { print_info "Cleaning up..." if [[ -n "$WEBSOCAT_PID" ]]; then kill "$WEBSOCAT_PID" 2>/dev/null || true wait "$WEBSOCAT_PID" 2>/dev/null || true fi # Send CLOSE message to clean up subscription on relay if command -v websocat &> /dev/null; then echo "[\"CLOSE\",\"$SUBSCRIPTION_ID\"]" | timeout 2s websocat "$RELAY_URL" 2>/dev/null || true fi print_info "Cleanup complete" exit 0 } # Set up signal handlers trap cleanup SIGINT SIGTERM # Parse events from relay responses parse_events() { while IFS= read -r line; do # Check if this is an EVENT message if echo "$line" | jq -e '. | type == "array" and length >= 3 and .[0] == "EVENT"' >/dev/null 2>&1; then # Extract event details local event_id=$(echo "$line" | jq -r '.[2].id' 2>/dev/null || echo "unknown") local event_kind=$(echo "$line" | jq -r '.[2].kind' 2>/dev/null || echo "unknown") local event_content=$(echo "$line" | jq -r '.[2].content' 2>/dev/null || echo "") local event_pubkey=$(echo "$line" | jq -r '.[2].pubkey' 2>/dev/null || echo "unknown") local event_created_at=$(echo "$line" | jq -r '.[2].created_at' 2>/dev/null || echo "unknown") local event_tags=$(echo "$line" | jq -r '.[2].tags | length' 2>/dev/null || echo "0") # Convert timestamp to readable format local readable_time="unknown" if [[ "$event_created_at" != "unknown" && "$event_created_at" =~ ^[0-9]+$ ]]; then readable_time=$(date -d "@$event_created_at" "+%Y-%m-%d %H:%M:%S" 2>/dev/null || echo "$event_created_at") fi # Print formatted event print_event "Kind: $event_kind | ID: ${event_id:0:16}... | Author: ${event_pubkey:0:16}..." echo -e " ${YELLOW}Time:${RESET} $readable_time | ${YELLOW}Tags:${RESET} $event_tags" # Show content (truncated if too long) if [[ -n "$event_content" ]]; then local truncated_content="${event_content:0:100}" if [[ ${#event_content} -gt 100 ]]; then truncated_content="${truncated_content}..." fi echo -e " ${YELLOW}Content:${RESET} $truncated_content" fi echo # Blank line for readability elif echo "$line" | jq -e '. | type == "array" and length >= 2 and .[0] == "EOSE"' >/dev/null 2>&1; then # End of stored events local sub_id=$(echo "$line" | jq -r '.[1]' 2>/dev/null) print_info "End of stored events for subscription: $sub_id" print_success "Persistent subscription is now active - waiting for new events..." echo elif echo "$line" | jq -e '. | type == "array" and length >= 3 and .[0] == "CLOSED"' >/dev/null 2>&1; then # Subscription closed local sub_id=$(echo "$line" | jq -r '.[1]' 2>/dev/null) local reason=$(echo "$line" | jq -r '.[2]' 2>/dev/null) print_warning "Subscription $sub_id was closed: $reason" elif echo "$line" | jq -e '. | type == "array" and length >= 4 and .[0] == "OK"' >/dev/null 2>&1; then # OK response to event publishing local event_id=$(echo "$line" | jq -r '.[1]' 2>/dev/null) local success=$(echo "$line" | jq -r '.[2]' 2>/dev/null) local message=$(echo "$line" | jq -r '.[3]' 2>/dev/null) if [[ "$success" == "true" ]]; then print_success "Event published: ${event_id:0:16}..." else print_error "Event publish failed: ${event_id:0:16}... - $message" fi else # Unknown message type - just show it print_info "Relay message: $line" fi done } # Main function main() { print_header "Persistent Subscription Test - Subscribe to All Events" # Check dependencies if ! command -v websocat &> /dev/null; then print_error "websocat command not found" print_info "Please install websocat for testing" return 1 fi if ! command -v jq &> /dev/null; then print_error "jq command not found" print_info "Please install jq for JSON processing" return 1 fi print_info "Subscription ID: $SUBSCRIPTION_ID" print_info "Relay URL: $RELAY_URL" print_info "Filter: {} (all events)" echo # Create REQ message to subscribe to all events local req_message="[\"REQ\",\"$SUBSCRIPTION_ID\",{}]" print_info "Establishing persistent subscription..." print_info "Press Ctrl+C to stop and cleanup" echo # Start websocat connection and keep it open { echo "$req_message" # Keep the connection alive by sleeping indefinitely # The connection will receive events as they come in while true; do sleep 1 done } | websocat "$RELAY_URL" | parse_events & # Store the background process ID WEBSOCAT_PID=$! # Wait for the background process (which runs indefinitely) # This will exit when we get a signal (Ctrl+C) wait "$WEBSOCAT_PID" 2>/dev/null || true } # Usage information usage() { echo "Usage: $0" echo echo "This script creates a persistent subscription to all events on the relay" echo "and displays them in real-time as they arrive. Perfect for testing" echo "the persistent subscription functionality." echo echo "To test:" echo "1. Run this script in one terminal" echo "2. Run 'tests/1_nip_test.sh' in another terminal" echo "3. Watch events appear in real-time in this terminal" echo echo "Press Ctrl+C to stop and cleanup the subscription." } # Handle help flag if [[ "$1" == "-h" || "$1" == "--help" ]]; then usage exit 0 fi # Run main function main "$@"