246 lines
7.7 KiB
Markdown
246 lines
7.7 KiB
Markdown
# LWVWV Member Subscription Automation
|
|
|
|
Automated Docker container for subscribing LWVWV members to Mailman 3 mailing lists.
|
|
|
|
## Overview
|
|
|
|
This automation coordinates:
|
|
1. **Downloading** the latest member roster from the LWVWV portal
|
|
2. **Converting** the roster to CSV format (email,first_name,last_name)
|
|
3. **Subscribing** members to the Mailman list via the connector API
|
|
|
|
## Architecture
|
|
|
|
```
|
|
┌─────────┐ ┌─────────────────────────────┐ ┌──────────────────┐
|
|
│ Ofelia │────>│ lwvwv-subscriber-cron │────>│ LWVWV Portal │
|
|
│Scheduler│cron │ (Docker Container) │ │ (download CSV) │
|
|
└─────────┘ └─────────────────────────────┘ └──────────────────┘
|
|
│
|
|
┌───────────────┼───────────────┐
|
|
▼ ▼ ▼
|
|
┌──────────┐ ┌──────────────┐ ┌──────────────┐
|
|
│download- │ │google-civic- │ │subscribe- │
|
|
│roster.js │──>│api.pl │──>│members.sh │
|
|
│(portal) │ │(email-csv) │ │(connector) │
|
|
└──────────┘ └──────────────┘ └──────────────┘
|
|
│
|
|
▼
|
|
┌──────────────┐
|
|
│mailman- │
|
|
│connector │
|
|
│(batch sub) │
|
|
└──────────────┘
|
|
```
|
|
|
|
## Files
|
|
|
|
| File | Description |
|
|
|------|-------------|
|
|
| `Dockerfile` | Container image definition |
|
|
| `docker-compose.yml` | Service orchestration with Ofelia labels |
|
|
| `entrypoint.sh` | Parses ../env and exports variables |
|
|
| `run-subscription.sh` | Master orchestration script |
|
|
| `start-automation.sh` | Quick-start helper script |
|
|
| `README.md` | This file |
|
|
|
|
## Environmental Variables
|
|
|
|
### Single Source of Truth: `../env`
|
|
|
|
All configuration is stored in **one file**: `../env` (in the parent directory)
|
|
|
|
This file uses **Perl-style syntax** (which existing scripts expect):
|
|
```perl
|
|
$VARIABLE_NAME = "value";
|
|
```
|
|
|
|
### How It Works
|
|
|
|
1. **`../env`** is the **single source of truth** for all configuration
|
|
2. The **entrypoint.sh** script parses `../env` and exports variables as environment variables
|
|
3. All scripts can then access them via standard environment variable syntax (`$VARIABLE_NAME`)
|
|
|
|
### Configuration Variables
|
|
|
|
#### Required for Subscription
|
|
| Variable | Description | Example |
|
|
|----------|-------------|---------|
|
|
| `$CONNECTOR_URL` | URL of mailman-connector | `https://mailman-connector.example.org` |
|
|
| `$CONNECTOR_PASSWORD` | Secret password for connector API | `your_secret_password` |
|
|
| `$MAILMAN_LIST_ID` | Target mailing list ID | `members.lists.example.org` |
|
|
|
|
#### Required for Portal Download
|
|
| Variable | Description | Example |
|
|
|----------|-------------|---------|
|
|
| `$PORTAL_URL` | LWVWV portal URL | `https://portal.lwv.org` |
|
|
| `$MEMBERSHIP_URL` | Membership page URL | `https://portal.lwv.org/groups/...` |
|
|
|
|
#### Email Notifications (Optional)
|
|
| Variable | Description | Example |
|
|
|----------|-------------|---------|
|
|
| `$SMTP_HOST` | SMTP server | `mail.example.org` |
|
|
| `$SMTP_PORT` | SMTP port | `587` |
|
|
| `$SMTP_USER` | SMTP username | `example@example.org` |
|
|
| `$SMTP_PASSWORD` | SMTP password | `your_smtp_password` |
|
|
| `$EMAIL_FROM` | Sender address | `example@example.org` |
|
|
| `$EMAIL_TO` | Recipient for alerts | `hello@example.org` |
|
|
|
|
#### Google API (for district lookup)
|
|
| Variable | Description | Example |
|
|
|----------|-------------|---------|
|
|
| `$key` | Google Civic API key | `AIzaSy...` |
|
|
| `$STATE` | State code | `WV` |
|
|
| `$stateLeagueID` | State league ID | `WV000` |
|
|
| `$localLeagueIDs` | Local league IDs | `WV102|WV103|WV112` |
|
|
|
|
### Example `../env` File
|
|
|
|
```perl
|
|
# Portal Configuration
|
|
$PORTAL_URL = "https://portal.lwv.org";
|
|
$MEMBERSHIP_URL = "https://portal.lwv.org/groups/53a93df1/league_membership_state_view";
|
|
|
|
# Connector Settings
|
|
$CONNECTOR_URL = "https://mailman-connector.example.org";
|
|
$CONNECTOR_PASSWORD = "your_secret_password";
|
|
$MAILMAN_LIST_ID = "members.lists.example.org";
|
|
|
|
# Email Notification Settings
|
|
$SMTP_HOST = "mail.example.org";
|
|
$SMTP_PORT = "587";
|
|
$SMTP_USER = "example@example.org";
|
|
$SMTP_PASSWORD = "your_smtp_password";
|
|
$EMAIL_FROM = "example@example.org";
|
|
$EMAIL_TO = "hello@example.org";
|
|
|
|
# Google API Configuration
|
|
$key = "LALKDdkdk_12LSL_RKFDL";
|
|
$STATE = "WV";
|
|
$stateLeagueID = "WV000";
|
|
$localLeagueIDs = "WV102|WV103|WV112";
|
|
```
|
|
|
|
## Quick Start
|
|
|
|
### 1. Configure Environment
|
|
|
|
Ensure `../env` exists with your settings:
|
|
|
|
```bash
|
|
cd automation
|
|
# The env file should already exist in the parent directory
|
|
ls ../env
|
|
```
|
|
|
|
### 2. Build and Start
|
|
|
|
```bash
|
|
docker-compose up -d
|
|
```
|
|
|
|
### 3. Verify Container is Running
|
|
|
|
```bash
|
|
docker ps | grep lwvwv-subscriber
|
|
```
|
|
|
|
## Usage
|
|
|
|
### Manual Trigger (for testing)
|
|
|
|
```bash
|
|
# Run the full workflow (downloads roster, converts, subscribes)
|
|
docker exec lwvwv-subscriber /app/run-subscription.sh
|
|
|
|
# With a specific CSV file (skips download)
|
|
docker exec lwvwv-subscriber /app/run-subscription.sh /path/to/members.csv
|
|
|
|
# Run subscribe-members.sh directly with env vars
|
|
docker exec lwvwv-subscriber /app/subscribe-members.sh /tmp/rosters/members.csv
|
|
```
|
|
|
|
### Scheduled Execution (via Ofelia)
|
|
|
|
The container includes Ofelia labels for automatic scheduling:
|
|
- **Default**: 4x daily at 00:00, 06:00, 12:00, 18:00
|
|
- **Format**: Cron expression `0 0,6,12,18 * * *`
|
|
|
|
To change schedule, edit `docker-compose.yml`:
|
|
```yaml
|
|
labels:
|
|
ofelia.enabled: "true"
|
|
ofelia.job-exec.lwvwv-subscribe.schedule: "0 0,6,12,18 * * *"
|
|
```
|
|
|
|
### Standalone Usage (without Docker)
|
|
|
|
The scripts also work outside Docker using positional arguments:
|
|
|
|
```bash
|
|
# subscribe-members.sh with all positional args
|
|
./subscribe-members.sh members.csv mypassword members.lists.example.org https://connector.example.com
|
|
|
|
# With some env vars, some positional
|
|
CONNECTOR_PASSWORD=mypassword ./subscribe-members.sh members.csv
|
|
```
|
|
|
|
## Logs
|
|
|
|
```bash
|
|
# View container logs
|
|
docker logs lwvwv-subscriber
|
|
|
|
# Follow logs in real-time
|
|
docker logs -f lwvwv-subscriber
|
|
|
|
# View Ofelia scheduler logs
|
|
docker logs ofelia
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### Session Expired
|
|
|
|
If portal download fails with "Session expired":
|
|
```bash
|
|
# Run save-session.js on host to refresh session
|
|
cd ..
|
|
node save-session.js
|
|
# Then restart container
|
|
docker-compose restart
|
|
```
|
|
|
|
### Missing Environment Variables
|
|
|
|
If you see errors like `CONNECTOR_URL not set`:
|
|
1. Check that `../env` exists and contains the variable
|
|
2. Verify the entrypoint is parsing it correctly:
|
|
```bash
|
|
docker exec lwvwv-subscriber env | grep CONNECTOR
|
|
```
|
|
|
|
### Manual CSV Subscription
|
|
|
|
To subscribe members without downloading:
|
|
```bash
|
|
# Place CSV file in shared volume
|
|
cp members.csv automation/rosters/
|
|
|
|
# Run with specific file
|
|
docker exec lwvwv-subscriber /app/run-subscription.sh /tmp/rosters/members.csv
|
|
```
|
|
|
|
## Network Requirements
|
|
|
|
The container needs access to:
|
|
- LWV Portal (`https://portal.lwv.org`)
|
|
- SMTP server (if using email alerts)
|
|
|
|
## Security Notes
|
|
|
|
- `../env` is mounted **read-only** (`:ro`) in the container
|
|
- Sensitive data is never committed to git
|
|
- Session file (`.session.json`) is also mounted read-only
|
|
- All scripts use the single `../env` file - no duplicated configuration
|