# Introduction

## Notifications for ColdBox

Megaphone is a library to send notifications to users across a variety of channels.  It is similar to [cbfs](https://cbfs.ortusbooks.com/), [cbmailservices](https://coldbox-mailservices.ortusbooks.com/), [qb](https://qb.ortusbooks.com/), or [cbq](https://cbq.ortusbooks.com/) in that it provides a provider-based approach that allows you to send a notification to multiple different channels.


# What's New?

## 1.0.4

* [**SlackProvider**](/providers/slackprovider): Use default [`SlackRoute`](/providers/slackprovider#routenotificationforslack) object if none is returned.

## 1.0.3

* Only invoke routing methods ([`routeFor{Provider}`](/reference/baseprovider#routenotificationfor)) if they exist.

## 1.0.2

* Ensure optional dependencies are activated when registering channels.

## 1.0.1

#### [EmailProvider](/providers/slackprovider#configuration)

* Use the default mailer from `cbMailServices` if no default mailer is configured for Megaphone.
* Log mail `send` successes to `info` and errors to `error` by default.

## 1.0.0

### Initial Release!


# Upgrade Guide


# Requirements

Megaphone requires ColdBox 6+ and either Adobe ColdFusion 2021+ or Lucee 5+.


# Installation

Megaphone is installed via [ForgeBox](https://forgebox.io/view/megaphone).

```bash
box install megaphone
```


# Configuration

Like cbmailservices and cbfs, Megaphone creates channels to send `Notification` instances on.  Channels are created by defining `provider` and any necessary `properties`.

<pre class="language-cfscript"><code class="lang-cfscript"><strong>// config/modules/megaphone.cfc
</strong>component {

    function configure() {
        return {
            "channels": {
                // this is the unique name for the channel
                "database": {
		    "provider": "DatabaseProvider@megaphone",
		    "properties": {
                        // this is the default table name
                        "tableName": "megaphone_notifications",
                        "datasource": "megaphone"
                    }
                },
                "db2": {
                    // providers can be used multiple times with different properties
		    "provider": "DatabaseProvider@megaphone",
		    "properties": {
                        "datasource": "db2"
                    }
                },
                "email": {
                    "provider": "EmailProvider@megaphone",
                    "properties": {
                        "mailer": "default",
                        "onSuccess": () => {},
                        "onError": () => {}
                     }
                },
                "slack": {
                    "provider": "SlackProvider@megaphone",
                    "properties": {
                        "token": getSystemSetting( "SLACK_BOT_TOKEN" ),
                        "defaultChannel": "##general"
                     }
                }
            }
        };
    }

}
</code></pre>

Each Provider defines the required and optional `properties` it accepts.  Refer to the individual Provider documentation for more information.


# Retrieving Channels

Though not a common use case, you can retrieve configured Channel instances using the Megaphone Channel WireBox DSL.

<pre class="language-cfscript"><code class="lang-cfscript"><strong>// config/modules/megaphone.cfc
</strong>component {

    function configure() {
        return {
            "channels": {
                // this is the unique name for the channel
                "database": {
		    "provider": "DatabaseProvider@megaphone",
		    "properties": {
                        // this is the default table name
                        "tableName": "megaphone_notifications",
                        "datasource": "megaphone"
                    }
                }
            }
        };
    }

}
</code></pre>

```cfscript
var databaseChannel = wirebox.getInstance( "megaphone:database" );
```


# Defining Notifications

### Defining a Notification

Notifications are CFCs that extend [`megaphone.models.BaseNotification`](/reference/basenotification).

```cfscript
// StockRebalancingCompleteNotification.cfc
component extends="megaphone.models.BaseNotification" accessors="true" {

    property name="stockSymbol";
    property name="completionTimestamp";

    public array function via( required any notifiable ) {
        return [ "database" ];
    }

    public struct function toDatabase( required any notifiable ) {
        return {
            "stockSymbol": getStockSymbol(),
            "completionTimestamp": getCompletionTimestamp()
        };
    }

}
```

You can create and set any custom properties you want to store on the notification.

The required methods for you to implement are the [`via`](#via) method and any [`to{ChannelType}`](#to-channeltype-methods) methods that the notification could be sent to.

### via

The `via` method defines what channels the `Notification` will be sent by returning an array of channel names.  It can return a static array or it can use the passed `Notifiable` instance to dynamically determine the channels.

You may choose certain channels for a certain `Notifiable` type, like only sending SMS messages to `User` instances, not `Team` instances. &#x20;

```cfscript
public array function via( required any notifiable ) {
    return notifiable.getNotifiableType() == "user" ?
        [ "sms", "email" ] :
        [ "email" ];
}
```

You can also store `Notifiable`-specific configuration, like allowing a `User` to opt-in to certain channels like `sms`, `email`, or `slack`.

```cfscript
public array function via( required any notifiable ) {
    return notifiable.getNotificationChannels();
}
```

### to{ChannelType} methods

For each channel type that the `Notification` could be sent on you need to implement a matching `to{ChannelType}` method.&#x20;

{% hint style="info" %}
Note that the method references the Channel Type name, not the Channel name.  If you have configured multiple `DatabaseProvider` channels you would only need one `toDatabase` method.

For example, if your `DatabaseProvider` channel was called `db`, your `via` method would return `[ "db" ]` and you would implement a `toDatabase` method.
{% endhint %}

For instance, if you are using a `DatabaseProvider`, you need a `toDatabase` method.

```cfscript
public array function via( required any notifiable ) {
    return [ "database" ];
}

public struct function toDatabase( required any notifiable ) {
    return {
        "stockSymbol": getStockSymbol(),
        "completionTimestamp": getCompletionTimestamp()
    };
}
```

The `to{ChannelType}` methods also receive the `Notifiable` reference as an argument in case you need to return different data based on the specific `Notifiable` instance.

Each Provider has their own requirements for their `to{ChannelType}` methods.  See the Provider-specific documentation for more information.


# Notifiables

A `Notifiable` is a something that can recieve a notification.  Traditionally it is your `User` object, but it isn't limited to that.  You may send notifications to a `Team`, a `MailingList`, a `Site`, or more.

### INotifiable

A `Notifiable` needs to implement the `INotifiable` interface (`implements` keyword optional).

```cfscript
interface displayName="INotifiable" {

    /**
     * The id representing this notifiable.
     */
    public string function getNotifiableId();

    /**
     * The type name representing this notifiable.
     */
    public string function getNotifiableType();

}
```

An example implementation for a `User` component could be as follows:

```cfscript
component
    name="User"
    accessors="true"
    implements="megaphone.models.Interfaces.INotifiable"
{

    property name="id";
    
    /**
     * The id representing this notifiable.
     */
    public string function getNotifiableId() {
        return getId();
    }

    /**
     * The type name representing this notifiable.
     */
    public string function getNotifiableType() {
        return "user";
    }

}
```

### via

`Notifiable` instances are passed to the `via` method on a `Notification`. This is to allow you to customize the channels used to each `Notifiable`.  You may choose certain channels for a certain `Notifiable` type, like only sending SMS messages to `User` instances, not `Team` instances.  You can also store `Notifiable`-specific configuration, like allowing a `User` to opt-in to certain channels like `sms`, `email`, or `slack`.

{% hint style="info" %}
See the [`via` docs on `Notifications`](/creating-and-sending-notifications/defining-notifications#via) for more information.
{% endhint %}

### routeNotificationFor

Providers may look for a `routeNotificationFor` method suffixed with the Provider type name.  For instance, the `EmailProvider` may look for a `routeNotificationForEmail` method on the `Notifiable`.&#x20;

{% hint style="info" %}
See the Provider-specific docs for more information.
{% endhint %}


# Sending Notifications

There are two ways to send notifications in Megaphone — using the [`NotificationService`](#notificationservice) or using [delegates](#sendsnotifications-delegate) (requires ColdBox 7+).

### NotificationService

Notifications are sent using the [`NotificationService`](/reference/notificationservice), often aliased as `megaphone`.

```cfscript
// handlers/StockRebalancing.cfc
component {

    property name="megaphone" inject="NotificationService@megaphone";

    function create( event, rc, prc ) {
        // ...
        var notification = getInstance( "StockRebalancingCompleteNotification" )
        notification.setStockSymbol( "APPL" );
        notification.setCompletionTimestamp( now() );
        megaphone.notify( auth().user(), notification );
        // ...
    }

}
```

For those of you allergic to calling `getInstance` (😜), you can also pass a string name and a struct of properties:

```cfc
// handlers/StockRebalancing.cfc
component {

    property name="megaphone" inject="NotificationService@megaphone";

    function create( event, rc, prc ) {
        // ...
        megaphone.notify(
            auth().user(),
            "StockRebalancingCompleteNotification",
            { "stockSymbol": "APPL", "completionTimestamp": now() }
        );
        // ...
    }

}
```

### SendsNotifications Delegate

Another way to send a Notification is by adding the [`SendsNotifications`](/reference/sendsnotifications) delegate to a [`Notifiable`](/reference/inotifiable) instance.

```cfc
component name="User" delegates="SendsNotifications@megaphone" accessors="true" {

    property name="id";

    public string function getNotifiableId() {
        return getId();
    }

    public string function getNotifiableType() {
        return "User";
    }

}
```

Then you can call a `notify` method on the [`Notifiable`](/reference/inotifiable) instance.

```cfc
// handlers/StockRebalancing.cfc
component {

    property name="megaphone" inject="NotificationService@megaphone";

    function create( event, rc, prc ) {
        // ...
        auth().user().notify(
            "StockRebalancingCompleteNotification",
            { "stockSymbol": "APPL", "completionTimestamp": now() }
        );
        // ...
    }

}
```

{% hint style="info" %}
The `notify` method from the delegate can be passed either a [`Notification`](/reference/basenotification) instance or a string name just like the `notify` method on the [`NotificationService`](/reference/notificationservice).
{% endhint %}


# DatabaseProvider

The `DatabaseProvider` stores notifications in a table that you can then query to show in your application.  It also provides a `DatabaseNotificationService` to interact with the notifications for a `Notifiable` including pagination and marking as read.

### Requirements

To use the `DatabaseProvider`, you need a table to store the notifications in.  A migration is provided in Megaphone that you can copy to your application to use.  If you are not using `cfmigrations`, create a table that has the same structure in your database.  The table name can be customized, if needed.

{% tabs %}
{% tab title="CFMigrations" %}

```cfscript
component {

    function up( schema ) {
        schema.create( "megaphone_notifications",  ( t ) => {
            t.guid( "id" ).primaryKey();
            t.string( "type" ); // notification wirebox id
            t.string( "notifiableId" );
            t.string( "notifiableType" );
            t.longText( "data" ); // serializeJSON of what is returned from `toDatabase`
            t.timestamp( "readDate" ).nullable();
            t.timestamp( "createdDate" ).withCurrent();

            t.index( "type" );
            t.index( "readDate" );
            t.index( name = "idx_megaphone_notifications_notifiable_index", columns = [ "notifiableId", "notifiableType" ] );
        } );
    }

    function down( schema ) {
        schema.dropIfExists( "megaphone_notifications" );
    }

}
```

{% endtab %}

{% tab title="MySQL" %}

```sql
CREATE TABLE ` megaphone_notifications` (
    `id` NCHAR(36) NOT NULL,
    `type` VARCHAR(255) NOT NULL,
    `notifiableId` VARCHAR(255) NOT NULL,
    `notifiableType` VARCHAR(255) NOT NULL,
    `data` LONGTEXT NOT NULL,
    `readDate` TIMESTAMP NULL DEFAULT NULL,
    `createdDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT `pk_megaphone_notifications_id` PRIMARY KEY (`id`),
    INDEX `idx_megaphone_notifications_type` (`type`),
    INDEX `idx_megaphone_notifications_readDate` (`readDate`),
    INDEX `idx_megaphone_notifications_notifiable_index` (`notifiableId`, `notifiableType`)
)
```

{% endtab %}

{% tab title="SQL Server" %}

```sql
CREATE TABLE [megaphone_notifications] (
    [id] uniqueidentifier NOT NULL,
    [type] VARCHAR(255) NOT NULL,
    [notifiableId] VARCHAR(255) NOT NULL,
    [notifiableType] VARCHAR(255) NOT NULL,
    [data] VARCHAR(MAX) NOT NULL,
    [readDate] DATETIME2,
    [createdDate] DATETIME2 NOT NULL CONSTRAINT [df_megaphone_notifications_createdDate] DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT [pk_megaphone_notifications_id] PRIMARY KEY ([id]),
    INDEX [idx_megaphone_notifications_type] ([type]),
    INDEX [idx_megaphone_notifications_readDate] ([readDate]),
    INDEX [idx_megaphone_notifications_notifiable_index] ([notifiableId], [notifiableType])
)
```

{% endtab %}
{% endtabs %}

### Configuration

The `DatabaseProvider` accepts the following properties:

```json
{
    "tableName": "megaphone_notifications",
    "datasource": null,
    "queryOptions": {}
}
```

These can be different for each channel you configure using the `DatabaseProvider`.

```cfscript
moduleSettings = {
    "megaphone": {
        "channels": {
            "db1": {
                "provider": "DatabaseProvider@megaphone",
                "properties": { "datasource": "db1" }
            },
            "db2": {
                "provider": "DatabaseProvider@megaphone",
                "properties": { "datasource": "db2" }
            }
        }
    }
};
```

{% hint style="warning" %}
The `datasource` property will override any `datasource` property on the passed-in `queryOptions`.
{% endhint %}

### toDatabase

The `toDatabase` method returns a `struct` of data to save as the body of the notification in the database.  This data will be available when reading the notifications back from the database later.

```cfscript
public struct function toDatabase( required any notifiable ) {
    return {
        "stockSymbol": getStockSymbol(),
        "completionTimestamp": getCompletionTimestamp()
    };
}
```

### Interacting with Database Notifications

Where most Megaphone Providers opearte as fire-and-forget, the notifications sent by the `DatabaseProvider` need to be shown in your application to be of any use.  The `DatabaseProvider` provides a few extra components to help you do this.

Just like sending notifications, there are two ways to retrieve notifications sent through the `DatabaseProvider`: using the `DatabaseNotificationService` and using the `HasDatabaseNotifications` delegate.  These two options return the same results, so use whichever one you prefer.

#### DatabaseNotificationService

The `DatabaseNotificationService` can be injected into any component in your application to retrieve `DatabaseNotification` instances for a `Notifiable`.

```cfscript
component {
    
    property
        name="databaseNotificationService"
        inject="DatabaseNotificationService@megaphone";

    function index( event, rc, prc ) {
        // ...
        var cursor = variables.databaseNotificationService.getUnreadNotifications(
            notifiable = auth().user(),
            channel = "database" // default is "database",
            initialPage = 1 // default is 1,
            maxRows = 25 // default is 25
        );
       // ...
    }
    
}
```

This will return a `DatabaseNotificationCursor` paging over all unread notifications for the passed in `Notifiable`.&#x20;

{% hint style="info" %}
The `DatabaseNotificationService` also includes methods for retrieving read notifications or all notifications.  See the [`DatabaseNotificationService` reference docs](/reference/baseprovider/databaseprovider/databasenotificationservice) for more information.
{% endhint %}

{% content-ref url="/pages/Bqgt4DtyDrIwKC8wKaaE" %}
[DatabaseNotificationService](/reference/baseprovider/databaseprovider/databasenotificationservice)
{% endcontent-ref %}

#### HasDatabaseNotifications

The `HasDatabaseNotifications` delegate allows you to get the notifications directly from a `Notifiable` instance.

```cfscript
component name="User" delegates="HasDatabaseNotifications@megaphone" accessors="true" {

    property name="id";

    public string function getNotifiableId() {
        return getId();
    }

    public string function getNotifiableType() {
        return "User";
    }

}
```

```cfscript
component {

    function index( event, rc, prc ) {
        // ...
        var cursor = auth().user().getUnreadNotifications(
            channel = "database" // default is "database",
            initialPage = 1 // default is 1,
            maxRows = 25 // default is 25
        );
        
        // if you want all the defaults:
        var cursor = auth().user().getUnreadNotifications();
        // ...
    }

}
```

{% content-ref url="/pages/Rb0a6MBVZvDVTbZWQi81" %}
[HasDatabaseNotifications](/reference/baseprovider/databaseprovider/hasdatabasenotifications)
{% endcontent-ref %}

#### DatabaseNotificationCursor

The `DatabaseNotificationCursor` provides a way to paginate through the notifications while also being able to either `markAllAsRead` or `deleteAll` of the notifications contained in the cursor.

```cfc
cursor.getPagination(); // { "maxRows": 25, "totalPages": 1, "offset": 0, "page": 1, "totalRecords": 5 }
cursor.getResults(); // [ DatabaseNotification ]
for ( var notification in cursor.getResults() ) {
    notification.getMemento(); // { id, type, notifiableType, notifiableId, data, readDate, createdDate }
    notification.getData(); // struct / already deserialized
    notification.getType(); // string — notification wirebox id
    notification.markAsRead( readDate = now() ); // sets and saves the readDate, default = now()
    notification.delete(); // deletes the notification from the database
}
cursor.hasPrevious(); // boolean
cursor.previous(); // loads previous page from database
cursor.hasNext(); // boolean
cursor.next(); // loads next page from database
cursor.markAllAsRead( readDate = now() ); // marks all as read, not just current page. default = now()
cursor.deleteAll(); // deletes all, not just current page
```

{% content-ref url="/pages/2wNnpFPem9YhwHWcGJn2" %}
[DatabaseNotificationCursor](/reference/baseprovider/databaseprovider/databasenotificationcursor)
{% endcontent-ref %}

#### DatabaseNotification

The component returned as the notification inside the `DatabaseNotificationCursor` is an instance of `DatabaseNotification`. This allows you to retrieve the data you sent as well as interact with the `DatabaseNotification` by checking the sending `Notification` type, marking the `DatabaseNotification` as read or deleting the `DatabaseNotification`.

```cfscript
notification.getMemento(); // { id, type, notifiableType, notifiableId, data, readDate, createdDate }
notification.getData(); // struct / already deserialized
notification.getType(); // string — notification wirebox id
notification.markAsRead( readDate = now() ); // sets and saves the readDate, default = now()
notification.delete(); // deletes the notification from the database
```

{% content-ref url="/pages/2f4tN0wF48y29zmXiwTJ" %}
[DatabaseNotification](/reference/baseprovider/databaseprovider/databasenotification)
{% endcontent-ref %}


# EmailProvider

The `EmailProvider` sends notifications using [cbMailServices](https://forgebox.io/view/cbmailservices).

### Requirements

To use the `EmailProvider`, you need [cbMailServices](https://forgebox.io/view/cbmailservices) installed. This is **not** installed by Megaphone.  If you do not have [cbMailServices](https://forgebox.io/view/cbmailservices) installed, an exception will be thrown if you try to define a channel with the `EmailProvider`.

### Configuration

The `EmailProvider` accepts the following properties:

```json
{
    "mailer": "default", // optional, uses the cbMailServices default otherwise
    "onSuccess": () => {}, // optional, logs to info otherwise
    "onFailure": () => {} // optional, logs to error otherwise
}
```

### toEmail

The `toEmail` method returns a `Mail@cbmailservices` instance to send. The `to` property can be either defined in the `toEmail` method or a `routeNotificationForEmail` method defined on the `Notifiable` instance.

```cfscript
public struct function toEmail( notifiable, newMail ) {
    return newMail(
        to = notifiable.getEmail(),
        from = "noreply@example.com",
        subject = "Megaphone Email Notification",
        type = "html",
        bodyTokens = { product: "ColdBox" }
    ).setBody( "
        <p>Thank you for downloading @product@, have a great day!</p>
    " );
}
```

### routeNotificationForEmail

You can let the `Notifiable` instance define how to send the Email Notification by adding a `routeNotificationForEmail` method.

```cfscript
component accessors="true" {
    
    property name="email";
    
    public string function routeNotificationForEmail() {
        return getEmail();
    }

}
```


# 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)
{% 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()
        );
    }

}
```


# Slack BlockKit

Megaphone provides a fluent BlockKit API to build a `SlackMessage`.  It starts by calling the `newSlackMessage` provided to the `toSlack` method on the Notification.

```cfscript
function toSlack( notifiable, newSlackMessage ) {
    return newSlackMessage();
}
```

For the individual methods and building blocks, please see the reference documentation.

{% content-ref url="/pages/5cZkhzyBsavdtm48NmDg" %}
[SlackMessage](/reference/baseprovider/slackprovider/slackmessage)
{% endcontent-ref %}

An important callout is the `dump` method.  This method can `writeDump` a memento of the `SlackMessage` instance when passing the `raw` parameter as `true`.  The default, however, is to `writeDump` a URL that takes you to Slack's [BlockKit Builder](https://app.slack.com/block-kit-builder/) to visually see your message.

```cfscript
public void function dump(
    boolean raw = false,
    string output = "browser",
    string format = "html",
    boolean abort = false,
    string label = "",
    boolean metainfo = false,
    numeric top = 9999,
    string show = "",
    string hide = "",
    numeric keys = 9999,
    boolean expand = true,
    boolean showUDFs = true
);
```

Example URL:

<https://app.slack.com/block-kit-builder/TBHQJRCEN#%7B%22blocks%22:%5B%7B%22text%22:%7B%22text%22:%22Invoice%20Paid%22,%22type%22:%22plain_text%22%7D,%22type%22:%22header%22%7D,%7B%22elements%22:%5B%7B%22text%22:%22Customer%20%231234%22,%22type%22:%22plain_text%22%7D%5D,%22type%22:%22context%22%7D,%7B%22fields%22:%5B%7B%22text%22:%22*Invoice%20No:*%5Cn1000%22,%22type%22:%22mrkdwn%22%7D,%7B%22text%22:%22*Invoice%20Recipient:*%5Cneric@ortussolutions.com%22,%22type%22:%22mrkdwn%22%7D%5D,%22text%22:%7B%22text%22:%22An%20invoice%20has%20been%20paid.%22,%22type%22:%22plain_text%22%7D,%22type%22:%22section%22%7D,%7B%22type%22:%22divider%22%7D,%7B%22text%22:%7B%22text%22:%22Congratulations!%22,%22type%22:%22plain_text%22%7D,%22type%22:%22section%22%7D%5D%7D>


# Creating Custom Providers

Providers must extend `megaphone.models.Providers.BaseProvider`.

There are two required methods to implement: `getProviderName` and `notify`.

```cfscript
/**
 * Returns the name for this Provider.
 * This name is the same across all different channels using the same Provider.
 *
 * @return string
 */
public string function getProviderName();

/**
 * Sends a `Notification` to a `Notifiable`.
 * This method will be called once for each `Notifiable` receiving the notification,
 * even if the `NotificationService#notify` method was called with multiple
 * `Notifiable` instances.
 *
 * @notifiable   The `Notifiable` instance receiving the `Notification`.
 * @notification The `Notification` instance to send to the `Notifiable` instance.
 *
 * @return The BaseNotification instance
 */
public BaseNotification function notify(
    required any notifiable,
    required BaseNotification notification
);
```

Inside the `notify` method, there are two helper methods to help you implement your Provider-specific logic: `Notification#routeForType` and `BaseProvider#routeNotificationFor`.

Here is an example using the `EmailProvider`:

```cfscript
public BaseNotification function notify(
    required any notifiable,
    required BaseNotification notification
) {
    var mail = arguments.notification.routeForType(
        type = "email",
        notifiable = notifiable,
        channelName = getName(),
        additionalArgs = {
            "newMail": () => {
                param arguments.mailer = variables.properties.mailer;
                return variables.mailService.newMail( argumentCollection = arguments );
            }
        }
    );

    if ( mail.getProperty( "to" ) == "" ) {
        mail.setProperty( "to", routeNotificationFor( "email", notifiable, getName() ) );
    }

    variables.mailService
        .send( mail )
        .onSuccess( variables.properties.onSuccess )
        .onError( variables.properties.onError );

    return arguments.notification;
}
```

{% hint style="warning" %}
When implementing this method, make sure not to modify the `Notification` instance as this instance will be used for each `Notifiable`.
{% endhint %}

### routeForType

The `routeForType` method is called on the `Notification` instance.  It is what is responsible for calling the `to{ChannelType}` function on the `Notification`.&#x20;

Inside `additionalArgs` you can pass additional parameters that will be passed to the `to{ChannelType}` method after the `Notifiable` instance.

This is a great place to pass helper functions to construct necessary objects for your Provider.  Here in the `EmailProvider`, we provider a `newMail` helper method to create a `Mail` instance from `cbMailServices`. Other Providers provide similar helper functions.

The return value from this function is `any`.  It is the responsibility of your Provider to ensure the return value of this function is what you expected.  For instance, the `DatabaseProvider` expects a struct, the `EmailProvider` expects a `Mail@cbmailservices` instance, and so forth.

```cfscript
var mail = arguments.notification.routeForType(
    type = "email",
    notifiable = notifiable,
    channelName = getName(),
    additionalArgs = {
        "newMail": () => {
            param arguments.mailer = variables.properties.mailer;
            return variables.mailService.newMail( argumentCollection = arguments );
        }
    }
);
```

### routeNotificationFor

The `routeNotificationFor` method is similar to the `routeForType` method.  It is used to ask the `Notifiable` instance to define routing information for a specific Channel type.  For instance, the `EmailProvider` would look for a `routeNotificationForEmail` method.

The `routeNotificationFor{ChannelType}` methods should be defined on the `Notifiable` instance.  The only arguments passed to this function are the `additionalArgs` passed when calling the `routeNotificationFor` methods.

Additionally, the `routeNotificationFor` method can be marked as `optional`.  Optional calls will not throw an exception if they are not defined on the `Notifiable` instance.

The return value from this function is `any`.  It is the responsibility of your Provider to ensure the return value of this function is what you expected.  For instance, the `EmailProvider` expects a `string` value, the `SlackProvider` expects either a `string` value or a `SlackRoute` value.

```cfscript
// EmailProvider.cfc
if ( mail.getProperty( "to" ) == "" ) {
    mail.setProperty( "to", routeNotificationFor( "email", notifiable, getName() ) );
}
```

```cfscript
// SlackProvider.cfc
var route = routeNotificationFor(
    type = "slack",
    notifiable = notifiable,
    channelName = getName(),
    additionalArgs = {
        "newSlackRoute": ( channel, token ) => {
            return variables.wirebox.getInstance(
                "SlackRoute@megaphone",
                { "channel": channel, "token": token }
            );
        }
    },
    optional = true
);
```


# Coming Soon


# NotificationService

### notify

Sends a notification to a single notifiable instance or an array of notifiable instances.

<table><thead><tr><th width="140">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>notifiables</td><td><a href="/pages/SQVKwkAuCy6QgkIRG8Uk"><code>INotifiable</code></a> | <code>array&#x3C;</code><a href="/pages/SQVKwkAuCy6QgkIRG8Uk"><code>INotifiable</code></a><code>></code></td><td>true</td><td></td><td>A single Notifiable instance or an array of Notifiable instances that will receive the notification.</td></tr><tr><td>notification</td><td><code>string</code> | <a href="/pages/pG0uLeeZ0niwuthcdNwE"><code>BaseNotification</code></a></td><td>true</td><td></td><td>The notification instance or a string WireBox mapping to send to the notifiables.</td></tr><tr><td>properties</td><td><code>struct</code></td><td>false</td><td><code>{}</code></td><td>A struct of properties to populate the notification with.</td></tr></tbody></table>

**Return**: `notification` instance, after it has been populated and sent to the `notifiables`.

### getChannel

Returns a channel instance by name.

<table><thead><tr><th width="149">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>channelName</td><td><code>string</code></td><td>true</td><td></td><td>The name of the channel to return.</td></tr></tbody></table>

**Return**: A [`BaseProvider`](/reference/baseprovider) instance for the channel name.

{% hint style="danger" %}
**Throws:** `Megaphone.Configuration.MissingChanel`
{% endhint %}

### getChannels

Returns a map of channel names to Provider instances.

<table><thead><tr><th width="149">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: A `struct` map of channel names to Provider instances.


# BaseNotification

### via

Returns an array of channel names to send this notification on.

<table><thead><tr><th width="140">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>notifiable</td><td><a href="/pages/SQVKwkAuCy6QgkIRG8Uk"><code>INotifiable</code></a></td><td>true</td><td></td><td>The notifiable instance being sent this notification instance.</td></tr></tbody></table>

**Return**: An array of `string` channel names.

### populate

Populates the passed in struct of properties onto the variables scope of the Notification.

<table><thead><tr><th width="140">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>properties</td><td><code>struct</code></td><td>false</td><td><code>{}</code></td><td>The properties to populate.</td></tr></tbody></table>

**Return**: The Notification instance.

### routeForType

Routes the notification to the correct `to{ChannelType}` method.

<table><thead><tr><th width="140">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>type</td><td><code>string</code></td><td>true</td><td></td><td>The type of channel to route to.</td></tr><tr><td>notifiable</td><td><a href="/pages/SQVKwkAuCy6QgkIRG8Uk"><code>INotifiable</code></a></td><td>true</td><td></td><td>The notifiable instance the notification is being sent to.</td></tr><tr><td>channelName</td><td><code>string</code></td><td>true</td><td></td><td>The name of the channel to route to.</td></tr><tr><td>additionalArgs</td><td><code>struct</code></td><td>false</td><td><code>{}</code></td><td>Any additional arguments to pass to the routing method (<code>to{ChannelType}</code> method).</td></tr></tbody></table>

**Return**: The result of the routing method. The variable type depends on the Provider.

### getNotificationType

Returns the WireBox ID of the Notification.

<table><thead><tr><th width="140">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: (string) The WireBox ID of the Notification.


# SendsNotifications

This is a [delegate component](https://wirebox.ortusbooks.com/usage/wirebox-delegators) and requires ColdBox 7+. It should be added to an [`INotifiable`](/reference/inotifiable) instance.

```cfscript
component
    name="User"
    delegates="SendsNotifications@megaphone"
    accessors="true"
{

    property name="id";

    public string function getNotifiableId() {
        return getId();
    }

    public string function getNotifiableType() {
        return "User";
    }

}
```

### notify

Sends a notification to this [`INotifiable`](/reference/inotifiable) instance.

<table><thead><tr><th width="140">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>notification</td><td><code>string</code> | <a href="/pages/pG0uLeeZ0niwuthcdNwE"><code>BaseNotification</code></a></td><td>true</td><td></td><td>The notification instance or a string WireBox mapping to send to the notifiables.</td></tr><tr><td>properties</td><td><code>struct</code></td><td>false</td><td><code>{}</code></td><td>A struct of properties to populate the notification with.</td></tr></tbody></table>

**Return**: `notification` instance, after it has been populated and sent to the `notifiables`.


# INotifiable

This is a required interface for any component that should be able to receive notifications in your application.  Using the `implements` keyword is optional.

## Required Methods

### getNotifiableId

The id representing this Notifiable.

<table><thead><tr><th width="140">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: (string) The Notifiable id.

### getNotifiableType

The type of this Notifiable.

<table><thead><tr><th width="140">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: (string) The Notifiable type.


# BaseProvider

### getProviderName

Returns the name for this Provider.

{% hint style="warning" %}
This name should be the same across all different channels using the same Provider.
{% endhint %}

<table><thead><tr><th width="140">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: (string) The Provider name

### notify

Sends a [`Notification`](/reference/basenotification) to a [`Notifiable`](/reference/inotifiable) through this Channel instance using the configured Provider.

This method will be called once for each [`Notifiable`](/reference/inotifiable) receiving the notification, even if the [`NotificationService#notify`](/reference/notificationservice#notify) method was called with multiple [`Notifiable`](/reference/inotifiable) instances.

{% hint style="warning" %}
When implementing this method, make sure not to modify the [`Notification`](/reference/basenotification) instance as this instance will be used for each [`Notifiable`](/reference/inotifiable).
{% endhint %}

<table><thead><tr><th width="140">Name</th><th width="229">Type</th><th width="123">Required</th><th width="58">Default</th><th>Description</th></tr></thead><tbody><tr><td>notifiable</td><td><a href="/pages/SQVKwkAuCy6QgkIRG8Uk"><code>INotifiable</code></a></td><td>true</td><td></td><td>The <a href="/pages/SQVKwkAuCy6QgkIRG8Uk"><code>Notifiable</code></a> instance receiving the <a href="/pages/pG0uLeeZ0niwuthcdNwE"><code>Notification</code></a>.</td></tr><tr><td>notification</td><td><a href="/pages/pG0uLeeZ0niwuthcdNwE"><code>BaseNotification</code></a></td><td>true</td><td></td><td>The Notification instance to send to the notifiable.</td></tr></tbody></table>

**Return**: [`Notification`](/reference/basenotification) instance, after it has been sent to the [`INotifiable`](/reference/inotifiable).

### routeNotificationFor

Determines the route the notification should be sent to by calling the `routeNotificationFor{ChannelType}` method, if it exists.

<table><thead><tr><th width="140">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>type</td><td><code>string</code></td><td>true</td><td></td><td>The type of channel to route to.</td></tr><tr><td>notifiable</td><td><a href="/pages/SQVKwkAuCy6QgkIRG8Uk"><code>INotifiable</code></a></td><td>true</td><td></td><td>The notifiable instance the notification is being sent to.</td></tr><tr><td>channelName</td><td><code>string</code></td><td>true</td><td></td><td>The name of the channel to route to.</td></tr><tr><td>additionalArgs</td><td><code>struct</code></td><td>false</td><td><code>{}</code></td><td>Any additional arguments to pass to the routing method (<code>to{ChannelType}</code> method).</td></tr><tr><td>optional</td><td><code>boolean</code></td><td>false</td><td><code>false</code></td><td>Boolean flag determining if the routing method is optional or not.</td></tr></tbody></table>

**Return**: The result of the `routeNotificationFor{ChannelType}` method. The variable type depends on the Provider.


# DatabaseProvider

See the `BaseProvider` for inherited methods.

{% content-ref url="/pages/6x7oBEQ8jyfTIxZgj3j2" %}
[BaseProvider](/reference/baseprovider)
{% endcontent-ref %}

### getTableName

Returns the configured table name for this Channel.

The default is `megaphone_notifications`. It can be overridden by setting the `tableName` property.

<table><thead><tr><th width="140">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: (string) The name of the table to use for storing and retrieving notifications.

### getQueryOptions

Returns the configured query options for this Provider.  This is eventually passed to `queryExecute`.

The default is an empty struct (`{}`). It can be overridden by setting the `queryOptions` property.

If the `datasource` property is set, it will be set on the `queryOptions` returned from this method.

<table><thead><tr><th width="140">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: The struct of query options for this Channel.


# DatabaseNotificationService

### getNotifications

Returns all database notifications for a Notifiable.

<table><thead><tr><th width="140">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>notifiable</td><td><a href="/pages/SQVKwkAuCy6QgkIRG8Uk"><code>INotifiable</code></a></td><td>true</td><td></td><td>The <a href="/pages/SQVKwkAuCy6QgkIRG8Uk"><code>INotifiable</code></a> instance to retrieve notifications for.</td></tr><tr><td>channelName</td><td><code>string</code></td><td>false</td><td><code>database</code></td><td>The name of the channel to retrieve notifications from.  Defaults to <code>database</code>.</td></tr><tr><td>initialPage</td><td><code>numeric</code></td><td>false</td><td><code>1</code></td><td>The initial page of the returned <code>DatabaseNotificationCursor</code>.</td></tr><tr><td>maxRows</td><td><code>numeric</code></td><td>false</td><td><code>25</code></td><td>The number of rows per page for the returned <code>DatabaseNotificationCursor</code>.</td></tr></tbody></table>

**Return**: A `DatabaseNotificationCursor` to interact with a paginated list of notifications for the notifiable.

{% hint style="danger" %}
**Throws:** `Megaphone.Configuration.MissingChannel`

**Throws:** `Megaphone.Configuration.InvalidChannelProvider`
{% endhint %}

### getReadNotifications

Returns all read database notifications for a Notifiable.

<table><thead><tr><th width="140">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>notifiable</td><td><a href="/pages/SQVKwkAuCy6QgkIRG8Uk"><code>INotifiable</code></a></td><td>true</td><td></td><td>The <a href="/pages/SQVKwkAuCy6QgkIRG8Uk"><code>INotifiable</code></a> instance to retrieve read notifications for.</td></tr><tr><td>channelName</td><td><code>string</code></td><td>false</td><td><code>database</code></td><td>The name of the channel to retrieve read notifications from.  Defaults to <code>database</code>.</td></tr><tr><td>initialPage</td><td><code>numeric</code></td><td>false</td><td><code>1</code></td><td>The initial page of the returned <code>DatabaseNotificationCursor</code>.</td></tr><tr><td>maxRows</td><td><code>numeric</code></td><td>false</td><td><code>25</code></td><td>The number of rows per page for the returned <code>DatabaseNotificationCursor</code>.</td></tr></tbody></table>

**Return**: A `DatabaseNotificationCursor` to interact with a paginated list of read notifications for the notifiable.

{% hint style="danger" %}
**Throws:** `Megaphone.Configuration.MissingChannel`

**Throws:** `Megaphone.Configuration.InvalidChannelProvider`
{% endhint %}

### getUnreadNotifications

Returns all unread database notifications for a Notifiable.

<table><thead><tr><th width="140">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>notifiable</td><td><a href="/pages/SQVKwkAuCy6QgkIRG8Uk"><code>INotifiable</code></a></td><td>true</td><td></td><td>The <a href="/pages/SQVKwkAuCy6QgkIRG8Uk"><code>INotifiable</code></a> instance to retrieve unread notifications for.</td></tr><tr><td>channelName</td><td><code>string</code></td><td>false</td><td><code>database</code></td><td>The name of the channel to retrieve unread notifications from.  Defaults to <code>database</code>.</td></tr><tr><td>initialPage</td><td><code>numeric</code></td><td>false</td><td><code>1</code></td><td>The initial page of the returned <code>DatabaseNotificationCursor</code>.</td></tr><tr><td>maxRows</td><td><code>numeric</code></td><td>false</td><td><code>25</code></td><td>The number of rows per page for the returned <code>DatabaseNotificationCursor</code>.</td></tr></tbody></table>

**Return**: A `DatabaseNotificationCursor` to interact with a paginated list of unread notifications for the notifiable.

{% hint style="danger" %}
**Throws:** `Megaphone.Configuration.MissingChannel`

**Throws:** `Megaphone.Configuration.InvalidChannelProvider`
{% endhint %}


# HasDatabaseNotifications

This is a [delegate component](https://wirebox.ortusbooks.com/usage/wirebox-delegators) and requires ColdBox 7+. It should be added to an [`INotifiable`](/reference/inotifiable) instance.

### getNotifications

Returns all database notifications for this Notifiable.

<table><thead><tr><th width="140">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>channelName</td><td><code>string</code></td><td>false</td><td><code>database</code></td><td>The name of the channel to retrieve notifications from.  Defaults to <code>database</code>.</td></tr><tr><td>initialPage</td><td><code>numeric</code></td><td>false</td><td><code>1</code></td><td>The initial page of the returned <code>DatabaseNotificationCursor</code>.</td></tr><tr><td>maxRows</td><td><code>numeric</code></td><td>false</td><td><code>25</code></td><td>The number of rows per page for the returned <code>DatabaseNotificationCursor</code>.</td></tr></tbody></table>

**Return**: A `DatabaseNotificationCursor` to interact with a paginated list of notifications for this notifiable.

{% hint style="danger" %}
**Throws:** `Megaphone.Configuration.MissingChannel`

**Throws:** `Megaphone.Configuration.InvalidChannelProvider`
{% endhint %}

### getReadNotifications

Returns all read database notifications for this Notifiable.

<table><thead><tr><th width="140">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>channelName</td><td><code>string</code></td><td>false</td><td><code>database</code></td><td>The name of the channel to retrieve read notifications from.  Defaults to <code>database</code>.</td></tr><tr><td>initialPage</td><td><code>numeric</code></td><td>false</td><td><code>1</code></td><td>The initial page of the returned <code>DatabaseNotificationCursor</code>.</td></tr><tr><td>maxRows</td><td><code>numeric</code></td><td>false</td><td><code>25</code></td><td>The number of rows per page for the returned <code>DatabaseNotificationCursor</code>.</td></tr></tbody></table>

**Return**: A `DatabaseNotificationCursor` to interact with a paginated list of read notifications for this notifiable.

{% hint style="danger" %}
**Throws:** `Megaphone.Configuration.MissingChannel`

**Throws:** `Megaphone.Configuration.InvalidChannelProvider`
{% endhint %}

### getUnreadNotifications

Returns all unread database notifications for this Notifiable.

<table><thead><tr><th width="140">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>channelName</td><td><code>string</code></td><td>false</td><td><code>database</code></td><td>The name of the channel to retrieve unread notifications from.  Defaults to <code>database</code>.</td></tr><tr><td>initialPage</td><td><code>numeric</code></td><td>false</td><td><code>1</code></td><td>The initial page of the returned <code>DatabaseNotificationCursor</code>.</td></tr><tr><td>maxRows</td><td><code>numeric</code></td><td>false</td><td><code>25</code></td><td>The number of rows per page for the returned <code>DatabaseNotificationCursor</code>.</td></tr></tbody></table>

**Return**: A `DatabaseNotificationCursor` to interact with a paginated list of unread notifications for this notifiable.

{% hint style="danger" %}
**Throws:** `Megaphone.Configuration.MissingChannel`

**Throws:** `Megaphone.Configuration.InvalidChannelProvider`
{% endhint %}


# DatabaseNotificationCursor

### configureQuery

Calls the provided callback to configure the underlying query for this `DatabaseNotificationCursor` instance.&#x20;

<table><thead><tr><th width="140">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>callback</td><td><code>function</code></td><td>true</td><td></td><td>The callback called to configure the underlying query of this <code>DatabaseNotificationCursor</code>.</td></tr></tbody></table>

**Return**: The `DatabaseNotificationCursor` instance.

### fetch

Executes the configured query and stores the pagination and results internally. Maps the resulting rows into `DatabaseNotification` instances.

<table><thead><tr><th width="140">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: The `DatabaseNotificationCursor` instance.

### hasNext

Returns `true` if there are more pages left in the cursor.

<table><thead><tr><th width="140">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: `boolean`

### next

Advances the page of the cursor and fetches the results.

<table><thead><tr><th width="140">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: The `DatabaseNotificationCursor` instance.

{% hint style="danger" %}
**Throws:** `Megaphone.DatabaseNotificationCursor.MaximumPageReached`
{% endhint %}

### hasPrevious

Returns `true` if there are more pages before the current page in the cursor.

<table><thead><tr><th width="157">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: `boolean`

### previous

Reverses the page of the cursor and fetches the results.

<table><thead><tr><th width="140">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: The `DatabaseNotificationCursor` instance.

{% hint style="danger" %}
**Throws:** `Megaphone.DatabaseNotificationCursor.MinimumPageReached`
{% endhint %}

### markAllAsRead

Marks all the notifications under the cursor as read.

{% hint style="info" %}
This marks all the notifications the cursor applies to, not just the currently loaded page.
{% endhint %}

<table><thead><tr><th width="180">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>readDate</td><td><code>date</code></td><td>false</td><td><code>now()</code></td><td>The date to use when marking the notifications as read.</td></tr></tbody></table>

**Return**: The `DatabaseNotificationCursor` instance.

### deleteAll

Deletes all the notifications under the cursor.

{% hint style="info" %}
This deletes all the notifications the cursor applies to, not just the currently loaded page.
{% endhint %}

<table><thead><tr><th width="180">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td><h3></h3></td><td></td><td><h3></h3></td><td></td></tr></tbody></table>

**Return**: The `DatabaseNotificationCursor` instance.


# DatabaseNotification

### markAsRead

Marks the notification as read and updates the database.

<table><thead><tr><th width="156">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>readDate</td><td><code>date</code></td><td>false</td><td><code>now()</code></td><td>The date to use when marking the notification as read.</td></tr></tbody></table>

**Return**: This `DatabaseNotification` instance.

### markAsRead

Deletes the notification from the database.

<table><thead><tr><th width="156">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: This `DatabaseNotification` instance.

### getMemento

Returns a serializable representation of this `DatabaseNotification`.

```cfscript
{
    "id": getId(),
    "type": getType(),
    "notifiableType": getNotifiableType(),
    "notifiableId": getNotifiableId(),
    "data": getData(),
    "readDate": getReadDate(),
    "createdDate": getCreatedDate()
}
```

<table><thead><tr><th width="156">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: (`struct`) The memento of this `DatabaseNotification` instance.

### populateFromDatabaseRow

Returns the Channel instance the notification belongs to.

This method also handles deserializing the `data` property from JSON.

<table><thead><tr><th width="156">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>properties</td><td><code>struct</code></td><td>true</td><td></td><td>The properties to set for this <code>DatabaseNotification</code> instance.</td></tr></tbody></table>

**Return**: This `DatabaseNotification` instance.

## Accessors

### getChannel

Returns the Channel instance the notification belongs to.

<table><thead><tr><th width="191">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: (`BaseProvider`) The Channel instance.

### getId

Returns the id in the database of this notification.

<table><thead><tr><th width="180">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: (`string`) The `DatabaseNotification` id.

### getType

Returns the Notification Type of the Notification. Populated in the database from calling [`Notification#getNotificationType`](/reference/basenotification#getnotificationtype) which defaults to the [WireBox id](https://wirebox.ortusbooks.com/usage/injection-dsl/wirebox-namespace#id-2nd-level-dsl) of the notification.

<table><thead><tr><th width="180">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: (`string`) The Notification Type of the `DatabaseNotification`.

### getNotifiableType

Returns the stored Notifiable type of the Notification. Populated in the database from calling [`INotifiable#getNotifiableType`](/reference/inotifiable#getnotifiabletype) when storing the notification.

<table><thead><tr><th width="180">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: (`string`) The Notifiable type of the `DatabaseNotification`.

### getNotifiableId

Returns the stored Notifiable id of the Notification. Populated in the database from calling [`INotifiable#getNotifiableId`](/reference/inotifiable#getnotifiableid) when storing the notification.

<table><thead><tr><th width="178">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: (`string`) The Notifiable id of the `DatabaseNotification`.

### getData

Returns the data sent for the notification. Populated in the database from calling [`toDatabase`](/providers/databaseprovider#todatabase) on the Notification instance when storing the notification.

<table><thead><tr><th width="174">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: (`struct`) The data of the `DatabaseNotification`.

### getReadDate

Returns the read date of the notification.  Returns an empty string if the notification hasn't been read.

<table><thead><tr><th width="180">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: (`date`) The read date of the `DatabaseNotification`.

### getCreatedDate

Returns the created date of the notification.

<table><thead><tr><th width="180">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: (`date`) The created date of the `DatabaseNotification`.

{% hint style="danger" %}
The setters of this component should be considered `private`.
{% endhint %}

### setChannel

Sets the Channel instance the notification belongs to.

<table><thead><tr><th width="180">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>channel</td><td><code>BaseProvider</code></td><td>true</td><td></td><td>The Channel instance the notification belongs to.</td></tr></tbody></table>

**Return**: This `DatabaseNotification` instance.

### setId

Sets the id of the `DatabaseNotification`.

<table><thead><tr><th width="180">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>id</td><td><code>string</code></td><td>true</td><td></td><td>The id of the <code>DatabaseNotification</code>.</td></tr></tbody></table>

**Return**: This `DatabaseNotification` instance.

### setType

Sets the type of the `DatabaseNotification`.

<table><thead><tr><th width="180">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>type</td><td><code>string</code></td><td>true</td><td></td><td>The type of the <code>DatabaseNotification</code>.</td></tr></tbody></table>

**Return**: This `DatabaseNotification` instance.

### setNotifiableType

Sets the Notifiable type of the `DatabaseNotification`.

<table><thead><tr><th width="180">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>notifiableType</td><td><code>string</code></td><td>true</td><td></td><td>The Notifiable type of the <code>DatabaseNotification</code>.</td></tr></tbody></table>

**Return**: This `DatabaseNotification` instance.

### setNotifiableId

Sets the Notifiable id of the `DatabaseNotification`.

<table><thead><tr><th width="180">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>notifiableId</td><td><code>string</code></td><td>true</td><td></td><td>The Notifiable id of the <code>DatabaseNotification</code>.</td></tr></tbody></table>

**Return**: This `DatabaseNotification` instance.

### setData

Sets the data of the `DatabaseNotification`.

<table><thead><tr><th width="180">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>data</td><td><code>struct</code></td><td>true</td><td></td><td>The data of the <code>DatabaseNotification</code>.</td></tr></tbody></table>

**Return**: This `DatabaseNotification` instance.

### setReadDate

Sets the read date of the `DatabaseNotification`.

{% hint style="warning" %}
Consider using the `markAsRead` method instead of interacting with this setter directly as the `markAsRead` method will also update the database.
{% endhint %}

<table><thead><tr><th width="180">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>readDate</td><td><code>date</code></td><td>true</td><td></td><td>The read date of the <code>DatabaseNotification</code>.</td></tr></tbody></table>

**Return**: This `DatabaseNotification` instance.

### setReadDate

Sets the created date of the `DatabaseNotification`.

<table><thead><tr><th width="180">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>createdDate</td><td><code>date</code></td><td>true</td><td></td><td>The created date of the <code>DatabaseNotification</code>.</td></tr></tbody></table>

**Return**: This `DatabaseNotification` instance.


# EmailProvider

See the `BaseProvider` for inherited methods.

{% content-ref url="/pages/6x7oBEQ8jyfTIxZgj3j2" %}
[BaseProvider](/reference/baseprovider)
{% endcontent-ref %}

### getMailService

Returns the `MailService@cbmailservices` singleton instance.

<table><thead><tr><th width="140">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: (`MailService`) The `MailService@cbmailservices` singleton instance.


# SlackProvider

See the `BaseProvider` for inherited methods.

{% content-ref url="/pages/6x7oBEQ8jyfTIxZgj3j2" %}
[BaseProvider](/reference/baseprovider)
{% endcontent-ref %}

### getClient

Returns the configured `HyperBuilder` instance.

<table><thead><tr><th width="140">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: (`HyperBuilder`) The configured `HyperBuilder` instance.


# SlackMessage

### to

Sets the channel, private group, or IM channel to send the message to.

{% hint style="info" %}
Slack Docs: <https://api.slack.com/methods/chat.postMessage#arg_channel>
{% endhint %}

<table><thead><tr><th width="140">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>channel</td><td><code>string</code></td><td>true</td><td></td><td>The channel, private group, or IM channel to send the message to.</td></tr></tbody></table>

**Return**: The `SlackMessage` instance.

### text

Sets the text of the message.

{% hint style="info" %}
Slack Docs: <https://api.slack.com/methods/chat.postMessage#arg_text>
{% endhint %}

<table><thead><tr><th width="139">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>text</td><td><code>string</code></td><td>true</td><td></td><td>The text of the message.</td></tr></tbody></table>

**Return**: The `SlackMessage` instance.

### actionsBlock

Creates and adds an [Actions Block](https://api.slack.com/reference/block-kit/blocks#actions) to the message's `blocks`. After creating the block, it will call the provided `callback` function to configure the Actions Block.

<table><thead><tr><th width="131">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>callback</td><td><code>function</code></td><td>true</td><td></td><td>The callback function to configure the created Actions Block.</td></tr></tbody></table>

**Return**: The `SlackMessage` instance.

{% content-ref url="/pages/2POR4Z9HyDtslUP78IiQ" %}
[ActionsBlock](/reference/baseprovider/slackprovider/slackmessage/actionsblock)
{% endcontent-ref %}

### contextBlock

Creates and adds a [Context Block](https://api.slack.com/reference/block-kit/blocks#context) to the message's `blocks`. After creating the block, it will call the provided `callback` function to configure the Context Block.

<table><thead><tr><th width="131">Name</th><th width="151">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>callback</td><td><code>function</code></td><td>true</td><td></td><td>The callback function to configure the created Context Block.</td></tr></tbody></table>

**Return**: The `SlackMessage` instance.

{% content-ref url="/pages/1EyQG5gKy2L4foBZFHJR" %}
[ContextBlock](/reference/baseprovider/slackprovider/slackmessage/contextblock)
{% endcontent-ref %}

### dividerBlock

Creates and adds a [Divider Block](https://api.slack.com/reference/block-kit/blocks#divider) to the message's `blocks`.

<table><thead><tr><th width="176">Name</th><th width="151">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: The `SlackMessage` instance.

{% content-ref url="/pages/yDoY8TJsjpsDt46HR4Ou" %}
[DividerBlock](/reference/baseprovider/slackprovider/slackmessage/dividerblock)
{% endcontent-ref %}

### headerBlock

Creates and adds a [Header Block](https://api.slack.com/reference/block-kit/blocks#header) to the message's `blocks` with the passed-in `text`. If a `callback` function is provided, it is called to configure the Header Block.

<table><thead><tr><th width="131">Name</th><th width="151">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>text</td><td><code>string</code></td><td>true</td><td></td><td>The text for the header.</td></tr><tr><td>callback</td><td><code>function</code></td><td>false</td><td><code>null</code></td><td>The callback function to configure the created Header Block.</td></tr></tbody></table>

**Return**: The `SlackMessage` instance.

{% content-ref url="/pages/6RjMh2Plo8UwxUfPPEZU" %}
[HeaderBlock](/reference/baseprovider/slackprovider/slackmessage/headerblock)
{% endcontent-ref %}

### imageBlock

Creates and adds an [Image Block](https://api.slack.com/reference/block-kit/blocks#image) to the message's `blocks` with the passed-in `imageUrl`.

If `altText` is not provided when constructing the Image Block, it must be provided in the `callback`.&#x20;

If a `callback` function is provided, it is called to configure the Image Block.

<table><thead><tr><th width="131">Name</th><th width="151">Type</th><th width="113">Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>imageUrl</td><td><code>string</code></td><td>true</td><td></td><td>The url for the image of the block.</td></tr><tr><td>altText</td><td><code>string</code></td><td>false</td><td><code>""</code> (empty string)</td><td>The alt text for the image.  If no alt text is provided, it must be configured in the <code>callback</code>.</td></tr><tr><td>callback</td><td><code>function</code></td><td>false</td><td><code>null</code></td><td>The callback function to configure the created Image Block.</td></tr></tbody></table>

**Return**: The `SlackMessage` instance.

{% content-ref url="/pages/yEMRhYe6oTLq5hRW8H2B" %}
[ImageBlock](/reference/baseprovider/slackprovider/slackmessage/imageblock)
{% endcontent-ref %}

### sectionBlock

Creates and adds a Section Block to the message's `blocks`.

The provided `callback` function is called to configure the Section Block.

<table><thead><tr><th width="131">Name</th><th width="151">Type</th><th width="113">Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>callback</td><td><code>function</code></td><td>true</td><td></td><td>The callback function to configure the created Section Block.</td></tr></tbody></table>

**Return**: The `SlackMessage` instance.

{% content-ref url="/pages/r0WcQMMPCar1J1UwACEi" %}
[SectionBlock](/reference/baseprovider/slackprovider/slackmessage/sectionblock)
{% endcontent-ref %}

### emoji

Sets the icon of the Slack Message to be the provided emoji.

<table><thead><tr><th width="131">Name</th><th width="151">Type</th><th width="113">Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>icon</td><td><code>string</code></td><td>true</td><td></td><td>The emoji code to set as the icon, e.g. <code>:chart_with_upwards_trend:</code></td></tr></tbody></table>

**Return**: The `SlackMessage` instance.

### image

Sets the icon of the Slack Message to be the provided image URL.

<table><thead><tr><th width="164">Name</th><th width="151">Type</th><th width="113">Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>image</td><td><code>string</code></td><td>true</td><td></td><td>The image URL to set as the icon.</td></tr></tbody></table>

**Return**: The `SlackMessage` instance.

### metadata

Add metadata for the given event type.

<table><thead><tr><th width="131">Name</th><th width="151">Type</th><th width="113">Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>eventType</td><td><code>string</code></td><td>true</td><td></td><td>The event type to track metadata for.</td></tr><tr><td>payload</td><td><code>struct</code></td><td>false</td><td><code>{}</code></td><td>The metadata to track.</td></tr></tbody></table>

**Return**: The `SlackMessage` instance.

{% content-ref url="/pages/IdKE0xEHxZh1ujim5V9O" %}
[EventMetadata](/reference/baseprovider/slackprovider/slackmessage/eventmetadata)
{% endcontent-ref %}

### disableMarkdownParsing

Disables markdown parsing of the Slack Message text.

<table><thead><tr><th width="131">Name</th><th width="151">Type</th><th width="113">Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: The `SlackMessage` instance.

### unfurlLinks

Pass `true` to enable unfurling of primarily text-based content.

<table><thead><tr><th width="145">Name</th><th width="151">Type</th><th width="113">Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>unfurlLinks</td><td><code>boolean</code></td><td>false</td><td><code>true</code></td><td>Boolean flag to unfurl links or not.</td></tr></tbody></table>

**Return**: The `SlackMessage` instance.

### unfurlMedia

Pass `true` to enable unfurling of media content.

<table><thead><tr><th width="138">Name</th><th width="151">Type</th><th width="113">Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>unfurlMedia</td><td><code>boolean</code></td><td>false</td><td><code>true</code></td><td>Boolean flag to unfurl media or not.</td></tr></tbody></table>

**Return**: The `SlackMessage` instance.

### username

Sets the username for the Slack Bot.

<table><thead><tr><th width="138">Name</th><th width="151">Type</th><th width="113">Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>username</td><td><code>string</code></td><td>true</td><td></td><td>The username to use for the Slack Bot.</td></tr></tbody></table>

**Return**: The `SlackMessage` instance.

### getMemento

Returns a serializable representation of this Slack Message.

<table><thead><tr><th width="176">Name</th><th width="151">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: (`struct`) The serializable Slack Message

{% hint style="danger" %}
**Throws:** `Megaphone.Provider.SlackBlockException`
{% endhint %}

### dump

Sends either the memento or a link to the Slack's [BlockKit Builder](https://app.slack.com/block-kit-builder/) to `writeDump`.

<table><thead><tr><th width="176">Name</th><th width="151">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>raw</td><td><code>boolean</code></td><td>false</td><td><code>false</code></td><td>If true, outputs the memento of the message.  Otherwise, outputs a URL to Slack's <a href="https://app.slack.com/block-kit-builder/TBHQJRCEN">BlockKit Builder</a>.</td></tr></tbody></table>

{% hint style="info" %}
This method also accepts all the same arguments as [`writeDump`](https://cfdocs.org/writedump).
{% endhint %}

**Return**: (`void`)&#x20;

### when

Control-flow helper to have `if` / `else` statements with method chaining.

<table><thead><tr><th width="176">Name</th><th width="151">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>target</td><td><code>boolean</code></td><td>true</td><td></td><td>The boolean evaluator.</td></tr><tr><td>success</td><td><code>function</code></td><td>true</td><td></td><td>The callback to execute if the boolean value is <code>true</code>.</td></tr><tr><td>failure</td><td><code>function</code></td><td>false</td><td><code>null</code></td><td>The optional callback to execute if the boolean value is <code>false</code>.</td></tr></tbody></table>

**Return**: The `SlackMessage` instance.


# EventMetadata

### init

Creates an `EventMetadata` instance for the given event type and payload.

{% hint style="info" %}
Slack Docs: <https://api.slack.com/metadata/using>
{% endhint %}

<table><thead><tr><th width="140">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>type</td><td><code>string</code></td><td>true</td><td></td><td>The event type to track metadata for.</td></tr><tr><td>payload</td><td><code>struct</code></td><td>false</td><td><code>{}</code></td><td>The metadata to track.</td></tr></tbody></table>

**Return**: The `EventMetadata` instance.

### getMemento

Converts the `EventMetadata` instance to a serializable format.

<table><thead><tr><th width="181">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: (`struct`) A struct representing this `EventMetadata` instance.

```cfscript
{
    "event_type": "type",
    "event_payload": { ... } 
}
```


# ActionsBlock

### init

Creates an `ActionsBlock` instance for the given event type and payload.

{% hint style="info" %}
Slack Docs: <https://api.slack.com/reference/block-kit/blocks#actions>
{% endhint %}

<table><thead><tr><th width="164">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: The `ActionsBlock` instance.

### id

Sets a custom identifier for the `ActionsBlock` instance.

<table><thead><tr><th width="164">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>id</td><td><code>string</code></td><td>true</td><td></td><td>The custom identifier for the <code>ActionsBlock</code> instance.</td></tr></tbody></table>

**Return**: The `ActionsBlock` instance.

### button

Adds a `ButtonElement` to this `ActionsBlock` instance.

{% content-ref url="/pages/lG6g0DgoLmwk599dj2qV" %}
[ButtonElement](/reference/baseprovider/slackprovider/slackmessage/buttonelement)
{% endcontent-ref %}

<table><thead><tr><th width="164">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>text</td><td><code>string</code></td><td>true</td><td></td><td>The text of the new button element.</td></tr></tbody></table>

**Return**: The new `ButtonElement` instance.

{% hint style="danger" %}
**Throws:** `Megaphone.Provider.SlackBlockException` when more than 25 elements are added.
{% endhint %}

### getMemento

Converts the `ActionsBlock` instance to a serializable format.

<table><thead><tr><th width="181">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: (`struct`) A struct representing this `ActionsBlock` instance.

{% hint style="danger" %}
**Throws:** `Megaphone.Provider.SlackBlockException` when either 0 or more than 25 elements are present.
{% endhint %}

```cfscript
{
    "type": "actions"
    "elements": [ ... ],
    "block_id": "optional"
}
```


# ContextBlock

### init

Creates an `ContextBlock` instance.

{% hint style="info" %}
Slack Docs: <https://api.slack.com/reference/block-kit/blocks#context>
{% endhint %}

<table><thead><tr><th width="164">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: The `ContextBlock` instance.

### id

Sets a custom identifier for the `ContextBlock` instance.

<table><thead><tr><th width="151">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>id</td><td><code>string</code></td><td>true</td><td></td><td>The custom identifier for the <code>ActionsBlock</code> instance.</td></tr></tbody></table>

**Return**: The `ContextBlock` instance.

### image

Adds an `ImageElement` to this `ContextBlock` instance.

{% content-ref url="/pages/MniWnBWSl009UuTe0ze3" %}
[ImageElement](/reference/baseprovider/slackprovider/slackmessage/imageelement)
{% endcontent-ref %}

<table><thead><tr><th width="164">Name</th><th width="149">Type</th><th width="94">Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>imageUrl</td><td><code>string</code></td><td>true</td><td></td><td>The url for the image.</td></tr><tr><td>altText</td><td><code>string</code></td><td>false</td><td><code>""</code> (empty string)</td><td>The alt text for the image.</td></tr></tbody></table>

**Return**: The new `ImageElement` instance.

{% hint style="danger" %}
**Throws:** `Megaphone.Provider.SlackBlockException` when more than 25 elements are added.
{% endhint %}

### text

Adds a `TextObject` to this `ContextBlock` instance.

{% content-ref url="/pages/8nFSQtmXEIhi6IneZJ3r" %}
[TextObject](/reference/baseprovider/slackprovider/slackmessage/textobject)
{% endcontent-ref %}

<table><thead><tr><th width="164">Name</th><th width="149">Type</th><th width="94">Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>text</td><td><code>string</code></td><td>true</td><td></td><td>The text for the <code>TextObject</code>.</td></tr></tbody></table>

**Return**: The new `TextObject` instance.

{% hint style="danger" %}
**Throws:** `Megaphone.Provider.SlackBlockException` when more than 25 elements are added.
{% endhint %}

### getMemento

Converts the `ContextBlock` instance to a serializable format.

<table><thead><tr><th width="181">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: (`struct`) A struct representing this `ContextBlock` instance.

{% hint style="danger" %}
**Throws:** `Megaphone.Provider.SlackBlockException` when either 0 or more than 25 elements are present.
{% endhint %}

```cfscript
{
    "type": "context"
    "elements": [ ... ],
    "block_id": "optional"
}
```


# DividerBlock

### init

Creates an `DividerBlock` instance.

{% hint style="info" %}
Slack Docs: <https://api.slack.com/reference/block-kit/blocks#divider>
{% endhint %}

<table><thead><tr><th width="164">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: The `DividerBlock` instance.

### id

Sets a custom identifier for the `DividerBlock` instance.

<table><thead><tr><th width="104">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>id</td><td><code>string</code></td><td>true</td><td></td><td>The custom identifier for the <code>DividerBlock</code> instance.</td></tr></tbody></table>

**Return**: The `DividerBlock` instance.

### getMemento

Converts the `DividerBlock` instance to a serializable format.

<table><thead><tr><th width="181">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: (`struct`) A struct representing this `DividerBlock` instance.

```cfscript
{
    "type": "divider"
    "block_id": "optional"
}
```


# HeaderBlock

### init

Creates an `HeaderBlock` instance.

{% hint style="info" %}
Slack Docs: <https://api.slack.com/reference/block-kit/blocks#header>
{% endhint %}

<table><thead><tr><th width="164">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>text</td><td><code>string</code></td><td>true</td><td></td><td>The text of the header. Maximum length of 150 characters.</td></tr><tr><td>callback</td><td><code>function</code></td><td>false</td><td><code>null</code></td><td>An optional callback to configure the new <code>HeaderBlock</code>.</td></tr></tbody></table>

**Return**: The `HeaderBlock` instance.

### id

Sets a custom identifier for the `HeaderBlock` instance.

<table><thead><tr><th width="104">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>id</td><td><code>string</code></td><td>true</td><td></td><td>The custom identifier for the <code>HeaderBlock</code> instance.</td></tr></tbody></table>

**Return**: The `HeaderBlock` instance.

### getMemento

Converts the `HeaderBlock` instance to a serializable format.

<table><thead><tr><th width="181">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: (`struct`) A struct representing this `HeaderBlock` instance.

```cfscript
{
    "type": "header",
    "text": {
        "type": "plain_text",
        "text": "My Header"
    },
    "block_id": "optional"
}
```


# ImageBlock

### init

Creates an `ImageBlock` instance.

{% hint style="info" %}
Slack Docs: <https://api.slack.com/reference/block-kit/blocks#image>
{% endhint %}

<table><thead><tr><th width="164">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>imageUrl</td><td><code>string</code></td><td>true</td><td></td><td>The url for the image.  Maximum of 3000 characters.</td></tr><tr><td>altText</td><td><code>string</code></td><td>false</td><td><code>""</code> (empty string)</td><td>The alt text for the <code>ImageBlock</code>.  If no alt text is provided here, it must be configured using the <code>alt</code> method before serializing.</td></tr></tbody></table>

**Return**: The `ImageBlock` instance.

### id

Sets a custom identifier for the `ImageBlock` instance.

<table><thead><tr><th width="104">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>id</td><td><code>string</code></td><td>true</td><td></td><td>The custom identifier for the <code>ImageBlock</code> instance.</td></tr></tbody></table>

**Return**: The `ImageBlock` instance.

### alt

Sets the alt text for the `ImageBlock` instance.

<table><thead><tr><th width="104">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>altText</td><td><code>string</code></td><td>true</td><td></td><td>The alt text for the image. Maximum of 2000 characters.</td></tr></tbody></table>

**Return**: The `ImageBlock` instance.

### title

Sets the title for the `ImageBlock` instance.

<table><thead><tr><th width="104">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>title</td><td><code>string</code></td><td>true</td><td></td><td>The title for the image. Maximum of 2000 characters.</td></tr></tbody></table>

**Return**: The `ImageBlock` instance.

### getMemento

Converts the `ImageBlock` instance to a serializable format.

<table><thead><tr><th width="181">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: (`struct`) A struct representing this `ImageBlock` instance.

```cfscript
{
    "type": "image",
    "image_url": "https://placekitten.com/200/300",
    "alt_text": "A cute kitten",
    "block_id": "optional"
    "text": {
        "type": "plain_text",
        "text": "My Title"
    },
}
```


# SectionBlock

### init

Creates an `SectionBlock` instance.

{% hint style="info" %}
Slack Docs: <https://api.slack.com/reference/block-kit/blocks#section>
{% endhint %}

<table><thead><tr><th width="164">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: The `SectionBlock` instance.

### id

Sets a custom identifier for the `SectionBlock` instance.

<table><thead><tr><th width="104">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>id</td><td><code>string</code></td><td>true</td><td></td><td>The custom identifier for the <code>SectionBlock</code> instance.</td></tr></tbody></table>

**Return**: The `SectionBlock` instance.

### text

Sets the text for the `SectionBlock` instance.

<table><thead><tr><th width="104">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>text</td><td><code>string</code></td><td>true</td><td></td><td>The text for the section. Maximum of 3000 characters.</td></tr></tbody></table>

**Return**: The `SectionBlock` instance.

### field

Adds a text field to the `SectionBlock` instance.

<table><thead><tr><th width="104">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>text</td><td><code>string</code></td><td>true</td><td></td><td>The text for the new text field. Maximum of 2000 characters.</td></tr></tbody></table>

**Return**: The `TextObject` added to the `SectionBlock` instance.

### accessory

Sets the accessory for the `SectionBlock` instance.

<table><thead><tr><th width="104">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>element</td><td><code>BlockKitElement</code></td><td>true</td><td></td><td>The Slack BlockKit element to set as the accessory for this <code>SectionBlock</code> instance.</td></tr></tbody></table>

**Return**: The `SectionBlock` instance.

### getMemento

Converts the `SectionBlock` instance to a serializable format.

<table><thead><tr><th width="181">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: (`struct`) A struct representing this `SectionBlock` instance.

```cfscript
{
    "type": "section",
    "text": {
        "type": "text",
        "text": "optional, either this or fields must be set"
    },
    "fields": [ ... ],
    "accessory": { ... },
    "block_id": "optional"
}
```


# ButtonElement

### init

Creates a `ButtonElement` instance.

{% hint style="info" %}
Slack Docs: <https://api.slack.com/reference/block-kit/block-elements#button>
{% endhint %}

<table><thead><tr><th width="164">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>text</td><td><code>string</code></td><td>true</td><td></td><td>The text for the button. Maximum length of 75.</td></tr><tr><td>callback</td><td><code>function</code></td><td>false</td><td><code>null</code></td><td>A callback function to configure the <code>ButtonElement</code>.</td></tr></tbody></table>

**Return**: The `ButtonElement` instance.

### url

Sets the link URL for the `ButtonElement` instance.

<table><thead><tr><th width="104">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>linkUrl</td><td><code>string</code></td><td>true</td><td></td><td>The link URL for the button instance. Maximum length of 3000 characters.</td></tr></tbody></table>

**Return**: The `ButtonElement` instance.

### id

Sets a custom identifier for the `ButtonElement` instance.

<table><thead><tr><th width="104">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>id</td><td><code>string</code></td><td>true</td><td></td><td>The custom identifier for the <code>ButtonElement</code> instance. Maximum of 255 characters.</td></tr></tbody></table>

**Return**: The `ButtonElement` instance.

### value

Sets the value for the `ButtonElement` instance.

<table><thead><tr><th width="104">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>value</td><td><code>string</code></td><td>true</td><td></td><td>The value for the <code>ButtonElement</code> instance.  Maximum of 2000 characters.</td></tr></tbody></table>

**Return**: The `ButtonElement` instance.

### primary

Sets the style of the `ButtonElement` to `primary`.

<table><thead><tr><th width="173">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: The `ButtonElement` instance.

### danger

Sets the style of the `ButtonElement` to `danger`.

<table><thead><tr><th width="173">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: The `ButtonElement` instance.

### confirm

Sets the confirm object for the `ButtonElement` instance.

<table><thead><tr><th width="104">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>text</td><td><code>string</code></td><td>true</td><td></td><td>The text of the confirm object.</td></tr><tr><td>callback</td><td><code>function</code></td><td>false</td><td></td><td>A callback function to configure the confirm object.</td></tr></tbody></table>

**Return**: The newly created `ConfirmObject` instance.

### accessibilityLabel

Sets the accessibility label for the button.

<table><thead><tr><th width="102">Name</th><th width="128">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>label</td><td><code>string</code></td><td>true</td><td></td><td>The accessibility label for the button.  Maximum length of 75 characters.</td></tr></tbody></table>

**Return**: The `ButtonElement` instance.

### getMemento

Converts the `ButtonElement` instance to a serializable format.

<table><thead><tr><th width="181">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: (`struct`) A struct representing this `ButtonElement` instance.

```cfscript
{
    "type": "button",
    "text": {
        "type": "plain_text",
        "text": "Click me"
    },
    "action_id": "button_click-me",
    "style": "optional, primary or danger",
    "confirm": {
        "title": {
            "type": "plain_text",
            "text": "Are you sure?"
        },
        "text": {
            "type": "plain_text",
            "text": "This will do some thing."
        },
        "confirm": {
            "type": "plain_text",
            "text": "Yes"
        },
        "deny": {
            "type": "plain_text",
            "text": "No"
        }
    },
    "accessibility_label": "optional, Button to do some thing"
}
```


# ConfirmObject

### init

Creates a `ConfirmObject` instance.

{% hint style="info" %}
Slack Docs: <https://api.slack.com/reference/block-kit/composition-objects#confirm>
{% endhint %}

<table><thead><tr><th width="164">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>text</td><td><code>string</code></td><td>true</td><td></td><td>The text for the confirm object.</td></tr></tbody></table>

**Return**: The `ConfirmObject` instance.

### title

Sets the title for the `ConfirmObject` instance.

<table><thead><tr><th width="104">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>title</td><td><code>string</code></td><td>true</td><td></td><td>The title for the <code>ConfirmObject</code>. Maximum character limit of 100.</td></tr></tbody></table>

**Return**: The `ConfirmObject` instance.

### text

Sets the text for the `ConfirmObject` instance.

<table><thead><tr><th width="104">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>text</td><td><code>string</code></td><td>true</td><td></td><td>The text for the <code>ConfirmObject</code>. Maximum character limit of 300.</td></tr></tbody></table>

**Return**: The `ConfirmObject` instance.

### confirm

Sets the confirm button label for the `ConfirmObject` instance.

<table><thead><tr><th width="104">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>label</td><td><code>string</code></td><td>true</td><td></td><td>The confirm button label for the <code>ConfirmObject</code>. Maximum character limit of 30.</td></tr></tbody></table>

**Return**: The `ConfirmObject` instance.

### deny

Sets the deny button label for the `ConfirmObject` instance.

<table><thead><tr><th width="104">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>label</td><td><code>string</code></td><td>true</td><td></td><td>The deny button label for the <code>ConfirmObject</code>. Maximum character limit of 30.</td></tr></tbody></table>

**Return**: The `ConfirmObject` instance.

### danger

Marks the `ConfirmObject` as dangerous.

<table><thead><tr><th width="104">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: The `ConfirmObject` instance.

### getMemento

Converts the `ConfirmObject` instance to a serializable format.

<table><thead><tr><th width="181">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: (`struct`) A struct representing this `ConfirmObject` instance.

```cfscript
{
    "title": {
        "type": "plain_text",
        "text": "Are you sure?"
    },
    "text": {
        "type": "plain_text",
        "text": "Please confirm this action."
    },
    "confirm": {
        "type": "plain_text",
        "text": "Yes"
    },
    "deny": {
        "type": "plain_text",
        "text": "No"
    },
    "style": "optional, danger"
}
```


# ImageElement

### init

Creates an `ImageElement` instance.

{% hint style="info" %}
Slack Docs: <https://api.slack.com/reference/block-kit/block-elements#image>
{% endhint %}

<table><thead><tr><th width="164">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>imageUrl</td><td><code>string</code></td><td>true</td><td></td><td>The url for the image.</td></tr><tr><td>altText</td><td><code>string</code></td><td>false</td><td><code>""</code> (empty string)</td><td>The alt text for the image.  If alt text is not provided in the constructor, it must be provided using the <code>alt</code> method before serializing.</td></tr></tbody></table>

**Return**: The `ImageElement` instance.

### alt

Sets the alt text for the `ImageElement` instance.

<table><thead><tr><th width="104">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>altText</td><td><code>string</code></td><td>true</td><td></td><td>The alt text for the <code>ImageElement</code>.</td></tr></tbody></table>

**Return**: The `ImageElement` instance.

### getMemento

Converts the `ImageElement` instance to a serializable format.

<table><thead><tr><th width="181">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: (`struct`) A struct representing this `ImageElement` instance.

```cfscript
{
    "type": "image",
    "image_url": "https://placekitten.com/200/300",
    "alt_text": "A cute kitten"
}
```


# TextObject

**Inherits from `PlainTextOnlyTextObject`**

{% content-ref url="/pages/XponDgB2h3D93mdKkUaF" %}
[PlainTextOnlyTextObject](/reference/baseprovider/slackprovider/slackmessage/plaintextonlytextobject)
{% endcontent-ref %}

### markdown

Sets the type for this `TextObject` to markdown.

<table><thead><tr><th width="104">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: The `TextObject` instance.

### verbatim

Indicate that URLs, conversation names and certain mentions should not be auto-linked. Only applicable for [markdown](#markdown) text objects.

<table><thead><tr><th width="104">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: The `TextObject` instance.


# PlainTextOnlyTextObject

### init

Creates a `PlainTextOnlyTextObject` instance.

<table><thead><tr><th width="164">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>text</td><td><code>string</code></td><td>true</td><td></td><td>The text to display.</td></tr><tr><td>maxLength</td><td><code>numeric</code></td><td>false</td><td><code>3000</code></td><td>The maximum length for the text object. Text over the maximum length will be truncated at the maximum length with <code>...</code> added at the end.</td></tr><tr><td>minLength</td><td><code>numeric</code></td><td>false</td><td><code>1</code></td><td>The minimum length for the text object.</td></tr></tbody></table>

**Return**: The `PlainTextOnlyTextObject` instance.

### emoji

Sets the `PlainTextOnlyTextObject` to interpret emoji in the text field.

<table><thead><tr><th width="104">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: The `PlainTextOnlyTextObject` instance.

### getMemento

Converts the `PlainTextOnlyTextObject` instance to a serializable format.

<table><thead><tr><th width="181">Name</th><th width="229">Type</th><th>Required</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>No arguments</td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Return**: (`struct`) A struct representing this `PlainTextOnlyTextObject` instance.

```cfscript
{
    "type": "plain_text",
    "text": "Some text here :tada:",
    "emoji": true
}
```


