-
Notifications
You must be signed in to change notification settings - Fork 223
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
476 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package zulip | ||
|
||
// Receiver encapsulates a receiver credentials for a direct or stream message. | ||
type Receiver struct { | ||
email string | ||
stream string | ||
topic string | ||
} | ||
|
||
// Direct specifies a Zulip Direct message | ||
func Direct(email string) *Receiver { | ||
return &Receiver{email: email} | ||
} | ||
|
||
// Stream specifies a Zulip Stream message | ||
func Stream(stream, topic string) *Receiver { | ||
return &Receiver{stream: stream, topic: topic} | ||
} | ||
|
||
type ErrorResponse struct { | ||
Code string `json:"code"` | ||
Message string `json:"msg"` | ||
Result string `json:"result"` | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
# Zulip Usage | ||
|
||
Ensure that you have already navigated to your GOPATH and installed the following packages: | ||
|
||
* `go get -u github.com/nikoksr/notify` | ||
|
||
## Steps for creating Zulip Bot | ||
|
||
These are general and very high level instructions | ||
|
||
1. Create a new Zulip bot (https://zulip.com/help/add-a-bot-or-integration) | ||
2. Copy your *Organization URL* from the browser address bar. You need to copy only subdomain `your-org` from the full url `your-org.zulipchat.com` without the hostname `.zulipchat.com`. | ||
3. Copy your *Bot Email* and *API Key* for usage below | ||
4. Copy the *Stream name* of the stream if you want to post a message to stream or just copy an email address of the receiver. | ||
5. Now you should be good to use the code below | ||
|
||
## Sample Code | ||
|
||
```go | ||
package main | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"github.com/nikoksr/notify" | ||
"github.com/nikoksr/notify/service/zulip" | ||
) | ||
|
||
func main() { | ||
|
||
notifier := notify.New() | ||
|
||
// Provide your Zulip Bot credentials | ||
zulipService := zulip.New( | ||
"your-org", | ||
"ZULIP_API_KEY", | ||
"[email protected]", | ||
) | ||
|
||
// Passing a Zulip receivers as a receiver for our messages. | ||
// Where to send our messages. | ||
// It can be direct or stream message | ||
zulipService.AddReceivers(zulip.Direct("[email protected]")) | ||
zulipService.AddReceivers(zulip.Stream("alerts", "critical")) | ||
|
||
// Tell our notifier to use the Zulip service. You can repeat the above process | ||
// for as many services as you like and just tell the notifier to use them. | ||
notifier.UseServices(zulipService) | ||
|
||
// Send a message | ||
err := notifier.Send( | ||
context.Background(), | ||
"Hello from notify :wave:\n", | ||
"Message written in Go!", | ||
) | ||
|
||
if err != nil { | ||
fmt.Println(err) | ||
} | ||
|
||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
package zulip | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
"io" | ||
"net/http" | ||
|
||
gzb "github.com/ifo/gozulipbot" | ||
"github.com/pkg/errors" | ||
) | ||
|
||
//go:generate mockery --name=zulipClient --output=. --case=underscore --inpackage | ||
type zulipClient interface { | ||
Message(gzb.Message) (*http.Response, error) | ||
} | ||
|
||
// Compile-time check to ensure that zulip message client implements the zulipClient interface. | ||
var _ zulipClient = new(gzb.Bot) | ||
|
||
// Zulip struct holds necessary data to communicate with the Zulip API. | ||
type Zulip struct { | ||
client zulipClient | ||
receivers []*Receiver | ||
} | ||
|
||
func New(domain, apiKey, botEmail string) *Zulip { | ||
client := &gzb.Bot{ | ||
APIURL: fmt.Sprintf("https://%s.zulipchat.com/api/v1/", domain), | ||
APIKey: apiKey, | ||
Email: botEmail, | ||
} | ||
|
||
client.Init() | ||
|
||
zulip := &Zulip{ | ||
client: client, | ||
receivers: make([]*Receiver, 0), | ||
} | ||
|
||
return zulip | ||
} | ||
|
||
func (z *Zulip) AddReceivers(receivers ...*Receiver) { | ||
z.receivers = append(z.receivers, receivers...) | ||
} | ||
|
||
func (z *Zulip) Send(ctx context.Context, subject, message string) error { | ||
fullMessage := subject + "\n" + message // Treating subject as message title | ||
|
||
for _, receiver := range z.receivers { | ||
select { | ||
case <-ctx.Done(): | ||
return ctx.Err() | ||
default: | ||
emails := make([]string, 0) | ||
if receiver.email != "" { | ||
emails = append(emails, receiver.email) | ||
} | ||
|
||
msg := gzb.Message{ | ||
Content: fullMessage, | ||
Emails: emails, | ||
Stream: receiver.stream, | ||
Topic: receiver.topic, | ||
} | ||
|
||
resp, err := z.client.Message(msg) | ||
if err != nil { | ||
return errors.Wrapf(err, "failed to send message to Zulip receiver") | ||
} | ||
defer resp.Body.Close() | ||
body, _ := io.ReadAll(resp.Body) | ||
|
||
switch resp.StatusCode { | ||
case http.StatusBadRequest: | ||
var errorResp ErrorResponse | ||
_ = json.Unmarshal(body, &errorResp) | ||
|
||
return errors.Errorf("failed to send message to Zulip receiver: %s", errorResp.Message) | ||
|
||
case http.StatusOK: | ||
break | ||
|
||
default: | ||
return errors.Errorf("failed to send message to Zulip receiver: %s", body) | ||
} | ||
} | ||
} | ||
|
||
return nil | ||
} |
Oops, something went wrong.