Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
iopred committed Dec 10, 2016
2 parents b5698e6 + 0759785 commit 002b6b9
Show file tree
Hide file tree
Showing 21 changed files with 2,905 additions and 568 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
language: go
go:
- 1.6
- tip
- 1.7
install:
- go get github.com/bwmarrin/discordgo
- go get -v .
Expand Down
142 changes: 4 additions & 138 deletions discord.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,10 @@
// Package discordgo provides Discord binding for Go
package discordgo

import (
"fmt"
"reflect"
)
import "fmt"

// VERSION of Discordgo, follows Symantic Versioning. (http://semver.org/)
const VERSION = "0.13.0"
const VERSION = "0.14.0-dev"

// New creates a new Discord session and will automate some startup
// tasks if given enough information to do so. Currently you can pass zero
Expand All @@ -39,11 +36,13 @@ func New(args ...interface{}) (s *Session, err error) {
// Create an empty Session interface.
s = &Session{
State: NewState(),
ratelimiter: NewRatelimiter(),
StateEnabled: true,
Compress: true,
ShouldReconnectOnError: true,
ShardID: 0,
ShardCount: 1,
MaxRestRetries: 3,
}

// If no arguments are passed return the empty Session interface.
Expand Down Expand Up @@ -124,136 +123,3 @@ func New(args ...interface{}) (s *Session, err error) {

return
}

// validateHandler takes an event handler func, and returns the type of event.
// eg.
// Session.validateHandler(func (s *discordgo.Session, m *discordgo.MessageCreate))
// will return the reflect.Type of *discordgo.MessageCreate
func (s *Session) validateHandler(handler interface{}) reflect.Type {

handlerType := reflect.TypeOf(handler)

if handlerType.NumIn() != 2 {
panic("Unable to add event handler, handler must be of the type func(*discordgo.Session, *discordgo.EventType).")
}

if handlerType.In(0) != reflect.TypeOf(s) {
panic("Unable to add event handler, first argument must be of type *discordgo.Session.")
}

eventType := handlerType.In(1)

// Support handlers of type interface{}, this is a special handler, which is triggered on every event.
if eventType.Kind() == reflect.Interface {
eventType = nil
}

return eventType
}

// AddHandler allows you to add an event handler that will be fired anytime
// the Discord WSAPI event that matches the interface fires.
// eventToInterface in events.go has a list of all the Discord WSAPI events
// and their respective interface.
// eg:
// Session.AddHandler(func(s *discordgo.Session, m *discordgo.MessageCreate) {
// })
//
// or:
// Session.AddHandler(func(s *discordgo.Session, m *discordgo.PresenceUpdate) {
// })
// The return value of this method is a function, that when called will remove the
// event handler.
func (s *Session) AddHandler(handler interface{}) func() {

s.initialize()

eventType := s.validateHandler(handler)

s.handlersMu.Lock()
defer s.handlersMu.Unlock()

h := reflect.ValueOf(handler)

s.handlers[eventType] = append(s.handlers[eventType], h)

// This must be done as we need a consistent reference to the
// reflected value, otherwise a RemoveHandler method would have
// been nice.
return func() {
s.handlersMu.Lock()
defer s.handlersMu.Unlock()

handlers := s.handlers[eventType]
for i, v := range handlers {
if h == v {
s.handlers[eventType] = append(handlers[:i], handlers[i+1:]...)
return
}
}
}
}

// handle calls any handlers that match the event type and any handlers of
// interface{}.
func (s *Session) handle(event interface{}) {

s.handlersMu.RLock()
defer s.handlersMu.RUnlock()

if s.handlers == nil {
return
}

handlerParameters := []reflect.Value{reflect.ValueOf(s), reflect.ValueOf(event)}

if handlers, ok := s.handlers[nil]; ok {
for _, handler := range handlers {
go handler.Call(handlerParameters)
}
}

if handlers, ok := s.handlers[reflect.TypeOf(event)]; ok {
for _, handler := range handlers {
go handler.Call(handlerParameters)
}
}
}

// initialize adds all internal handlers and state tracking handlers.
func (s *Session) initialize() {

s.log(LogInformational, "called")

s.handlersMu.Lock()
if s.handlers != nil {
s.handlersMu.Unlock()
return
}

s.handlers = map[interface{}][]reflect.Value{}
s.handlersMu.Unlock()

s.AddHandler(s.onReady)
s.AddHandler(s.onResumed)
s.AddHandler(s.onVoiceServerUpdate)
s.AddHandler(s.onVoiceStateUpdate)
s.AddHandler(s.State.onInterface)
}

// onReady handles the ready event.
func (s *Session) onReady(se *Session, r *Ready) {

// Store the SessionID within the Session struct.
s.sessionID = r.SessionID

// Start the heartbeat to keep the connection alive.
go s.heartbeat(s.wsConn, s.listening, r.HeartbeatInterval)
}

// onResumed handles the resumed event.
func (s *Session) onResumed(se *Session, r *Resumed) {

// Start the heartbeat to keep the connection alive.
go s.heartbeat(s.wsConn, s.listening, r.HeartbeatInterval)
}
8 changes: 4 additions & 4 deletions discord_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,8 +223,8 @@ func TestAddHandler(t *testing.T) {
d.AddHandler(interfaceHandler)
d.AddHandler(bogusHandler)

d.handle(&MessageCreate{})
d.handle(&MessageDelete{})
d.handleEvent(messageCreateEventType, &MessageCreate{})
d.handleEvent(messageDeleteEventType, &MessageDelete{})

<-time.After(500 * time.Millisecond)

Expand Down Expand Up @@ -253,11 +253,11 @@ func TestRemoveHandler(t *testing.T) {
d := Session{}
r := d.AddHandler(testHandler)

d.handle(&MessageCreate{})
d.handleEvent(messageCreateEventType, &MessageCreate{})

r()

d.handle(&MessageCreate{})
d.handleEvent(messageCreateEventType, &MessageCreate{})

<-time.After(500 * time.Millisecond)

Expand Down
18 changes: 18 additions & 0 deletions endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ var (
EndpointChannels = EndpointAPI + "channels/"
EndpointUsers = EndpointAPI + "users/"
EndpointGateway = EndpointAPI + "gateway"
EndpointWebhooks = EndpointAPI + "webhooks/"

EndpointAuth = EndpointAPI + "auth/"
EndpointLogin = EndpointAuth + "login"
Expand Down Expand Up @@ -61,6 +62,7 @@ var (
EndpointGuildChannels = func(gID string) string { return EndpointGuilds + gID + "/channels" }
EndpointGuildMembers = func(gID string) string { return EndpointGuilds + gID + "/members" }
EndpointGuildMember = func(gID, uID string) string { return EndpointGuilds + gID + "/members/" + uID }
EndpointGuildMemberRole = func(gID, uID, rID string) string { return EndpointGuilds + gID + "/members/" + uID + "/roles/" + rID }
EndpointGuildBans = func(gID string) string { return EndpointGuilds + gID + "/bans" }
EndpointGuildBan = func(gID, uID string) string { return EndpointGuilds + gID + "/bans/" + uID }
EndpointGuildIntegrations = func(gID string) string { return EndpointGuilds + gID + "/integrations" }
Expand All @@ -73,6 +75,7 @@ var (
EndpointGuildPrune = func(gID string) string { return EndpointGuilds + gID + "/prune" }
EndpointGuildIcon = func(gID, hash string) string { return EndpointGuilds + gID + "/icons/" + hash + ".jpg" }
EndpointGuildSplash = func(gID, hash string) string { return EndpointGuilds + gID + "/splashes/" + hash + ".jpg" }
EndpointGuildWebhooks = func(gID string) string { return EndpointGuilds + gID + "/webhooks" }

EndpointChannel = func(cID string) string { return EndpointChannels + cID }
EndpointChannelPermissions = func(cID string) string { return EndpointChannels + cID + "/permissions" }
Expand All @@ -86,6 +89,21 @@ var (
EndpointChannelMessagesPins = func(cID string) string { return EndpointChannel(cID) + "/pins" }
EndpointChannelMessagePin = func(cID, mID string) string { return EndpointChannel(cID) + "/pins/" + mID }

EndpointChannelWebhooks = func(cID string) string { return EndpointChannel(cID) + "/webhooks" }
EndpointWebhook = func(wID string) string { return EndpointWebhooks + wID }
EndpointWebhookToken = func(wID, token string) string { return EndpointWebhooks + wID + "/" + token }

EndpointMessageReactions = func(cID, mID, eID string) string {
return EndpointChannelMessage(cID, mID) + "/reactions/" + eID
}
EndpointMessageReaction = func(cID, mID, eID, uID string) string {
return EndpointMessageReactions(cID, mID, eID) + "/" + uID
}

EndpointRelationships = func() string { return EndpointUsers + "@me" + "/relationships" }
EndpointRelationship = func(uID string) string { return EndpointRelationships() + "/" + uID }
EndpointRelationshipsMutual = func(uID string) string { return EndpointUsers + uID + "/relationships" }

EndpointInvite = func(iID string) string { return EndpointAPI + "invite/" + iID }

EndpointIntegrationsJoin = func(iID string) string { return EndpointAPI + "integrations/" + iID + "/join" }
Expand Down

0 comments on commit 002b6b9

Please sign in to comment.