slack

package
v0.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 12, 2026 License: AGPL-3.0 Imports: 21 Imported by: 0

Documentation

Overview

Package slack (piece ③) connects Exhale to a Slack workspace over Socket Mode: a WebSocket the app opens outward, so no public URL or open port is needed (ADR 0001, 0007). Each team runs its own Slack app, created from the manifest in manifest.go.

Like the Telegram adapter it only renders action-layer messages (as Block Kit) and passes button presses and typed answers back. The app inside a message (ADR 0019) lives in the direct message with the bot and, as a permanent surface, in the app's Home tab.

For the action layer a Slack chat is always a person: ChatRef.ChatID is the Slack user id, whatever the button was pressed in (the DM, the Home tab or a shared channel). Questions that need a typed answer therefore always continue in the DM.

Index

Constants

View Source
const Manifest = `` /* 909-byte string literal not displayed */

Manifest describes the Slack app a team creates in its own workspace (api.slack.com/apps → Create New App → From a manifest). It asks for exactly what the adapter uses; docs/guides/slack.md explains each scope.

Socket Mode means no URL appears anywhere: events, button presses and the slash command all arrive over the WebSocket the app opens outward.

View Source
const Name = "slack"

Name is the channel name stored in channel links.

Variables

View Source
var ErrNotRunning = errors.New("slack is not set up")

ErrNotRunning is returned when there is no Slack app to send through.

Functions

func CreateURL

func CreateURL() string

CreateURL opens Slack's "create an app" page with the manifest filled in.

Types

type Adapter

type Adapter struct {
	// contains filtered or unexported fields
}

Adapter is the Slack channel for one pair of tokens.

func New

func New(botToken, appToken, apiURL string, svc *app.Service, log *slog.Logger) *Adapter

New creates the adapter. apiURL overrides the Web API URL (tests). SetEngine must be called before Serve.

func (*Adapter) Connected

func (a *Adapter) Connected() bool

Connected reports whether the socket to Slack is up.

func (*Adapter) Edit

func (a *Adapter) Edit(ctx context.Context, chatID, messageID string, m actions.Message) error

Edit replaces a message in place. The Home tab is edited by publishing its view again.

func (*Adapter) LastError

func (a *Adapter) LastError() string

LastError is why the socket is down ("" when it is up or still trying).

func (*Adapter) Name

func (a *Adapter) Name() string

func (*Adapter) Send

func (a *Adapter) Send(ctx context.Context, chatID string, m actions.Message) (string, error)

Send posts a message and returns its id (Slack's ts).

func (*Adapter) Serve

func (a *Adapter) Serve(ctx context.Context) error

Serve keeps the socket open until ctx is cancelled. The library reconnects when the socket drops or Slack asks for a refresh; Serve returns an error only when Slack rejects the tokens.

func (*Adapter) SetEngine

func (a *Adapter) SetEngine(e *actions.Engine)

SetEngine wires the action layer (which itself needs the adapter).

func (*Adapter) String

func (a *Adapter) String() string

func (*Adapter) Workspace

func (a *Adapter) Workspace() Workspace

Workspace returns what is known about the workspace and the bot.

type Config

type Config struct {
	BotToken string  `json:"botToken,omitempty" doc:"Bot User OAuth Token, xoxb-…"`
	AppToken string  `json:"appToken,omitempty" doc:"app-level token with connections:write, xapp-…"`
	Channel  *string `json:"channel,omitempty" doc:"channel name or id for reminders of shared subscriptions; empty to stop posting there"`
}

Config is what the owner sets from the web. Tokens are optional once the app is connected, so the channel can change on its own.

type Deliverer

type Deliverer interface {
	Deliver(ctx context.Context, item app.OutboxItem) error
}

Deliverer is the scheduler's delivery step.

type Manager

type Manager struct {
	// contains filtered or unexported fields
}

Manager runs the Slack adapter. It implements actions.Channel and the platform service interface.

func NewManager

func NewManager(envBot, envApp, apiURL string, svc *app.Service, log *slog.Logger) *Manager

NewManager returns a manager. Tokens from the environment (both, or they are ignored) win over tokens saved from the web; apiURL overrides the Slack API URL (tests).

func (*Manager) Configure

func (m *Manager) Configure(ctx context.Context, in Config) (Status, error)

Configure checks new tokens with Slack, saves them and switches the app to them; it can also set or clear the team channel. It returns the new status.

func (*Manager) Deliverer

func (m *Manager) Deliverer(next Deliverer) Deliverer

Deliverer wraps the delivery step so that a reminder of a shared subscription is also posted once to the team channel. A failure there never fails the delivery: the scheduler would send the DMs again.

func (*Manager) Edit

func (m *Manager) Edit(ctx context.Context, chatID, messageID string, msg actions.Message) error

Edit edits through the running app.

func (*Manager) Name

func (m *Manager) Name() string

func (*Manager) Remove

func (m *Manager) Remove(ctx context.Context) (Status, error)

Remove forgets tokens saved from the web and disconnects the app.

func (*Manager) Send

func (m *Manager) Send(ctx context.Context, chatID string, msg actions.Message) (string, error)

Send posts through the running app.

func (*Manager) Serve

func (m *Manager) Serve(ctx context.Context) error

Serve runs the app for the current tokens and restarts it when they change, until ctx ends.

func (*Manager) SetEngine

func (m *Manager) SetEngine(e *actions.Engine)

SetEngine wires the action layer.

func (*Manager) Status

func (m *Manager) Status(ctx context.Context) Status

Status reports whether an app is configured and connected.

func (*Manager) String

func (m *Manager) String() string

type Status

type Status struct {
	Configured bool   `json:"configured"`
	Source     string `` /* 139-byte string literal not displayed */
	Running    bool   `json:"running" doc:"the socket to Slack is open"`
	Team       string `json:"team,omitempty" doc:"workspace name"`
	Bot        string `json:"bot,omitempty" doc:"the bot's name in the workspace"`
	AppURL     string `json:"appUrl,omitempty" doc:"link that opens the app in Slack"`
	Channel    string `json:"channel,omitempty" doc:"channel where reminders of shared subscriptions are also posted"`
	Error      string `json:"error,omitempty" doc:"why the app is not connected, when Slack says so"`
	Manifest   string `json:"manifest" doc:"app manifest (YAML) to create the Slack app from"`
	CreateURL  string `json:"createUrl" doc:"opens Slack's create-app page with the manifest filled in"`
}

Status describes the Slack app for the settings UI. It never carries a token.

type Workspace

type Workspace struct {
	Team      string
	TeamID    string
	TeamURL   string
	Bot       string
	BotUserID string
	AppID     string
}

Workspace describes the workspace and the bot the tokens belong to.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL