|
| 1 | +# CDL Bot |
| 2 | + |
| 3 | +Slack bot for the Contextual Dynamics Laboratory. Automates onboarding, offboarding, and term meeting scheduling. |
| 4 | + |
| 5 | +## Quick Start |
| 6 | + |
| 7 | +```bash |
| 8 | +# First time: create venv and install |
| 9 | +python -m venv venv |
| 10 | +source venv/bin/activate |
| 11 | +pip install -e . |
| 12 | + |
| 13 | +# Configure credentials |
| 14 | +cp cdl_bot/.env.example cdl_bot/.env |
| 15 | +nano cdl_bot/.env |
| 16 | + |
| 17 | +# Start the bot |
| 18 | +cdl-bot start |
| 19 | +``` |
| 20 | + |
| 21 | +The `cdl-bot` CLI manages the bot process: |
| 22 | + |
| 23 | +```bash |
| 24 | +cdl-bot start # Start (no-op if already running) |
| 25 | +cdl-bot stop # Stop (no-op if not running) |
| 26 | +cdl-bot restart # Stop + start |
| 27 | +cdl-bot status # Show PID or "not running" |
| 28 | +cdl-bot logs # Tail the log file |
| 29 | +``` |
| 30 | + |
| 31 | +## Features |
| 32 | + |
| 33 | +### Onboarding (`/cdl-onboard` or Workflow Builder) |
| 34 | + |
| 35 | +Two entry points for new members: |
| 36 | + |
| 37 | +1. **Workflow Builder** (recommended): New member runs "Join the lab!" workflow. Bot validates GitHub username, sends admin approval, then invites to GitHub org, shares calendars, processes profile photo. |
| 38 | + |
| 39 | +2. **Admin-initiated**: `/cdl-onboard @user` opens a form for the new member. Collects GitHub username, bio, photo, website. Bio edited to CDL style via Claude. Photo gets hand-drawn green border. |
| 40 | + |
| 41 | +### Offboarding (`/cdl-offboard` or Workflow Builder) |
| 42 | + |
| 43 | +Admin selects access to revoke (GitHub, calendars). Generates a checklist — does NOT auto-remove anyone. |
| 44 | + |
| 45 | +### Term Scheduling (`/cdl-schedule`) |
| 46 | + |
| 47 | +1. Director runs `/cdl-schedule` — config modal auto-populates projects from database |
| 48 | +2. Creates When2Meet survey (Mon-Fri weekly) and posts to #general with project list and emoji reactions |
| 49 | +3. "Collect Responses" scrapes respondent names, checks for :zoom: individual meeting requests |
| 50 | +4. Assignment modal: director assigns respondents to projects, marks senior/external |
| 51 | +5. Algorithm maximizes attendance with PI-required, senior 3x weighting, day concentration |
| 52 | +6. Director reviews proposed schedule, approves to post announcement |
| 53 | + |
| 54 | +**Project database** (`data/projects.json`): Stores emoji, Slack channels, description, and default duration per project. Auto-populated from previous terms. New projects added during scheduling are saved for future use. |
| 55 | + |
| 56 | +Project format in the config modal (one per line): |
| 57 | +``` |
| 58 | +Project Name | duration_blocks | :emoji: |
| 59 | +Lab Meeting | 4 | :raising_hand: |
| 60 | +Kraken | 4 | :octopus: |
| 61 | +``` |
| 62 | + |
| 63 | +Duration is in 15-minute blocks (4 = 60min). Append `.5` for biweekly (2.5 = biweekly 30min). |
| 64 | + |
| 65 | +## Setup |
| 66 | + |
| 67 | +### Slack App |
| 68 | + |
| 69 | +1. Go to [api.slack.com/apps](https://api.slack.com/apps) |
| 70 | +2. Create new app from manifest (`cdl_bot/manifest.json`) or manually: |
| 71 | + - Enable Socket Mode, create app-level token with `connections:write` |
| 72 | + - Bot scopes: `chat:write`, `commands`, `users:read`, `users:read.email`, `im:write`, `im:history`, `files:read`, `files:write`, `workflow.steps:execute`, `reactions:read` |
| 73 | + - Events: `file_shared`, `function_executed` |
| 74 | + - Slash commands: `/cdl-onboard`, `/cdl-offboard`, `/cdl-schedule`, `/cdl-ping`, `/cdl-help` |
| 75 | + - Enable Interactivity |
| 76 | + |
| 77 | +### Credentials (`.env`) |
| 78 | + |
| 79 | +Required: |
| 80 | +- `SLACK_BOT_TOKEN` — Bot OAuth token (xoxb-...) |
| 81 | +- `SLACK_APP_TOKEN` — App-level token (xapp-...) |
| 82 | +- `SLACK_ADMIN_USER_ID` — Director's Slack user ID |
| 83 | +- `GITHUB_TOKEN` — PAT with `admin:org` scope |
| 84 | + |
| 85 | +Optional: |
| 86 | +- `GOOGLE_CREDENTIALS_FILE` — Service account JSON for calendar sharing |
| 87 | +- `GOOGLE_CALENDAR_*` — Calendar IDs |
| 88 | +- `ANTHROPIC_API_KEY` — For Claude bio editing |
| 89 | + |
| 90 | +## Testing |
| 91 | + |
| 92 | +```bash |
| 93 | +pytest tests/test_onboarding/ -v # All tests |
| 94 | +pytest tests/test_onboarding/test_scheduling.py -v # Scheduling only (no API keys needed) |
| 95 | +``` |
| 96 | + |
| 97 | +Tests use real API calls (no mocks). Tests skip automatically when credentials are missing. |
| 98 | + |
| 99 | +## Architecture |
| 100 | + |
| 101 | +``` |
| 102 | +cdl_bot/ |
| 103 | +├── bot.py # Entry point, Slack app setup |
| 104 | +├── cli.py # cdl-bot CLI (start/stop/restart/status/logs) |
| 105 | +├── config.py # Environment/config management |
| 106 | +├── project_store.py # Project database CRUD |
| 107 | +├── scheduling_storage.py # Scheduling session persistence |
| 108 | +├── manifest.json # Slack app manifest |
| 109 | +├── data/ |
| 110 | +│ └── projects.json # Project database (emojis, channels, descriptions) |
| 111 | +├── handlers/ |
| 112 | +│ ├── onboard.py # /cdl-onboard |
| 113 | +│ ├── approval.py # Admin approval workflow |
| 114 | +│ ├── offboard.py # /cdl-offboard |
| 115 | +│ ├── schedule.py # /cdl-schedule term scheduling flow |
| 116 | +│ └── workflow_step.py # Workflow Builder custom steps |
| 117 | +├── models/ |
| 118 | +│ ├── onboarding_request.py |
| 119 | +│ └── scheduling_session.py |
| 120 | +└── services/ |
| 121 | + ├── github_service.py # GitHub org invitations |
| 122 | + ├── calendar_service.py # Google Calendar sharing |
| 123 | + ├── image_service.py # Photo border processing (Pillow) |
| 124 | + ├── bio_service.py # Bio editing via Claude API |
| 125 | + ├── when2meet_service.py # When2Meet create + scrape |
| 126 | + └── scheduling_service.py # Meeting scheduling algorithm |
| 127 | +``` |
0 commit comments