# League of Women Voters of West Virginia Custom-developed software designed for the League of Women Voters of West Virginia, as well as any state or local League affiliated with the League of Women Voters. ## IMPORTANT: Format for roster **NEW (December 2025):** MAL are now included in the Local League Membership in Your State. This makes issues with the MAL‑specific list irrelevant, since it is no longer required. **NEW (July 2025):** A new column has been added to the roster for MAL. To resolve this, remove the *Middle Name* column. ## REQUIRED FILE A file called `env` is required in the same directory as the programs. This file contains configuration for both the Perl and JavaScript scripts. ### Complete env File Example ``` # Portal Configuration (for download-roster.js and save-session.js) $PORTAL_URL = "https://portal.lwv.org"; $MEMBERSHIP_URL = "https://portal.lwv.org/groups/43a93df1-901a-4676-88c3-f4ea430d4884/league_membership_state_view"; # Email Notification Settings (for download-roster.js - error notifications via s-nail) $SMTP_HOST = "mail.bikelover.org"; $SMTP_PORT = "587"; $SMTP_USE_STARTTLS = "true"; $SMTP_AUTH = "login"; $SMTP_USER = "your-email@lwv.org"; $SMTP_PASSWORD = "your-password"; $SSL_VERIFY_IGNORE = "ignore"; $EMAIL_FROM = "your-email@lwv.org"; $EMAIL_TO = "recipient@lwv.org"; # Google API Configuration (for google-civic-api.pl) $key = "your-google-api-key"; $STATE = "WV"; $stateLeagueID = "WV000"; $localLeagueIDs = "WV102|WV103|WV112"; ``` ### Configuration Details | Variable | Required | Description | |----------|----------|-------------| | `PORTAL_URL` | Yes | Base URL of the LWV portal (default: https://portal.lwv.org) | | `MEMBERSHIP_URL` | Yes | Your league's membership page URL. Find this by navigating to your league's membership page in the portal and copying the URL | | `SMTP_HOST` | No | SMTP server hostname for error email notifications (requires s-nail) | | `SMTP_PORT` | No | SMTP server port (default: 587) | | `SMTP_USER` | No | SMTP authentication username | | `SMTP_PASSWORD` | No | SMTP authentication password | | `EMAIL_FROM` | No | Sender email address for error notifications | | `EMAIL_TO` | No | Recipient email address for error notifications | | `key` | For google-civic-api.pl | Google Civic Information API key | | `STATE` | For google-civic-api.pl | Two-letter state code (e.g., WV) | | `stateLeagueID` | For google-civic-api.pl | State league ID (e.g., WV000) | | `localLeagueIDs` | For google-civic-api.pl | Pipe-separated list of local league IDs | ## JavaScript Scripts (download-roster.js and save-session.js) These scripts automate downloading the membership roster CSV from the LWV portal. ### Prerequisites ```bash # Install Node.js dependencies npm install playwright npx playwright install chromium # Install s-nail (required for error email notifications) # On Debian/Ubuntu: sudo apt-get install s-nail ``` ### First-Time Setup (Run Once) Before running the download script for the first time, you need to save your browser session: ```bash node save-session.js ``` This will: 1. Open a browser window 2. Prompt you to log in using the **magic link** method (email) 3. Wait for you to complete login and press Enter 4. Save your session to `.session.json` The session is valid for 10 years (indefinite), but if it ever expires or fails, running `save-session.js` again will refresh it. ### Downloading the Roster To download the latest membership CSV: ```bash node download-roster.js ``` This will: 1. Load your saved session 2. Navigate to the membership page 3. Click Export → Download 4. Save the CSV file with timestamp (e.g., `league_membership_state_view_2026-04-15T05-00-24.csv`) ### Testing Error Email To test that error emails work correctly: ```bash # Temporarily rename the session file mv .session.json .session.json.bak # Run download - should fail and send error email node download-roster.js # Restore the session file mv .session.json.bak .session.json ``` ### Error Notifications When `download-roster.js` fails (due to missing/expired session, download error, etc.), it will send an error email via **s-nail** to the address specified in `EMAIL_TO`. The email will include: - The error message - Instructions to run `save-session.js` to refresh the session **Note:** s-nail must be installed for error emails to work. See Prerequisites above. ## LLAW Google Civic Information API Query version 2 Copyright (C) 2025 - by Jonathan Rosenbaum This may be freely redistributed under the terms of the GNU General Public License Usage: ./google-civic-api.pl google ./roster-file (queries Google Civic Api Delegate and Senate District for all LWVWV members) ./google-civic-api.pl WV000 '*.csv' (show all information for members at large, but do not query Google) ./google-civic-api.pl WV000 '*.csv' email (only show email addresses for members at large, but do not query Google) 1st argument can be one of these types: google (all members with senate/delegate district query) which prints out this csv data: 'Name,Email,Phone,Address,Delegate District,Senate District,League ID,Join Date' ALL (all members without senate/delegate district query) League ID: WV000 (members at large) WV102 (Huntington) WV103 (Morgantown-Monogalia) WV112 (Jefferson) 2nd argument must be the location of the LWVWV roster file, and prints out this csv information: Name,Email,Phone,Address,Join Date, 3rd argument 'email' will only print out the email addresses, and only works with the ALL or League ID type argument You will want to send results to a file. Example: ./google-civic-api.pl google '*.csv' > 2023-districts