lwvwv/automation/run-subscription.sh

199 lines
6.4 KiB
Bash
Executable File

#!/bin/bash
source "$(dirname "$0")/entrypoint.sh" 2>/dev/null || true
# Master orchestration script for LWVWV member subscription automation
# This script coordinates the entire workflow:
# 1. Download roster from LWVWV portal (if download-roster.js is available)
# 2. Convert roster to CSV format, filtered by League ID per list
# 3. Subscribe members to Mailman list(s) via connector API
# 4. Cleanup temporary files
#
# Environment Variables (loaded from /app/env via entrypoint.sh):
# CONNECTOR_URL - URL of mailman-connector
# CONNECTOR_PASSWORD - Secret password for connector API
# MAILMAN_LIST_ID - Target mailing list ID(s). Format: "list_id:league_id, list_id:league_id"
# If :league_id is omitted, defaults to "ALL" (all members)
# EMAIL_TO - Email for failure notifications
# SMTP_HOST - SMTP server for notifications
#
# Examples:
# Single list, all members: "members.lists.lwvwv.org"
# Single list, WV000 only: "members.lists.lwvwv.org:WV000"
# Multiple lists: "members.lists.lwvwv.org:WV000, morgantown.lists.lwvwv.org:WV103"
set -e # Exit on error
# Configuration from environment
WORK_DIR="${WORK_DIR:-/tmp/rosters}"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
ROSTER_FILE="$WORK_DIR/roster_$TIMESTAMP.csv"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
}
error_exit() {
echo "[ERROR] $1" >&2
# Send alert email if configured
if [ -n "$EMAIL_TO" ] && [ -n "$SMTP_HOST" ]; then
echo "$1" | s-nail -s "LWVWV Subscription Failed" "$EMAIL_TO" 2>/dev/null || true
fi
exit 1
}
# Create work directory
mkdir -p "$WORK_DIR"
# Determine CSV input source or download
if [ -n "$1" ]; then
# CSV file provided as argument
ROSTER_FILE="$1"
log "Using provided roster file: $ROSTER_FILE"
if [ ! -f "$ROSTER_FILE" ]; then
error_exit "Roster file not found: $ROSTER_FILE"
fi
else
# No CSV provided - try to download from portal
if [ ! -f "./download-roster.js" ]; then
error_exit "No CSV file provided and download-roster.js not found"
fi
# Step 1: Download roster
log "Downloading roster from LWVWV portal..."
if ! node download-roster.js; then
error_exit "Failed to download roster"
fi
# Find the downloaded file
ROSTER_FILE=$(ls -t league_membership_state_view_*.csv 2>/dev/null | head -1)
if [ -z "$ROSTER_FILE" ]; then
error_exit "No roster file found after download"
fi
log "Downloaded roster: $ROSTER_FILE"
fi
# Validate required environment variables
if [ -z "$CONNECTOR_URL" ]; then
error_exit "CONNECTOR_URL not set. Ensure /app/env is mounted and contains \$CONNECTOR_URL"
fi
if [ -z "$CONNECTOR_PASSWORD" ]; then
error_exit "CONNECTOR_PASSWORD not set. Ensure /app/env is mounted and contains \$CONNECTOR_PASSWORD"
fi
if [ -z "$MAILMAN_LIST_ID" ]; then
error_exit "MAILMAN_LIST_ID not set. Ensure /app/env is mounted and contains \$MAILMAN_LIST_ID"
fi
if [ ! -f "./google-civic-api.pl" ]; then
error_exit "google-civic-api.pl not found for roster conversion"
fi
if [ ! -f "./subscribe-members.sh" ]; then
error_exit "subscribe-members.sh not found"
fi
# Parse multiple list configurations (comma-separated)
# Format: list_id:league_id or just list_id (defaults to ALL)
IFS=',' read -ra LIST_CONFIGS <<< "$MAILMAN_LIST_ID"
log "=========================================="
log "Starting batch subscription"
log "=========================================="
log "Roster File: $ROSTER_FILE"
log "Connector URL: $CONNECTOR_URL"
log "Total Lists: ${#LIST_CONFIGS[@]}"
log "=========================================="
# Track success/failure per list
SUCCESS_COUNT=0
FAILED_LISTS=()
# Helper function to increment counter (avoids set -e issues with arithmetic)
increment_count() {
SUCCESS_COUNT=$((SUCCESS_COUNT + 1))
}
# Loop through each list configuration
for CONFIG in "${LIST_CONFIGS[@]}"; do
# Trim whitespace
CONFIG=$(echo "$CONFIG" | xargs)
# Parse list_id and league_id (format: list_id:league_id or just list_id)
if [[ "$CONFIG" =~ ^([^:]+):(.*)$ ]]; then
LIST_ID="${BASH_REMATCH[1]}"
LEAGUE_ID="${BASH_REMATCH[2]}"
else
LIST_ID="$CONFIG"
LEAGUE_ID="ALL"
fi
log ""
log "----------------------------------------"
log "Processing List: $LIST_ID"
log "League Filter: $LEAGUE_ID"
log "----------------------------------------"
# Generate filtered CSV for this list
FILTERED_CSV="$WORK_DIR/members_${LEAGUE_ID}_${TIMESTAMP}.csv"
log "Filtering roster for League ID: $LEAGUE_ID..."
if ! ./google-civic-api.pl "$LEAGUE_ID" "$ROSTER_FILE" email-csv > "$FILTERED_CSV" 2>/dev/null; then
log "✗ Failed to filter roster for $LEAGUE_ID"
FAILED_LISTS+=("$LIST_ID")
rm -f "$FILTERED_CSV"
continue
fi
# Check if any members were found
MEMBER_COUNT=$(wc -l < "$FILTERED_CSV" | tr -d ' ')
log "Found $MEMBER_COUNT members for $LEAGUE_ID"
if [ "$MEMBER_COUNT" -eq 0 ]; then
log "⚠ No members found for League ID $LEAGUE_ID, skipping $LIST_ID"
rm -f "$FILTERED_CSV"
continue
fi
# Subscribe members to this list
log "Subscribing $MEMBER_COUNT members to $LIST_ID..."
if ./subscribe-members.sh "$FILTERED_CSV" "$CONNECTOR_PASSWORD" "$LIST_ID" "$CONNECTOR_URL"; then
log "✓ Successfully subscribed to $LIST_ID"
increment_count
# Clean up filtered CSV on success
rm -f "$FILTERED_CSV"
else
log "✗ Failed to subscribe to $LIST_ID"
FAILED_LISTS+=("$LIST_ID")
# Keep filtered CSV for debugging on failure
log " Filtered CSV retained: $FILTERED_CSV"
fi
done
# Summary
log ""
log "=========================================="
log "Subscription Summary"
log "=========================================="
log "Total Lists: ${#LIST_CONFIGS[@]}"
log "Successful: $SUCCESS_COUNT"
log "Failed: ${#FAILED_LISTS[@]}"
log "=========================================="
# Cleanup original roster if we downloaded it
if [ -z "$1" ] && [ -f "$ROSTER_FILE" ]; then
log "Cleaning up roster file..."
rm -f "$ROSTER_FILE"
fi
# If any lists failed, report error
if [ ${#FAILED_LISTS[@]} -gt 0 ]; then
error_exit "Failed to subscribe to the following list(s): ${FAILED_LISTS[*]}"
fi
log "Subscription process completed successfully"
exit 0