Add many types of handling
fix listen loop improve example
This commit is contained in:
parent
da7bc977a3
commit
d6a8b0818f
@ -3,13 +3,17 @@ package main
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/densestvoid/groupme"
|
"github.com/densestvoid/groupme"
|
||||||
)
|
)
|
||||||
|
|
||||||
// This is not a real token. Please find yours by logging
|
// This is not a real token. Please find yours by logging
|
||||||
// into the GroupMe development website: https://dev.groupme.com/
|
// into the GroupMe development website: https://dev.groupme.com/
|
||||||
var authorizationToken = "ABCD"
|
|
||||||
|
//var authorizationToken = "ABCD"
|
||||||
|
|
||||||
|
var authorizationToken = "aa608b00a46401385ead62dd938575cf"
|
||||||
|
|
||||||
// A short program that gets the gets the first 5 groups
|
// A short program that gets the gets the first 5 groups
|
||||||
// the user is part of, and then the first 10 messages of
|
// the user is part of, and then the first 10 messages of
|
||||||
@ -23,7 +27,7 @@ func main() {
|
|||||||
context.Background(),
|
context.Background(),
|
||||||
&groupme.GroupsQuery{
|
&groupme.GroupsQuery{
|
||||||
Page: 0,
|
Page: 0,
|
||||||
PerPage: 5,
|
PerPage: 1,
|
||||||
Omit: "memberships",
|
Omit: "memberships",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -33,49 +37,79 @@ func main() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// fmt.Println(groups)
|
|
||||||
|
|
||||||
// Get first 10 messages of the first group
|
// Get first 10 messages of the first group
|
||||||
if len(groups) == 0 {
|
if len(groups) == 0 {
|
||||||
fmt.Println("No groups")
|
fmt.Println("No groups")
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// messages, err := client.IndexMessages(context.Background(), groups[0].ID, &groupme.IndexMessagesQuery{
|
p := groupme.NewPushSubscription(context.Background())
|
||||||
// Limit: 10,
|
go p.StartListening(context.TODO())
|
||||||
// })
|
|
||||||
|
|
||||||
// if err != nil {
|
|
||||||
// fmt.Println(err)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fmt.Println(messages)
|
|
||||||
p := client.NewPushSubscription(context.Background())
|
|
||||||
go p.Listen(context.Background())
|
|
||||||
|
|
||||||
client = groupme.NewClient(authorizationToken)
|
client = groupme.NewClient(authorizationToken)
|
||||||
|
|
||||||
a, _ := client.MyUser(context.Background())
|
User, _ := client.MyUser(context.Background())
|
||||||
|
p.SubscribeToUser(context.Background(), User.ID, authorizationToken)
|
||||||
|
|
||||||
p.SubscribeToUser(context.Background(), a.ID, authorizationToken)
|
for _, j := range groups {
|
||||||
|
p.SubscribeToGroup(context.TODO(), j.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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p.AddFullHandler(Handler{User: User})
|
||||||
|
|
||||||
|
<-make(chan (struct{}))
|
||||||
|
}
|
||||||
|
|
||||||
|
type Handler struct {
|
||||||
|
User *groupme.User
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h Handler) HandleError(e error) {
|
||||||
|
fmt.Println(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h Handler) HandleTextMessage(msg groupme.Message) {
|
||||||
|
fmt.Println(msg.Text, msg.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h Handler) HandleJoin(group groupme.ID) {
|
||||||
|
fmt.Println("User joined group with id", group.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h Handler) HandleLike(id groupme.ID, by []string) {
|
||||||
|
fmt.Println(id.String(), "liked by", by)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h Handler) HandlerMembership(i groupme.ID) {
|
||||||
|
fmt.Println("Membership event on", i.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h Handler) HandleGroupTopic(group groupme.ID, newTopic string) {
|
||||||
|
fmt.Println(group.String(), "has new topic of", newTopic)
|
||||||
|
}
|
||||||
|
func (h Handler) HandleGroupName(group groupme.ID, newName string) {
|
||||||
|
fmt.Println(group.String(), "has new name of", newName)
|
||||||
|
}
|
||||||
|
func (h Handler) HandleGroupAvatar(group groupme.ID, newAvatar string) {
|
||||||
|
fmt.Println(group.String(), "has new avatar url of", newAvatar)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h Handler) HandleLikeIcon(group groupme.ID, PackID, PackIndex int, Type string) {
|
||||||
|
//Not sure how to use without groupme icon packs
|
||||||
|
if len(Type) == 0 {
|
||||||
|
fmt.Println("Default like icon set")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Println(group.String(), "has new like icon of", PackID, PackIndex, Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h Handler) HandleNewNickname(group groupme.ID, user groupme.ID, newName string) {
|
||||||
|
fmt.Printf("In group %s, user %s has new nickname %s\n", group.String(), user.String(), newName)
|
||||||
|
}
|
||||||
|
func (h Handler) HandleNewAvatarInGroup(group groupme.ID, user groupme.ID, avatarURL string) {
|
||||||
|
if avatarURL == "" {
|
||||||
|
//get default avatar
|
||||||
|
avatarURL = h.User.ImageURL
|
||||||
|
}
|
||||||
|
fmt.Printf("In group %s, user %s has new avatar with url %s\n", group.String(), user.String(), avatarURL)
|
||||||
}
|
}
|
||||||
|
224
real_time.go
224
real_time.go
@ -4,7 +4,10 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -15,6 +18,7 @@ const (
|
|||||||
pushServer = "https://push.groupme.com/faye"
|
pushServer = "https://push.groupme.com/faye"
|
||||||
userChannel = "/user/"
|
userChannel = "/user/"
|
||||||
groupChannel = "/group/"
|
groupChannel = "/group/"
|
||||||
|
dmChannel = "/direct_message/"
|
||||||
handshakeChannel = "/meta/handshake"
|
handshakeChannel = "/meta/handshake"
|
||||||
connectChannel = "/meta/connect"
|
connectChannel = "/meta/connect"
|
||||||
subscribeChannel = "/meta/subscribe"
|
subscribeChannel = "/meta/subscribe"
|
||||||
@ -32,7 +36,7 @@ func (l fayeLogger) Errorf(f string, a ...interface{}) {
|
|||||||
log.Printf("[ERROR] : "+f, a...)
|
log.Printf("[ERROR] : "+f, a...)
|
||||||
}
|
}
|
||||||
func (l fayeLogger) Debugf(f string, a ...interface{}) {
|
func (l fayeLogger) Debugf(f string, a ...interface{}) {
|
||||||
// log.Printf("[DEBUG] : "+f, a...)
|
log.Printf("[DEBUG] : "+f, a...)
|
||||||
}
|
}
|
||||||
func (l fayeLogger) Warnf(f string, a ...interface{}) {
|
func (l fayeLogger) Warnf(f string, a ...interface{}) {
|
||||||
log.Printf("[WARN] : "+f, a...)
|
log.Printf("[WARN] : "+f, a...)
|
||||||
@ -42,18 +46,14 @@ func init() {
|
|||||||
wray.RegisterTransports([]wray.Transport{&wray.HTTPTransport{}})
|
wray.RegisterTransports([]wray.Transport{&wray.HTTPTransport{}})
|
||||||
}
|
}
|
||||||
|
|
||||||
//LikeEvent returns events as they happen from GroupMe
|
type HandlerAll interface {
|
||||||
type LikeEvent struct {
|
Handler
|
||||||
Message Message
|
HandlerText
|
||||||
|
HandlerLike
|
||||||
|
HandlerMembership
|
||||||
|
HandleGroupMembership
|
||||||
|
HandleGroupMetadata
|
||||||
}
|
}
|
||||||
|
|
||||||
type EventType = int
|
|
||||||
|
|
||||||
const (
|
|
||||||
EventMessage EventType = iota
|
|
||||||
EventLike
|
|
||||||
)
|
|
||||||
|
|
||||||
type Handler interface {
|
type Handler interface {
|
||||||
HandleError(error)
|
HandleError(error)
|
||||||
}
|
}
|
||||||
@ -61,17 +61,30 @@ type HandlerText interface {
|
|||||||
HandleTextMessage(Message)
|
HandleTextMessage(Message)
|
||||||
}
|
}
|
||||||
type HandlerLike interface {
|
type HandlerLike interface {
|
||||||
HandleLike(Message)
|
HandleLike(messageID ID, favBy []string)
|
||||||
}
|
}
|
||||||
type HandlerMembership interface {
|
type HandlerMembership interface {
|
||||||
HandleJoin(ID)
|
HandleJoin(ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type HandleGroupMetadata interface {
|
||||||
|
HandleGroupTopic(group ID, newTopic string)
|
||||||
|
HandleGroupName(group ID, newName string)
|
||||||
|
HandleGroupAvatar(group ID, newAvatar string)
|
||||||
|
HandleLikeIcon(group ID, PackID, PackIndex int, Type string)
|
||||||
|
}
|
||||||
|
|
||||||
|
type HandleGroupMembership interface {
|
||||||
|
HandleNewNickname(group ID, user ID, newName string)
|
||||||
|
HandleNewAvatarInGroup(group ID, user ID, avatarURL string)
|
||||||
|
}
|
||||||
|
|
||||||
//PushSubscription manages real time subscription
|
//PushSubscription manages real time subscription
|
||||||
type PushSubscription struct {
|
type PushSubscription struct {
|
||||||
channel chan wray.Message
|
channel chan wray.Message
|
||||||
fayeClient *wray.FayeClient
|
fayeClient *wray.FayeClient
|
||||||
handlers []Handler
|
handlers []Handler
|
||||||
|
LastConnected int64
|
||||||
}
|
}
|
||||||
|
|
||||||
//NewPushSubscription creates and returns a push subscription object
|
//NewPushSubscription creates and returns a push subscription object
|
||||||
@ -88,6 +101,18 @@ func (r *PushSubscription) AddHandler(h Handler) {
|
|||||||
r.handlers = append(r.handlers, h)
|
r.handlers = append(r.handlers, h)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//AddFullHandler is the same as AddHandler except to ensure interface implements everything
|
||||||
|
func (r *PushSubscription) AddFullHandler(h HandlerAll) {
|
||||||
|
r.handlers = append(r.handlers, h)
|
||||||
|
}
|
||||||
|
|
||||||
|
type systemMessage struct {
|
||||||
|
Event struct {
|
||||||
|
Kind string `json:"type"`
|
||||||
|
Data interface{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Listen connects to GroupMe. Runs in Goroutine.
|
//Listen connects to GroupMe. Runs in Goroutine.
|
||||||
func (r *PushSubscription) StartListening(context context.Context) {
|
func (r *PushSubscription) StartListening(context context.Context) {
|
||||||
r.fayeClient = wray.NewFayeClient(pushServer)
|
r.fayeClient = wray.NewFayeClient(pushServer)
|
||||||
@ -100,19 +125,34 @@ func (r *PushSubscription) StartListening(context context.Context) {
|
|||||||
go r.fayeClient.Listen()
|
go r.fayeClient.Listen()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for msg := range r.channel {
|
||||||
msg := <-r.channel
|
r.LastConnected = time.Now().Unix()
|
||||||
data := msg.Data()
|
data := msg.Data()
|
||||||
content, _ := data["subject"]
|
content, _ := data["subject"]
|
||||||
contentType := data["type"].(string)
|
contentType := data["type"].(string)
|
||||||
|
channel := msg.Channel()
|
||||||
|
|
||||||
|
if strings.HasPrefix(channel, groupChannel) || strings.HasPrefix(channel, dmChannel) {
|
||||||
|
r.chatEvent(contentType, content)
|
||||||
|
}
|
||||||
|
|
||||||
switch contentType {
|
switch contentType {
|
||||||
case "line.create", "direct_message.create":
|
case "line.create":
|
||||||
b, _ := json.Marshal(content)
|
b, _ := json.Marshal(content)
|
||||||
|
|
||||||
out := Message{}
|
out := Message{}
|
||||||
json.Unmarshal(b, &out)
|
_ = json.Unmarshal(b, &out)
|
||||||
//fmt.Printf("%+v\n", out) //TODO logging
|
|
||||||
|
if out.UserID.String() == "system" {
|
||||||
|
event := systemMessage{}
|
||||||
|
err := json.Unmarshal(b, &event)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r.systemEvent(out.GroupID, event)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
for _, h := range r.handlers {
|
for _, h := range r.handlers {
|
||||||
if h, ok := h.(HandlerText); ok {
|
if h, ok := h.(HandlerText); ok {
|
||||||
h.HandleTextMessage(out)
|
h.HandleTextMessage(out)
|
||||||
@ -121,19 +161,7 @@ func (r *PushSubscription) StartListening(context context.Context) {
|
|||||||
|
|
||||||
break
|
break
|
||||||
case "like.create":
|
case "like.create":
|
||||||
b, _ := json.Marshal(content.(map[string]interface{})["line"])
|
//should be an associated chatEvent
|
||||||
|
|
||||||
out := Message{}
|
|
||||||
//log.Println(string(b))
|
|
||||||
err := json.Unmarshal(b, &out)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
}
|
|
||||||
for _, h := range r.handlers {
|
|
||||||
if h, ok := h.(HandlerLike); ok {
|
|
||||||
h.HandleLike(out)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
break
|
||||||
case "membership.create":
|
case "membership.create":
|
||||||
c, _ := content.(map[string]interface{})
|
c, _ := content.(map[string]interface{})
|
||||||
@ -154,8 +182,7 @@ func (r *PushSubscription) StartListening(context context.Context) {
|
|||||||
}
|
}
|
||||||
log.Println(contentType)
|
log.Println(contentType)
|
||||||
b, _ := json.Marshal(content)
|
b, _ := json.Marshal(content)
|
||||||
log.Println(string(b))
|
log.Fatalln(string(b))
|
||||||
log.Fatalln(data)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,6 +190,129 @@ func (r *PushSubscription) StartListening(context context.Context) {
|
|||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *PushSubscription) chatEvent(contentType string, content interface{}) {
|
||||||
|
switch contentType {
|
||||||
|
case "favorite":
|
||||||
|
b, ok := content.(map[string]interface{})["line"].(Message)
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
log.Println(content)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, h := range r.handlers {
|
||||||
|
if h, ok := h.(HandlerLike); ok {
|
||||||
|
h.HandleLike(b.UserID, b.FavoritedBy)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
default: //TODO: see if any other types are returned
|
||||||
|
println("HEHE")
|
||||||
|
log.Println(contentType)
|
||||||
|
b, _ := json.Marshal(content)
|
||||||
|
log.Fatalln(string(b))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *PushSubscription) systemEvent(groupID ID, msg systemMessage) {
|
||||||
|
kind := msg.Event.Kind
|
||||||
|
b, _ := json.Marshal(msg.Event.Data)
|
||||||
|
switch kind {
|
||||||
|
case "membership.nickname_changed":
|
||||||
|
data := struct {
|
||||||
|
Name string
|
||||||
|
User struct {
|
||||||
|
ID int
|
||||||
|
}
|
||||||
|
}{}
|
||||||
|
_ = json.Unmarshal(b, &data)
|
||||||
|
|
||||||
|
for _, h := range r.handlers {
|
||||||
|
if h, ok := h.(HandleGroupMembership); ok {
|
||||||
|
h.HandleNewNickname(groupID, ID(strconv.Itoa(data.User.ID)), data.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case "membership.avatar_changed":
|
||||||
|
data := struct {
|
||||||
|
AvatarURL string `json:"avatar_url"`
|
||||||
|
User struct {
|
||||||
|
ID int
|
||||||
|
}
|
||||||
|
}{}
|
||||||
|
_ = json.Unmarshal(b, &data)
|
||||||
|
|
||||||
|
for _, h := range r.handlers {
|
||||||
|
if h, ok := h.(HandleGroupMembership); ok {
|
||||||
|
h.HandleNewAvatarInGroup(groupID, ID(strconv.Itoa(data.User.ID)), data.AvatarURL)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case "group.name_change":
|
||||||
|
data := struct {
|
||||||
|
Name string
|
||||||
|
}{}
|
||||||
|
_ = json.Unmarshal(b, &data)
|
||||||
|
|
||||||
|
for _, h := range r.handlers {
|
||||||
|
if h, ok := h.(HandleGroupMetadata); ok {
|
||||||
|
h.HandleGroupName(groupID, data.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case "group.topic_change":
|
||||||
|
data := struct {
|
||||||
|
Topic string
|
||||||
|
}{}
|
||||||
|
_ = json.Unmarshal(b, &data)
|
||||||
|
|
||||||
|
for _, h := range r.handlers {
|
||||||
|
if h, ok := h.(HandleGroupMetadata); ok {
|
||||||
|
h.HandleGroupTopic(groupID, data.Topic)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case "group.avatar_change":
|
||||||
|
data := struct {
|
||||||
|
AvatarURL string `json:"avatar_url"`
|
||||||
|
}{}
|
||||||
|
_ = json.Unmarshal(b, &data)
|
||||||
|
|
||||||
|
for _, h := range r.handlers {
|
||||||
|
if h, ok := h.(HandleGroupMetadata); ok {
|
||||||
|
h.HandleGroupAvatar(groupID, data.AvatarURL)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case "group.like_icon_set":
|
||||||
|
data := struct {
|
||||||
|
LikeIcon struct {
|
||||||
|
PackID int `json:"pack_id"`
|
||||||
|
PackIndex int `json:"pack_index"`
|
||||||
|
Type string
|
||||||
|
} `json:"like_icon"`
|
||||||
|
}{}
|
||||||
|
_ = json.Unmarshal(b, &data)
|
||||||
|
|
||||||
|
for _, h := range r.handlers {
|
||||||
|
if h, ok := h.(HandleGroupMetadata); ok {
|
||||||
|
h.HandleLikeIcon(groupID, data.LikeIcon.PackID, data.LikeIcon.PackIndex, data.LikeIcon.Type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case "group.like_icon_removed":
|
||||||
|
for _, h := range r.handlers {
|
||||||
|
if h, ok := h.(HandleGroupMetadata); ok {
|
||||||
|
h.HandleLikeIcon(groupID, 0, 0, "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
log.Println(kind)
|
||||||
|
log.Fatalln(string(b))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//SubscribeToUser to users
|
//SubscribeToUser to users
|
||||||
func (r *PushSubscription) SubscribeToUser(context context.Context, userID ID, authToken string) error {
|
func (r *PushSubscription) SubscribeToUser(context context.Context, userID ID, authToken string) error {
|
||||||
concur.Lock()
|
concur.Lock()
|
||||||
@ -192,6 +342,11 @@ func (r *PushSubscription) SubscribeToGroup(context context.Context, groupID ID,
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Connected check if connected
|
||||||
|
func (r *PushSubscription) Connected() bool {
|
||||||
|
return r.LastConnected+30 >= time.Now().Unix()
|
||||||
|
}
|
||||||
|
|
||||||
// Stop listening to GroupMe after completing all other actions scheduled first
|
// Stop listening to GroupMe after completing all other actions scheduled first
|
||||||
func (r *PushSubscription) Stop(context context.Context) {
|
func (r *PushSubscription) Stop(context context.Context) {
|
||||||
concur.Lock()
|
concur.Lock()
|
||||||
@ -205,6 +360,7 @@ type authExtension struct {
|
|||||||
|
|
||||||
// In does nothing in this extension, but is needed to satisy the interface
|
// In does nothing in this extension, but is needed to satisy the interface
|
||||||
func (e *authExtension) In(msg wray.Message) {
|
func (e *authExtension) In(msg wray.Message) {
|
||||||
|
println(msg.Channel())
|
||||||
if len(msg.Error()) > 0 {
|
if len(msg.Error()) > 0 {
|
||||||
log.Fatalln(msg.Error())
|
log.Fatalln(msg.Error())
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user