# SlackProvider

The `SlackProvider` sends notifications to Slack using [Hyper](https://forgebox.io/view/hyper).

### Requirements

To use the `SlackProvider`, you need Hyper installed. This is **not** installed by Megaphone.  If you do not have Hyper installed, an exception will be thrown if you try to define a channel with the `SlackProvider`.

Additionally, the `SlackProvider` requires a `token` to be set in the configuration.  You will need a [Slack App installed](https://api.slack.com/apps?new_app=1) in your Slack Workspace to retrieve that token. The Slack App will need the `chat:write`, `chat:write.public`, and `chat:write.customize` scopes, at a minimum.  It may need more scopes if you want to send messages to private channels or direct messages, for example. Consult the [Slack App permission documentation](https://api.slack.com/scopes) to determine what scopes your application needs.

### Configuration

The `SlackProvider` accepts the following properties:

```json
{
    "token": null,
    "defaultChannel": "##general"
}
```

### toSlack

The `toSlack` method should return a `SlackMessage` instance.

```cfscript
public struct function toSlack( notifiable, newSlackMessage ) {
    return newSlackMessage()
        .to( "##payments" )
        .text( "One of your invoices has been paid!" )
        .headerBlock( "Invoice Paid" )
        .contextBlock( ( block ) => {
            block.text( "Customer ###notifiable.getCustomerId()#" );
        } )
        .sectionBlock( ( block ) => {
            block.text( "An invoice has been paid." );
            block.field( "*Invoice No:*#chr( 10 )##getInvoiceNumber()#" ).markdown();
            block.field( "*Invoice Recipient:*#chr( 10 )##notifiable.getEmail()#" ).markdown();
        } )
        .dividerBlock()
        .sectionBlock( ( block ) => {
            block.text( "Congratulations!" );
        } );
}
```

Megaphone includes components to build out a Slack BlockKit payload using a fluent API. This is the preferred way to build a Slack Message.

{% content-ref url="/pages/MyZlkxIQhP88yoEPwPtl" %}
[Slack BlockKit](/providers/slackprovider/slack-blockkit.md)
{% endcontent-ref %}

Additionally, you can return a struct representation of the Slack BlockKit payload instead of using `SlackMessage` or the included `SlackBlockKit` components.

```cfscript
public struct function toSlack( notifiable, newSlackMessage ) {
    return {
        "channel": "##general",
        "text": "A super simple message"
    };
}
```

### routeNotificationForSlack

You can let the `Notifiable` instance define the channel to send the Slack Notification by adding a `routeNotificationForSlack` method.

```cfscript
component accessors="true" {
    
    property name="slackDirectMessageID";
    
    public string function routeNotificationForSlack() {
        return getSlackDirectMessageID();
    }

}
```

Additionally, you may need to use a different token for a notification.  Reasons for this can include sending your notification to multiple different Slack Workspaces depending on the `Notifiable` instance's configuration.  In these cases, you need to return a `SlackRoute` instance from this method.  A helper function is provided to create the `SlackRoute` as a parameter to the `routeNotificationForSlack` method.

```cfscript
component accessors="true" {
    
    property name="slackDirectMessageID";
    property name="slackToken";
    
    public SlackRoute function routeNotificationForSlack( newSlackRoute ) {
        return newSlackRoute(
            getSlackDirectMessageID(),
            getSlackToken()
        );
    }

}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://megaphone.ortusbooks.com/providers/slackprovider.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
