correspond.channels.slack_events#
Slack Events API receiver: Slack pushes a channel’s messages, edits and deletions, so listen need not poll.
mk_events_app() is the receiver, an ASGI app that checks every request with
verify() (X-Slack-Signature under the signing
secret, over a timestamp at most five minutes old: nothing unverified is read), answers
Slack’s url_verification challenge, and keeps the message events under the data
root (slack-events/). With delivery = "events" in the slack config, listen
reads what the receiver stored instead of polling conversations.history, and reports
edits (message.updated) and deletions (message.deleted) too.
serve_events() runs the receiver (with uvicorn, the server extra) on
127.0.0.1:8083 unless webhook_allow_remote is set; put your HTTPS reverse proxy in
front, and give its URL as the app’s Event Subscriptions Request URL, subscribed to the
bot events message.channels (and message.groups for private channels).
Functions
|
|
Where the receiver keeps events: the |
|
|
The receiver as an ASGI app: Slack POSTs signed requests, the app stores the |
|
Delete the stored events that arrived more than |
|
Run the receiver (with uvicorn) on |
|
|
- correspond.channels.slack_events.events_app_from_env()[source]#
mk_events_app()configured from the settings, foruvicorn --factory.The signing secret is required here, so a receiver without one refuses to start rather than refusing every request.
- correspond.channels.slack_events.events_store()[source]#
Where the receiver keeps events: the
slackwebhook_storesetting’smodule:attr, else files under the data root.- Return type:
- correspond.channels.slack_events.mk_events_app(*, verify=None, events=None, max_body_bytes=1000000, clock=<built-in function time_ns>, prune_every_ns=3600000000000, keep=None, stamps=None)[source]#
The receiver as an ASGI app: Slack POSTs signed requests, the app stores the
messageevents inevents.verifygrades a request from its headers and raw body; onlycryptopasses, anything else gets 401 and nothing is read from it. It defaults toSlack.verify(the signing secret, five-minute window). A verifiedurl_verificationgets its challenge back; any other verified request that is not amessageevent is acknowledged (200) and dropped. A kept event is stored under<arrival ns>-<event id>.jsonas{event_id, team_id, channel, event, received_ns}; a retry Slack sends for an event already stored (a retry,X-Slack-Retry-Num, or a replay within the signature’s window) is acknowledged and not stored twice.eventsdefaults to files under the data root (slack-events/).keepsays which channel ids’ events are stored (the others are acknowledged and dropped); it defaults to thekeep_channelssetting as the receiver starts (restart it after changing the setting), and to every channel when that is unset.stamps(anArrivalStamps, by default the one Socket Mode listens share) stamps each event and holds its lock while the event is stored, so writers on one machine take turns and none stores an event below a cursor a listen already passed.The receiver deletes events older than the retention itself (
prune_events()), on a write, at most once perprune_every_ns.
- correspond.channels.slack_events.prune_events(events, *, now_ns, retention_ns=604800000000000)[source]#
Delete the stored events that arrived more than
retention_nsbeforenow_ns; return how many.Only keys the receiver writes are considered: anything else in the store is left alone.
>>> store = {"00000000000000000001-Ev1.json": {}, "00000000000000000009-Ev2.json": {}, "x": 0} >>> prune_events(store, now_ns=10, retention_ns=5) 1 >>> sorted(store) ['00000000000000000009-Ev2.json', 'x']
- Return type:
- correspond.channels.slack_events.serve_events(*, host='127.0.0.1', port=8083, allow_remote=None, app=None, run=None)[source]#
Run the receiver (with uvicorn) on
host, this machine unlessallow_remote.allow_remotedefaults to theslackwebhook_allow_remotesetting. Put your HTTPS reverse proxy in front.- Return type:
- correspond.channels.slack_events.serve_main(argv=None)[source]#
correspond-slack-events: run the Events API receiver (serve_events()).- Return type: