Skip to content

Notify

Build Status Coverage Status Go Reference

This library provides ability to send notifications using multiple services:

  • Email
  • Telegram
  • Slack
  • Webhook

Install

go get -u github.com/go-pkgz/notify

Usage

All supported notification methods could adhere to the following interface. Example on how to use it:

package main

import (
    "context"
    "fmt"

    "github.com/go-pkgz/notify"
)

func main() {
    // create notifiers
    notifiers := []notify.Notifier{
        notify.NewWebhook(notify.WebhookParams{}),
        notify.NewEmail(notify.SMTPParams{}),
        notify.NewSlack("token"),
    }
    tg, err := notify.NewTelegram(notify.TelegramParams{Token: "token"})
    if err == nil {
        notifiers = append(notifiers, tg)
    }
    err = notify.Send(context.Background(), notifiers, "https://example.com/webhook", "Hello, world!")
    if err != nil {
        fmt.Printf("Sent message error: %s", err))
    }
}

Email

mailto: scheme is supported. Only subject and from query params are used.

Examples:

  • mailto:"John Wayne"<john@example.org>?subject=test-subj&from="Notifier"<notify@example.org>
  • mailto:addr1@example.org,addr2@example.org?&subject=test-subj&from=notify@example.org
package main

import (
    "context"
    "log"
    "time"

    "github.com/go-pkgz/notify"
)

func main() {
    wh := notify.NewEmail(notify.SMTPParams{
        Host:        "localhost", // the only required field, others are optional
        Port:        25,
        TLS:         false, // TLS, but not STARTTLS
        ContentType: "text/html",
        Charset:     "UTF-8",
        Username:    "username",
        Password:    "password",
        TimeOut:     time.Second * 10, // default is 30 seconds
    })
    err := wh.Send(
        context.Background(),
        `mailto:"John Wayne"<john@example.org>?subject=test-subj&from="Notifier"<notify@example.org>`,
        "Hello, World!",
    )
    if err != nil {
        log.Fatalf("problem sending message using email, %v", err)
    }
}

Telegram

telegram: scheme akin to mailto: is supported. Query params parseMode (doc, legacy Markdown by default, preferable use MarkdownV2 or HTML instead). Examples:

  • telegram:channel
  • telegram:channelID // channel ID is a number, like -1001480738202: use that instruction to obtain it
  • telegram:userID

Here is an instruction on obtaining token for your notification bot.

package main

import (
    "context"
    "log"
    "time"

    "github.com/go-pkgz/notify"
)

func main() {
    tg, err := notify.NewTelegram(notify.TelegramParams{
        Token:      "token",          // required
        Timeout:    time.Second * 10, // default is 5 seconds
        SuccessMsg: "Success",        // optional, for auth, set by default
        ErrorMsg:   "Error",          // optional, for auth, unset by default
    })
    if err != nil {
        log.Fatalf("problem creating telegram notifier, %v", err)
    }
    err = tg.Send(context.Background(), "telegram:-1001480738202", "Hello, World!")
    if err != nil {
        log.Fatalf("problem sending message using telegram, %v", err)
    }
}

HTML Formatting

parseMode HTML supports limited set of tags, so Telegram provides TelegramSupportedHTML method which strips all unsupported tags and replaces h1-h3 with <b> and h4-h6 with <i><b> to preserve formatting.

If you want to post text into HTML tag like text, you can use EscapeTelegramText method to escape it (by replacing symbols &, <, > with &amp;, &lt;, &gt;).

Authorisation

You can use Telegram notifications as described above, just to send messages. But also, you can use Telegram to authorise users as a login method or to sign them up for notifications. Functions used for processing updates from users are GetBotUsername, AddToken, CheckToken, Request, and Run or ProcessUpdate (only one of two can be used at a time).

Normal flow is following: 1. you run the Run goroutine 2. call AddToken and provide user with that token 3. user clicks on the link https://t.me/<BOT_USERNAME>/?start=<TOKEN> 4. you call CheckToken to verify that the user clicked the link, and if so you will receive user’s UserID

Alternative flow is the same, but instead of running the Run goroutine, you set up process update flow separately (to use with auth as well, for example) and run ProcessUpdate when update is received. Example of such a setup can be seen in Remark42.

Slack

slack: scheme akin to mailto: is supported. title, titleLink, attachmentText and query params are used: if they are defined, message would be sent with a text attachment. Examples:

  • slack:channel
  • slack:channelID
  • slack:userID
  • slack:channel?title=title&attachmentText=test%20text&titleLink=https://example.org
package main

import (
    "context"
    "log"

    "github.com/go-pkgz/notify"
    "github.com/slack-go/slack"
)

func main() {
    wh := notify.NewSlack(
        "token",
        slack.OptionDebug(true), // optional, you can pass any slack.Options
    )
    err := wh.Send(context.Background(), "slack:general", "Hello, World!")
    if err != nil {
        log.Fatalf("problem sending message using slack, %v", err)
    }
}

Webhook

http:// and https:// schemas are supported.

package main

import (
    "context"
    "log"
    "time"

    "github.com/go-pkgz/notify"
)

func main() {
    wh := notify.NewWebhook(notify.WebhookParams{
        Timeout: time.Second,                                          // optional, default is 5 seconds
        Headers: []string{"Content-Type:application/json,text/plain"}, // optional
    })
    err := wh.Send(context.Background(), "https://example.org/webhook", "Hello, World!")
    if err != nil {
        log.Fatalf("problem sending message using webhook, %v", err)
    }
}

Status

The library extracted from remark42 project. The original code in production use on multiple sites and seems to work fine.

go-pkgz/notify library still in development and until version 1 released some breaking changes possible.