# `WardrikSlack`

Slack for Wardrik. A `WardrikChannel` adapter for a Slack app of your own.

Agents answer in threads. Before a call they can't make alone, they ask there, with Approve and
Deny buttons.

    config :my_app, MyApp.AgentRuntime,
      channels: [
        slack:
          {WardrikSlack,
           token: "xoxb-...",
           signing_secret: "...",
           owner: "acme",
           approvers: ["@maria"]}
      ]

## Options

Takes `WardrikChannel`'s options, such as `:owner` and `:approvers`, and these:

  * `:token` - the bot token, `xoxb-...`. Adds the app to the one workspace it belongs to.
  * `:signing_secret` - takes Slack's requests over HTTP, at `/v1/channels/{channel}/events`
    and `/v1/channels/{channel}/actions`. See `WardrikSlack.HTTP`.
  * `:app_token` - an app-level token, `xapp-...`, with `connections:write`. Takes Slack's
    requests over Socket Mode instead, with no public address. For testing. See
    `WardrikSlack.Socket`.
  * `:client_id`, `:client_secret`, `:redirect_uri` - add one app to many workspaces. See
    `WardrikSlack.Install`.
  * `:req_options` - merged into every request to Slack.

Over Socket Mode, give Wardrik a Slack app of its own. Slack spreads an app's events across
every open connection.

## Approvers

`:approvers` are named by `@handle`, email address or Slack member ID, or `:anyone`.

  1. A call an agent waits on is sent to each approver in the app's Messages tab, with a link
     to its thread.
  2. The thread says who it waits on.
  3. If Slack reaches none of them, the call is asked in the thread instead.

## In the thread

  * While an agent works, the thread shows what it's doing as the app's status.
  * A message the agent takes gets :eyes:, then :white_check_mark: once it's answered.

# `check`

```elixir
@spec check(keyword()) :: {:ok, String.t()} | {:error, String.t()}
```

Checks a channel's tokens with Slack.

    WardrikSlack.check(token: "xoxb-...", app_token: "xapp-...")
    #=> {:ok, "posts as @wardrik in Acme"}

    WardrikSlack.check(token: "xoxb-wrong")
    #=> {:error, "Slack refused its token: "invalid_auth""}

Checks `:token` with `auth.test`, and `:app_token` by opening a Socket Mode URL. Without
`:token`, the channel keeps a token for each workspace, and those aren't checked.

# `include?`

Returns whether `member` is among `names`. Each name is a `@handle`, email address or member ID.

# `install_url`

Returns the URL where someone acting for `owner` adds the app. See `WardrikSlack.Install.url/3`.

# `installed`

Adds the app to a workspace once Slack sends someone back. See `WardrikSlack.Install.installed/3`.

# `tasks`

```elixir
@spec tasks(WardrikChannel.Channel.t()) :: atom()
```

Returns the name of the task supervisor that handles what Slack sends the channel.

# `uninstall`

Uninstalls the app from `workspace` and forgets the workspace.

The workspace is forgotten even if Slack refuses. Slack confirms with an `app_uninstalled` event.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
