1
0
mirror of https://github.com/nikoksr/notify.git synced 2025-03-19 21:08:48 +02:00

feat(service): Add Viber (#415)

This commit is contained in:
Irfan Sofyana Putra 2022-10-25 15:45:06 +07:00 committed by GitHub
parent 7624ce31aa
commit 8aa5c9d2b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 362 additions and 4 deletions

View File

@ -102,6 +102,7 @@ Yes, please! Contributions of all kinds are very welcome! Feel free to check our
| [TextMagic](https://www.textmagic.com) | [service/textmagic](service/textmagic) | [textmagic/textmagic-rest-go-v2](https://github.com/textmagic/textmagic-rest-go-v2) | :heavy_check_mark: |
| [Twilio](https://www.twilio.com/) | [service/twilio](service/twilio) | [kevinburke/twilio-go](https://github.com/kevinburke/twilio-go) | :heavy_check_mark: |
| [Twitter](https://twitter.com) | [service/twitter](service/twitter) | [dghubble/go-twitter](https://github.com/dghubble/go-twitter) | :heavy_check_mark: |
| [Viber](https://www.viber.com) | [service/viber](service/viber) | [mileusna/viber](https://github.com/mileusna/viber) | :heavy_check_mark: |
| [WeChat](https://www.wechat.com) | [service/wechat](service/wechat) | [silenceper/wechat](https://github.com/silenceper/wechat) | :heavy_check_mark: |
| [WhatsApp](https://www.whatsapp.com) | [service/whatsapp](service/whatsapp) | [Rhymen/go-whatsapp](https://github.com/Rhymen/go-whatsapp) | :x: |

3
go.mod
View File

@ -67,6 +67,9 @@ require (
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/mileusna/viber v1.0.1
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect

8
go.sum
View File

@ -149,6 +149,14 @@ github.com/line/line-bot-sdk-go v7.8.0+incompatible h1:Uf9/OxV0zCVfqyvwZPH8CrdiH
github.com/line/line-bot-sdk-go v7.8.0+incompatible/go.mod h1:0RjLjJEAU/3GIcHkC3av6O4jInAbt25nnZVmOFUgDBg=
github.com/mailgun/mailgun-go/v4 v4.8.1 h1:1+MdKakJuXnW2JJDbyPdO1ngAANOyHyVPxQvFF8Sq6c=
github.com/mailgun/mailgun-go/v4 v4.8.1/go.mod h1:FJlF9rI5cQT+mrwujtJjPMbIVy3Ebor9bKTVsJ0QU40=
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mileusna/viber v1.0.1 h1:gWB6/lKoWYVxkH0Jb8jRnGIRZ/9DEM7RBZRJHRfdYWs=
github.com/mileusna/viber v1.0.1/go.mod h1:Pxu/iPMnYjnHgu+bEp3SiKWHWmlf/kDp/yOX8XUdYrQ=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=

View File

@ -3,12 +3,10 @@
package matrix
import (
mock "github.com/stretchr/testify/mock"
mautrix "maunium.net/go/mautrix"
event "maunium.net/go/mautrix/event"
id "maunium.net/go/mautrix/id"
mautrix "maunium.net/go/mautrix"
mock "github.com/stretchr/testify/mock"
)
// mockMatrixClient is an autogenerated mock type for the matrixClient type

75
service/viber/README Normal file
View File

@ -0,0 +1,75 @@
# Viber
## Prerequisites
### Create a Viber Bot
In order to use the Viber notification service, we'll need to create a new Viber bot [here](https://partners.viber.com/account/create-bot-account).
### Setting the webhook
After we have done with the bot setup, we'll need to have a webhook that will be used to receive callbacks from the Viber server otherwise we will not be able to send a message.
Please note that your webhook needs to be valid otherwise it will not work properly. You can read more details about the Viber webhook [here](https://developers.viber.com/docs/api/rest-bot-api/#webhooks) and about the callback [here](https://developers.viber.com/docs/api/rest-bot-api/#callbacks).
#### Tips: Easy setup for webhook
If you need to set up webhook easily like for example only for local testing, you can utilize [Google App Scripts](https://www.google.com/script/start/) and create a simple Web app from it. Here is the example script:
```javascript
function doPost(e) {
  const contents = JSON.parse(e.postData.contents)
  Logger.log(JSON.stringify(contents))
}
```
_In short, it will just receive the POST request, and log the content_.
Don't forget to deploy the script as a web app and share the access with anyone.
You'll get a URL like https://script.google.com/macros/s/xxx/exec and this URL will be your webhook URL.
## Usage
Here is an example use case on how you can use Viber:
```go
package main
import (
"context"
"log"
"github.com/nikoksr/notify"
"github.com/nikoksr/notify/service/viber"
)
const appKey = "your-viber-token"
const webhookURL = "https://webhook.com"
const senderName = "vibersofyana"
func main() {
viberSvc := viber.New(appKey, senderName, "")
err := viberSvc.SetWebhook(webhookURL) // this only needs to be called once
if err != nil {
log.Fatalf("set webhook to viber server failed: %v", err)
}
viberSvc.AddReceivers("receiver-viber-user-id") // can add as many as required
notifier := notify.New()
notifier.UseServices(viberSvc)
if err := notifier.Send(context.Background(), "TEST", "Message using golang notifier library"); err != nil {
log.Fatalf("notifier.Send() failed: %s", err.Error())
}
log.Println("Notification sent")
}
```
> ❗️**Viber is only allowing the bot to send the message to their subscriber**. Therefore, in order to send the notification, we need to make sure that the receiver already subscribed to the bot. Read more details here: https://developers.viber.com/docs/api/rest-bot-api/#send-message
## Attachment
- [Viber API Documentation](https://developers.viber.com/docs/)

39
service/viber/doc.go Normal file
View File

@ -0,0 +1,39 @@
/*
Package viber provides a service for sending messages to viber.
Usage:
package main
import (
"context"
"log"
"github.com/nikoksr/notify"
"github.com/nikoksr/notify/service/viber"
)
const appKey = "your-viber-token"
const webhookURL = "https://webhook.com"
const senderName = "vibersofyana"
func main() {
viberSvc := viber.New(appKey, senderName, "")
err := viberSvc.SetWebhook(webhookURL) // this only needs to be called once
if err != nil {
log.Fatalf("set webhook to viber server failed: %v", err)
}
viberSvc.AddReceivers("receiver-viber-user-id") // can add as many as required
notifier := notify.New()
notifier.UseServices(viberSvc)
if err := notifier.Send(context.Background(), "TEST", "Message using golang notifier library"); err != nil {
log.Fatalf("notifier.Send() failed: %s", err.Error())
}
log.Println("Notification sent")
}
*/
package viber

View File

@ -0,0 +1,70 @@
// Code generated by mockery v2.14.0. DO NOT EDIT.
package viber
import (
mileusnaviber "github.com/mileusna/viber"
mock "github.com/stretchr/testify/mock"
)
// mockViberClient is an autogenerated mock type for the viberClient type
type mockViberClient struct {
mock.Mock
}
// SendTextMessage provides a mock function with given fields: receiver, msg
func (_m *mockViberClient) SendTextMessage(receiver string, msg string) (uint64, error) {
ret := _m.Called(receiver, msg)
var r0 uint64
if rf, ok := ret.Get(0).(func(string, string) uint64); ok {
r0 = rf(receiver, msg)
} else {
r0 = ret.Get(0).(uint64)
}
var r1 error
if rf, ok := ret.Get(1).(func(string, string) error); ok {
r1 = rf(receiver, msg)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// SetWebhook provides a mock function with given fields: url, eventTypes
func (_m *mockViberClient) SetWebhook(url string, eventTypes []string) (mileusnaviber.WebhookResp, error) {
ret := _m.Called(url, eventTypes)
var r0 mileusnaviber.WebhookResp
if rf, ok := ret.Get(0).(func(string, []string) mileusnaviber.WebhookResp); ok {
r0 = rf(url, eventTypes)
} else {
r0 = ret.Get(0).(mileusnaviber.WebhookResp)
}
var r1 error
if rf, ok := ret.Get(1).(func(string, []string) error); ok {
r1 = rf(url, eventTypes)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
type mockConstructorTestingTnewMockViberClient interface {
mock.TestingT
Cleanup(func())
}
// newMockViberClient creates a new instance of mockViberClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
func newMockViberClient(t mockConstructorTestingTnewMockViberClient) *mockViberClient {
mock := &mockViberClient{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}

61
service/viber/viber.go Normal file
View File

@ -0,0 +1,61 @@
package viber
import (
"context"
vb "github.com/mileusna/viber"
"github.com/pkg/errors"
)
//go:generate mockery --name=viberClient --output=. --case=underscore --inpackage
type viberClient interface {
SetWebhook(url string, eventTypes []string) (vb.WebhookResp, error)
SendTextMessage(receiver, msg string) (uint64, error)
}
// Compile-time check to ensure that vb.Viber implements the viberClient interface.
var _ viberClient = new(vb.Viber)
// Viber struct holds necessary fields to communicate with Viber API
type Viber struct {
Client viberClient
SubscribedUserIDs []string
}
// New returns a new instance of Viber notification service
func New(appKey, senderName, senderAvatar string) *Viber {
return &Viber{
Client: vb.New(appKey, senderName, senderAvatar),
SubscribedUserIDs: []string{},
}
}
// AddReceivers receives subscribed user IDs then add them to internal receivers list
func (v *Viber) AddReceivers(subscribedUserIDs ...string) {
v.SubscribedUserIDs = append(v.SubscribedUserIDs, subscribedUserIDs...)
}
// SetWebhook receives a URL that will we used as a webhook URL for Viber
func (v *Viber) SetWebhook(webhookURL string) error {
_, err := v.Client.SetWebhook(webhookURL, []string{})
return err
}
// Send takes a message subject and a message body and sends them to all previously set userIds
func (v *Viber) Send(ctx context.Context, subject, message string) error {
fullMessage := subject + "\n" + message // Treating subject as message title
for _, subscribedUserID := range v.SubscribedUserIDs {
select {
case <-ctx.Done():
return ctx.Err()
default:
_, err := v.Client.SendTextMessage(subscribedUserID, fullMessage)
if err != nil {
return errors.Wrapf(err, "failed to send message to User ID '%s'", subscribedUserID)
}
}
}
return nil
}

103
service/viber/viber_test.go Normal file
View File

@ -0,0 +1,103 @@
package viber
import (
"context"
"errors"
"testing"
vb "github.com/mileusna/viber"
"github.com/stretchr/testify/require"
)
func TestViber_New(t *testing.T) {
t.Parallel()
assert := require.New(t)
viber := New("appkey", "senderName", "senderAvatar")
assert.NotNil(viber)
}
func TestViber_AddReceivers(t *testing.T) {
t.Parallel()
assert := require.New(t)
viber := New("appkey", "senderName", "senderAvatar")
assert.Len(viber.SubscribedUserIDs, 0)
viber.AddReceivers("first-subscriber")
assert.Len(viber.SubscribedUserIDs, 1)
viber.AddReceivers("second-subscriber", "third-subscriber")
assert.Len(viber.SubscribedUserIDs, 3)
}
func TestViber_SetWebhook(t *testing.T) {
t.Parallel()
assert := require.New(t)
viber := New("appkey", "senderName", "senderAvatar")
assert.NotNil(viber)
// Test error
viberMock := newMockViberClient(t)
webhookURLMock := "https://example-webhook.com"
viberMock.
On("SetWebhook", webhookURLMock, []string{}).
Return(vb.WebhookResp{}, errors.New("set webhook error"))
viber.Client = viberMock
err := viber.SetWebhook(webhookURLMock)
assert.NotNil(err)
viberMock.AssertExpectations(t)
// Test success
viberMock = newMockViberClient(t)
viberMock.
On("SetWebhook", webhookURLMock, []string{}).
Return(vb.WebhookResp{}, nil)
viber.Client = viberMock
err = viber.SetWebhook(webhookURLMock)
assert.Nil(err)
viberMock.AssertExpectations(t)
}
func TestViber_Send(t *testing.T) {
t.Parallel()
assert := require.New(t)
viber := New("appkey", "senderName", "senderAvatar")
assert.NotNil(viber)
// No receivers added
ctx := context.Background()
err := viber.Send(ctx, "subject", "message")
assert.Nil(err)
// Test error response
viberMock := newMockViberClient(t)
viberMock.
On("SendTextMessage", "receiver1", "subject\nmessage").
Return(uint64(0), errors.New("error send text message"))
viber.Client = viberMock
viber.AddReceivers("receiver1")
err = viber.Send(ctx, "subject", "message")
assert.NotNil(err)
viberMock.AssertExpectations(t)
// Test success response
viberMock = newMockViberClient(t)
viberMock.
On("SendTextMessage", "receiver1", "subject\nmessage").
Return(uint64(0), nil)
viberMock.
On("SendTextMessage", "receiver2", "subject\nmessage").
Return(uint64(0), nil)
viber.Client = viberMock
viber.AddReceivers("receiver2")
err = viber.Send(ctx, "subject", "message")
assert.Nil(err)
viberMock.AssertExpectations(t)
}