diff --git a/examples/real_time_updates/main.go b/examples/real_time_updates/main.go index b3be668..494be0f 100644 --- a/examples/real_time_updates/main.go +++ b/examples/real_time_updates/main.go @@ -11,7 +11,8 @@ import ( // This is not a real token. Please find yours by logging // into the GroupMe development website: https://dev.groupme.com/ -var authorizationToken = "ABCD" +var authorizationToken = "ASD" +var authorizationToken2 = "ASDF" // A short program that subscribes to 2 groups and 2 direct chats // and prints out all recognized events in those @@ -26,12 +27,15 @@ func main() { // Create a new client with your auth token client := groupme.NewClient() User, _ := client.MyUser(context.Background(), authorizationToken) + User2, _ := client.MyUser(context.Background(), authorizationToken2) //handles (in this case prints) all messages - p.AddFullHandler(Handler{User: User}) + p.AddFullHandler(Handler{User: User}, authorizationToken) + p.AddHandler(Handler{User: User2}, authorizationToken2) //Subscribe to get messages and events for the specific user - err = p.SubscribeToUser(context.Background(), User.ID, authorizationToken) + p.SubscribeToUser(context.Background(), User.ID, authorizationToken) + p.SubscribeToUser(context.Background(), User2.ID, authorizationToken2) if err != nil { log.Fatal(err) } @@ -45,6 +49,14 @@ func main() { Omit: "memberships", }, authorizationToken) + groups2, err := client.IndexGroups( + context.Background(), + &groupme.GroupsQuery{ + Page: 0, + PerPage: 2, + Omit: "memberships", + }, authorizationToken2) + if err != nil { fmt.Println(err) return @@ -57,18 +69,43 @@ func main() { } } + for _, j := range groups2 { + err = p.SubscribeToGroup(context.TODO(), j.ID, authorizationToken2) + if err != nil { + log.Fatal(err) + } + } + //get chats your user is part of chats, err := client.IndexChats(context.Background(), &groupme.IndexChatsQuery{ Page: 0, PerPage: 2, }, authorizationToken) + chats2, err := client.IndexChats(context.Background(), + &groupme.IndexChatsQuery{ + Page: 0, + PerPage: 2, + }, authorizationToken2) //subscribe to all those chats for _, j := range chats { - err = p.SubscribeToDM(context.TODO(), j.LastMessage.ConversationID, authorizationToken) - if err != nil { - log.Fatal(err) - } + go func() { + err := p.SubscribeToDM(context.TODO(), j.LastMessage.ConversationID, authorizationToken) + if err != nil { + log.Fatal(err) + } + }() + + } + + for _, j := range chats2 { + go func() { + err := p.SubscribeToDM(context.TODO(), j.LastMessage.ConversationID, authorizationToken2) + if err != nil { + log.Fatal(err) + } + }() + } //blocking diff --git a/go.mod b/go.mod index 5635e0b..308d872 100755 --- a/go.mod +++ b/go.mod @@ -3,10 +3,15 @@ module gitea.watsonlabs.net/watsonb8/groupme-lib go 1.21.0 require ( - gitea.watsonlabs.net/watsonb8/fayec v0.0.3 + gitea.watsonlabs.net/watsonb8/fayec v0.0.4 github.com/google/uuid v1.2.0 github.com/gorilla/mux v1.8.0 github.com/stretchr/testify v1.7.0 ) -require github.com/gorilla/websocket v1.5.0 // indirect +require ( + github.com/davecgh/go-spew v1.1.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect +) diff --git a/go.sum b/go.sum index cb0f622..57b214d 100755 --- a/go.sum +++ b/go.sum @@ -8,6 +8,8 @@ gitea.watsonlabs.net/watsonb8/fayec v0.0.2 h1:tqbgr1vRZ6Wq4W81xBg+FTOywSv3EJpK26 gitea.watsonlabs.net/watsonb8/fayec v0.0.2/go.mod h1:gv8CWMq6dFJQhH30u8bO3u4k2irKlclZktLNYDebQ/0= gitea.watsonlabs.net/watsonb8/fayec v0.0.3 h1:YpaZBIee8Ix6uGm1UoEtBix1dEU1TURChAsJGJ3pVRo= gitea.watsonlabs.net/watsonb8/fayec v0.0.3/go.mod h1:gv8CWMq6dFJQhH30u8bO3u4k2irKlclZktLNYDebQ/0= +gitea.watsonlabs.net/watsonb8/fayec v0.0.4 h1:SLvwip1DQy13QngVsEgoLtN7T6bS+X6348p6PQhUF2A= +gitea.watsonlabs.net/watsonb8/fayec v0.0.4/go.mod h1:gv8CWMq6dFJQhH30u8bO3u4k2irKlclZktLNYDebQ/0= github.com/autogrowsystems/wray v0.0.0-20160519030252-f36984f6648c/go.mod h1:druJ8QMeBCUmwJ7ZSFowx77dWxEWF3SYlQlsqZaLZQg= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/real_time.go b/real_time.go index 0332a5e..9f3b80e 100644 --- a/real_time.go +++ b/real_time.go @@ -90,7 +90,7 @@ type HandleMembers interface { type PushSubscription struct { channel chan message.Data client *fayec.Client - handlers []Handler + handlers map[string][]Handler // key == token LastConnected int64 } @@ -98,23 +98,35 @@ type PushSubscription struct { func NewPushSubscription(context context.Context) PushSubscription { r := PushSubscription{ - channel: make(chan message.Data), + channel: make(chan message.Data), + handlers: make(map[string][]Handler), } return r } -func (r *PushSubscription) AddHandler(h Handler) { - r.handlers = append(r.handlers, h) +func (r *PushSubscription) AddHandler(h Handler, authToken string) { + if r.handlers[authToken] == nil { + r.handlers[authToken] = []Handler{h} + } else { + r.handlers[authToken] = append(r.handlers[authToken], h) + } + //r.handlers = append(r.handlers, h) } // AddFullHandler is the same as AddHandler except it ensures the interface implements everything -func (r *PushSubscription) AddFullHandler(h HandlerAll) { - r.handlers = append(r.handlers, h) +func (r *PushSubscription) AddFullHandler(h HandlerAll, authToken string) { + if r.handlers[authToken] == nil { + r.handlers[authToken] = []Handler{h} + } else { + r.handlers[authToken] = append(r.handlers[authToken], h) + } + + //r.handlers = append(r.handlers, h) } -var RealTimeHandlers map[string]func(r *PushSubscription, channel string, data ...interface{}) -var RealTimeSystemHandlers map[string]func(r *PushSubscription, channel string, id ID, rawData []byte) +var RealTimeHandlers map[string]func(r *PushSubscription, channel string, authToken string, data ...interface{}) +var RealTimeSystemHandlers map[string]func(r *PushSubscription, channel string, id ID, authToken string, rawData []byte) // Listen connects to GroupMe. Runs in Goroutine. func (r *PushSubscription) Connect(context context.Context) error { @@ -172,7 +184,7 @@ func (r *PushSubscription) subscribeWithPrefix(prefix string, context context.Co log.Println("Unable to handle GroupMe message type", contentType) } - handler(r, channel, content) + handler(r, channel, authToken, content) }) return nil diff --git a/real_time_handler.go b/real_time_handler.go index f608a53..a203d83 100644 --- a/real_time_handler.go +++ b/real_time_handler.go @@ -9,10 +9,10 @@ import ( func init() { - RealTimeHandlers = make(map[string]func(r *PushSubscription, channel string, data ...interface{})) + RealTimeHandlers = make(map[string]func(r *PushSubscription, channel string, authToken string, data ...interface{})) //Base Handlers on user channel - RealTimeHandlers["direct_message.create"] = func(r *PushSubscription, channel string, data ...interface{}) { + RealTimeHandlers["direct_message.create"] = func(r *PushSubscription, channel string, authToken string, data ...interface{}) { b, _ := json.Marshal(data[0]) out := Message{} _ = json.Unmarshal(b, &out) @@ -44,11 +44,13 @@ func init() { id = out.ConversationID } - handler(r, channel, id, rawData) + handler(r, channel, id, authToken, rawData) return } - for _, h := range r.handlers { + handlers := r.handlers[authToken] + + for _, h := range handlers { if h, ok := h.(HandlerText); ok { h.HandleTextMessage(out) } @@ -57,14 +59,16 @@ func init() { RealTimeHandlers["line.create"] = RealTimeHandlers["direct_message.create"] - RealTimeHandlers["like.create"] = func(r *PushSubscription, channel string, data ...interface{}) { //should be an associated chatEvent + RealTimeHandlers["like.create"] = func(r *PushSubscription, channel string, authToken string, data ...interface{}) { //should be an associated chatEvent } - RealTimeHandlers["membership.create"] = func(r *PushSubscription, channel string, data ...interface{}) { + RealTimeHandlers["membership.create"] = func(r *PushSubscription, channel string, authToken string, data ...interface{}) { c, _ := data[0].(map[string]interface{}) id, _ := c["id"].(string) - for _, h := range r.handlers { + handlers := r.handlers[authToken] + + for _, h := range handlers { if h, ok := h.(HandlerMembership); ok { h.HandleJoin(ID(id)) } @@ -73,7 +77,7 @@ func init() { } //following are for each chat - RealTimeHandlers["favorite"] = func(r *PushSubscription, channel string, data ...interface{}) { + RealTimeHandlers["favorite"] = func(r *PushSubscription, channel string, authToken string, data ...interface{}) { c, ok := data[0].(map[string]interface{}) if !ok { fmt.Println(data, "err") @@ -87,7 +91,10 @@ func init() { d, _ := json.Marshal(e) msg := Message{} _ = json.Unmarshal(d, &msg) - for _, h := range r.handlers { + + handlers := r.handlers[authToken] + + for _, h := range handlers { if h, ok := h.(HandlerLike); ok { h.HandleLike(msg) } @@ -95,9 +102,9 @@ func init() { } //following are for messages from system (administrative/settings changes) - RealTimeSystemHandlers = make(map[string]func(r *PushSubscription, channel string, id ID, rawData []byte)) + RealTimeSystemHandlers = make(map[string]func(r *PushSubscription, channel string, id ID, authToken string, rawData []byte)) - RealTimeSystemHandlers["membership.nickname_changed"] = func(r *PushSubscription, channel string, id ID, rawData []byte) { + RealTimeSystemHandlers["membership.nickname_changed"] = func(r *PushSubscription, channel string, id ID, authToken string, rawData []byte) { thing := struct { Name string User struct { @@ -106,7 +113,9 @@ func init() { }{} _ = json.Unmarshal(rawData, &thing) - for _, h := range r.handlers { + handlers := r.handlers[authToken] + + for _, h := range handlers { if h, ok := h.(HandleMemberNewNickname); ok { h.HandleNewNickname(id, ID(strconv.Itoa(thing.User.ID)), thing.Name) } @@ -114,7 +123,7 @@ func init() { } - RealTimeSystemHandlers["membership.avatar_changed"] = func(r *PushSubscription, channel string, id ID, rawData []byte) { + RealTimeSystemHandlers["membership.avatar_changed"] = func(r *PushSubscription, channel string, id ID, authToken string, rawData []byte) { content := struct { AvatarURL string `json:"avatar_url"` User struct { @@ -123,7 +132,9 @@ func init() { }{} _ = json.Unmarshal(rawData, &content) - for _, h := range r.handlers { + handlers := r.handlers[authToken] + + for _, h := range handlers { if h, ok := h.(HandleMemberNewAvatar); ok { h.HandleNewAvatarInGroup(id, ID(strconv.Itoa(content.User.ID)), content.AvatarURL) } @@ -131,24 +142,28 @@ func init() { } - RealTimeSystemHandlers["membership.announce.added"] = func(r *PushSubscription, channel string, id ID, rawData []byte) { + RealTimeSystemHandlers["membership.announce.added"] = func(r *PushSubscription, channel string, id ID, authToken string, rawData []byte) { data := struct { Added []Member `json:"added_users"` }{} _ = json.Unmarshal(rawData, &data) - for _, h := range r.handlers { + handlers := r.handlers[authToken] + + for _, h := range handlers { if h, ok := h.(HandleMembers); ok { h.HandleMembers(id, data.Added, true) } } } - RealTimeSystemHandlers["membership.notifications.removed"] = func(r *PushSubscription, channel string, id ID, rawData []byte) { + RealTimeSystemHandlers["membership.notifications.removed"] = func(r *PushSubscription, channel string, id ID, authToken string, rawData []byte) { data := struct { Added Member `json:"removed_user"` }{} _ = json.Unmarshal(rawData, &data) - for _, h := range r.handlers { + handlers := r.handlers[authToken] + + for _, h := range handlers { if h, ok := h.(HandleMembers); ok { h.HandleMembers(id, []Member{data.Added}, false) } @@ -156,62 +171,70 @@ func init() { } - RealTimeSystemHandlers["membership.name_change"] = func(r *PushSubscription, channel string, id ID, rawData []byte) { + RealTimeSystemHandlers["membership.name_change"] = func(r *PushSubscription, channel string, id ID, authToken string, rawData []byte) { data := struct { Name string }{} _ = json.Unmarshal(rawData, &data) - for _, h := range r.handlers { + handlers := r.handlers[authToken] + + for _, h := range handlers { if h, ok := h.(HandleGroupName); ok { h.HandleGroupName(id, data.Name) } } } - RealTimeSystemHandlers["group.name_change"] = func(r *PushSubscription, channel string, id ID, rawData []byte) { + RealTimeSystemHandlers["group.name_change"] = func(r *PushSubscription, channel string, id ID, authToken string, rawData []byte) { data := struct { Name string }{} _ = json.Unmarshal(rawData, &data) - for _, h := range r.handlers { + handlers := r.handlers[authToken] + + for _, h := range handlers { if h, ok := h.(HandleGroupName); ok { h.HandleGroupName(id, data.Name) } } } - RealTimeSystemHandlers["group.topic_change"] = func(r *PushSubscription, channel string, id ID, rawData []byte) { + RealTimeSystemHandlers["group.topic_change"] = func(r *PushSubscription, channel string, id ID, authToken string, rawData []byte) { data := struct { Topic string }{} _ = json.Unmarshal(rawData, &data) - for _, h := range r.handlers { + handlers := r.handlers[authToken] + + for _, h := range handlers { if h, ok := h.(HandleGroupTopic); ok { h.HandleGroupTopic(id, data.Topic) } } } - RealTimeSystemHandlers["group.avatar_change"] = func(r *PushSubscription, channel string, id ID, rawData []byte) { + RealTimeSystemHandlers["group.avatar_change"] = func(r *PushSubscription, channel string, id ID, authToken string, rawData []byte) { data := struct { AvatarURL string `json:"avatar_url"` }{} _ = json.Unmarshal(rawData, &data) - for _, h := range r.handlers { + handlers := r.handlers[authToken] + + for _, h := range handlers { if h, ok := h.(HandleGroupAvatar); ok { h.HandleGroupAvatar(id, data.AvatarURL) } } } - RealTimeSystemHandlers["group.like_icon_set"] = func(r *PushSubscription, channel string, id ID, rawData []byte) { + RealTimeSystemHandlers["group.like_icon_set"] = func(r *PushSubscription, channel string, id ID, authToken string, rawData []byte) { data := struct { LikeIcon struct { PackID int `json:"pack_id"` @@ -221,15 +244,19 @@ func init() { }{} _ = json.Unmarshal(rawData, &data) - for _, h := range r.handlers { + handlers := r.handlers[authToken] + + for _, h := range handlers { if h, ok := h.(HandleGroupLikeIcon); ok { h.HandleLikeIcon(id, data.LikeIcon.PackID, data.LikeIcon.PackIndex, data.LikeIcon.Type) } } } - RealTimeSystemHandlers["group.like_icon_removed"] = func(r *PushSubscription, channel string, id ID, rawData []byte) { - for _, h := range r.handlers { + RealTimeSystemHandlers["group.like_icon_removed"] = func(r *PushSubscription, channel string, id ID, authToken string, rawData []byte) { + handlers := r.handlers[authToken] + + for _, h := range handlers { if h, ok := h.(HandleGroupLikeIcon); ok { h.HandleLikeIcon(id, 0, 0, "") }