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/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 ++++++++ 9 files changed, 881 insertions(+) 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 (limited to 'vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime') 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 +} -- cgit v1.2.3