Slash command handlers (drop, pick, swap) were posting notifications to command["channel_id"] — wherever the command was run. If someone ran /oncall drop from a DM, the notification went there instead of the schedule channel. Pickup buttons didn't have this problem because body["channel"]["id"] is always the channel where the button lives. Added SHIFT_CHANNEL_PARAM to the SlackBotFunction env vars, read it on cold start, and route all slash command shift-change notifications to the configured schedule channel. Closes #21 |
||
|---|---|---|
| scripts | ||
| src | ||
| .gitignore | ||
| README.md | ||
| requirements.txt | ||
| SETUP.md | ||
| template.yaml | ||
After-Hours Shift Manager
Slack bot for managing after-hours on-call shifts at Sea Haven Industries. Employees can pick up, drop, and swap shifts directly from Slack. Changes automatically update 3CX ring group 800 routing.
How It Works
A recurring weekly schedule assigns employees to after-hours phone duty (5pm-8am). Any unassigned day shows as Available in Slack with a pickup button. When someone picks up or drops a shift for today, the 3CX phone system is updated immediately. Future changes take effect when the 3CX scheduler runs at 8am.
Slack Commands
| Command | Description |
|---|---|
/oncall |
Show this week's schedule |
/oncall next |
Show next week's schedule |
/oncall pick <date> |
Pick up an available shift |
/oncall drop <date> |
Drop your shift (marks it available) |
/oncall swap <date> @person |
Hand your shift to someone else |
/oncall register <ext> |
Link your Slack account to your phone extension |
/oncall roster |
Show all employees and their link status |
/oncall help |
Show help |
Dates accept: today, tomorrow, monday-sunday, 4/5, 2026-04-05
Architecture
- Runtime: Python 3.12 on AWS Lambda (via API Gateway)
- Data: DynamoDB single-table (
afterhours-shifts) - IaC: AWS SAM (
template.yaml) - Slack: Slack Bolt framework with
/oncallslash command - 3CX Integration: Invokes the
3cx-ring-group-schedulerLambda for same-day changes; the scheduler reads DynamoDB for future dates
DynamoDB Schema
Single table with PK / SK keys:
| PK | SK | Description |
|---|---|---|
ROSTER |
<extension> |
Employee: name, extension, slack_user_id |
WEEKLY |
<DayName> |
Default weekly schedule: extension, name |
OVERRIDE |
<YYYY-MM-DD> |
Date override from pickup/drop (or OPEN) |
CONFIG |
CONFIG |
Settings: ring_group, fallback_extension |
Deployment
See SETUP.md for full deployment and Slack app creation instructions.
Quick reference:
# Build and deploy
sam build
sam deploy --guided --stack-name afterhours-shift-manager --region us-east-1
# Seed initial schedule data
python scripts/seed_schedule.py
SSM Parameters
| Parameter | Description |
|---|---|
/afterhours-shift-manager/slack-bot-token |
Slack bot OAuth token (xoxb-...) |
/afterhours-shift-manager/slack-signing-secret |
Slack app signing secret |
/afterhours-shift-manager/channel-id |
Slack channel ID for notifications |
Weekly Auto-Post
Every Monday at 7am ET, the bot posts the week's schedule to the configured channel with pickup buttons for any available shifts.
Pay Report Email
A weekly Bonus Pay Summary email is sent via SES to payroll@seahaven.com with a table showing each employee's name, rate, and total pay for the week.
Related
- 3cx-ring-scheduler — the Lambda that updates 3CX ring group routing daily