real time push basics

This commit is contained in:
Karmanyaah Malhotra 2021-01-28 23:47:48 -05:00
parent 6d42a230d1
commit 784cfe93c1
4 changed files with 278 additions and 0 deletions

View File

@ -0,0 +1,81 @@
package main
import (
"context"
"fmt"
"github.com/densestvoid/groupme"
)
// This is not a real token. Please find yours by logging
// into the GroupMe development website: https://dev.groupme.com/
var authorizationToken = "ABCD"
// A short program that gets the gets the first 5 groups
// the user is part of, and then the first 10 messages of
// the first group in that list
func main() {
// Create a new client with your auth token
client := groupme.NewClient(authorizationToken)
// Get the groups your user is part of
groups, err := client.IndexGroups(
context.Background(),
&groupme.GroupsQuery{
Page: 0,
PerPage: 5,
Omit: "memberships",
},
)
if err != nil {
fmt.Println(err)
return
}
// fmt.Println(groups)
// Get first 10 messages of the first group
if len(groups) == 0 {
fmt.Println("No groups")
}
// messages, err := client.IndexMessages(context.Background(), groups[0].ID, &groupme.IndexMessagesQuery{
// Limit: 10,
// })
// if err != nil {
// fmt.Println(err)
// }
// fmt.Println(messages)
p := client.NewPushSubscription(context.Background())
go p.Listen(context.Background())
client = groupme.NewClient(authorizationToken)
a, _ := client.MyUser(context.Background())
p.SubscribeToUser(context.Background(), a.ID, authorizationToken)
authorizationToken = "BCDF"
client = groupme.NewClient(authorizationToken)
a, _ = client.MyUser(context.Background())
p.SubscribeToUser(context.Background(), a.ID, authorizationToken)
for {
select {
case msg := <-p.MessageChannel:
println(msg.Text)
break
case like := <-p.LikeChannel:
println("Liked")
println(like.Message.ID.String())
println(like.Message.Text)
break
}
}
}

3
go.mod
View File

@ -2,8 +2,11 @@ module github.com/densestvoid/groupme
go 1.15 go 1.15
replace github.com/karmanyaahm/wray => ../wray
require ( require (
github.com/google/uuid v1.2.0 github.com/google/uuid v1.2.0
github.com/gorilla/mux v1.8.0 github.com/gorilla/mux v1.8.0
github.com/karmanyaahm/wray v0.0.0-20160519030252-f36984f6648c
github.com/stretchr/testify v1.7.0 github.com/stretchr/testify v1.7.0
) )

14
go.sum
View File

@ -1,15 +1,29 @@
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 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=

180
real_time.go Normal file
View File

@ -0,0 +1,180 @@
package groupme
import (
"context"
"encoding/json"
"errors"
"log"
"sync"
"time"
"github.com/karmanyaahm/wray"
)
const (
pushServer = "https://push.groupme.com/faye"
userChannel = "/user/"
groupChannel = "/group/"
handshakeChannel = "/meta/handshake"
connectChannel = "/meta/connect"
subscribeChannel = "/meta/subscribe"
)
var concur = sync.Mutex{}
var token string
type fayeLogger struct{}
func (l fayeLogger) Infof(f string, a ...interface{}) {
log.Printf("[INFO] : "+f, a...)
}
func (l fayeLogger) Errorf(f string, a ...interface{}) {
log.Printf("[ERROR] : "+f, a...)
}
func (l fayeLogger) Debugf(f string, a ...interface{}) {
// log.Printf("[DEBUG] : "+f, a...)
}
func (l fayeLogger) Warnf(f string, a ...interface{}) {
log.Printf("[WARN] : "+f, a...)
}
func init() {
wray.RegisterTransports([]wray.Transport{&wray.HTTPTransport{}})
}
//LikeEvent returns events as they happen from GroupMe
type LikeEvent struct {
Message Message
}
//PushSubscription manages real time subscription
type PushSubscription struct {
channel chan wray.Message
//Channel to return things
MessageChannel chan Message
LikeChannel chan LikeEvent
fayeClient *wray.FayeClient
}
//NewPushSubscription creates and returns a push subscription object
func NewPushSubscription(context context.Context) PushSubscription {
r := PushSubscription{
channel: make(chan wray.Message),
MessageChannel: make(chan Message),
LikeChannel: make(chan LikeEvent),
}
return r
}
//Listen connects to GroupMe. Runs in Goroutine.
func (r *PushSubscription) Listen(context context.Context) {
r.fayeClient = wray.NewFayeClient(pushServer)
r.fayeClient.SetLogger(fayeLogger{})
r.fayeClient.AddExtension(&authExtension{})
//r.fayeClient.AddExtension(r.fayeClient) //verbose output
go r.fayeClient.Listen()
for {
msg := <-r.channel
data := msg.Data()
content, _ := data["subject"]
contentType := data["type"].(string)
switch contentType {
case "line.create":
b, _ := json.Marshal(content)
out := Message{}
json.Unmarshal(b, &out)
//fmt.Printf("%+v\n", out) //TODO
r.MessageChannel <- out
break
case "like.create":
b, _ := json.Marshal(content.(map[string]interface{})["line"])
out := Message{}
//log.Println(string(b))
err := json.Unmarshal(b, &out)
if err != nil {
log.Println(err)
}
outt := LikeEvent{Message: out}
//fmt.Printf("Like on %+v \n", outt.Message)
r.LikeChannel <- outt
break
case "ping":
break
default: //TODO: see if any other types are returned
if len(contentType) == 0 || content == nil {
break
}
log.Println(contentType)
log.Fatalln(data)
}
}
}
//SubscribeToUser to users
func (r *PushSubscription) SubscribeToUser(context context.Context, userID ID, authToken string) error {
concur.Lock()
defer concur.Unlock()
if r.fayeClient == nil {
return errors.New("Not Listening") //TODO: Proper error
}
token = authToken
r.fayeClient.WaitSubscribe(userChannel+userID.String(), r.channel)
return nil
}
//SubscribeToGroup to groups for typing notification
func (r *PushSubscription) SubscribeToGroup(context context.Context, groupID ID, authToken string) error {
concur.Lock()
defer concur.Unlock()
if r.fayeClient == nil {
return errors.New("Not Listening") //TODO: Proper error
}
token = authToken
r.fayeClient.WaitSubscribe(groupChannel+groupID.String(), r.channel)
return nil
}
// Stop listening to GroupMe after completing all other actions scheduled first
func (r *PushSubscription) Stop(context context.Context) {
concur.Lock()
defer concur.Unlock()
//TODO: stop listening
}
type authExtension struct {
}
// In does nothing in this extension, but is needed to satisy the interface
func (e *authExtension) In(msg wray.Message) {
if len(msg.Error()) > 0 {
log.Fatalln(msg.Error())
}
}
// Out adds the authentication token to the messages ext field
func (e *authExtension) Out(msg wray.Message) {
if msg.Channel() == subscribeChannel {
ext := msg.Ext()
ext["access_token"] = token
ext["timestamp"] = time.Now().Unix()
}
}