Problem (Why)
Pushi can already fan events out to browsers (Web Push), mobile devices (APN), email (SMTP) and webhooks, but it has no way to deliver notifications into Slack, which is where many teams actually watch for operational and product events. Without a Slack adapter, integrators must stand up their own webhook bridge on top of pushi, duplicating routing and subscription logic that pushi already owns. Adding first-class Slack support lets any pushi app route a channel/event straight to a Slack channel or user with no glue code.
Description (What)
Introduce a SlackHandler adapter that delivers pushi events to Slack, alongside a Slack subscription model, a REST controller, and an API client, mirroring the existing Web Push / APN adapters. A destination Slack channel (or user) may be stored per subscription and overridden per published event. Credentials (a Slack bot/webhook token) follow the existing App-model + environment-variable configuration pattern.
Implementation (How)
- Add a
SlackHandler(handler.Handler) in src/pushi/base/slack.py implementing load, add, remove, subscribe, unsubscribe, send(app_id, event, json_d, invalid={}), plus a direct send_to_channels(...); honor a per-event destination override falling back to the subscription's stored channel.
- Post to Slack via
netius.clients.HTTPClient (chat.postMessage / incoming webhook), consistent with base/web.py.
- Add config fields on the App model in
src/pushi/app/models/app.py (e.g. slack_token) and read global env-var fallbacks via appier.conf, matching the SMTP/VAPID pattern.
- Add the
Slack subscription model in src/pushi/app/models/slack.py with fields (channel, event) and post_create/post_update/post_delete hooks that sync the handler.
- API: add a
SlackController in src/pushi/app/controllers/slack.py exposing GET/POST /slacks and DELETE /slacks/<channel> (list/subscribe/unsubscribe), mirroring web_push.py.
- API client: add
SlackAPI in src/pushi/api/slack.py with create_slack / delete_slack / subscribe_slack / unsubscribe_slack.
- Register the handler in
State.load_handlers() in src/pushi/base/state.py (instantiate, load(), append to self.handlers, set self.slack_handler).
- Export the new symbols from the
base, api, app/models, and app/controllers __init__.py files.
- Add tests in
src/pushi/test/slack.py following the test/apn.py mock-owner pattern (send with/without destination, subscription sync, config resolution).
- Update
README.md, add an examples/slack/ subscribe example, and add a [Unreleased] CHANGELOG entry.
Problem (Why)
Pushi can already fan events out to browsers (Web Push), mobile devices (APN), email (SMTP) and webhooks, but it has no way to deliver notifications into Slack, which is where many teams actually watch for operational and product events. Without a Slack adapter, integrators must stand up their own webhook bridge on top of pushi, duplicating routing and subscription logic that pushi already owns. Adding first-class Slack support lets any pushi app route a channel/event straight to a Slack channel or user with no glue code.
Description (What)
Introduce a
SlackHandleradapter that delivers pushi events to Slack, alongside aSlacksubscription model, a REST controller, and an API client, mirroring the existing Web Push / APN adapters. A destination Slack channel (or user) may be stored per subscription and overridden per published event. Credentials (a Slack bot/webhook token) follow the existing App-model + environment-variable configuration pattern.Implementation (How)
SlackHandler(handler.Handler)insrc/pushi/base/slack.pyimplementingload,add,remove,subscribe,unsubscribe,send(app_id, event, json_d, invalid={}), plus a directsend_to_channels(...); honor a per-event destination override falling back to the subscription's stored channel.netius.clients.HTTPClient(chat.postMessage / incoming webhook), consistent withbase/web.py.src/pushi/app/models/app.py(e.g.slack_token) and read global env-var fallbacks viaappier.conf, matching the SMTP/VAPID pattern.Slacksubscription model insrc/pushi/app/models/slack.pywith fields (channel,event) andpost_create/post_update/post_deletehooks that sync the handler.SlackControllerinsrc/pushi/app/controllers/slack.pyexposingGET/POST /slacksandDELETE /slacks/<channel>(list/subscribe/unsubscribe), mirroringweb_push.py.SlackAPIinsrc/pushi/api/slack.pywithcreate_slack/delete_slack/subscribe_slack/unsubscribe_slack.State.load_handlers()insrc/pushi/base/state.py(instantiate,load(), append toself.handlers, setself.slack_handler).base,api,app/models, andapp/controllers__init__.pyfiles.src/pushi/test/slack.pyfollowing thetest/apn.pymock-owner pattern (send with/without destination, subscription sync, config resolution).README.md, add anexamples/slack/subscribe example, and add a[Unreleased]CHANGELOG entry.