https://github.com/alliraine/legialerts
A Twitter and Google Sheets Bot for tracking anti-lgbtq legislation
https://github.com/alliraine/legialerts
automation legislation lgbtqia
Last synced: 5 months ago
JSON representation
A Twitter and Google Sheets Bot for tracking anti-lgbtq legislation
- Host: GitHub
- URL: https://github.com/alliraine/legialerts
- Owner: alliraine
- License: apache-2.0
- Created: 2023-01-04T20:39:33.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2025-12-26T16:48:49.000Z (6 months ago)
- Last Synced: 2026-01-12T14:12:42.513Z (6 months ago)
- Topics: automation, legislation, lgbtqia
- Language: Python
- Homepage: https://legialerts.com
- Size: 814 KB
- Stars: 26
- Watchers: 2
- Forks: 4
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
[](https://github.com/alliraine/legialerts/actions/workflows/trigger-legialerts.yml)
[](https://uptime.betterstack.com/?utm_source=status_badge)
[](https://uptime.betterstack.com/?utm_source=status_badge)
[](https://uptime.betterstack.com/?utm_source=status_badge)
# LegiAlerts
A Twitter/Bsky bot and automation platform for tracking anti-LGBTQ legislation. The bot updates the tracker at https://legialerts.org and posts alerts when new bills appear or when statuses change.
## How it works
- Pulls session master lists and bill details from the LegiScan API.
- Updates Google Sheets worksheets for anti/pro and rollover bills.
- Posts alerts to X (Twitter) and Bluesky, and sends HTML email reports.
- Caches session lists and sheet snapshots in `cache/` (or `/var/data` when `PRODUCTION=true`) to limit API calls.
## Requirements
- Python 3
- A LegiScan API key
- A Google service account for Sheets access
- Social accounts and SMTP credentials for notifications
Install dependencies:
```bash
pip install -r requirements.txt
```
## Configuration (environment variables)
The bot reads all secrets from environment variables (see `.env.example` for a template):
- `legiscan_key`: LegiScan API key.
- `gsuite_service_account` **or** `GSUITE_SERVICE_ACCOUNT_FILE`: Google service account credentials (JSON string or secure file path). Keep the JSON out of version control.
- `TRACKER_YEARS`: Comma-separated list of tracker years (defaults to `2026`). Each year needs a matching `gsheet_key_` value.
- `gsheet_key_`: Google Sheet key for each tracker year (e.g., `gsheet_key_2026`).
- `twitter_consumer_key`, `twitter_consumer_secret`, `twitter_access_token`, `twitter_access_token_secret`: X/Twitter API credentials.
- `bsky_user`, `bsky_pass`: Bluesky credentials.
- `GOOGLE_TOKEN`: Gmail SMTP app password used to send email reports.
- `API_AUTH_TOKEN`: Bearer token required for the Flask endpoints (set `API_ALLOW_ANONYMOUS=true` to intentionally disable auth).
- `LOG_LEVEL`: Logging verbosity (DEBUG, INFO, WARNING, ERROR, CRITICAL). Default is INFO.
- `LOG_FILE`: Optional log file path (defaults to `cache/legialerts.log`, or `/var/data/legialerts.log` in production).
- `LEGISCAN_MIN_INTERVAL`: Optional delay between LegiScan API calls in seconds.
- `REQUEST_TIMEOUT`: Request timeout in seconds for LegiScan calls (defaults to 30).
- `SEARCH_CACHE_TTL`: Optional cache TTL for search results in seconds (defaults to 3600).
- `SOCIAL_ENABLED`: Set to `false` to disable posting to X/Twitter and Bluesky.
- `PRODUCTION`: Set to `true` to store cache files under `/var/data` instead of `cache/`.
Security note: Do not commit real tokens, service accounts, or SMTP secrets. Use environment variables or a mounted secret file instead of tracking credentials in Git.
## Running
The bot runs continuously and sleeps ~15 minutes between cycles:
```bash
python main.py
```
It can also be run under a process manager (systemd, supervisor) or a cronjob that invokes the script repeatedly.
## Web endpoint (Flask)
You can trigger a single run via a lightweight Flask app:
```bash
flask --app app run --host 0.0.0.0 --port 8080
```
Endpoints:
- `GET /run`: triggers one update cycle; returns 409 if a run is already in progress.
- `GET /health`: basic health check.
- `GET /stats`: run metrics and worksheet summary stats from cached sheets.
### Authentication
Authentication is required by default; set `API_AUTH_TOKEN` and provide the same token in requests. To deliberately allow anonymous access, set `API_ALLOW_ANONYMOUS=true`. Example:
```bash
curl -H "Authorization: Bearer $API_AUTH_TOKEN" http://localhost:8080/health
```
## Sheets and cache expectations
- Worksheets expected: `Anti-LGBTQ Bills`, `Pro-LGBTQ Bills`, `Rollover Anti-LGBTQ Bills`, `Rollover Pro-LGBTQ Bills`.
- The header row is used as the schema; the bot fills in fields like `Status`, `Date`, `Change Hash`, `Sponsors`, `History`, and `PDF`.
- Cache files are written to `cache/` (or `/var/data` in production), including `sessions.csv`, per-state session lists, and `gsheet--.csv`.
## Notes
- The `years` list in `main.py` controls which tracker years are updated.
- Email templates live in `utils/email.html`.
## Attribution
LegiAlerts uses data from LegiScan. All data is licensed under Creative Commons Attribution 4.0; attribution to LegiScan is required.
# Credits
Created by Allison Chapman
Code Base Maintained By: Allison Chapman @AlliRaine22, Kim MC42, and others
Spreadsheet Maintained by Allison Chapman @AlliRaine22, Alejandra Caraballo @esqueer_, and Erin Reed @erininthemorn