slack package - github.com/goravel/slack - Go Packages

slack

package module
v0.0.0-...-3f42493 Latest Latest
Warning

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

Go to latest
Published: Aug 19, 2026 License: MIT Imports: 14 Imported by: 0

README

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.

Documentation

Index

Constants

View Source
const Module = "slack"

Module tags every error in this package for goravel/framework's error-module system.

Variables

View Source
var (
	ErrorEmptyRoute         = errors.New("slack channel: %T.RouteNotificationFor(\"slack\") returned empty channel/route").SetModule(Module)
	ErrorMarshalPayload     = errors.New("slack channel: failed to marshal payload for %T: %v").SetModule(Module)
	ErrorUnmarshalPayload   = errors.New("slack channel: failed to unmarshal payload: %v").SetModule(Module)
	ErrorPostMessageFailed  = errors.New("slack channel: chat.postMessage failed: %v").SetModule(Module)
	ErrorTokenNotConfigured = errors.New("slack channel: no bot token configured (set SLACK_BOT_TOKEN or slack.token)").SetModule(Module)
)

Named error constructors for this package, per goravel/framework's convention of declaring errors centrally rather than inline. %v is used throughout, not %w — this error type's Error() method uses fmt.Sprintf, which doesn't support %w.

Functions

This section is empty.

Types

type Channel

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

Channel delivers notifications to Slack via chat.postMessage.

func NewChannel

func NewChannel(token string, opts ...slack.Option) *Channel

func (*Channel) Deliver

func (c *Channel) Deliver(route string, payload []byte) error

func (*Channel) Name

func (c *Channel) Name() string

func (*Channel) Resolve

func (*Channel) Send

type ServiceProvider

type ServiceProvider struct{}

func (*ServiceProvider) Boot

func (r *ServiceProvider) Boot(app foundation.Application)

func (*ServiceProvider) Register

func (r *ServiceProvider) Register(app foundation.Application)

func (*ServiceProvider) Relationship

func (r *ServiceProvider) Relationship() binding.Relationship

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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