mirror of
https://github.com/nikoksr/notify.git
synced 2025-01-07 23:01:59 +02:00
Merge branch 'main' into main
This commit is contained in:
commit
541fdf294b
@ -86,6 +86,7 @@ Yes, please! Contributions of all kinds are very welcome! Feel free to check our
|
||||
| [Discord](https://discord.com) | [service/discord](service/discord) | [bwmarrin/discordgo](https://github.com/bwmarrin/discordgo) |
|
||||
| [Email](https://wikipedia.org/wiki/Email) | [service/mail](service/mail) | [jordan-wright/email](https://github.com/jordan-wright/email) |
|
||||
| [Firebase Cloud Messaging](https://firebase.google.com/docs/cloud-messaging) | [service/fcm](service/fcm) | [appleboy/go-fcm](https://github.com/appleboy/go-fcm) |
|
||||
| [Lark](https://www.larksuite.com/) | [service/lark](service/lark) | [go-lark/lark](https://github.com/go-lark/lark) |
|
||||
| [Line](https://line.me) | [service/line](service/line) | [line/line-bot-sdk-go](https://github.com/line/line-bot-sdk-go) |
|
||||
| [Line Notify](https://notify-bot.line.me) | [service/line](service/line) | [utahta/go-linenotify](https://github.com/utahta/go-linenotify) |
|
||||
| [Mailgun](https://www.mailgun.com) | [service/mailgun](service/mailgun) | [mailgun/mailgun-go](https://github.com/mailgun/mailgun-go) |
|
||||
@ -98,6 +99,7 @@ Yes, please! Contributions of all kinds are very welcome! Feel free to check our
|
||||
| [Syslog](https://wikipedia.org/wiki/Syslog) | [service/syslog](service/syslog) | [log/syslog](https://pkg.go.dev/log/syslog) |
|
||||
| [Telegram](https://telegram.org) | [service/telegram](service/telegram) | [go-telegram-bot-api/telegram-bot-api](https://github.com/go-telegram-bot-api/telegram-bot-api) |
|
||||
| [TextMagic](https://www.textmagic.com) | [service/textmagic](service/textmagic) | [textmagic/textmagic-rest-go-v2](https://github.com/textmagic/textmagic-rest-go-v2) |
|
||||
| [Twilio](https://www.twilio.com/) | [service/twilio](service/twilio) | [kevinburke/twilio-go](https://github.com/kevinburke/twilio-go) |
|
||||
| [Twitter](https://twitter.com) | [service/twitter](service/twitter) | [dghubble/go-twitter](https://github.com/dghubble/go-twitter) |
|
||||
| [WeChat](https://www.wechat.com) | [service/wechat](service/wechat) | [silenceper/wechat](https://github.com/silenceper/wechat) |
|
||||
| [WhatsApp](https://www.whatsapp.com) | [service/whatsapp](service/whatsapp) | [Rhymen/go-whatsapp](https://github.com/Rhymen/go-whatsapp) |
|
||||
|
8
go.mod
8
go.mod
@ -35,7 +35,9 @@ require (
|
||||
|
||||
require (
|
||||
github.com/appleboy/go-fcm v0.1.5
|
||||
github.com/go-lark/lark v1.7.2
|
||||
github.com/google/go-cmp v0.5.8
|
||||
github.com/kevinburke/twilio-go v0.0.0-20220615032439-b0fe9b151b0e
|
||||
)
|
||||
|
||||
require (
|
||||
@ -55,6 +57,7 @@ require (
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/fatih/structs v1.1.0 // indirect
|
||||
github.com/go-redis/redis/v8 v8.11.6-0.20220405070650-99c79f7041fc // indirect
|
||||
github.com/gofrs/uuid v4.2.0+incompatible // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
@ -62,6 +65,8 @@ require (
|
||||
github.com/gorilla/websocket v1.5.0 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/kevinburke/go-types v0.0.0-20210723172823-2deba1f80ba7 // indirect
|
||||
github.com/kevinburke/rest v0.0.0-20210506044642-5611499aa33c // indirect
|
||||
github.com/mattn/go-colorable v0.1.12 // indirect
|
||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
@ -76,10 +81,13 @@ require (
|
||||
github.com/tidwall/gjson v1.14.1 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.0 // indirect
|
||||
github.com/ttacon/builder v0.0.0-20170518171403-c099f663e1c2 // indirect
|
||||
github.com/ttacon/libphonenumber v1.2.1 // indirect
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect
|
||||
golang.org/x/net v0.0.0-20220802222814-0bcc04d9c69b // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20220722155238-128564f6959c // indirect
|
||||
golang.org/x/sys v0.0.0-20220803195053-6e608f9ce704 // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/protobuf v1.28.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
|
17
go.sum
17
go.sum
@ -83,6 +83,8 @@ github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/go-lark/lark v1.7.2 h1:F2LlwbRrZVuHPs8lz1D7owDevUndPy88Hbw6ZXaho/A=
|
||||
github.com/go-lark/lark v1.7.2/go.mod h1:6ltbSztPZRT6IaO9ZIQyVaY5pVp/KeMizDYtfZkU+vM=
|
||||
github.com/go-redis/redis/v8 v8.11.6-0.20220405070650-99c79f7041fc h1:jZY+lpZB92nvBo2f31oPC/ivGll6NcsnEOORm8Fkr4M=
|
||||
github.com/go-redis/redis/v8 v8.11.6-0.20220405070650-99c79f7041fc/go.mod h1:25mL1NKxbJhB63ihiK8MnNeTRd+xAizd6bOdydrTLUQ=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
@ -90,6 +92,8 @@ github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible h1:2cauKuaEL
|
||||
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible/go.mod h1:qf9acutJ8cwBUhm1bqgz6Bei9/C/c93FPDljKWwsOgM=
|
||||
github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho=
|
||||
github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
|
||||
github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0=
|
||||
github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
@ -134,11 +138,19 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y
|
||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
||||
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
|
||||
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
||||
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible h1:jdpOPRN1zP63Td1hDQbZW73xKmzDvZHzVdNYxhnTMDA=
|
||||
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible/go.mod h1:1c7szIrayyPPB/987hsnvNzLushdWf4o/79s3P08L8A=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/kevinburke/go-types v0.0.0-20210723172823-2deba1f80ba7 h1:K8qael4LemsmJCGt+ccI8b0fCNFDttmEu3qtpFt3G0M=
|
||||
github.com/kevinburke/go-types v0.0.0-20210723172823-2deba1f80ba7/go.mod h1:/Pk5i/SqYdYv1cie5wGwoZ4P6TpgMi+Yf58mtJSHdOw=
|
||||
github.com/kevinburke/rest v0.0.0-20210506044642-5611499aa33c h1:hnbwWED5rIu+UaMkLR3JtnscMVGqp35lfzQwLuZAAUY=
|
||||
github.com/kevinburke/rest v0.0.0-20210506044642-5611499aa33c/go.mod h1:pD+iEcdAGVXld5foVN4e24zb/6fnb60tgZPZ3P/3T/I=
|
||||
github.com/kevinburke/twilio-go v0.0.0-20220615032439-b0fe9b151b0e h1:2HUamy+op/UxwJxDIg19oy/tIO/2M2tSasvihvhex4s=
|
||||
github.com/kevinburke/twilio-go v0.0.0-20220615032439-b0fe9b151b0e/go.mod h1:PDdDH7RSKjjy9iFyoMzfeChOSmXpXuMEUqmAJSihxx4=
|
||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/line/line-bot-sdk-go v7.8.0+incompatible h1:Uf9/OxV0zCVfqyvwZPH8CrdiHXXmMRa/L91G3btQblQ=
|
||||
@ -223,6 +235,10 @@ github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/ttacon/builder v0.0.0-20170518171403-c099f663e1c2 h1:5u+EJUQiosu3JFX0XS0qTf5FznsMOzTjGqavBGuCbo0=
|
||||
github.com/ttacon/builder v0.0.0-20170518171403-c099f663e1c2/go.mod h1:4kyMkleCiLkgY6z8gK5BkI01ChBtxR0ro3I1ZDcGM3w=
|
||||
github.com/ttacon/libphonenumber v1.2.1 h1:fzOfY5zUADkCkbIafAed11gL1sW+bJ26p6zWLBMElR4=
|
||||
github.com/ttacon/libphonenumber v1.2.1/go.mod h1:E0TpmdVMq5dyVlQ7oenAkhsLu86OkUl+yR4OAxyEg/M=
|
||||
github.com/utahta/go-linenotify v0.5.0 h1:E1tJaB/XhqRY/iz203FD0MaHm10DjQPOq5/Mem2A3Gs=
|
||||
github.com/utahta/go-linenotify v0.5.0/go.mod h1:KsvBXil2wx+ByaCR0e+IZKTbp4pDesc7yjzRigLf6pE=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
@ -322,5 +338,6 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
99
service/lark/README.md
Normal file
99
service/lark/README.md
Normal file
@ -0,0 +1,99 @@
|
||||
# Lark
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Depending on your requirements, you'll need either a custom app or a Lark group
|
||||
chat webhook. The latter is easier to set up, but can only send messages to the
|
||||
group it is in. You may refer to the doc
|
||||
[here](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMuhttps://open.larksuite.com/document/home/develop-a-bot-in-5-minutes/create-an-appkTM/bot-v3/use-custom-bots-in-a-group)
|
||||
to set up a webhook bot, and the doc
|
||||
[here](https://open.larksuite.com/document/home/develop-a-bot-in-5-minutes/create-an-app)
|
||||
to set up a custom app.
|
||||
|
||||
## Usage
|
||||
|
||||
### Webhook
|
||||
|
||||
For webhook bots, we only need the webhook URL, which might look something like
|
||||
`https://open.feishu.cn/open-apis/bot/v2/hook/xxx`. Note that there is no
|
||||
method to configure receivers, because the webhook bot can only send messages
|
||||
to the group in which it was created.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
|
||||
"github.com/nikoksr/notify"
|
||||
"github.com/nikoksr/notify/service/lark"
|
||||
)
|
||||
|
||||
// Replace this with your own webhook URL.
|
||||
const webHookURL = "https://open.feishu.cn/open-apis/bot/v2/hook/xxx"
|
||||
|
||||
func main() {
|
||||
larkWebhookSvc := lark.NewWebhookService(webHookURL)
|
||||
|
||||
notifier := notify.New()
|
||||
notifier.UseServices(larkWebhookSvc)
|
||||
|
||||
if err := notifier.Send(context.Background(), "subject", "message"); err != nil {
|
||||
log.Fatalf("notifier.Send() failed: %s", err.Error())
|
||||
}
|
||||
|
||||
log.Println("notification sent")
|
||||
}
|
||||
```
|
||||
|
||||
### Custom App
|
||||
|
||||
For custom apps, we need to pass in the App ID and App Secret when creating a
|
||||
new notification service. When adding receivers, the type of the receiver ID
|
||||
must be specified, as shown in the example below. You may refer to the section
|
||||
entitled "Query parameters" in the doc
|
||||
[here](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/reference/im-v1/message/create)
|
||||
for more information about the different ID types.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
|
||||
"github.com/nikoksr/notify"
|
||||
"github.com/nikoksr/notify/service/lark"
|
||||
)
|
||||
|
||||
// Replace these with the credentials from your custom app.
|
||||
const (
|
||||
appId = "xxx"
|
||||
appSecret = "xxx"
|
||||
)
|
||||
|
||||
func main() {
|
||||
larkCustomAppService := lark.NewCustomAppService(appId, appSecret)
|
||||
|
||||
// Lark implements five types of receiver IDs. You'll need to specify the
|
||||
// type using the respective helper functions when adding them as receivers.
|
||||
larkCustomAppService.AddReceivers(
|
||||
lark.OpenID("xxx"),
|
||||
lark.UserID("xxx"),
|
||||
lark.UnionID("xxx"),
|
||||
lark.Email("xyz@example.com"),
|
||||
lark.ChatID("xxx"),
|
||||
)
|
||||
|
||||
notifier := notify.New()
|
||||
notifier.UseServices(larkCustomAppService)
|
||||
|
||||
if err := notifier.Send(context.Background(), "subject", "message"); err != nil {
|
||||
log.Fatalf("notifier.Send() failed: %s", err.Error())
|
||||
}
|
||||
|
||||
log.Println("notification sent")
|
||||
}
|
||||
```
|
||||
|
58
service/lark/common.go
Normal file
58
service/lark/common.go
Normal file
@ -0,0 +1,58 @@
|
||||
package lark
|
||||
|
||||
// sender is an interface for sending a message to an already defined receiver.
|
||||
type sender interface {
|
||||
Send(subject, message string) error
|
||||
}
|
||||
|
||||
// sender is an interface for sending a message to a specific receiver ID.
|
||||
type sendToer interface {
|
||||
SendTo(subject, message, id, idType string) error
|
||||
}
|
||||
|
||||
// receiverID encapsulates a receiver ID and its type in Lark.
|
||||
type receiverID struct {
|
||||
id string
|
||||
typ receiverIDType
|
||||
}
|
||||
|
||||
// OpenID specifies an ID as a Lark Open ID.
|
||||
func OpenID(s string) *receiverID {
|
||||
return &receiverID{s, openID}
|
||||
}
|
||||
|
||||
// UserID specifies an ID as a Lark User ID.
|
||||
func UserID(s string) *receiverID {
|
||||
return &receiverID{s, userID}
|
||||
}
|
||||
|
||||
// UnionID specifies an ID as a Lark Union ID.
|
||||
func UnionID(s string) *receiverID {
|
||||
return &receiverID{s, unionID}
|
||||
}
|
||||
|
||||
// Email specifies a receiver ID as an email.
|
||||
func Email(s string) *receiverID {
|
||||
return &receiverID{s, email}
|
||||
}
|
||||
|
||||
// ChatID specifies an ID as a Lark Chat ID.
|
||||
func ChatID(s string) *receiverID {
|
||||
return &receiverID{s, chatID}
|
||||
}
|
||||
|
||||
// receiverIDType represents the different ID types implemented by Lark. This
|
||||
// information is required when sending a message. More information about the
|
||||
// different ID types can be found in the "Query parameters" section of
|
||||
// the https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/reference/im-v1/message/create,
|
||||
// or on
|
||||
// https://open.larksuite.com/document/home/user-identity-introduction/introduction.
|
||||
type receiverIDType string
|
||||
|
||||
const (
|
||||
openID receiverIDType = "open_id"
|
||||
userID receiverIDType = "user_id"
|
||||
unionID receiverIDType = "union_id"
|
||||
email receiverIDType = "email"
|
||||
chatID receiverIDType = "chat_id"
|
||||
)
|
111
service/lark/custom_app.go
Normal file
111
service/lark/custom_app.go
Normal file
@ -0,0 +1,111 @@
|
||||
package lark
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/go-lark/lark"
|
||||
|
||||
"github.com/nikoksr/notify"
|
||||
)
|
||||
|
||||
type customAppService struct {
|
||||
receiveIDs []*receiverID
|
||||
cli sendToer
|
||||
}
|
||||
|
||||
// Compile time check that larkCustomAppService implements notify.Notifer.
|
||||
var _ notify.Notifier = &customAppService{}
|
||||
|
||||
// NewCustomAppService returns a new instance of a Lark notify service using a
|
||||
// Lark custom app.
|
||||
func NewCustomAppService(appID, appSecret string) *customAppService {
|
||||
bot := lark.NewChatBot(appID, appSecret)
|
||||
|
||||
// We need to set the bot to use Lark's open.larksuite.com domain instead of
|
||||
// the default open.feishu.cn domain.
|
||||
bot.SetDomain(lark.DomainLark)
|
||||
|
||||
// Let the bot use a HTTP client with a longer timeout than the default 5
|
||||
// seconds.
|
||||
bot.SetClient(&http.Client{
|
||||
Timeout: 8 * time.Second,
|
||||
})
|
||||
|
||||
_ = bot.StartHeartbeat()
|
||||
|
||||
return &customAppService{
|
||||
receiveIDs: make([]*receiverID, 0),
|
||||
cli: &larkClientGoLarkChatBot{
|
||||
bot: bot,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// AddReceivers adds recipients to future notifications. There are five different
|
||||
// types of receiver IDs available in Lark and they must be specified here. For
|
||||
// example:
|
||||
//
|
||||
// larkService.AddReceivers(
|
||||
// lark.OpenID("ou_c99c5f35d542efc7ee492afe11af19ef"),
|
||||
// lark.UserID("8335aga2"),
|
||||
// lark.UnionID("on_cad4860e7af114fb4ff6c5d496d1dd76"),
|
||||
// lark.Email("xyz@example.com"),
|
||||
// lark.ChatID("oc_a0553eda9014c201e6969b478895c230"),
|
||||
// )
|
||||
func (c *customAppService) AddReceivers(ids ...*receiverID) {
|
||||
c.receiveIDs = append(c.receiveIDs, ids...)
|
||||
}
|
||||
|
||||
// Send takes a message subject and a message body and sends them to all
|
||||
// previously registered recipient IDs.
|
||||
func (c *customAppService) Send(ctx context.Context, subject, message string) error {
|
||||
for _, id := range c.receiveIDs {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
default:
|
||||
if err := c.cli.SendTo(subject, message, id.id, string(id.typ)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// larkClientGoLarkChatBot is a wrapper around go-lark/lark's Bot, to be used
|
||||
// for sending messages with custom apps.
|
||||
type larkClientGoLarkChatBot struct {
|
||||
bot *lark.Bot
|
||||
}
|
||||
|
||||
// SendTo implements the sendToer interface using a go-lark/lark chat bot.
|
||||
func (l *larkClientGoLarkChatBot) SendTo(subject, message, receiverID, idType string) error {
|
||||
content := lark.NewPostBuilder().
|
||||
Title(subject).
|
||||
TextTag(message, 1, false).
|
||||
Render()
|
||||
msg := lark.NewMsgBuffer(lark.MsgPost).Post(content)
|
||||
switch receiverIDType(idType) {
|
||||
case openID:
|
||||
msg.BindOpenID(receiverID)
|
||||
case userID:
|
||||
msg.BindUserID(receiverID)
|
||||
case unionID:
|
||||
msg.BindUnionID(receiverID)
|
||||
case email:
|
||||
msg.BindEmail(receiverID)
|
||||
case chatID:
|
||||
msg.BindChatID(receiverID)
|
||||
}
|
||||
res, err := l.bot.PostMessage(msg.Build())
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to send message: %w", err)
|
||||
}
|
||||
if res.Code != 0 {
|
||||
return fmt.Errorf("send failed with error code %d, please see https://open.larksuite.com/document/ukTMukTMukTM/ugjM14COyUjL4ITN for details", res.Code)
|
||||
}
|
||||
return nil
|
||||
}
|
80
service/lark/custom_app_test.go
Normal file
80
service/lark/custom_app_test.go
Normal file
@ -0,0 +1,80 @@
|
||||
package lark
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestAddReceivers(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
xs := []*receiverID{
|
||||
OpenID("ou_c99c5f35d542efc7ee492afe11af19ef"),
|
||||
UserID("8335aga2"),
|
||||
}
|
||||
svc := NewCustomAppService("", "")
|
||||
svc.AddReceivers(xs...)
|
||||
|
||||
assert.ElementsMatch(t, svc.receiveIDs, xs)
|
||||
|
||||
// Test if adding more receivers afterwards works.
|
||||
ys := []*receiverID{
|
||||
UnionID("on_cad4860e7af114fb4ff6c5d496d1dd76"),
|
||||
Email("xyz@example.com"),
|
||||
ChatID("oc_a0553eda9014c201e6969b478895c230"),
|
||||
}
|
||||
svc.AddReceivers(ys...)
|
||||
|
||||
assert.ElementsMatch(t, svc.receiveIDs, append(xs, ys...))
|
||||
}
|
||||
|
||||
func TestSendCustomApp(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx := context.Background()
|
||||
assert := assert.New(t)
|
||||
|
||||
tests := []*receiverID{
|
||||
OpenID("ou_c99c5f35d542efc7ee492afe11af19ef"),
|
||||
UserID("8335aga2"),
|
||||
UnionID("on_cad4860e7af114fb4ff6c5d496d1dd76"),
|
||||
Email("xyz@example.com"),
|
||||
ChatID("oc_a0553eda9014c201e6969b478895c230"),
|
||||
}
|
||||
|
||||
// First, test for when the sender returns an error.
|
||||
for _, tt := range tests {
|
||||
mockSendToer := NewSendToer(t)
|
||||
mockSendToer.
|
||||
On("SendTo", "subject", "message", tt.id, string(tt.typ)).
|
||||
Return(errors.New(""))
|
||||
|
||||
svc := NewCustomAppService("", "")
|
||||
svc.cli = mockSendToer
|
||||
|
||||
svc.AddReceivers(tt)
|
||||
err := svc.Send(ctx, "subject", "message")
|
||||
assert.NotNil(err)
|
||||
|
||||
mockSendToer.AssertExpectations(t)
|
||||
}
|
||||
|
||||
// Then test for when the sender does not return an error.
|
||||
for _, tt := range tests {
|
||||
mockSendToer := NewSendToer(t)
|
||||
mockSendToer.
|
||||
On("SendTo", "subject", "message", tt.id, string(tt.typ)).
|
||||
Return(nil)
|
||||
|
||||
svc := NewCustomAppService("", "")
|
||||
svc.cli = mockSendToer
|
||||
|
||||
svc.AddReceivers(tt)
|
||||
err := svc.Send(ctx, "subject", "message")
|
||||
assert.Nil(err)
|
||||
|
||||
mockSendToer.AssertExpectations(t)
|
||||
}
|
||||
}
|
53
service/lark/doc.go
Normal file
53
service/lark/doc.go
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
Package lark provides message notification integration for Lark. Two kinds of
|
||||
bots on Lark are supported -- webhooks and custom apps. For information on
|
||||
webhook bots, see
|
||||
https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/bot-v3/use-custom-bots-in-a-group,
|
||||
and for info on custom apps, see
|
||||
https://open.larksuite.com/document/home/develop-a-bot-in-5-minutes/create-an-app.
|
||||
|
||||
Usage:
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
|
||||
"github.com/nikoksr/notify"
|
||||
"github.com/nikoksr/notify/service/lark"
|
||||
)
|
||||
|
||||
const (
|
||||
webhookURL = "https://open.feishu.cn/open-apis/bot/v2/hook/xxx"
|
||||
appId = "xxx"
|
||||
appSecret = "xxx"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Two types of services are available depending on your requirements.
|
||||
larkWebhookService := lark.NewWebhookService(webhookURL)
|
||||
larkCustomAppService := lark.NewCustomAppService(appId, appSecret)
|
||||
|
||||
// Lark implements five types of receiver IDs. You'll need to specify the
|
||||
// type using the respective helper functions when adding them as receivers
|
||||
// for the custom app service.
|
||||
larkCustomAppService.AddReceivers(
|
||||
lark.OpenID("xxx"),
|
||||
lark.UserID("xxx"),
|
||||
lark.UnionID("xxx"),
|
||||
lark.Email("xyz@example.com"),
|
||||
lark.ChatID("xxx"),
|
||||
)
|
||||
|
||||
notifier := notify.New()
|
||||
notifier.UseServices(larkWebhookService, larkCustomAppService)
|
||||
|
||||
if err := notifier.Send(context.Background(), "subject", "message"); err != nil {
|
||||
log.Fatalf("notifier.Send() failed: %s", err.Error())
|
||||
}
|
||||
|
||||
log.Println("notification sent")
|
||||
}
|
||||
*/
|
||||
package lark
|
39
service/lark/mock_sendToer.go
Normal file
39
service/lark/mock_sendToer.go
Normal file
@ -0,0 +1,39 @@
|
||||
// Code generated by mockery v2.12.3. DO NOT EDIT.
|
||||
|
||||
package lark
|
||||
|
||||
import "github.com/stretchr/testify/mock"
|
||||
|
||||
// SendToer is an autogenerated mock type for the sendToer type
|
||||
type SendToer struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// SendTo provides a mock function with given fields: subject, message, id, idType
|
||||
func (_m *SendToer) SendTo(subject string, message string, id string, idType string) error {
|
||||
ret := _m.Called(subject, message, id, idType)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(string, string, string, string) error); ok {
|
||||
r0 = rf(subject, message, id, idType)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
type NewSendToerT interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}
|
||||
|
||||
// NewSendToer creates a new instance of SendToer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
func NewSendToer(t NewSendToerT) *SendToer {
|
||||
mock := &SendToer{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
39
service/lark/mock_sender.go
Normal file
39
service/lark/mock_sender.go
Normal file
@ -0,0 +1,39 @@
|
||||
// Code generated by mockery v2.12.3. DO NOT EDIT.
|
||||
|
||||
package lark
|
||||
|
||||
import "github.com/stretchr/testify/mock"
|
||||
|
||||
// Sender is an autogenerated mock type for the sender type
|
||||
type Sender struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// Send provides a mock function with given fields: subject, message
|
||||
func (_m *Sender) Send(subject string, message string) error {
|
||||
ret := _m.Called(subject, message)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(string, string) error); ok {
|
||||
r0 = rf(subject, message)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
type NewSenderT interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}
|
||||
|
||||
// NewSender creates a new instance of Sender. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
func NewSender(t NewSenderT) *Sender {
|
||||
mock := &Sender{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
58
service/lark/webhook.go
Normal file
58
service/lark/webhook.go
Normal file
@ -0,0 +1,58 @@
|
||||
package lark
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/go-lark/lark"
|
||||
|
||||
"github.com/nikoksr/notify"
|
||||
)
|
||||
|
||||
type webhookService struct {
|
||||
cli sender
|
||||
}
|
||||
|
||||
// Compile time check that larkCustomAppService implements notify.Notifer.
|
||||
var _ notify.Notifier = &webhookService{}
|
||||
|
||||
// NewWebhookService returns a new instance of a Lark notify service using a
|
||||
// Lark group chat webhook. Note that this service does not take any
|
||||
// notification receivers because it can only push messages to the group chat
|
||||
// it belongs to.
|
||||
func NewWebhookService(webhookURL string) *webhookService {
|
||||
bot := lark.NewNotificationBot(webhookURL)
|
||||
return &webhookService{
|
||||
cli: &larkClientGoLarkNotificationBot{
|
||||
bot: bot,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Send sends the message subject and body to the group chat.
|
||||
func (w *webhookService) Send(ctx context.Context, subject, message string) error {
|
||||
return w.cli.Send(subject, message)
|
||||
}
|
||||
|
||||
// larkClientGoLarkNotificationBot is a wrapper around go-lark/lark's Bot, to
|
||||
// be used for notifications via webhooks only.
|
||||
type larkClientGoLarkNotificationBot struct {
|
||||
bot *lark.Bot
|
||||
}
|
||||
|
||||
// Send implements the sender interface using a go-lark/lark notification bot.
|
||||
func (w *larkClientGoLarkNotificationBot) Send(subject, message string) error {
|
||||
content := lark.NewPostBuilder().
|
||||
Title(subject).
|
||||
TextTag(message, 1, false).
|
||||
Render()
|
||||
msg := lark.NewMsgBuffer(lark.MsgPost).Post(content)
|
||||
res, err := w.bot.PostNotificationV2(msg.Build())
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to post webhook message: %w", err)
|
||||
}
|
||||
if res.Code != 0 {
|
||||
return fmt.Errorf("send failed with error code %d, please see https://open.larksuite.com/document/ukTMukTMukTM/ugjM14COyUjL4ITN for details", res.Code)
|
||||
}
|
||||
return nil
|
||||
}
|
44
service/lark/webhook_test.go
Normal file
44
service/lark/webhook_test.go
Normal file
@ -0,0 +1,44 @@
|
||||
package lark
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestSendWebhook(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := assert.New(t)
|
||||
ctx := context.Background()
|
||||
|
||||
// First, test for when the sender returns an error.
|
||||
{
|
||||
mockSender := NewSender(t)
|
||||
mockSender.
|
||||
On("Send", "subject", "message").
|
||||
Return(errors.New(""))
|
||||
|
||||
svc := NewWebhookService("")
|
||||
svc.cli = mockSender
|
||||
err := svc.Send(ctx, "subject", "message")
|
||||
assert.NotNil(err)
|
||||
mockSender.AssertExpectations(t)
|
||||
}
|
||||
|
||||
// Then test for when the sender does not return an error.
|
||||
{
|
||||
mockSender := NewSender(t)
|
||||
mockSender.
|
||||
On("Send", "subject", "message").
|
||||
Return(nil)
|
||||
|
||||
svc := NewWebhookService("")
|
||||
svc.cli = mockSender
|
||||
err := svc.Send(ctx, "subject", "message")
|
||||
assert.Nil(err)
|
||||
mockSender.AssertExpectations(t)
|
||||
}
|
||||
}
|
43
service/twilio/README.md
Normal file
43
service/twilio/README.md
Normal file
@ -0,0 +1,43 @@
|
||||
# Twilio (Message Service)
|
||||
|
||||
[![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/nikoksr/notify/service/twilio)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Navigate to Twilio [console](https://console.twilio.com/), create a new account or login with an existing one.
|
||||
You will find the `Account SID` and the `Auth Token` under the `Account Info` tab. You may also request a Twilio phone number, if required.
|
||||
|
||||
To test the integration with a phone number you can just use the sample code below.
|
||||
|
||||
## Usage
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
|
||||
"github.com/nikoksr/notify"
|
||||
"github.com/nikoksr/notify/service/twilio"
|
||||
)
|
||||
|
||||
func main() {
|
||||
twilioSvc, err := twilio.New("account_sid", "auth_token", "your_phone_number")
|
||||
if err != nil {
|
||||
log.Fatalf("twilio.New() failed: %s", err.Error())
|
||||
}
|
||||
|
||||
twilioSvc.AddReceivers("recipient_phone_number")
|
||||
|
||||
notifier := notify.New()
|
||||
notifier.UseServices(twilioSvc)
|
||||
|
||||
err = notifier.Send(context.Background(), "subject", "message")
|
||||
if err != nil {
|
||||
log.Fatalf("notifier.Send() failed: %s", err.Error())
|
||||
}
|
||||
|
||||
log.Println("notification sent")
|
||||
}
|
||||
```
|
35
service/twilio/doc.go
Normal file
35
service/twilio/doc.go
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
Package twilio provides message notification integration for Twilio (Message Service).
|
||||
|
||||
Usage:
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
|
||||
"github.com/nikoksr/notify"
|
||||
"github.com/nikoksr/notify/service/twilio"
|
||||
)
|
||||
|
||||
func main() {
|
||||
twilioSvc, err := twilio.New("account_sid", "auth_token", "your_phone_number")
|
||||
if err != nil {
|
||||
log.Fatalf("twilio.New() failed: %s", err.Error())
|
||||
}
|
||||
|
||||
twilioSvc.AddReceivers("recipient_phone_number")
|
||||
|
||||
notifier := notify.New()
|
||||
notifier.UseServices(twilioSvc)
|
||||
|
||||
err = notifier.Send(context.Background(), "subject", "message")
|
||||
if err != nil {
|
||||
log.Fatalf("notifier.Send() failed: %s", err.Error())
|
||||
}
|
||||
|
||||
log.Println("notification sent")
|
||||
}
|
||||
*/
|
||||
package twilio
|
49
service/twilio/mock_twilioClient.go
Normal file
49
service/twilio/mock_twilioClient.go
Normal file
@ -0,0 +1,49 @@
|
||||
// Code generated by mockery v2.12.2. DO NOT EDIT.
|
||||
|
||||
package twilio
|
||||
|
||||
import (
|
||||
url "net/url"
|
||||
testing "testing"
|
||||
|
||||
twilio "github.com/kevinburke/twilio-go"
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
// mockTwilioClient is an autogenerated mock type for the twilioClient type
|
||||
type mockTwilioClient struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// SendMessage provides a mock function with given fields: from, to, body, mediaURLs
|
||||
func (_m *mockTwilioClient) SendMessage(from string, to string, body string, mediaURLs []*url.URL) (*twilio.Message, error) {
|
||||
ret := _m.Called(from, to, body, mediaURLs)
|
||||
|
||||
var r0 *twilio.Message
|
||||
if rf, ok := ret.Get(0).(func(string, string, string, []*url.URL) *twilio.Message); ok {
|
||||
r0 = rf(from, to, body, mediaURLs)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*twilio.Message)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(string, string, string, []*url.URL) error); ok {
|
||||
r1 = rf(from, to, body, mediaURLs)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// newMockTwilioClient creates a new instance of mockTwilioClient. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
func newMockTwilioClient(t testing.TB) *mockTwilioClient {
|
||||
mock := &mockTwilioClient{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
63
service/twilio/twilio.go
Normal file
63
service/twilio/twilio.go
Normal file
@ -0,0 +1,63 @@
|
||||
package twilio
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
|
||||
"github.com/kevinburke/twilio-go"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Compile-time check that twilio.MessageService satisfies twilioClient interface.
|
||||
var _ twilioClient = &twilio.MessageService{}
|
||||
|
||||
// twilioClient abstracts twilio-go MessageService for writing unit tests
|
||||
type twilioClient interface {
|
||||
SendMessage(from, to, body string, mediaURLs []*url.URL) (*twilio.Message, error)
|
||||
}
|
||||
|
||||
// Service encapsulates the Twilio Message Service client along with internal state for storing recipient phone numbers.
|
||||
type Service struct {
|
||||
client twilioClient
|
||||
|
||||
fromPhoneNumber string
|
||||
toPhoneNumbers []string
|
||||
}
|
||||
|
||||
// New returns a new instance of Twilio notification service.
|
||||
func New(accountSID, authToken, fromPhoneNumber string) (*Service, error) {
|
||||
client := twilio.NewClient(accountSID, authToken, nil)
|
||||
|
||||
s := &Service{
|
||||
client: client.Messages,
|
||||
fromPhoneNumber: fromPhoneNumber,
|
||||
toPhoneNumbers: []string{},
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// AddReceivers takes strings of recipient phone numbers and appends them to the internal phone numbers slice.
|
||||
// The Send method will send a given message to all those phone numbers.
|
||||
func (s *Service) AddReceivers(phoneNumbers ...string) {
|
||||
s.toPhoneNumbers = append(s.toPhoneNumbers, phoneNumbers...)
|
||||
}
|
||||
|
||||
// Send takes a message subject and a message body and sends them to all previously set phone numbers.
|
||||
func (s *Service) Send(ctx context.Context, subject, message string) error {
|
||||
body := subject + "\n" + message
|
||||
|
||||
for _, toPhoneNumber := range s.toPhoneNumbers {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
default:
|
||||
|
||||
_, err := s.client.SendMessage(s.fromPhoneNumber, toPhoneNumber, body, []*url.URL{})
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to send message to phone number '%s' using Twilio", toPhoneNumber)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
90
service/twilio/twilio_test.go
Normal file
90
service/twilio/twilio_test.go
Normal file
@ -0,0 +1,90 @@
|
||||
package twilio
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
testing "testing"
|
||||
|
||||
twilio "github.com/kevinburke/twilio-go"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestAddReceivers(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := require.New(t)
|
||||
|
||||
svc := &Service{
|
||||
toPhoneNumbers: []string{},
|
||||
}
|
||||
toPhoneNumbers := []string{"PhoneNumber1", "PhoneNumber2", "PhoneNumber3"}
|
||||
svc.AddReceivers(toPhoneNumbers...)
|
||||
|
||||
assert.Equal(svc.toPhoneNumbers, toPhoneNumbers)
|
||||
}
|
||||
|
||||
func TestSend(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := require.New(t)
|
||||
|
||||
svc := &Service{
|
||||
fromPhoneNumber: "my_phone_number",
|
||||
toPhoneNumbers: []string{},
|
||||
}
|
||||
|
||||
mockPhoneNumber := "recipient_phone_number"
|
||||
mockBody := "subject\nmessage"
|
||||
mockError := errors.New("some error")
|
||||
|
||||
// test twilio client send
|
||||
mockClient := newMockTwilioClient(t)
|
||||
mockClient.On("SendMessage",
|
||||
svc.fromPhoneNumber,
|
||||
mockPhoneNumber,
|
||||
mockBody,
|
||||
[]*url.URL{}).Return(&twilio.Message{Body: "a response message"}, nil)
|
||||
svc.client = mockClient
|
||||
svc.AddReceivers(mockPhoneNumber)
|
||||
err := svc.Send(context.Background(), "subject", "message")
|
||||
assert.Nil(err)
|
||||
mockClient.AssertExpectations(t)
|
||||
|
||||
// test twilio client send returning error
|
||||
mockClient = newMockTwilioClient(t)
|
||||
mockClient.On("SendMessage",
|
||||
svc.fromPhoneNumber,
|
||||
mockPhoneNumber,
|
||||
mockBody,
|
||||
[]*url.URL{}).Return(nil, mockError)
|
||||
svc.client = mockClient
|
||||
svc.AddReceivers(mockPhoneNumber)
|
||||
err = svc.Send(context.Background(), "subject", "message")
|
||||
assert.NotNil(err)
|
||||
assert.Equal(
|
||||
fmt.Sprintf("failed to send message to phone number '%s' using Twilio: %s", mockPhoneNumber, mockError.Error()),
|
||||
err.Error())
|
||||
mockClient.AssertExpectations(t)
|
||||
|
||||
// test twilio client send multiple receivers
|
||||
anotherMockPhoneNumber := "another_recipient_phone_number"
|
||||
mockClient = newMockTwilioClient(t)
|
||||
mockClient.On("SendMessage",
|
||||
svc.fromPhoneNumber,
|
||||
mockPhoneNumber,
|
||||
mockBody,
|
||||
[]*url.URL{}).Return(&twilio.Message{Body: "a response message"}, nil)
|
||||
mockClient.On("SendMessage",
|
||||
svc.fromPhoneNumber,
|
||||
anotherMockPhoneNumber,
|
||||
mockBody,
|
||||
[]*url.URL{}).Return(&twilio.Message{Body: "a response message"}, nil)
|
||||
svc.client = mockClient
|
||||
svc.AddReceivers(mockPhoneNumber)
|
||||
svc.AddReceivers(anotherMockPhoneNumber)
|
||||
err = svc.Send(context.Background(), "subject", "message")
|
||||
assert.Nil(err)
|
||||
mockClient.AssertExpectations(t)
|
||||
}
|
Loading…
Reference in New Issue
Block a user