summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/matterbridge/gozulipbot/bot.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/matterbridge/gozulipbot/bot.go')
-rw-r--r--vendor/github.com/matterbridge/gozulipbot/bot.go256
1 files changed, 256 insertions, 0 deletions
diff --git a/vendor/github.com/matterbridge/gozulipbot/bot.go b/vendor/github.com/matterbridge/gozulipbot/bot.go
new file mode 100644
index 00000000..24bc8768
--- /dev/null
+++ b/vendor/github.com/matterbridge/gozulipbot/bot.go
@@ -0,0 +1,256 @@
+package gozulipbot
+
+import (
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "strings"
+ "time"
+)
+
+type Bot struct {
+ APIKey string
+ APIURL string
+ Email string
+ Queues []*Queue
+ Streams []string
+ Client Doer
+ Backoff time.Duration
+ Retries int64
+}
+
+type Doer interface {
+ Do(*http.Request) (*http.Response, error)
+}
+
+// Init adds an http client to an existing bot struct.
+func (b *Bot) Init() *Bot {
+ b.Client = &http.Client{}
+ return b
+}
+
+// GetStreamList gets the raw http response when requesting all public streams.
+func (b *Bot) GetStreamList() (*http.Response, error) {
+ req, err := b.constructRequest("GET", "streams", "")
+ if err != nil {
+ return nil, err
+ }
+
+ return b.Client.Do(req)
+}
+
+type StreamJSON struct {
+ Msg string `json:"msg"`
+ Streams []struct {
+ StreamID int `json:"stream_id"`
+ InviteOnly bool `json:"invite_only"`
+ Description string `json:"description"`
+ Name string `json:"name"`
+ } `json:"streams"`
+ Result string `json:"result"`
+}
+
+// GetStreams returns a list of all public streams
+func (b *Bot) GetStreams() ([]string, error) {
+ resp, err := b.GetStreamList()
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+ body, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ return nil, err
+ }
+
+ var sj StreamJSON
+ err = json.Unmarshal(body, &sj)
+ if err != nil {
+ return nil, err
+ }
+
+ var streams []string
+ for _, s := range sj.Streams {
+ streams = append(streams, s.Name)
+ }
+
+ return streams, nil
+}
+
+// GetStreams returns a list of all public streams
+func (b *Bot) GetRawStreams() (StreamJSON, error) {
+ var sj StreamJSON
+ resp, err := b.GetStreamList()
+ if err != nil {
+ return sj, err
+ }
+ defer resp.Body.Close()
+ body, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ return sj, err
+ }
+
+ err = json.Unmarshal(body, &sj)
+ if err != nil {
+ return sj, err
+ }
+ return sj, nil
+}
+
+// Subscribe will set the bot to receive messages from the given streams.
+// If no streams are given, it will subscribe the bot to the streams in the bot struct.
+func (b *Bot) Subscribe(streams []string) (*http.Response, error) {
+ if streams == nil {
+ streams = b.Streams
+ }
+
+ var toSubStreams []map[string]string
+ for _, name := range streams {
+ toSubStreams = append(toSubStreams, map[string]string{"name": name})
+ }
+
+ bodyBts, err := json.Marshal(toSubStreams)
+ if err != nil {
+ return nil, err
+ }
+
+ body := "subscriptions=" + string(bodyBts)
+
+ req, err := b.constructRequest("POST", "users/me/subscriptions", body)
+ if err != nil {
+ return nil, err
+ }
+
+ return b.Client.Do(req)
+}
+
+// Unsubscribe will remove the bot from the given streams.
+// If no streams are given, nothing will happen and the function will error.
+func (b *Bot) Unsubscribe(streams []string) (*http.Response, error) {
+ if len(streams) == 0 {
+ return nil, fmt.Errorf("No streams were provided")
+ }
+
+ body := `delete=["` + strings.Join(streams, `","`) + `"]`
+
+ req, err := b.constructRequest("PATCH", "users/me/subscriptions", body)
+ if err != nil {
+ return nil, err
+ }
+
+ return b.Client.Do(req)
+}
+
+func (b *Bot) ListSubscriptions() (*http.Response, error) {
+ req, err := b.constructRequest("GET", "users/me/subscriptions", "")
+ if err != nil {
+ return nil, err
+ }
+
+ return b.Client.Do(req)
+}
+
+type EventType string
+
+const (
+ Messages EventType = "messages"
+ Subscriptions EventType = "subscriptions"
+ RealmUser EventType = "realm_user"
+ Pointer EventType = "pointer"
+)
+
+type Narrow string
+
+const (
+ NarrowPrivate Narrow = `[["is", "private"]]`
+ NarrowAt Narrow = `[["is", "mentioned"]]`
+)
+
+// RegisterEvents adds a queue to the bot. It includes the EventTypes and
+// Narrow given. If neither is given, it will default to all Messages.
+func (b *Bot) RegisterEvents(ets []EventType, n Narrow) (*Queue, error) {
+ resp, err := b.RawRegisterEvents(ets, n)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+
+ body, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ return nil, err
+ }
+
+ q := &Queue{Bot: b}
+ err = json.Unmarshal(body, q)
+ if err != nil {
+ return nil, err
+ }
+
+ if q.LastEventID < q.MaxMessageID {
+ q.LastEventID = q.MaxMessageID
+ }
+
+ b.Queues = append(b.Queues, q)
+
+ return q, nil
+}
+
+func (b *Bot) RegisterAll() (*Queue, error) {
+ return b.RegisterEvents(nil, "")
+}
+
+func (b *Bot) RegisterAt() (*Queue, error) {
+ return b.RegisterEvents(nil, NarrowAt)
+}
+
+func (b *Bot) RegisterPrivate() (*Queue, error) {
+ return b.RegisterEvents(nil, NarrowPrivate)
+}
+
+func (b *Bot) RegisterSubscriptions() (*Queue, error) {
+ events := []EventType{Subscriptions}
+ return b.RegisterEvents(events, "")
+}
+
+// RawRegisterEvents tells Zulip to include message events in the bots events queue.
+// Passing nil as the slice of EventType will default to receiving Messages
+func (b *Bot) RawRegisterEvents(ets []EventType, n Narrow) (*http.Response, error) {
+ // default to Messages if no EventTypes given
+ query := `event_types=["message"]`
+
+ if len(ets) != 0 {
+ query = `event_types=["`
+ for i, s := range ets {
+ query += fmt.Sprintf("%s", s)
+ if i != len(ets)-1 {
+ query += `", "`
+ }
+ }
+ query += `"]`
+ }
+
+ if n != "" {
+ query += fmt.Sprintf("&narrow=%s", n)
+ }
+ query += fmt.Sprintf("&all_public_streams=true")
+ req, err := b.constructRequest("POST", "register", query)
+ if err != nil {
+ return nil, err
+ }
+
+ return b.Client.Do(req)
+}
+
+// constructRequest makes a zulip request and ensures the proper headers are set.
+func (b *Bot) constructRequest(method, endpoint, body string) (*http.Request, error) {
+ url := b.APIURL + endpoint
+ req, err := http.NewRequest(method, url, strings.NewReader(body))
+ if err != nil {
+ return nil, err
+ }
+
+ req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
+ req.SetBasicAuth(b.Email, b.APIKey)
+
+ return req, nil
+}