Add vendor matterbridge/gozulipbot
This commit is contained in:
256
vendor/github.com/matterbridge/gozulipbot/bot.go
generated
vendored
Normal file
256
vendor/github.com/matterbridge/gozulipbot/bot.go
generated
vendored
Normal file
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user