From 9f45f7ac8a995f010c5c958d98ea9b6768082c84 Mon Sep 17 00:00:00 2001 From: Tim Cooper Date: Fri, 21 Nov 2014 17:49:51 -0400 Subject: [PATCH] basic user stats support --- gumble/event.go | 1 + gumble/handlers.go | 52 ++++++++++++++++++++++++++++++++++++-------- gumble/user.go | 17 +++++++++++++++ gumble/user_stats.go | 26 ++++++++++++++++++++++ 4 files changed, 87 insertions(+), 9 deletions(-) create mode 100644 gumble/user_stats.go diff --git a/gumble/event.go b/gumble/event.go index a58cf20..3c90230 100644 --- a/gumble/event.go +++ b/gumble/event.go @@ -32,6 +32,7 @@ type UserChangeEvent struct { NameChanged bool ChannelChanged bool CommentChanged bool + StatsChanged bool } type ChannelChangeEvent struct { diff --git a/gumble/handlers.go b/gumble/handlers.go index a0fbe45..f9f0ef4 100644 --- a/gumble/handlers.go +++ b/gumble/handlers.go @@ -3,6 +3,7 @@ package gumble import ( "bytes" "errors" + "time" "code.google.com/p/goprotobuf/proto" "github.com/bontibon/gopus" @@ -51,12 +52,7 @@ func init() { } } -func handleVersion(client *Client, buffer []byte) error { - var packet MumbleProto.Version - if err := proto.Unmarshal(buffer, &packet); err != nil { - return err - } - +func parseVersion(packet *MumbleProto.Version) Version { var version Version if packet.Version != nil { version.version = *packet.Version @@ -70,8 +66,16 @@ func handleVersion(client *Client, buffer []byte) error { if packet.OsVersion != nil { version.osVersion = *packet.OsVersion } - client.server.version = version + return version +} +func handleVersion(client *Client, buffer []byte) error { + var packet MumbleProto.Version + if err := proto.Unmarshal(buffer, &packet); err != nil { + return err + } + + client.server.version = parseVersion(&packet) return nil } @@ -515,8 +519,38 @@ func handleCodecVersion(client *Client, buffer []byte) error { } func handleUserStats(client *Client, buffer []byte) error { - // TODO - return errUnimplementedHandler + var packet MumbleProto.UserStats + if err := proto.Unmarshal(buffer, &packet); err != nil { + return err + } + + if packet.Session == nil { + return errIncompleteProtobuf + } + user := client.users.BySession(uint(*packet.Session)) + if user == nil { + return errInvalidProtobuf + } + + if packet.Version != nil { + user.stats.version = parseVersion(packet.Version) + } + if packet.Onlinesecs != nil { + user.stats.connected = time.Now().Add(time.Duration(*packet.Onlinesecs) * -time.Second) + } + if packet.Idlesecs != nil { + user.stats.idle = time.Duration(*packet.Idlesecs) * time.Second + } + + user.statsFetched = true + + event := &UserChangeEvent{ + Client: client, + User: user, + StatsChanged: true, + } + client.listeners.OnUserChange(event) + return nil } func handleRequestBlob(client *Client, buffer []byte) error { diff --git a/gumble/user.go b/gumble/user.go index 0865112..f4d9476 100644 --- a/gumble/user.go +++ b/gumble/user.go @@ -20,6 +20,9 @@ type User struct { texture, textureHash []byte prioritySpeaker bool recording bool + + statsFetched bool + stats UserStats } // Session returns the user's session Id. @@ -197,3 +200,17 @@ func (u *User) SetSelfDeafened(muted bool) { } u.client.Send(protoMessage{&packet}) } + +// Stats returns the user's stats, and a boolean value specifying if the stats +// are valid or not. +func (u *User) Stats() (UserStats, bool) { + return u.stats, u.statsFetched +} + +// RequestStats requests user stats of the given user. +func (u *User) RequestStats() { + packet := MumbleProto.UserStats{ + Session: &u.session, + } + u.client.Send(protoMessage{&packet}) +} diff --git a/gumble/user_stats.go b/gumble/user_stats.go new file mode 100644 index 0000000..02931ab --- /dev/null +++ b/gumble/user_stats.go @@ -0,0 +1,26 @@ +package gumble + +import ( + "time" +) + +type UserStats struct { + version Version + connected time.Time + idle time.Duration +} + +// Version returns the user's version. +func (us *UserStats) Version() Version { + return us.version +} + +// Connected returns when the user connected to the server. +func (us *UserStats) Connected() time.Time { + return us.connected +} + +// Idle returns how long the user has been idle. +func (us *UserStats) Idle() time.Duration { + return us.idle +}