Skip to content

Commit

Permalink
Merge pull request #93 from iopred/login
Browse files Browse the repository at this point in the history
BREAKING - Refactor open/close logic. Support OnConnect and OnDisconnect. Closes #5.
  • Loading branch information
bwmarrin committed Jan 21, 2016
2 parents 654c78a + ddddfa3 commit 94b087c
Show file tree
Hide file tree
Showing 7 changed files with 213 additions and 248 deletions.
52 changes: 2 additions & 50 deletions discord.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,56 +111,8 @@ func New(args ...interface{}) (s *Session, err error) {
}
}

// TODO: Add code here to fetch authenticated user info like settings,
// avatar, User ID, etc. If fails, return error.

// Open websocket connection
err = s.Open()
if err != nil {
fmt.Println(err)
return
}

// Do websocket handshake.
err = s.Handshake()
if err != nil {
fmt.Println(err)
return
}

// Listen for events.
go s.Listen()
// The Session is now able to have RestAPI methods called on it.
// It is recommended that you now call Open() so that events will trigger.

return
}

// Close closes a Discord session
// TODO: Add support for Voice WS/UDP connections
func (s *Session) Close() {

s.DataReady = false

if s.heartbeatChan != nil {
select {
case <-s.heartbeatChan:
break
default:
close(s.heartbeatChan)
}
s.heartbeatChan = nil
}

if s.listenChan != nil {
select {
case <-s.listenChan:
break
default:
close(s.listenChan)
}
s.listenChan = nil
}

if s.wsConn != nil {
s.wsConn.Close()
}
}
81 changes: 56 additions & 25 deletions discord_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@ var (
envAdmin string = os.Getenv("DG_ADMIN") // User ID of admin user to use for tests
)

func init() {
if envEmail == "" || envPassword == "" || envToken == "" {
return
}

if d, err := New(envEmail, envPassword, envToken); err == nil {
dg = d
}
}

//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////// HELPER FUNCTIONS USED FOR TESTING

Expand Down Expand Up @@ -76,12 +86,16 @@ func TestNew(t *testing.T) {

// TestInvalidToken tests the New() function with an invalid token
func TestInvalidToken(t *testing.T) {
d, err := New("asjkldhflkjasdh")
if err != nil {
t.Fatalf("New(InvalidToken) returned error: %+v", err)
}

_, err := New("asjkldhflkjasdh")
// New with just a token does not do any communication, so attempt an api call.
_, err = d.UserSettings()
if err == nil {
t.Errorf("New(InvalidToken) returned nil error.")
t.Errorf("New(InvalidToken), d.UserSettings returned nil error.")
}

}

// TestInvalidUserPass tests the New() function with an invalid Email and Pass
Expand All @@ -108,8 +122,7 @@ func TestInvalidPass(t *testing.T) {
}

// TestNewUserPass tests the New() function with a username and password.
// This should return a valid Session{}, a valid Session.Token, and open
// a websocket connection to Discord.
// This should return a valid Session{}, a valid Session.Token.
func TestNewUserPass(t *testing.T) {

if envEmail == "" || envPassword == "" {
Expand All @@ -129,22 +142,6 @@ func TestNewUserPass(t *testing.T) {
if d.Token == "" {
t.Fatal("New(user,pass), d.Token is empty, should be a valid Token.")
}

if !waitBoolEqual(10*time.Second, &d.DataReady, true) {
t.Fatal("New(user,pass), d.DataReady is false after 10 seconds. Should be true.")
}

t.Log("Successfully connected to Discord via New(user,pass).")
dg = d
if envToken == "" {
envToken = dg.Token
}
}

func TestClose(t *testing.T) {
if dg != nil {
dg.Close()
}
}

// TestNewToken tests the New() function with a Token. This should return
Expand All @@ -167,12 +164,46 @@ func TestNewToken(t *testing.T) {
if d.Token == "" {
t.Fatal("New(envToken), d.Token is empty, should be a valid Token.")
}
}

if !waitBoolEqual(10*time.Second, &d.DataReady, true) {
t.Fatal("New(envToken), d.DataReady is false after 10 seconds. Should be true.")
// TestNewUserPassToken tests the New() function with a username, password and token.
// This should return the same as the TestNewUserPass function.
func TestNewUserPassToken(t *testing.T) {

if envEmail == "" || envPassword == "" || envToken == "" {
t.Skip("Skipping New(username,password,token), DG_EMAIL, DG_PASSWORD or DG_TOKEN not set")
return
}

t.Log("Successfully connected to Discord via New(token).")
dg = d
d, err := New(envEmail, envPassword, envToken)
if err != nil {
t.Fatalf("New(user,pass,token) returned error: %+v", err)
}

if d == nil {
t.Fatal("New(user,pass,token), d is nil, should be Session{}")
}

if d.Token == "" {
t.Fatal("New(user,pass,token), d.Token is empty, should be a valid Token.")
}
}

func TestOpenClose(t *testing.T) {
if envToken == "" {
t.Skip("Skipping TestClose, DG_TOKEN not set")
}

d, err := New(envToken)
if err != nil {
t.Fatalf("TestClose, New(envToken) returned error: %+v", err)
}

if err = d.Open(); err != nil {
t.Fatalf("TestClose, d.Open failed: %+v", err)
}

if err = d.Close(); err != nil {
t.Fatalf("TestClose, d.Close failed: %+v", err)
}
}
9 changes: 0 additions & 9 deletions examples/api_basic/api_basic.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,6 @@ func main() {
fmt.Println(err)
}

// Do websocket handshake.
err = dg.Handshake()
if err != nil {
fmt.Println(err)
}

// Listen for events.
go dg.Listen()

// Simple way to keep program running until any key press.
var input string
fmt.Scanln(&input)
Expand Down
3 changes: 3 additions & 0 deletions examples/new_basic/new_basic.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ func main() {
// Register messageCreate as a callback for the OnMessageCreate event.
dg.OnMessageCreate = messageCreate

// Open the websocket and begin listening.
dg.Open()

// Simple way to keep program running until any key press.
var input string
fmt.Scanln(&input)
Expand Down
38 changes: 14 additions & 24 deletions restapi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import (
// TestLogout tests the Logout() function. This should not return an error.
func TestLogout(t *testing.T) {

if dg == nil || dg.Token == "" {
t.Skip("Cannot test logout, dg.Token not set.")
if dg == nil {
t.Skip("Cannot TestLogout, dg not set.")
}

err := dg.Logout()
Expand All @@ -21,8 +21,8 @@ func TestLogout(t *testing.T) {
}

func TestUserAvatar(t *testing.T) {
if !isConnected() {
t.Skip("Skipped, Not connected to Discord.")
if dg == nil {
t.Skip("Cannot TestUserAvatar, dg not set.")
}

a, err := dg.UserAvatar("@me")
Expand All @@ -39,14 +39,8 @@ func TestUserAvatar(t *testing.T) {
}

func TestUserUpdate(t *testing.T) {

if envEmail == "" || envPassword == "" {
t.Skip("Skipping, DG_USERNAME or DG_PASSWORD not set")
return
}

if !isConnected() {
t.Skip("Skipped, Not connected to Discord.")
if dg == nil {
t.Skip("Cannot test logout, dg not set.")
}

u, err := dg.User("@me")
Expand All @@ -73,9 +67,8 @@ func TestUserUpdate(t *testing.T) {
//func (s *Session) UserChannelCreate(recipientID string) (st *Channel, err error) {

func TestUserChannelCreate(t *testing.T) {

if !isConnected() {
t.Skip("Skipped, Not connected to Discord.")
if dg == nil {
t.Skip("Cannot TestUserChannelCreate, dg not set.")
}

if envAdmin == "" {
Expand All @@ -91,9 +84,8 @@ func TestUserChannelCreate(t *testing.T) {
}

func TestUserChannels(t *testing.T) {

if !isConnected() {
t.Skip("Skipped, Not connected to Discord.")
if dg == nil {
t.Skip("Cannot TestUserChannels, dg not set.")
}

_, err := dg.UserChannels()
Expand All @@ -103,9 +95,8 @@ func TestUserChannels(t *testing.T) {
}

func TestUserGuilds(t *testing.T) {

if !isConnected() {
t.Skip("Skipped, Not connected to Discord.")
if dg == nil {
t.Skip("Cannot TestUserGuilds, dg not set.")
}

_, err := dg.UserGuilds()
Expand All @@ -115,9 +106,8 @@ func TestUserGuilds(t *testing.T) {
}

func TestUserSettings(t *testing.T) {

if !isConnected() {
t.Skip("Skipped, Not connected to Discord.")
if dg == nil {
t.Skip("Cannot TestUserSettings, dg not set.")
}

_, err := dg.UserSettings()
Expand Down
19 changes: 11 additions & 8 deletions structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,19 @@ import (
// token : The authentication token returned from Discord
// Debug : If set to ture debug logging will be displayed.
type Session struct {
sync.RWMutex

// General configurable settings.
Token string // Authentication token for this session
Debug bool // Debug for printing JSON request/responses

// Settable Callback functions for Internal Events
// OnConnect is called when the websocket connection opens.
OnConnect func(*Session)
// OnDisconnect is called when the websocket connection closes.
// This is a good handler to add reconnection logic to.
OnDisconnect func(*Session)

// Settable Callback functions for Websocket Events
OnEvent func(*Session, *Event)
OnReady func(*Session, *Ready)
Expand Down Expand Up @@ -81,14 +90,8 @@ type Session struct {
StateEnabled bool
StateMaxMessageCount int

// Mutex/Bools for locks that prevent accidents.
// TODO: Add channels.

heartbeatLock sync.Mutex
heartbeatChan chan struct{}

listenLock sync.Mutex
listenChan chan struct{}
// When nil, the session is not listening.
listening chan interface{}
}

// A VoiceRegion stores data for a specific voice region server.
Expand Down
Loading

0 comments on commit 94b087c

Please sign in to comment.