This commit is contained in:
Bruce Marriner 2016-01-28 08:36:09 -06:00
parent 53db54ea8c
commit edc09778a7
6 changed files with 132 additions and 54 deletions

View file

@ -12,13 +12,13 @@ import (
var (
dg *Session // Stores global discordgo session
envToken string = os.Getenv("DG_TOKEN") // Token to use when authenticating
envEmail string = os.Getenv("DG_EMAIL") // Email to use when authenticating
envPassword string = os.Getenv("DG_PASSWORD") // Password to use when authenticating
envGuild string = os.Getenv("DG_GUILD") // Guild ID to use for tests
envChannel string = os.Getenv("DG_CHANNEL") // Channel ID to use for tests
envUser string = os.Getenv("DG_USER") // User ID to use for tests
envAdmin string = os.Getenv("DG_ADMIN") // User ID of admin user to use for tests
envToken = os.Getenv("DG_TOKEN") // Token to use when authenticating
envEmail = os.Getenv("DG_EMAIL") // Email to use when authenticating
envPassword = os.Getenv("DG_PASSWORD") // Password to use when authenticating
envGuild = os.Getenv("DG_GUILD") // Guild ID to use for tests
envChannel = os.Getenv("DG_CHANNEL") // Channel ID to use for tests
envUser = os.Getenv("DG_USER") // User ID to use for tests
envAdmin = os.Getenv("DG_ADMIN") // User ID of admin user to use for tests
)
func init() {

View file

@ -25,7 +25,7 @@ import (
"time"
)
// Error returned for unmarshal errors.
// ErrJSONUnmarshal is returned for JSON Unmarshall errors.
var ErrJSONUnmarshal = errors.New("json unmarshal")
// Request makes a (GET/POST/...) Requests to Discord REST API.
@ -69,10 +69,15 @@ func (s *Session) Request(method, urlStr string, data interface{}) (response []b
client := &http.Client{Timeout: (20 * time.Second)}
resp, err := client.Do(req)
defer resp.Body.Close()
if err != nil {
return
}
defer func() {
err := resp.Body.Close()
if err != nil {
fmt.Println("error closing resp body")
}
}()
response, err = ioutil.ReadAll(resp.Body)
if err != nil {

View file

@ -12,9 +12,13 @@
package discordgo
import "errors"
import (
"errors"
"fmt"
)
var nilError error = errors.New("State not instantiated, please use discordgo.New() or assign Session.State.")
// ErrNilState is returned when the state is nil.
var ErrNilState = errors.New("State not instantiated, please use discordgo.New() or assign Session.State.")
// NewState creates an empty state.
func NewState() *State {
@ -29,7 +33,7 @@ func NewState() *State {
// OnReady takes a Ready event and updates all internal state.
func (s *State) OnReady(r *Ready) error {
if s == nil {
return nilError
return ErrNilState
}
s.Lock()
defer s.Unlock()
@ -42,7 +46,7 @@ func (s *State) OnReady(r *Ready) error {
// updates it if it already exists.
func (s *State) GuildAdd(guild *Guild) error {
if s == nil {
return nilError
return ErrNilState
}
s.Lock()
defer s.Unlock()
@ -67,7 +71,7 @@ func (s *State) GuildAdd(guild *Guild) error {
// GuildRemove removes a guild from current world state.
func (s *State) GuildRemove(guild *Guild) error {
if s == nil {
return nilError
return ErrNilState
}
s.Lock()
defer s.Unlock()
@ -88,7 +92,7 @@ func (s *State) GuildRemove(guild *Guild) error {
// isInGuild := err == nil
func (s *State) Guild(guildID string) (*Guild, error) {
if s == nil {
return nil, nilError
return nil, ErrNilState
}
s.RLock()
defer s.RUnlock()
@ -108,7 +112,7 @@ func (s *State) Guild(guildID string) (*Guild, error) {
// updates it if it already exists.
func (s *State) MemberAdd(member *Member) error {
if s == nil {
return nilError
return ErrNilState
}
guild, err := s.Guild(member.GuildID)
@ -133,7 +137,7 @@ func (s *State) MemberAdd(member *Member) error {
// MemberRemove removes a member from current world state.
func (s *State) MemberRemove(member *Member) error {
if s == nil {
return nilError
return ErrNilState
}
guild, err := s.Guild(member.GuildID)
@ -157,7 +161,7 @@ func (s *State) MemberRemove(member *Member) error {
// Member gets a member by ID from a guild.
func (s *State) Member(guildID, userID string) (*Member, error) {
if s == nil {
return nil, nilError
return nil, ErrNilState
}
guild, err := s.Guild(guildID)
@ -183,7 +187,7 @@ func (s *State) Member(guildID, userID string) (*Member, error) {
// a guild.
func (s *State) ChannelAdd(channel *Channel) error {
if s == nil {
return nilError
return ErrNilState
}
if channel.IsPrivate {
@ -229,7 +233,7 @@ func (s *State) ChannelAdd(channel *Channel) error {
// ChannelRemove removes a channel from current world state.
func (s *State) ChannelRemove(channel *Channel) error {
if s == nil {
return nilError
return ErrNilState
}
if channel.IsPrivate {
@ -265,7 +269,7 @@ func (s *State) ChannelRemove(channel *Channel) error {
// GuildChannel gets a channel by ID from a guild.
func (s *State) GuildChannel(guildID, channelID string) (*Channel, error) {
if s == nil {
return nil, nilError
return nil, ErrNilState
}
guild, err := s.Guild(guildID)
@ -288,7 +292,7 @@ func (s *State) GuildChannel(guildID, channelID string) (*Channel, error) {
// PrivateChannel gets a private channel by ID.
func (s *State) PrivateChannel(channelID string) (*Channel, error) {
if s == nil {
return nil, nilError
return nil, ErrNilState
}
s.RLock()
defer s.RUnlock()
@ -305,7 +309,7 @@ func (s *State) PrivateChannel(channelID string) (*Channel, error) {
// Channel gets a channel by ID, it will look in all guilds an private channels.
func (s *State) Channel(channelID string) (*Channel, error) {
if s == nil {
return nil, nilError
return nil, ErrNilState
}
c, err := s.PrivateChannel(channelID)
@ -326,7 +330,7 @@ func (s *State) Channel(channelID string) (*Channel, error) {
// Emoji returns an emoji for a guild and emoji id.
func (s *State) Emoji(guildID, emojiID string) (*Emoji, error) {
if s == nil {
return nil, nilError
return nil, ErrNilState
}
guild, err := s.Guild(guildID)
@ -349,7 +353,7 @@ func (s *State) Emoji(guildID, emojiID string) (*Emoji, error) {
// EmojiAdd adds an emoji to the current world state.
func (s *State) EmojiAdd(guildID string, emoji *Emoji) error {
if s == nil {
return nilError
return ErrNilState
}
guild, err := s.Guild(guildID)
@ -386,7 +390,7 @@ func (s *State) EmojisAdd(guildID string, emojis []*Emoji) error {
// Messages are kept in state up to s.MaxMessageCount
func (s *State) MessageAdd(message *Message) error {
if s == nil {
return nilError
return ErrNilState
}
c, err := s.Channel(message.ChannelID)
@ -410,7 +414,10 @@ func (s *State) MessageAdd(message *Message) error {
if len(c.Messages) > s.MaxMessageCount {
s.Unlock()
for len(c.Messages) > s.MaxMessageCount {
s.MessageRemove(c.Messages[0])
err := s.MessageRemove(c.Messages[0])
if err != nil {
fmt.Println("message remove error: ", err)
}
}
s.Lock()
}
@ -420,7 +427,7 @@ func (s *State) MessageAdd(message *Message) error {
// MessageRemove removes a message from the world state.
func (s *State) MessageRemove(message *Message) error {
if s == nil {
return nilError
return ErrNilState
}
c, err := s.Channel(message.ChannelID)
if err != nil {
@ -443,7 +450,7 @@ func (s *State) MessageRemove(message *Message) error {
// Message gets a message by channel and message ID.
func (s *State) Message(channelID, messageID string) (*Message, error) {
if s == nil {
return nil, nilError
return nil, ErrNilState
}
c, err := s.Channel(channelID)
if err != nil {

View file

@ -151,6 +151,7 @@ type PermissionOverwrite struct {
Allow int `json:"allow"`
}
// Emoji struct holds data related to Emoji's
type Emoji struct {
Roles []string `json:"roles"`
RequireColons bool `json:"require_colons"`
@ -212,6 +213,7 @@ type Presence struct {
Game *Game `json:"game"`
}
// A Game struct holds the name of the "playing .." game for a user
type Game struct {
Name string `json:"name"`
}
@ -277,6 +279,8 @@ type Ready struct {
PrivateChannels []*Channel `json:"private_channels"`
Guilds []*Guild `json:"guilds"`
}
// A RateLimit struct holds information related to a specific rate limit.
type RateLimit struct {
Bucket string `json:"bucket"`
Message string `json:"message"`

View file

@ -112,11 +112,17 @@ func (v *Voice) Open() (err error) {
func (v *Voice) Close() {
if v.UDPConn != nil {
v.UDPConn.Close()
err := v.UDPConn.Close()
if err != nil {
fmt.Println("error closing udp connection: ", err)
}
}
if v.wsConn != nil {
v.wsConn.Close()
err := v.wsConn.Close()
if err != nil {
fmt.Println("error closing websocket connection: ", err)
}
}
}
@ -363,7 +369,7 @@ func (v *Voice) udpOpen() (err error) {
func (v *Voice) udpKeepAlive(i time.Duration) {
var err error
var sequence uint64 = 0
var sequence uint64
packet := make([]byte, 8)
@ -403,8 +409,8 @@ func (v *Voice) opusSender(opus <-chan []byte, rate, size int) {
v.Ready = true
defer func() { v.Ready = false }()
var sequence uint16 = 0
var timestamp uint32 = 0
var sequence uint16
var timestamp uint32
udpHeader := make([]byte, 12)
// build the parts that don't change in the udpHeader
@ -432,12 +438,16 @@ func (v *Voice) opusSender(opus <-chan []byte, rate, size int) {
// block here until we're exactly at the right time :)
// Then send rtp audio packet to Discord over UDP
<-ticker.C
v.UDPConn.Write(sendbuf)
_, err := v.UDPConn.Write(sendbuf)
if err != nil {
fmt.Println("error writing to udp connection: ", err)
}
if (sequence) == 0xFFFF {
sequence = 0
} else {
sequence += 1
sequence++
}
if (timestamp + uint32(size)) >= 0xFFFFFFFF {

View file

@ -134,7 +134,10 @@ func (s *Session) listen(wsConn *websocket.Conn, listening <-chan interface{}) {
if sameConnection {
// There has been an error reading, Close() the websocket so that
// OnDisconnect is fired.
s.Close()
err := s.Close()
if err != nil {
fmt.Println("error closing session connection: ", err)
}
// Attempt to reconnect, with expenonential backoff up to 10 minutes.
if s.ShouldReconnectOnError {
@ -262,7 +265,8 @@ func unmarshalEvent(event *Event, i interface{}) (err error) {
// broken up into smaller functions to be more idiomatic Go.
// Events will be handled by any implemented handler in Session.
// All unhandled events will then be handled by OnEvent.
func (s *Session) event(messageType int, message []byte) (err error) {
func (s *Session) event(messageType int, message []byte) {
var err error
var reader io.Reader
reader = bytes.NewBuffer(message)
@ -270,9 +274,14 @@ func (s *Session) event(messageType int, message []byte) (err error) {
z, err1 := zlib.NewReader(reader)
if err1 != nil {
fmt.Println(err1)
return err1
return
}
defer z.Close()
defer func() {
err := z.Close()
if err != nil {
fmt.Println("error closing zlib:", err)
}
}()
reader = z
}
@ -293,7 +302,11 @@ func (s *Session) event(messageType int, message []byte) (err error) {
if err = unmarshalEvent(e, &st); err == nil {
go s.heartbeat(s.wsConn, s.listening, st.HeartbeatInterval)
if s.StateEnabled {
s.State.OnReady(st)
err := s.State.OnReady(st)
if err != nil {
fmt.Println("error: ", err)
}
}
if s.OnReady != nil {
s.OnReady(s, st)
@ -353,7 +366,10 @@ func (s *Session) event(messageType int, message []byte) (err error) {
var st *Message
if err = unmarshalEvent(e, &st); err == nil {
if stateEnabled {
s.State.MessageAdd(st)
err := s.State.MessageAdd(st)
if err != nil {
fmt.Println("error :", err)
}
}
if s.OnMessageCreate != nil {
s.OnMessageCreate(s, st)
@ -370,7 +386,10 @@ func (s *Session) event(messageType int, message []byte) (err error) {
var st *Message
if err = unmarshalEvent(e, &st); err == nil {
if stateEnabled {
s.State.MessageAdd(st)
err := s.State.MessageAdd(st)
if err != nil {
fmt.Println("error :", err)
}
}
if s.OnMessageUpdate != nil {
s.OnMessageUpdate(s, st)
@ -385,7 +404,10 @@ func (s *Session) event(messageType int, message []byte) (err error) {
var st *Message
if err = unmarshalEvent(e, &st); err == nil {
if stateEnabled {
s.State.MessageRemove(st)
err := s.State.MessageRemove(st)
if err != nil {
fmt.Println("error :", err)
}
}
if s.OnMessageDelete != nil {
s.OnMessageDelete(s, st)
@ -407,7 +429,10 @@ func (s *Session) event(messageType int, message []byte) (err error) {
var st *Channel
if err = unmarshalEvent(e, &st); err == nil {
if s.StateEnabled {
s.State.ChannelAdd(st)
err := s.State.ChannelAdd(st)
if err != nil {
fmt.Println("error :", err)
}
}
if s.OnChannelCreate != nil {
s.OnChannelCreate(s, st)
@ -423,7 +448,10 @@ func (s *Session) event(messageType int, message []byte) (err error) {
var st *Channel
if err = unmarshalEvent(e, &st); err == nil {
if s.StateEnabled {
s.State.ChannelAdd(st)
err := s.State.ChannelAdd(st)
if err != nil {
fmt.Println("error :", err)
}
}
if s.OnChannelUpdate != nil {
s.OnChannelUpdate(s, st)
@ -439,7 +467,10 @@ func (s *Session) event(messageType int, message []byte) (err error) {
var st *Channel
if err = unmarshalEvent(e, &st); err == nil {
if s.StateEnabled {
s.State.ChannelRemove(st)
err := s.State.ChannelRemove(st)
if err != nil {
fmt.Println("error :", err)
}
}
if s.OnChannelDelete != nil {
s.OnChannelDelete(s, st)
@ -455,7 +486,10 @@ func (s *Session) event(messageType int, message []byte) (err error) {
var st *Guild
if err = unmarshalEvent(e, &st); err == nil {
if s.StateEnabled {
s.State.GuildAdd(st)
err := s.State.GuildAdd(st)
if err != nil {
fmt.Println("error :", err)
}
}
if s.OnGuildCreate != nil {
s.OnGuildCreate(s, st)
@ -471,7 +505,10 @@ func (s *Session) event(messageType int, message []byte) (err error) {
var st *Guild
if err = unmarshalEvent(e, &st); err == nil {
if s.StateEnabled {
s.State.GuildAdd(st)
err := s.State.GuildAdd(st)
if err != nil {
fmt.Println("error :", err)
}
}
if s.OnGuildCreate != nil {
s.OnGuildUpdate(s, st)
@ -487,7 +524,10 @@ func (s *Session) event(messageType int, message []byte) (err error) {
var st *Guild
if err = unmarshalEvent(e, &st); err == nil {
if s.StateEnabled {
s.State.GuildRemove(st)
err := s.State.GuildRemove(st)
if err != nil {
fmt.Println("error :", err)
}
}
if s.OnGuildDelete != nil {
s.OnGuildDelete(s, st)
@ -503,7 +543,10 @@ func (s *Session) event(messageType int, message []byte) (err error) {
var st *Member
if err = unmarshalEvent(e, &st); err == nil {
if s.StateEnabled {
s.State.MemberAdd(st)
err := s.State.MemberAdd(st)
if err != nil {
fmt.Println("error :", err)
}
}
if s.OnGuildMemberAdd != nil {
s.OnGuildMemberAdd(s, st)
@ -519,7 +562,10 @@ func (s *Session) event(messageType int, message []byte) (err error) {
var st *Member
if err = unmarshalEvent(e, &st); err == nil {
if s.StateEnabled {
s.State.MemberRemove(st)
err := s.State.MemberRemove(st)
if err != nil {
fmt.Println("error :", err)
}
}
if s.OnGuildMemberRemove != nil {
s.OnGuildMemberRemove(s, st)
@ -535,7 +581,10 @@ func (s *Session) event(messageType int, message []byte) (err error) {
var st *Member
if err = unmarshalEvent(e, &st); err == nil {
if s.StateEnabled {
s.State.MemberAdd(st)
err := s.State.MemberAdd(st)
if err != nil {
fmt.Println("error :", err)
}
}
if s.OnGuildMemberUpdate != nil {
s.OnGuildMemberUpdate(s, st)
@ -599,7 +648,10 @@ func (s *Session) event(messageType int, message []byte) (err error) {
var st *GuildEmojisUpdate
if err = unmarshalEvent(e, &st); err == nil {
if s.StateEnabled {
s.State.EmojisAdd(st.GuildID, st.Emojis)
err := s.State.EmojisAdd(st.GuildID, st.Emojis)
if err != nil {
fmt.Println("error :", err)
}
}
if s.OnGuildEmojisUpdate != nil {
s.OnGuildEmojisUpdate(s, st)