Skip to content

Repository files navigation

Doc Go Release Test Report Card Codecov License

A Slack notification channel for Goravel's notification module, using the Slack Web API (chat.postMessage + a bot token) instead of Incoming Webhooks — so RouteNotificationFor("slack") can return a channel name like #general or a user ID for a DM, rather than being locked to whichever single channel an Incoming Webhook was created for.

Version

Not yet tagged

Install

Run the command below in your project to install the package automatically:

./artisan package:install github.com/goravel/slack

Or check the setup file to install the package manually.

Configuration

./artisan package:install github.com/goravel/slack generates config/slack.go in your app automatically — no separate publish step needed. Set your bot token in .env:

SLACK_BOT_TOKEN=xoxb-your-token-here

Create a bot at api.slack.com/apps with the chat:write scope, then invite it to any channel it needs to post in — a bot can only post to channels it's been added to.

The generated config (import path varies per app — this is what goravel/goravel's default skeleton generates; your app's own app/facades package, not github.com/goravel/framework/facades directly, since the template substitutes whatever your app's own facades package path actually is):

package config

import (
	"goravel/app/facades"
)

func init() {
	config := facades.Config()

	config.Add("slack", map[string]any{
		"token": config.Env("SLACK_BOT_TOKEN", ""),
	})
}

Usage

Implement contracts.Notification on any notification and add "slack" to its Via() list:

package notifications

import (
	"github.com/goravel/framework/contracts/notification"
	"github.com/goravel/slack/contracts"
)

type InvoicePaid struct {
	Invoice *models.Invoice
}

func (n *InvoicePaid) Via(notifiable notification.Notifiable) []string {
	return []string{contracts.ChannelName}
}

func (n *InvoicePaid) ToSlack(notifiable notification.Notifiable) contracts.Message {
	return contracts.Message{
		Text: "Invoice #" + n.Invoice.Number + " was paid.",
		Attachments: []contracts.Attachment{
			{
				Color: "good",
				Fields: []contracts.Field{
					{Title: "Amount", Value: n.Invoice.Amount, Short: true},
					{Title: "Customer", Value: n.Invoice.CustomerName, Short: true},
				},
			},
		},
	}
}

Route to a channel or user by implementing contracts.Routable on your notifiable model — preferred over the generic RouteNotificationFor, since a typo'd channel name string can't silently drop the route:

func (u *User) RouteNotificationForSlack(notification notification.Notification) string {
	return "#billing" // or a user ID for a DM, e.g. "U0123ABC456"
}

An empty result from RouteNotificationForSlack isn't itself an error — it falls back to the generic RouteNotificationFor, using contracts.ChannelName instead of a raw "slack" string so a typo is a compile error, not a silently dropped notification:

func (u *User) RouteNotificationFor(channel string) any {
	if channel == contracts.ChannelName {
		return "#billing"
	}
	return nil
}

A notification that doesn't implement contracts.Notification still gets a minimal default message (its Go type name) if "slack" is in Via() — useful for quick alerts without writing a ToSlack method.

On-demand notifications

import "github.com/goravel/slack/contracts"

facades.Notification().
	Route(contracts.ChannelName, "#alerts").
	Notify(&DeploymentFinished{})

Testing

slack.NewChannel takes slack-go/slack's own variadic Options — use OptionAPIURL to point requests at an httptest.Server instead of hitting the real Slack API:

mux := http.NewServeMux()
mux.HandleFunc("/chat.postMessage", func(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte(`{"ok": true}`))
})
server := httptest.NewServer(mux)
defer server.Close()

ch := slack.NewChannel("xoxb-test", slackgo.OptionAPIURL(server.URL+"/"))

Need a custom *http.Client instead (a shared connection pool, a proxy, request logging)? Pass slackgo.OptionHTTPClient(yourClient) the same way — there's no separate parameter for it, just another Option.

Why slack-go/slack instead of a hand-rolled HTTP client?

It's the de facto standard, actively maintained Go Slack SDK, and it already handles Slack's biggest testing gotcha for you: Slack's Web API returns HTTP 200 even when a request fails — the real success/failure signal is the "ok" boolean in the JSON response body, not the status code. slack-go/slack's PostMessage surfaces that as a normal Go error automatically, so this package doesn't do any manual status-code or response-body parsing itself.

Why not Incoming Webhooks?

Slack's older Incoming Webhooks mechanism binds one webhook URL to one fixed channel, decided when the webhook is created — there's no way to pick a different channel per notification. The Web API's chat.postMessage takes the target channel as a request parameter instead, so a single bot token can post anywhere it's been invited, and RouteNotificationFor can vary per notifiable the same way the mail and database channels do.

License

The Goravel Slack package is open-sourced software licensed under the MIT license.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages