From 6ebd5cbbd8a941e0bc5f99f0d8e99cfd1d8ac0d7 Mon Sep 17 00:00:00 2001 From: Wim Date: Sun, 10 Feb 2019 17:00:11 +0100 Subject: Refactor and update RocketChat bridge * Add support for editing/deleting messages * Add support for uploading files * Add support for avatars * Use the Rocket.Chat.Go.SDK * Use the rest and streaming api --- .../Rocket.Chat.Go.SDK/models/channel.go | 39 +++ .../matterbridge/Rocket.Chat.Go.SDK/models/info.go | 133 +++++++++++ .../Rocket.Chat.Go.SDK/models/message.go | 75 ++++++ .../Rocket.Chat.Go.SDK/models/permission.go | 7 + .../Rocket.Chat.Go.SDK/models/setting.go | 21 ++ .../matterbridge/Rocket.Chat.Go.SDK/models/user.go | 29 +++ .../Rocket.Chat.Go.SDK/models/userCredentials.go | 10 + .../Rocket.Chat.Go.SDK/realtime/channels.go | 263 +++++++++++++++++++++ .../Rocket.Chat.Go.SDK/realtime/client.go | 96 ++++++++ .../Rocket.Chat.Go.SDK/realtime/emoji.go | 10 + .../Rocket.Chat.Go.SDK/realtime/events.go | 21 ++ .../Rocket.Chat.Go.SDK/realtime/messages.go | 240 +++++++++++++++++++ .../Rocket.Chat.Go.SDK/realtime/permissions.go | 54 +++++ .../Rocket.Chat.Go.SDK/realtime/settings.go | 53 +++++ .../Rocket.Chat.Go.SDK/realtime/subscriptions.go | 41 ++++ .../Rocket.Chat.Go.SDK/realtime/users.go | 103 ++++++++ .../Rocket.Chat.Go.SDK/rest/channels.go | 64 +++++ .../matterbridge/Rocket.Chat.Go.SDK/rest/client.go | 176 ++++++++++++++ .../Rocket.Chat.Go.SDK/rest/information.go | 98 ++++++++ .../Rocket.Chat.Go.SDK/rest/messages.go | 67 ++++++ .../matterbridge/Rocket.Chat.Go.SDK/rest/users.go | 145 ++++++++++++ 21 files changed, 1745 insertions(+) create mode 100644 vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/models/channel.go create mode 100644 vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/models/info.go create mode 100644 vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/models/message.go create mode 100644 vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/models/permission.go create mode 100644 vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/models/setting.go create mode 100644 vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/models/user.go create mode 100644 vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/models/userCredentials.go create mode 100644 vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime/channels.go create mode 100644 vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime/client.go create mode 100644 vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime/emoji.go create mode 100644 vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime/events.go create mode 100644 vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime/messages.go create mode 100644 vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime/permissions.go create mode 100644 vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime/settings.go create mode 100644 vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime/subscriptions.go create mode 100644 vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime/users.go create mode 100644 vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/rest/channels.go create mode 100644 vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/rest/client.go create mode 100644 vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/rest/information.go create mode 100644 vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/rest/messages.go create mode 100644 vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/rest/users.go (limited to 'vendor/github.com/matterbridge') diff --git a/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/models/channel.go b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/models/channel.go new file mode 100644 index 00000000..c6579ece --- /dev/null +++ b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/models/channel.go @@ -0,0 +1,39 @@ +package models + +import "time" + +type Channel struct { + ID string `json:"_id"` + Name string `json:"name"` + Fname string `json:"fname,omitempty"` + Type string `json:"t"` + Msgs int `json:"msgs"` + + ReadOnly bool `json:"ro,omitempty"` + SysMes bool `json:"sysMes,omitempty"` + Default bool `json:"default"` + Broadcast bool `json:"broadcast,omitempty"` + + Timestamp *time.Time `json:"ts,omitempty"` + UpdatedAt *time.Time `json:"_updatedAt,omitempty"` + + User *User `json:"u,omitempty"` + LastMessage *Message `json:"lastMessage,omitempty"` + + // Lm interface{} `json:"lm"` + // CustomFields struct { + // } `json:"customFields,omitempty"` +} + +type ChannelSubscription struct { + ID string `json:"_id"` + Alert bool `json:"alert"` + Name string `json:"name"` + DisplayName string `json:"fname"` + Open bool `json:"open"` + RoomId string `json:"rid"` + Type string `json:"c"` + User User `json:"u"` + Roles []string `json:"roles"` + Unread float64 `json:"unread"` +} diff --git a/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/models/info.go b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/models/info.go new file mode 100644 index 00000000..fb99e7c2 --- /dev/null +++ b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/models/info.go @@ -0,0 +1,133 @@ +package models + +import "time" + +type Info struct { + Version string `json:"version"` + + Build struct { + NodeVersion string `json:"nodeVersion"` + Arch string `json:"arch"` + Platform string `json:"platform"` + Cpus int `json:"cpus"` + } `json:"build"` + + Commit struct { + Hash string `json:"hash"` + Date string `json:"date"` + Author string `json:"author"` + Subject string `json:"subject"` + Tag string `json:"tag"` + Branch string `json:"branch"` + } `json:"commit"` +} + +type Pagination struct { + Count int `json:"count"` + Offset int `json:"offset"` + Total int `json:"total"` +} + +type Directory struct { + Result []struct { + ID string `json:"_id"` + CreatedAt time.Time `json:"createdAt"` + Emails []struct { + Address string `json:"address"` + Verified bool `json:"verified"` + } `json:"emails"` + Name string `json:"name"` + Username string `json:"username"` + } `json:"result"` + + Pagination +} + +type Spotlight struct { + Users []User `json:"users"` + Rooms []Channel `json:"rooms"` +} + +type Statistics struct { + ID string `json:"_id"` + UniqueID string `json:"uniqueId"` + Version string `json:"version"` + + ActiveUsers int `json:"activeUsers"` + NonActiveUsers int `json:"nonActiveUsers"` + OnlineUsers int `json:"onlineUsers"` + AwayUsers int `json:"awayUsers"` + OfflineUsers int `json:"offlineUsers"` + TotalUsers int `json:"totalUsers"` + + TotalRooms int `json:"totalRooms"` + TotalChannels int `json:"totalChannels"` + TotalPrivateGroups int `json:"totalPrivateGroups"` + TotalDirect int `json:"totalDirect"` + TotlalLivechat int `json:"totlalLivechat"` + TotalMessages int `json:"totalMessages"` + TotalChannelMessages int `json:"totalChannelMessages"` + TotalPrivateGroupMessages int `json:"totalPrivateGroupMessages"` + TotalDirectMessages int `json:"totalDirectMessages"` + TotalLivechatMessages int `json:"totalLivechatMessages"` + + InstalledAt time.Time `json:"installedAt"` + LastLogin time.Time `json:"lastLogin"` + LastMessageSentAt time.Time `json:"lastMessageSentAt"` + LastSeenSubscription time.Time `json:"lastSeenSubscription"` + + Os struct { + Type string `json:"type"` + Platform string `json:"platform"` + Arch string `json:"arch"` + Release string `json:"release"` + Uptime int `json:"uptime"` + Loadavg []float64 `json:"loadavg"` + Totalmem int64 `json:"totalmem"` + Freemem int `json:"freemem"` + Cpus []struct { + Model string `json:"model"` + Speed int `json:"speed"` + Times struct { + User int `json:"user"` + Nice int `json:"nice"` + Sys int `json:"sys"` + Idle int `json:"idle"` + Irq int `json:"irq"` + } `json:"times"` + } `json:"cpus"` + } `json:"os"` + + Process struct { + NodeVersion string `json:"nodeVersion"` + Pid int `json:"pid"` + Uptime float64 `json:"uptime"` + } `json:"process"` + + Deploy struct { + Method string `json:"method"` + Platform string `json:"platform"` + } `json:"deploy"` + + Migration struct { + ID string `json:"_id"` + Version int `json:"version"` + Locked bool `json:"locked"` + LockedAt time.Time `json:"lockedAt"` + BuildAt time.Time `json:"buildAt"` + } `json:"migration"` + + InstanceCount int `json:"instanceCount"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"_updatedAt"` +} + +type StatisticsInfo struct { + Statistics Statistics `json:"statistics"` +} + +type StatisticsList struct { + Statistics []Statistics `json:"statistics"` + + Pagination +} diff --git a/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/models/message.go b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/models/message.go new file mode 100644 index 00000000..8be3e3b6 --- /dev/null +++ b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/models/message.go @@ -0,0 +1,75 @@ +package models + +import "time" + +type Message struct { + ID string `json:"_id"` + RoomID string `json:"rid"` + Msg string `json:"msg"` + EditedBy string `json:"editedBy,omitempty"` + + Groupable bool `json:"groupable,omitempty"` + + EditedAt *time.Time `json:"editedAt,omitempty"` + Timestamp *time.Time `json:"ts,omitempty"` + UpdatedAt *time.Time `json:"_updatedAt,omitempty"` + + Mentions []User `json:"mentions,omitempty"` + User *User `json:"u,omitempty"` + PostMessage + + // Bot interface{} `json:"bot"` + // CustomFields interface{} `json:"customFields"` + // Channels []interface{} `json:"channels"` + // SandstormSessionID interface{} `json:"sandstormSessionId"` +} + +// PostMessage Payload for postmessage rest API +// +// https://rocket.chat/docs/developer-guides/rest-api/chat/postmessage/ +type PostMessage struct { + RoomID string `json:"roomId,omitempty"` + Channel string `json:"channel,omitempty"` + Text string `json:"text,omitempty"` + ParseUrls bool `json:"parseUrls,omitempty"` + Alias string `json:"alias,omitempty"` + Emoji string `json:"emoji,omitempty"` + Avatar string `json:"avatar,omitempty"` + Attachments []Attachment `json:"attachments,omitempty"` +} + +// Attachment Payload for postmessage rest API +// +// https://rocket.chat/docs/developer-guides/rest-api/chat/postmessage/ +type Attachment struct { + Color string `json:"color,omitempty"` + Text string `json:"text,omitempty"` + Timestamp string `json:"ts,omitempty"` + ThumbURL string `json:"thumb_url,omitempty"` + MessageLink string `json:"message_link,omitempty"` + Collapsed bool `json:"collapsed"` + + AuthorName string `json:"author_name,omitempty"` + AuthorLink string `json:"author_link,omitempty"` + AuthorIcon string `json:"author_icon,omitempty"` + + Title string `json:"title,omitempty"` + TitleLink string `json:"title_link,omitempty"` + TitleLinkDownload string `json:"title_link_download,omitempty"` + + ImageURL string `json:"image_url,omitempty"` + + AudioURL string `json:"audio_url,omitempty"` + VideoURL string `json:"video_url,omitempty"` + + Fields []AttachmentField `json:"fields,omitempty"` +} + +// AttachmentField Payload for postmessage rest API +// +// https://rocket.chat/docs/developer-guides/rest-api/chat/postmessage/ +type AttachmentField struct { + Short bool `json:"short"` + Title string `json:"title"` + Value string `json:"value"` +} diff --git a/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/models/permission.go b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/models/permission.go new file mode 100644 index 00000000..052bad8a --- /dev/null +++ b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/models/permission.go @@ -0,0 +1,7 @@ +package models + +type Permission struct { + ID string `json:"_id"` + UpdatedAt string `json:"_updatedAt.$date"` + Roles []string `json:"roles"` +} diff --git a/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/models/setting.go b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/models/setting.go new file mode 100644 index 00000000..aeacb385 --- /dev/null +++ b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/models/setting.go @@ -0,0 +1,21 @@ +package models + +type Setting struct { + ID string `json:"_id"` + Blocked bool `json:"blocked"` + Group string `json:"group"` + Hidden bool `json:"hidden"` + Public bool `json:"public"` + Type string `json:"type"` + PackageValue string `json:"packageValue"` + Sorter int `json:"sorter"` + Value string `json:"value"` + ValueBool bool `json:"valueBool"` + ValueInt float64 `json:"valueInt"` + ValueSource string `json:"valueSource"` + ValueAsset Asset `json:"asset"` +} + +type Asset struct { + DefaultUrl string `json:"defaultUrl"` +} diff --git a/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/models/user.go b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/models/user.go new file mode 100644 index 00000000..ee56bdc3 --- /dev/null +++ b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/models/user.go @@ -0,0 +1,29 @@ +package models + +type User struct { + ID string `json:"_id"` + Name string `json:"name"` + UserName string `json:"username"` + Status string `json:"status"` + Token string `json:"token"` + TokenExpires int64 `json:"tokenExpires"` +} + +type CreateUserRequest struct { + Name string `json:"name"` + Email string `json:"email"` + Password string `json:"password"` + Username string `json:"username"` + CustomFields map[string]string `json:"customFields,omitempty"` +} + +type UpdateUserRequest struct { + UserID string `json:"userId"` + Data struct { + Name string `json:"name"` + Email string `json:"email"` + Password string `json:"password"` + Username string `json:"username"` + CustomFields map[string]string `json:"customFields,omitempty"` + } `json:"data"` +} diff --git a/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/models/userCredentials.go b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/models/userCredentials.go new file mode 100644 index 00000000..296e26fb --- /dev/null +++ b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/models/userCredentials.go @@ -0,0 +1,10 @@ +package models + +type UserCredentials struct { + ID string `json:"id"` + Token string `json:"token"` + + Email string `json:"email"` + Name string `json:"name"` + Password string `json:"pass"` +} diff --git a/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime/channels.go b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime/channels.go new file mode 100644 index 00000000..5779cb38 --- /dev/null +++ b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime/channels.go @@ -0,0 +1,263 @@ +package realtime + +import ( + "github.com/Jeffail/gabs" + "github.com/matterbridge/Rocket.Chat.Go.SDK/models" +) + +func (c *Client) GetChannelId(name string) (string, error) { + rawResponse, err := c.ddp.Call("getRoomIdByNameOrId", name) + if err != nil { + return "", err + } + + //log.Println(rawResponse) + + return rawResponse.(string), nil +} + +// GetChannelsIn returns list of channels +// Optionally includes date to get all since last check or 0 to get all +// +// https://rocket.chat/docs/developer-guides/realtime-api/method-calls/get-rooms/ +func (c *Client) GetChannelsIn() ([]models.Channel, error) { + rawResponse, err := c.ddp.Call("rooms/get", map[string]int{ + "$date": 0, + }) + if err != nil { + return nil, err + } + + document, _ := gabs.Consume(rawResponse.(map[string]interface{})["update"]) + + chans, err := document.Children() + + var channels []models.Channel + + for _, i := range chans { + channels = append(channels, models.Channel{ + ID: stringOrZero(i.Path("_id").Data()), + //Default: stringOrZero(i.Path("default").Data()), + Name: stringOrZero(i.Path("name").Data()), + Type: stringOrZero(i.Path("t").Data()), + }) + } + + return channels, nil +} + +// GetChannelSubscriptions gets users channel subscriptions +// Optionally includes date to get all since last check or 0 to get all +// +// https://rocket.chat/docs/developer-guides/realtime-api/method-calls/get-subscriptions +func (c *Client) GetChannelSubscriptions() ([]models.ChannelSubscription, error) { + rawResponse, err := c.ddp.Call("subscriptions/get", map[string]int{ + "$date": 0, + }) + if err != nil { + return nil, err + } + + document, _ := gabs.Consume(rawResponse.(map[string]interface{})["update"]) + + channelSubs, err := document.Children() + + var channelSubscriptions []models.ChannelSubscription + + for _, sub := range channelSubs { + channelSubscription := models.ChannelSubscription{ + ID: stringOrZero(sub.Path("_id").Data()), + Alert: sub.Path("alert").Data().(bool), + Name: stringOrZero(sub.Path("name").Data()), + DisplayName: stringOrZero(sub.Path("fname").Data()), + Open: sub.Path("open").Data().(bool), + Type: stringOrZero(sub.Path("t").Data()), + User: models.User{ + ID: stringOrZero(sub.Path("u._id").Data()), + UserName: stringOrZero(sub.Path("u.username").Data()), + }, + Unread: sub.Path("unread").Data().(float64), + } + + if sub.Path("roles").Data() != nil { + var roles []string + for _, role := range sub.Path("roles").Data().([]interface{}) { + roles = append(roles, role.(string)) + } + + channelSubscription.Roles = roles + } + + channelSubscriptions = append(channelSubscriptions, channelSubscription) + } + + return channelSubscriptions, nil +} + +// GetChannelRoles returns room roles +// +// https://rocket.chat/docs/developer-guides/realtime-api/method-calls/get-room-roles +func (c *Client) GetChannelRoles(roomId string) error { + _, err := c.ddp.Call("getRoomRoles", roomId) + if err != nil { + return err + } + + return nil +} + +// CreateChannel creates a channel +// Takes name and users array +// +// https://rocket.chat/docs/developer-guides/realtime-api/method-calls/create-channels +func (c *Client) CreateChannel(name string, users []string) error { + _, err := c.ddp.Call("createChannel", name, users) + if err != nil { + return err + } + + return nil +} + +// CreateGroup creates a private group +// Takes group name and array of users +// +// https://rocket.chat/docs/developer-guides/realtime-api/method-calls/create-private-groups +func (c *Client) CreateGroup(name string, users []string) error { + _, err := c.ddp.Call("createPrivateGroup", name, users) + if err != nil { + return err + } + + return nil +} + +// JoinChannel joins a channel +// Takes roomId +// +// https://rocket.chat/docs/developer-guides/realtime-api/method-calls/joining-channels +func (c *Client) JoinChannel(roomId string) error { + _, err := c.ddp.Call("joinRoom", roomId) + if err != nil { + return err + } + + return nil +} + +// LeaveChannel leaves a channel +// Takes roomId +// +// https://rocket.chat/docs/developer-guides/realtime-api/method-calls/leaving-rooms +func (c *Client) LeaveChannel(roomId string) error { + _, err := c.ddp.Call("leaveRoom", roomId) + if err != nil { + return err + } + + return nil +} + +// ArchiveChannel archives the channel +// Takes roomId +// +// https://rocket.chat/docs/developer-guides/realtime-api/method-calls/archive-rooms +func (c *Client) ArchiveChannel(roomId string) error { + _, err := c.ddp.Call("archiveRoom", roomId) + if err != nil { + return err + } + + return nil +} + +// UnArchiveChannel unarchives the channel +// Takes roomId +// +// https://rocket.chat/docs/developer-guides/realtime-api/method-calls/unarchive-rooms +func (c *Client) UnArchiveChannel(roomId string) error { + _, err := c.ddp.Call("unarchiveRoom", roomId) + if err != nil { + return err + } + + return nil +} + +// DeleteChannel deletes the channel +// Takes roomId +// +// https://rocket.chat/docs/developer-guides/realtime-api/method-calls/delete-rooms +func (c *Client) DeleteChannel(roomId string) error { + _, err := c.ddp.Call("eraseRoom", roomId) + if err != nil { + return err + } + + return nil +} + +// SetChannelTopic sets channel topic +// takes roomId and topic +// +// https://rocket.chat/docs/developer-guides/realtime-api/method-calls/save-room-settings +func (c *Client) SetChannelTopic(roomId string, topic string) error { + _, err := c.ddp.Call("saveRoomSettings", roomId, "roomTopic", topic) + if err != nil { + return err + } + + return nil +} + +// SetChannelType sets the channel type +// takes roomId and roomType +// +// https://rocket.chat/docs/developer-guides/realtime-api/method-calls/save-room-settings +func (c *Client) SetChannelType(roomId string, roomType string) error { + _, err := c.ddp.Call("saveRoomSettings", roomId, "roomType", roomType) + if err != nil { + return err + } + + return nil +} + +// SetChannelJoinCode sets channel join code +// takes roomId and joinCode +// +// https://rocket.chat/docs/developer-guides/realtime-api/method-calls/save-room-settings +func (c *Client) SetChannelJoinCode(roomId string, joinCode string) error { + _, err := c.ddp.Call("saveRoomSettings", roomId, "joinCode", joinCode) + if err != nil { + return err + } + + return nil +} + +// SetChannelReadOnly sets channel as read only +// takes roomId and boolean +// +// https://rocket.chat/docs/developer-guides/realtime-api/method-calls/save-room-settings +func (c *Client) SetChannelReadOnly(roomId string, readOnly bool) error { + _, err := c.ddp.Call("saveRoomSettings", roomId, "readOnly", readOnly) + if err != nil { + return err + } + + return nil +} + +// SetChannelDescription sets channels description +// takes roomId and description +// +// https://rocket.chat/docs/developer-guides/realtime-api/method-calls/save-room-settings +func (c *Client) SetChannelDescription(roomId string, description string) error { + _, err := c.ddp.Call("saveRoomSettings", roomId, "roomDescription", description) + if err != nil { + return err + } + + return nil +} diff --git a/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime/client.go b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime/client.go new file mode 100644 index 00000000..1dde80bf --- /dev/null +++ b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime/client.go @@ -0,0 +1,96 @@ +// Provides access to Rocket.Chat's realtime API via ddp +package realtime + +import ( + "fmt" + "math/rand" + "net/url" + "strconv" + "time" + + "github.com/gopackage/ddp" +) + +type Client struct { + ddp *ddp.Client +} + +// Creates a new instance and connects to the websocket. +func NewClient(serverURL *url.URL, debug bool) (*Client, error) { + rand.Seed(time.Now().UTC().UnixNano()) + + wsURL := "ws" + port := 80 + + if serverURL.Scheme == "https" { + wsURL = "wss" + port = 443 + } + + if len(serverURL.Port()) > 0 { + port, _ = strconv.Atoi(serverURL.Port()) + } + + wsURL = fmt.Sprintf("%s://%v:%v%s/websocket", wsURL, serverURL.Hostname(), port, serverURL.Path) + + // log.Println("About to connect to:", wsURL, port, serverURL.Scheme) + + c := new(Client) + c.ddp = ddp.NewClient(wsURL, serverURL.String()) + + if debug { + c.ddp.SetSocketLogActive(true) + } + + if err := c.ddp.Connect(); err != nil { + return nil, err + } + + return c, nil +} + +type statusListener struct { + listener func(int) +} + +func (s statusListener) Status(status int) { + s.listener(status) +} + +func (c *Client) AddStatusListener(listener func(int)) { + c.ddp.AddStatusListener(statusListener{listener: listener}) +} + +func (c *Client) Reconnect() { + c.ddp.Reconnect() +} + +// ConnectionAway sets connection status to away +func (c *Client) ConnectionAway() error { + _, err := c.ddp.Call("UserPresence:away") + if err != nil { + return err + } + + return nil +} + +// ConnectionOnline sets connection status to online +func (c *Client) ConnectionOnline() error { + _, err := c.ddp.Call("UserPresence:online") + if err != nil { + return err + } + + return nil +} + +// Close closes the ddp session +func (c *Client) Close() { + c.ddp.Close() +} + +// Some of the rocketchat objects need unique IDs specified by the client +func (c *Client) newRandomId() string { + return fmt.Sprintf("%f", rand.Float64()) +} diff --git a/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime/emoji.go b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime/emoji.go new file mode 100644 index 00000000..90f2c6ee --- /dev/null +++ b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime/emoji.go @@ -0,0 +1,10 @@ +package realtime + +func (c *Client) getCustomEmoji() error { + _, err := c.ddp.Call("listEmojiCustom") + if err != nil { + return err + } + + return nil +} diff --git a/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime/events.go b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime/events.go new file mode 100644 index 00000000..f3c945cf --- /dev/null +++ b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime/events.go @@ -0,0 +1,21 @@ +package realtime + +import "fmt" + +func (c *Client) StartTyping(roomId string, username string) error { + _, err := c.ddp.Call("stream-notify-room", fmt.Sprintf("%s/typing", roomId), username, true) + if err != nil { + return err + } + + return nil +} + +func (c *Client) StopTyping(roomId string, username string) error { + _, err := c.ddp.Call("stream-notify-room", fmt.Sprintf("%s/typing", roomId), username, false) + if err != nil { + return err + } + + return nil +} diff --git a/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime/messages.go b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime/messages.go new file mode 100644 index 00000000..9c0c9bb4 --- /dev/null +++ b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime/messages.go @@ -0,0 +1,240 @@ +package realtime + +import ( + "fmt" + "strconv" + "time" + + "github.com/Jeffail/gabs" + "github.com/gopackage/ddp" + "github.com/matterbridge/Rocket.Chat.Go.SDK/models" +) + +const ( + // RocketChat doesn't send the `added` event for new messages by default, only `changed`. + send_added_event = true + default_buffer_size = 100 +) + +// LoadHistory loads history +// Takes roomId +// +// https://rocket.chat/docs/developer-guides/realtime-api/method-calls/load-history +func (c *Client) LoadHistory(roomId string) error { + _, err := c.ddp.Call("loadHistory", roomId) + if err != nil { + return err + } + + return nil +} + +// SendMessage sends message to channel +// takes channel and message +// +// https://rocket.chat/docs/developer-guides/realtime-api/method-calls/send-message +func (c *Client) SendMessage(m *models.Message) (*models.Message, error) { + m.ID = c.newRandomId() + + rawResponse, err := c.ddp.Call("sendMessage", m) + if err != nil { + return nil, err + } + + return getMessageFromData(rawResponse.(map[string]interface{})), nil +} + +// EditMessage edits a message +// takes message object +// +// https://rocket.chat/docs/developer-guides/realtime-api/method-calls/update-message +func (c *Client) EditMessage(message *models.Message) error { + _, err := c.ddp.Call("updateMessage", message) + if err != nil { + return err + } + + return nil +} + +// DeleteMessage deletes a message +// takes a message object +// +// https://rocket.chat/docs/developer-guides/realtime-api/method-calls/delete-message +func (c *Client) DeleteMessage(message *models.Message) error { + _, err := c.ddp.Call("deleteMessage", map[string]string{ + "_id": message.ID, + }) + if err != nil { + return err + } + + return nil +} + +// ReactToMessage adds a reaction to a message +// takes a message and emoji +// +// https://rocket.chat/docs/developer-guides/realtime-api/method-calls/set-reaction +func (c *Client) ReactToMessage(message *models.Message, reaction string) error { + _, err := c.ddp.Call("setReaction", reaction, message.ID) + if err != nil { + return err + } + + return nil +} + +// StarMessage stars message +// takes a message object +// +// https://rocket.chat/docs/developer-guides/realtime-api/method-calls/star-message +func (c *Client) StarMessage(message *models.Message) error { + _, err := c.ddp.Call("starMessage", map[string]interface{}{ + "_id": message.ID, + "rid": message.RoomID, + "starred": true, + }) + + if err != nil { + return err + } + + return nil +} + +// UnStarMessage unstars message +// takes message object +// +// https://rocket.chat/docs/developer-guides/realtime-api/method-calls/star-message +func (c *Client) UnStarMessage(message *models.Message) error { + _, err := c.ddp.Call("starMessage", map[string]interface{}{ + "_id": message.ID, + "rid": message.RoomID, + "starred": false, + }) + + if err != nil { + return err + } + + return nil +} + +// PinMessage pins a message +// takes a message object +// +// https://rocket.chat/docs/developer-guides/realtime-api/method-calls/pin-message +func (c *Client) PinMessage(message *models.Message) error { + _, err := c.ddp.Call("pinMessage", message) + + if err != nil { + return err + } + + return nil +} + +// UnPinMessage unpins message +// takes a message object +// +// https://rocket.chat/docs/developer-guides/realtime-api/method-calls/unpin-messages +func (c *Client) UnPinMessage(message *models.Message) error { + _, err := c.ddp.Call("unpinMessage", message) + + if err != nil { + return err + } + + return nil +} + +// SubscribeToMessageStream Subscribes to the message updates of a channel +// Returns a buffered channel +// +// https://rocket.chat/docs/developer-guides/realtime-api/subscriptions/stream-room-messages/ +func (c *Client) SubscribeToMessageStream(channel *models.Channel, msgChannel chan models.Message) error { + + if err := c.ddp.Sub("stream-room-messages", channel.ID, send_added_event); err != nil { + return err + } + + //msgChannel := make(chan models.Message, default_buffer_size) + c.ddp.CollectionByName("stream-room-messages").AddUpdateListener(messageExtractor{msgChannel, "update"}) + + return nil +} + +func getMessagesFromUpdateEvent(update ddp.Update) []models.Message { + document, _ := gabs.Consume(update["args"]) + args, err := document.Children() + + if err != nil { + // log.Printf("Event arguments are in an unexpected format: %v", err) + return make([]models.Message, 0) + } + + messages := make([]models.Message, len(args)) + + for i, arg := range args { + messages[i] = *getMessageFromDocument(arg) + } + + return messages +} + +func getMessageFromData(data interface{}) *models.Message { + // TODO: We should know what this will look like, we shouldn't need to use gabs + document, _ := gabs.Consume(data) + return getMessageFromDocument(document) +} + +func getMessageFromDocument(arg *gabs.Container) *models.Message { + var ts *time.Time + date := stringOrZero(arg.Path("ts.$date").Data()) + if len(date) > 0 { + if ti, err := strconv.ParseFloat(date, 64); err == nil { + t := time.Unix(int64(ti)/1e3, int64(ti)%1e3) + ts = &t + } + } + return &models.Message{ + ID: stringOrZero(arg.Path("_id").Data()), + RoomID: stringOrZero(arg.Path("rid").Data()), + Msg: stringOrZero(arg.Path("msg").Data()), + Timestamp: ts, + User: &models.User{ + ID: stringOrZero(arg.Path("u._id").Data()), + UserName: stringOrZero(arg.Path("u.username").Data()), + }, + } +} + +func stringOrZero(i interface{}) string { + if i == nil { + return "" + } + + switch i.(type) { + case string: + return i.(string) + case float64: + return fmt.Sprintf("%f", i.(float64)) + default: + return "" + } +} + +type messageExtractor struct { + messageChannel chan models.Message + operation string +} + +func (u messageExtractor) CollectionUpdate(collection, operation, id string, doc ddp.Update) { + if operation == u.operation { + msgs := getMessagesFromUpdateEvent(doc) + for _, m := range msgs { + u.messageChannel <- m + } + } +} diff --git a/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime/permissions.go b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime/permissions.go new file mode 100644 index 00000000..fc5df3da --- /dev/null +++ b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime/permissions.go @@ -0,0 +1,54 @@ +package realtime + +import ( + "github.com/Jeffail/gabs" + "github.com/matterbridge/Rocket.Chat.Go.SDK/models" +) + +// GetPermissions gets permissions +// +// https://rocket.chat/docs/developer-guides/realtime-api/method-calls/get-permissions +func (c *Client) GetPermissions() ([]models.Permission, error) { + rawResponse, err := c.ddp.Call("permissions/get") + if err != nil { + return nil, err + } + + document, _ := gabs.Consume(rawResponse) + + perms, _ := document.Children() + + var permissions []models.Permission + + for _, permission := range perms { + var roles []string + for _, role := range permission.Path("roles").Data().([]interface{}) { + roles = append(roles, role.(string)) + } + + permissions = append(permissions, models.Permission{ + ID: stringOrZero(permission.Path("_id").Data()), + Roles: roles, + }) + } + + return permissions, nil +} + +// GetUserRoles gets current users roles +// +// https://rocket.chat/docs/developer-guides/realtime-api/method-calls/get-user-roles +func (c *Client) GetUserRoles() error { + rawResponse, err := c.ddp.Call("getUserRoles") + if err != nil { + return err + } + + document, _ := gabs.Consume(rawResponse) + + _, err = document.Children() + // TODO: Figure out if this function is even useful if so return it + //log.Println(roles) + + return nil +} diff --git a/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime/settings.go b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime/settings.go new file mode 100644 index 00000000..c37eedbd --- /dev/null +++ b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime/settings.go @@ -0,0 +1,53 @@ +package realtime + +import ( + "github.com/Jeffail/gabs" + "github.com/matterbridge/Rocket.Chat.Go.SDK/models" +) + +// GetPublicSettings gets public settings +// +// https://rocket.chat/docs/developer-guides/realtime-api/method-calls/get-public-settings +func (c *Client) GetPublicSettings() ([]models.Setting, error) { + rawResponse, err := c.ddp.Call("public-settings/get") + if err != nil { + return nil, err + } + + document, _ := gabs.Consume(rawResponse) + + sett, _ := document.Children() + + var settings []models.Setting + + for _, rawSetting := range sett { + setting := models.Setting{ + ID: stringOrZero(rawSetting.Path("_id").Data()), + Type: stringOrZero(rawSetting.Path("type").Data()), + } + + switch setting.Type { + case "boolean": + setting.ValueBool = rawSetting.Path("value").Data().(bool) + case "string": + setting.Value = stringOrZero(rawSetting.Path("value").Data()) + case "code": + setting.Value = stringOrZero(rawSetting.Path("value").Data()) + case "color": + setting.Value = stringOrZero(rawSetting.Path("value").Data()) + case "int": + setting.ValueInt = rawSetting.Path("value").Data().(float64) + case "asset": + setting.ValueAsset = models.Asset{ + DefaultUrl: stringOrZero(rawSetting.Path("value").Data().(map[string]interface{})["defaultUrl"]), + } + + default: + // log.Println(setting.Type, rawSetting.Path("value").Data()) + } + + settings = append(settings, setting) + } + + return settings, nil +} diff --git a/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime/subscriptions.go b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime/subscriptions.go new file mode 100644 index 00000000..5013e53d --- /dev/null +++ b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime/subscriptions.go @@ -0,0 +1,41 @@ +package realtime + +import ( + "fmt" + + "github.com/gopackage/ddp" +) + +// Subscribes to stream-notify-logged +// Returns a buffered channel +// +// https://rocket.chat/docs/developer-guides/realtime-api/subscriptions/stream-room-messages/ +func (c *Client) Sub(name string, args ...interface{}) (chan string, error) { + + if args == nil { + //log.Println("no args passed") + if err := c.ddp.Sub(name); err != nil { + return nil, err + } + } else { + if err := c.ddp.Sub(name, args[0], false); err != nil { + return nil, err + } + } + + msgChannel := make(chan string, default_buffer_size) + c.ddp.CollectionByName("stream-room-messages").AddUpdateListener(genericExtractor{msgChannel, "update"}) + + return msgChannel, nil +} + +type genericExtractor struct { + messageChannel chan string + operation string +} + +func (u genericExtractor) CollectionUpdate(collection, operation, id string, doc ddp.Update) { + if operation == u.operation { + u.messageChannel <- fmt.Sprintf("%s -> update", collection) + } +} diff --git a/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime/users.go b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime/users.go new file mode 100644 index 00000000..09a4f1f4 --- /dev/null +++ b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime/users.go @@ -0,0 +1,103 @@ +package realtime + +import ( + "crypto/sha256" + "encoding/hex" + "strconv" + + "github.com/Jeffail/gabs" + "github.com/matterbridge/Rocket.Chat.Go.SDK/models" +) + +type ddpLoginRequest struct { + User ddpUser `json:"user"` + Password ddpPassword `json:"password"` +} + +type ddpTokenLoginRequest struct { + Token string `json:"resume"` +} + +type ddpUser struct { + Email string `json:"email"` +} + +type ddpPassword struct { + Digest string `json:"digest"` + Algorithm string `json:"algorithm"` +} + +// RegisterUser a new user on the server. This function does not need a logged in user. The registered user gets logged in +// to set its username. +func (c *Client) RegisterUser(credentials *models.UserCredentials) (*models.User, error) { + + if _, err := c.ddp.Call("registerUser", credentials); err != nil { + return nil, err + } + + user, err := c.Login(credentials) + if err != nil { + return nil, err + } + + if _, err := c.ddp.Call("setUsername", credentials.Name); err != nil { + return nil, err + } + + return user, nil +} + +// Login a user. +// token shouldn't be nil, otherwise the password and the email are not allowed to be nil. +// +// https://rocket.chat/docs/developer-guides/realtime-api/method-calls/login/ +func (c *Client) Login(credentials *models.UserCredentials) (*models.User, error) { + var request interface{} + if credentials.Token != "" { + request = ddpTokenLoginRequest{ + Token: credentials.Token, + } + } else { + digest := sha256.Sum256([]byte(credentials.Password)) + request = ddpLoginRequest{ + User: ddpUser{Email: credentials.Email}, + Password: ddpPassword{ + Digest: hex.EncodeToString(digest[:]), + Algorithm: "sha-256", + }, + } + } + + rawResponse, err := c.ddp.Call("login", request) + if err != nil { + return nil, err + } + + user := getUserFromData(rawResponse.(map[string]interface{})) + if credentials.Token == "" { + credentials.ID, credentials.Token = user.ID, user.Token + } + + return user, nil +} + +func getUserFromData(data interface{}) *models.User { + document, _ := gabs.Consume(data) + + expires, _ := strconv.ParseFloat(stringOrZero(document.Path("tokenExpires.$date").Data()), 64) + return &models.User{ + ID: stringOrZero(document.Path("id").Data()), + Token: stringOrZero(document.Path("token").Data()), + TokenExpires: int64(expires), + } +} + +// SetPresence set user presence +func (c *Client) SetPresence(status string) error { + _, err := c.ddp.Call("UserPresence:setDefaultStatus", status) + if err != nil { + return err + } + + return nil +} diff --git a/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/rest/channels.go b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/rest/channels.go new file mode 100644 index 00000000..71377500 --- /dev/null +++ b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/rest/channels.go @@ -0,0 +1,64 @@ +package rest + +import ( + "bytes" + "fmt" + "net/url" + + "github.com/matterbridge/Rocket.Chat.Go.SDK/models" +) + +type ChannelsResponse struct { + Status + models.Pagination + Channels []models.Channel `json:"channels"` +} + +type ChannelResponse struct { + Status + Channel models.Channel `json:"channel"` +} + +// GetPublicChannels returns all channels that can be seen by the logged in user. +// +// https://rocket.chat/docs/developer-guides/rest-api/channels/list +func (c *Client) GetPublicChannels() (*ChannelsResponse, error) { + response := new(ChannelsResponse) + if err := c.Get("channels.list", nil, response); err != nil { + return nil, err + } + + return response, nil +} + +// GetJoinedChannels returns all channels that the user has joined. +// +// https://rocket.chat/docs/developer-guides/rest-api/channels/list-joined +func (c *Client) GetJoinedChannels(params url.Values) (*ChannelsResponse, error) { + response := new(ChannelsResponse) + if err := c.Get("channels.list.joined", params, response); err != nil { + return nil, err + } + + return response, nil +} + +// LeaveChannel leaves a channel. The id of the channel has to be not nil. +// +// https://rocket.chat/docs/developer-guides/rest-api/channels/leave +func (c *Client) LeaveChannel(channel *models.Channel) error { + var body = fmt.Sprintf(`{ "roomId": "%s"}`, channel.ID) + return c.Post("channels.leave", bytes.NewBufferString(body), new(ChannelResponse)) +} + +// GetChannelInfo get information about a channel. That might be useful to update the usernames. +// +// https://rocket.chat/docs/developer-guides/rest-api/channels/info +func (c *Client) GetChannelInfo(channel *models.Channel) (*models.Channel, error) { + response := new(ChannelResponse) + if err := c.Get("channels.info", url.Values{"roomId": []string{channel.ID}}, response); err != nil { + return nil, err + } + + return &response.Channel, nil +} diff --git a/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/rest/client.go b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/rest/client.go new file mode 100644 index 00000000..0e37123e --- /dev/null +++ b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/rest/client.go @@ -0,0 +1,176 @@ +//Package rest provides a RocketChat rest client. +package rest + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "io" + "io/ioutil" + "log" + "net/http" + "net/url" +) + +var ( + ResponseErr = fmt.Errorf("got false response") +) + +type Response interface { + OK() error +} + +type Client struct { + Protocol string + Host string + Path string + Port string + Version string + + // Use this switch to see all network communication. + Debug bool + + auth *authInfo +} + +type Status struct { + Success bool `json:"success"` + Error string `json:"error"` + + Status string `json:"status"` + Message string `json:"message"` +} + +type authInfo struct { + token string + id string +} + +func (s Status) OK() error { + if s.Success { + return nil + } + + if len(s.Error) > 0 { + return fmt.Errorf(s.Error) + } + + if s.Status == "success" { + return nil + } + + if len(s.Message) > 0 { + return fmt.Errorf("status: %s, message: %s", s.Status, s.Message) + } + return ResponseErr +} + +// StatusResponse The base for the most of the json responses +type StatusResponse struct { + Status + Channel string `json:"channel"` +} + +func NewClient(serverUrl *url.URL, debug bool) *Client { + protocol := "http" + port := "80" + + if serverUrl.Scheme == "https" { + protocol = "https" + port = "443" + } + + if len(serverUrl.Port()) > 0 { + port = serverUrl.Port() + } + + return &Client{Host: serverUrl.Hostname(), Path: serverUrl.Path, Port: port, Protocol: protocol, Version: "v1", Debug: debug} +} + +func (c *Client) getUrl() string { + if len(c.Version) == 0 { + c.Version = "v1" + } + return fmt.Sprintf("%v://%v:%v%s/api/%s", c.Protocol, c.Host, c.Port, c.Path, c.Version) +} + +// Get call Get +func (c *Client) Get(api string, params url.Values, response Response) error { + return c.doRequest(http.MethodGet, api, params, nil, response) +} + +// Post call as JSON +func (c *Client) Post(api string, body io.Reader, response Response) error { + return c.doRequest(http.MethodPost, api, nil, body, response) +} + +// PostForm call as Form Data +func (c *Client) PostForm(api string, params url.Values, response Response) error { + return c.doRequest(http.MethodPost, api, params, nil, response) +} + +func (c *Client) doRequest(method, api string, params url.Values, body io.Reader, response Response) error { + contentType := "application/x-www-form-urlencoded" + if method == http.MethodPost { + if body != nil { + contentType = "application/json" + } else if len(params) > 0 { + body = bytes.NewBufferString(params.Encode()) + } + } + + request, err := http.NewRequest(method, c.getUrl()+"/"+api, body) + if err != nil { + return err + } + + if method == http.MethodGet { + if len(params) > 0 { + request.URL.RawQuery = params.Encode() + } + } else { + request.Header.Set("Content-Type", contentType) + } + + if c.auth != nil { + request.Header.Set("X-Auth-Token", c.auth.token) + request.Header.Set("X-User-Id", c.auth.id) + } + + if c.Debug { + log.Println(request) + } + + resp, err := http.DefaultClient.Do(request) + + if err != nil { + return err + } + + defer resp.Body.Close() + bodyBytes, err := ioutil.ReadAll(resp.Body) + + if c.Debug { + log.Println(string(bodyBytes)) + } + + var parse bool + if err == nil { + if e := json.Unmarshal(bodyBytes, response); e == nil { + parse = true + } + } + if resp.StatusCode != http.StatusOK { + if parse { + return response.OK() + } + return errors.New("Request error: " + resp.Status) + } + + if err != nil { + return err + } + + return response.OK() +} diff --git a/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/rest/information.go b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/rest/information.go new file mode 100644 index 00000000..dd831c85 --- /dev/null +++ b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/rest/information.go @@ -0,0 +1,98 @@ +package rest + +import ( + "net/url" + + "github.com/matterbridge/Rocket.Chat.Go.SDK/models" +) + +type InfoResponse struct { + Status + Info models.Info `json:"info"` +} + +// GetServerInfo a simple method, requires no authentication, +// that returns information about the server including version information. +// +// https://rocket.chat/docs/developer-guides/rest-api/miscellaneous/info +func (c *Client) GetServerInfo() (*models.Info, error) { + response := new(InfoResponse) + if err := c.Get("info", nil, response); err != nil { + return nil, err + } + + return &response.Info, nil +} + +type DirectoryResponse struct { + Status + models.Directory +} + +// GetDirectory a method, that searches by users or channels on all users and channels available on server. +// It supports the Offset, Count, and Sort Query Parameters along with Query and Fields Query Parameters. +// +// https://rocket.chat/docs/developer-guides/rest-api/miscellaneous/directory +func (c *Client) GetDirectory(params url.Values) (*models.Directory, error) { + response := new(DirectoryResponse) + if err := c.Get("directory", params, response); err != nil { + return nil, err + } + + return &response.Directory, nil +} + +type SpotlightResponse struct { + Status + models.Spotlight +} + +// GetSpotlight searches for users or rooms that are visible to the user. +// WARNING: It will only return rooms that user didn’t join yet. +// +// https://rocket.chat/docs/developer-guides/rest-api/miscellaneous/spotlight +func (c *Client) GetSpotlight(params url.Values) (*models.Spotlight, error) { + response := new(SpotlightResponse) + if err := c.Get("spotlight", params, response); err != nil { + return nil, err + } + + return &response.Spotlight, nil +} + +type StatisticsResponse struct { + Status + models.StatisticsInfo +} + +// GetStatistics +// Statistics about the Rocket.Chat server. +// +// https://rocket.chat/docs/developer-guides/rest-api/miscellaneous/statistics +func (c *Client) GetStatistics() (*models.StatisticsInfo, error) { + response := new(StatisticsResponse) + if err := c.Get("statistics", nil, response); err != nil { + return nil, err + } + + return &response.StatisticsInfo, nil +} + +type StatisticsListResponse struct { + Status + models.StatisticsList +} + +// GetStatisticsList +// Selectable statistics about the Rocket.Chat server. +// It supports the Offset, Count and Sort Query Parameters along with just the Fields and Query Parameters. +// +// https://rocket.chat/docs/developer-guides/rest-api/miscellaneous/statistics.list +func (c *Client) GetStatisticsList(params url.Values) (*models.StatisticsList, error) { + response := new(StatisticsListResponse) + if err := c.Get("statistics.list", params, response); err != nil { + return nil, err + } + + return &response.StatisticsList, nil +} diff --git a/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/rest/messages.go b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/rest/messages.go new file mode 100644 index 00000000..b3ad5846 --- /dev/null +++ b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/rest/messages.go @@ -0,0 +1,67 @@ +package rest + +import ( + "bytes" + "encoding/json" + "fmt" + "html" + "net/url" + "strconv" + + "github.com/matterbridge/Rocket.Chat.Go.SDK/models" +) + +type MessagesResponse struct { + Status + Messages []models.Message `json:"messages"` +} + +type MessageResponse struct { + Status + Message models.Message `json:"message"` +} + +// Sends a message to a channel. The name of the channel has to be not nil. +// The message will be html escaped. +// +// https://rocket.chat/docs/developer-guides/rest-api/chat/postmessage +func (c *Client) Send(channel *models.Channel, msg string) error { + body := fmt.Sprintf(`{ "channel": "%s", "text": "%s"}`, channel.Name, html.EscapeString(msg)) + return c.Post("chat.postMessage", bytes.NewBufferString(body), new(MessageResponse)) +} + +// PostMessage send a message to a channel. The channel or roomId has to be not nil. +// The message will be json encode. +// +// https://rocket.chat/docs/developer-guides/rest-api/chat/postmessage +func (c *Client) PostMessage(msg *models.PostMessage) (*MessageResponse, error) { + body, err := json.Marshal(msg) + if err != nil { + return nil, err + } + + response := new(MessageResponse) + err = c.Post("chat.postMessage", bytes.NewBuffer(body), response) + return response, err +} + +// Get messages from a channel. The channel id has to be not nil. Optionally a +// count can be specified to limit the size of the returned messages. +// +// https://rocket.chat/docs/developer-guides/rest-api/channels/history +func (c *Client) GetMessages(channel *models.Channel, page *models.Pagination) ([]models.Message, error) { + params := url.Values{ + "roomId": []string{channel.ID}, + } + + if page != nil { + params.Add("count", strconv.Itoa(page.Count)) + } + + response := new(MessagesResponse) + if err := c.Get("channels.history", params, response); err != nil { + return nil, err + } + + return response.Messages, nil +} diff --git a/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/rest/users.go b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/rest/users.go new file mode 100644 index 00000000..dcf783a0 --- /dev/null +++ b/vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/rest/users.go @@ -0,0 +1,145 @@ +package rest + +import ( + "bytes" + "encoding/json" + "fmt" + "net/url" + "time" + + "github.com/matterbridge/Rocket.Chat.Go.SDK/models" +) + +type logoutResponse struct { + Status + Data struct { + Message string `json:"message"` + } `json:"data"` +} + +type logonResponse struct { + Status + Data struct { + Token string `json:"authToken"` + UserID string `json:"userID"` + } `json:"data"` +} + +type CreateUserResponse struct { + Status + User struct { + ID string `json:"_id"` + CreatedAt time.Time `json:"createdAt"` + Services struct { + Password struct { + Bcrypt string `json:"bcrypt"` + } `json:"password"` + } `json:"services"` + Username string `json:"username"` + Emails []struct { + Address string `json:"address"` + Verified bool `json:"verified"` + } `json:"emails"` + Type string `json:"type"` + Status string `json:"status"` + Active bool `json:"active"` + Roles []string `json:"roles"` + UpdatedAt time.Time `json:"_updatedAt"` + Name string `json:"name"` + CustomFields map[string]string `json:"customFields"` + } `json:"user"` +} + +// Login a user. The Email and the Password are mandatory. The auth token of the user is stored in the Client instance. +// +// https://rocket.chat/docs/developer-guides/rest-api/authentication/login +func (c *Client) Login(credentials *models.UserCredentials) error { + if c.auth != nil { + return nil + } + + if credentials.ID != "" && credentials.Token != "" { + c.auth = &authInfo{id: credentials.ID, token: credentials.Token} + return nil + } + + response := new(logonResponse) + data := url.Values{"user": {credentials.Email}, "password": {credentials.Password}} + if err := c.PostForm("login", data, response); err != nil { + return err + } + + c.auth = &authInfo{id: response.Data.UserID, token: response.Data.Token} + credentials.ID, credentials.Token = response.Data.UserID, response.Data.Token + return nil +} + +// CreateToken creates an access token for a user +// +// https://rocket.chat/docs/developer-guides/rest-api/users/createtoken/ +func (c *Client) CreateToken(userID, username string) (*models.UserCredentials, error) { + response := new(logonResponse) + data := url.Values{"userId": {userID}, "username": {username}} + if err := c.PostForm("users.createToken", data, response); err != nil { + return nil, err + } + credentials := &models.UserCredentials{} + credentials.ID, credentials.Token = response.Data.UserID, response.Data.Token + return credentials, nil +} + +// Logout a user. The function returns the response message of the server. +// +// https://rocket.chat/docs/developer-guides/rest-api/authentication/logout +func (c *Client) Logout() (string, error) { + + if c.auth == nil { + return "Was not logged in", nil + } + + response := new(logoutResponse) + if err := c.Get("logout", nil, response); err != nil { + return "", err + } + + return response.Data.Message, nil +} + +// CreateUser being logged in with a user that has permission to do so. +// +// https://rocket.chat/docs/developer-guides/rest-api/users/create +func (c *Client) CreateUser(req *models.CreateUserRequest) (*CreateUserResponse, error) { + body, err := json.Marshal(req) + if err != nil { + return nil, err + } + + response := new(CreateUserResponse) + err = c.Post("users.create", bytes.NewBuffer(body), response) + return response, err +} + +// UpdateUser updates a user's data being logged in with a user that has permission to do so. +// +// https://rocket.chat/docs/developer-guides/rest-api/users/update/ +func (c *Client) UpdateUser(req *models.UpdateUserRequest) (*CreateUserResponse, error) { + body, err := json.Marshal(req) + if err != nil { + return nil, err + } + + response := new(CreateUserResponse) + err = c.Post("users.update", bytes.NewBuffer(body), response) + return response, err +} + +// SetUserAvatar updates a user's avatar being logged in with a user that has permission to do so. +// Currently only passing an URL is possible. +// +// https://rocket.chat/docs/developer-guides/rest-api/users/setavatar/ +func (c *Client) SetUserAvatar(userID, username, avatarURL string) (*Status, error) { + body := fmt.Sprintf(`{ "userId": "%s","username": "%s","avatarUrl":"%s"}`, userID, username, avatarURL) + response := new(Status) + err := c.Post("users.setAvatar", bytes.NewBufferString(body), response) + return response, err +} -- cgit v1.2.3