Skip to content
premdayPublic

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Premday Bot

A small Slack app for organizing Premday usergroup meetings.

Features

  • /meeting opens a Slack modal with a default meeting one month from now at 18:00 Europe/Paris, converted to the creator's Slack timezone. PREMDAY_TIMEZONE is used if Slack does not provide a valid timezone.
  • The bot creates a Slack Canvas for each channel and meeting year, named Premday meetings <year>, then adds later meetings from that channel and year.
  • The bot emails calendar invitations to channel members through SMTP.
  • The bot posts a meeting message with the Proton Meet link, Canvas link, and a Receive invitation button for newcomers.
  • Meetings are persisted in SQLite so button clicks still work after process restarts.
  • RSVP replies to calendar invitations are accepted through an LMTP listener and update the meeting message with Going, Maybe, and Can't go counts.
  • A View RSVPs button privately shows responder names in independently expandable Going, Absent, and Maybe sections. Expanded names appear in two columns, using Slack user mentions for members and email addresses for invitees without a Slack account.

Setup

cp .env.example .env

Create a Slack app from slack/app-manifest.yaml, then set the values in .env.

The app uses Socket Mode, so it does not need a public HTTP endpoint.

Required Slack scopes:

  • commands
  • chat:write
  • users:read
  • users:read.email
  • channels:read
  • channels:history
  • groups:read
  • im:read
  • mpim:read
  • canvases:write
  • canvases:read

Run

On a server with Docker Compose, create .env from .env.example, fill in the Slack and SMTP settings, then start the bot:

cp .env.example .env
docker compose up -d --build
docker compose logs -f premday-bot

The SQLite database lives in the premday_data Docker volume, so it survives container rebuilds and restarts. Compose sets PREMDAY_DB_PATH to /data/premday.sqlite3 inside the container. The app connects to Slack using Socket Mode; Compose publishes the optional RSVP listener on host loopback port 2525 for the local OpenSMTPD relay.

To receive calendar replies, configure RSVP_EMAIL_ADDRESS in .env. Docker publishes the listener on host loopback port 2525 by default (RSVP_SMTP_HOST_PORT can change it). Configure OpenSMTPD to deliver mail for RSVP_EMAIL_ADDRESS over LMTP to 127.0.0.1:2525. The listener only accepts that recipient and binds through a loopback-only Docker port mapping; do not expose it directly to the Internet. PREMDAY_EMAIL_FROM should use RSVP_EMAIL_ADDRESS, because calendar clients send replies to the organizer address.

For RSVP_EMAIL_ADDRESS=rsvp@example.com, add this action with your other actions and put the match rule before broader recipient rules:

action "premday_rsvp" relay host lmtp://127.0.0.1:2525
match from any for rcpt-to "rsvp@example.com" action "premday_rsvp"

If moving an existing installation, stop the old bot and copy its database into the volume before the first Compose start. This preserves the Canvas IDs used to append meetings to the existing Canvas:

docker compose build
docker compose run --rm --no-deps \
  --volume "$PWD/premday.sqlite3:/tmp/old.sqlite3:ro" \
  --entrypoint sh premday-bot \
  -c 'cp /tmp/old.sqlite3 /data/premday.sqlite3'
docker compose up -d

To stop the bot, run docker compose down (leave the volume in place).

For a local run without Docker:

uv sync
uv run premday-bot

In Slack:

/meeting

Environment

Variable Required Description
SLACK_BOT_TOKEN yes Bot token, usually xoxb-....
SLACK_APP_TOKEN yes Socket Mode app token, usually xapp-....
SLACK_TEAM_ID no Team ID used to build a Canvas URL if Slack does not return one.
PREMDAY_TIMEZONE no Fallback timezone when Slack has no valid timezone for the creator; defaults to Europe/Paris.
PREMDAY_DEFAULT_HOUR no Defaults to 18.
PREMDAY_DEFAULT_DURATION_MINUTES no Defaults to 90.
PREMDAY_DB_PATH no Defaults to premday.sqlite3.
SMTP_HOST yes SMTP server hostname.
SMTP_PORT no Defaults to 587.
SMTP_USERNAME no SMTP login.
SMTP_PASSWORD no SMTP password.
SMTP_USE_TLS no STARTTLS, defaults to true.
SMTP_USE_SSL no Implicit TLS, defaults to false.
PREMDAY_EMAIL_FROM yes Sender header for invitations.
RSVP_EMAIL_ADDRESS no Address in calendar invites and only recipient accepted by the RSVP listener.
RSVP_SMTP_HOST_PORT no Host loopback port published by Compose; defaults to 2525.

Development

uv run ruff check .
uv run pyright
uv run pytest

Ideas Not Implemented Yet

  • Topic proposal and voting before each meeting.
  • Automatic reminder messages one week and one day before the meeting.
  • Speaker signup with agenda slots.
  • Post-meeting recap generation from Canvas content.
  • RSVP attendee names in the Slack message (currently only response counts are shown).

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages