Created a client.go with low level access functions and started

working on "easy access" methods in each data structure that point
to the low level client.go functions.  Added channel.go, server.go
This commit is contained in:
Bruce Marriner 2015-11-03 08:35:58 -06:00
parent b8b42f4898
commit 66da5a3ae4
6 changed files with 221 additions and 164 deletions

19
channel.go Normal file
View file

@ -0,0 +1,19 @@
package discordgo
type Channel struct {
Server_id int `json:"guild_id,string,omitempty"`
Id int `json:"id,string"`
Name string `json:"name"`
Topic string `json:"topic"`
Position int `json:"position"`
Last_message_id int `json:"last_message_id,string"`
Type string `json:"type"`
Is_private bool `json:"is_private"`
Permission_overwrites string `json:"-"` // ignored for now
Session *Session
}
/*
func (c *Channel) Messages() (messages []Message) {
}
*/

165
client.go Normal file
View file

@ -0,0 +1,165 @@
/******************************************************************************
* Discordgo by Bruce Marriner <bruce@sqls.net>
* A Discord API for Golang.
* See discord.go for more information.
*
* This file contains functions for interacting with the Discord API
* at the lowest level. See other files for easier methods of access.
*/
package discordgo
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
"time"
)
// RequestToken asks the Discord server for an authentication token
func RequestToken(session *Session, email string, password string) (token string, err error) {
var urlStr string = fmt.Sprintf("%s/%s", discordApi, "auth/login")
req, err := http.NewRequest("POST", urlStr, bytes.NewBuffer([]byte(fmt.Sprintf(`{"email":"%s", "password":"%s"}`, email, password))))
if err != nil {
return
}
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: (20 * time.Second)}
resp, err := client.Do(req)
if err != nil {
return
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
if resp.StatusCode != 200 {
err = errors.New(fmt.Sprintf("StatusCode: %d, %s", resp.StatusCode, string(body)))
return
}
if session.Debug {
var prettyJSON bytes.Buffer
error := json.Indent(&prettyJSON, body, "", "\t")
if error != nil {
fmt.Print("JSON parse error: ", error)
return
}
fmt.Println("requestToken Response:\n", string(prettyJSON.Bytes()))
}
temp := &Session{} // TODO Must be a better way
err = json.Unmarshal(body, &temp)
token = temp.Token
return
}
// Request makes a REST API GET Request with Discord.
func Request(session *Session, urlStr string) (body []byte, err error) {
req, err := http.NewRequest("GET", urlStr, bytes.NewBuffer([]byte(fmt.Sprintf(``))))
if err != nil {
return
}
req.Header.Set("authorization", session.Token)
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: (20 * time.Second)}
resp, err := client.Do(req)
if err != nil {
return
}
body, err = ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
return
}
if resp.StatusCode != 200 {
err = errors.New(fmt.Sprintf("StatusCode: %d, %s", resp.StatusCode, string(body)))
return
}
if session.Debug {
var prettyJSON bytes.Buffer
error := json.Indent(&prettyJSON, body, "", "\t")
if error != nil {
fmt.Print("JSON parse error: ", error)
return
}
fmt.Println(urlStr+" Response:\n", string(prettyJSON.Bytes()))
}
return
}
// Returns the user details of the given userId
// session : An active session connection to Discord
// user : A user Id or name
func Users(session *Session, userId string) (user User, err error) {
body, err := Request(session, fmt.Sprintf("%s/%s", discordApi, "users/%s", userId))
err = json.Unmarshal(body, &user)
return
}
// PrivateChannels returns an array of Channel structures for all private
// channels for a user
func PrivateChannels(session *Session, userId string) (channels []Channel, err error) {
body, err := Request(session, fmt.Sprintf("%s/%s", discordApi, fmt.Sprintf("users/%s/channels", userId)))
err = json.Unmarshal(body, &channels)
return
}
// Servers returns an array of Server structures for all servers for a user
func Servers(session *Session, userId string) (servers []Server, err error) {
body, err := Request(session, fmt.Sprintf("%s/%s", discordApi, fmt.Sprintf("users/%s/guilds", userId)))
err = json.Unmarshal(body, &servers)
return
}
// Channels returns an array of Channel structures for all channels of a given
// server.
func Channels(session *Session, serverId int) (channels []Channel, err error) {
body, err := Request(session, fmt.Sprintf("%s/%s", discordApi, fmt.Sprintf("guilds/%d/channels", serverId)))
err = json.Unmarshal(body, &channels)
return
}
// Close ends a session and logs out from the Discord REST API.
func Close(session *Session) (err error) {
req, err := http.NewRequest("POST", fmt.Sprintf("%s/%s", discordApi, fmt.Sprintf("auth/logout")), bytes.NewBuffer([]byte(fmt.Sprintf(``))))
if err != nil {
return
}
req.Header.Set("authorization", session.Token)
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: (20 * time.Second)}
resp, err := client.Do(req)
if err != nil {
return
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return
}
resp.Body.Close()
if resp.StatusCode != 204 && resp.StatusCode != 200 {
err = errors.New(fmt.Sprintf("StatusCode: %d, %s", resp.StatusCode, string(body)))
return
}
return
}

View file

@ -30,7 +30,7 @@ type Discord struct {
// New creates a new connection to Discord and returns a Discord structure. // New creates a new connection to Discord and returns a Discord structure.
// This provides an easy entry where most commonly needed information is // This provides an easy entry where most commonly needed information is
// automatically fetched. // automatically fetched.
func New(email string, password string) (discord *Discord, err error) { func New(email string, password string) (d *Discord, err error) {
session := Session{} session := Session{}
@ -46,7 +46,7 @@ func New(email string, password string) (discord *Discord, err error) {
servers, err := session.Servers() servers, err := session.Servers()
discord = &Discord{session, user, servers} d = &Discord{session, user, servers}
return return
} }
@ -55,10 +55,10 @@ func New(email string, password string) (discord *Discord, err error) {
// This will update all the user, server, and channel information that was // This will update all the user, server, and channel information that was
// fetched with the New command. This is not an efficient way of doing this // fetched with the New command. This is not an efficient way of doing this
// but if used infrequently it does provide convenience. // but if used infrequently it does provide convenience.
func (discord *Discord) Renew() (err error) { func (d *Discord) Renew() (err error) {
discord.User, err = discord.Session.Self() d.User, err = Users(&d.Session, "@me")
discord.Servers, err = discord.Session.Servers() d.Servers, err = Servers(&d.Session, "@me")
return return
} }

23
server.go Normal file
View file

@ -0,0 +1,23 @@
package discordgo
type Server struct {
Id int `json:"id,string"`
Name string `json:"name"`
Icon string `json:"icon"`
Region string `json:"region"`
Joined_at string `json:"joined_at"`
Afk_timeout int `json:"afk_timeout"`
Afk_channel_id int `json:"afk_channel_id"`
Embed_channel_id int `json:"embed_channel_id"`
Embed_enabled bool `json:"embed_enabled"`
Owner_id int `json:"owner_id,string"`
Roles []Role `json:"roles"`
Session *Session // I got to be doing it wrong here.
}
// Channels returns an array of Channel structures for channels within
// this Server
func (s *Server) Channels() (c []Channel, err error) {
c, err = Channels(s.Session, s.Id)
return
}

View file

@ -5,16 +5,6 @@
package discordgo package discordgo
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
"time"
)
// A Session represents a connection to the Discord REST API. // A Session represents a connection to the Discord REST API.
// Token : The authentication token returned from Discord // Token : The authentication token returned from Discord
// Debug : If set to ture debug logging will be displayed. // Debug : If set to ture debug logging will be displayed.
@ -23,146 +13,32 @@ type Session struct {
Debug bool Debug bool
} }
// RequestToken asks the Discord server for an authentication token /******************************************************************************
* The below functions are "shortcut" methods for functions in client.go
* Reference the client.go file for more documentation.
*/
func (session *Session) RequestToken(email string, password string) (token string, err error) { func (session *Session) RequestToken(email string, password string) (token string, err error) {
token, err = RequestToken(session, email, password)
var urlStr string = fmt.Sprintf("%s/%s", discordApi, "auth/login")
req, err := http.NewRequest("POST", urlStr, bytes.NewBuffer([]byte(fmt.Sprintf(`{"email":"%s", "password":"%s"}`, email, password))))
if err != nil {
return
}
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: (20 * time.Second)}
resp, err := client.Do(req)
if err != nil {
return
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
if resp.StatusCode != 200 {
err = errors.New(fmt.Sprintf("StatusCode: %d, %s", resp.StatusCode, string(body)))
return
}
if session.Debug {
var prettyJSON bytes.Buffer
error := json.Indent(&prettyJSON, body, "", "\t")
if error != nil {
fmt.Print("JSON parse error: ", error)
return
}
fmt.Println("requestToken Response:\n", string(prettyJSON.Bytes()))
}
temp := &Session{} // TODO Must be a better way
err = json.Unmarshal(body, &temp)
token = temp.Token
return return
} }
// Self returns a User structure of the session authenticated user.
func (session *Session) Self() (user User, err error) { func (session *Session) Self() (user User, err error) {
user, err = Users(session, "@me")
body, err := Request(session, fmt.Sprintf("%s/%s", discordApi, "users/@me"))
err = json.Unmarshal(body, &user)
return return
} }
// Request makes a REST API GET Request with Discord.
func Request(session *Session, urlStr string) (body []byte, err error) {
req, err := http.NewRequest("GET", urlStr, bytes.NewBuffer([]byte(fmt.Sprintf(``))))
if err != nil {
return
}
req.Header.Set("authorization", session.Token)
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: (20 * time.Second)}
resp, err := client.Do(req)
if err != nil {
return
}
body, err = ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
return
}
if resp.StatusCode != 200 {
err = errors.New(fmt.Sprintf("StatusCode: %d, %s", resp.StatusCode, string(body)))
return
}
if session.Debug {
var prettyJSON bytes.Buffer
error := json.Indent(&prettyJSON, body, "", "\t")
if error != nil {
fmt.Print("JSON parse error: ", error)
return
}
fmt.Println(urlStr+" Response:\n", string(prettyJSON.Bytes()))
}
return
}
// PrivateChannels returns an array of Channel structures for all private
// channels of the session authenticated user.
func (session *Session) PrivateChannels() (channels []Channel, err error) { func (session *Session) PrivateChannels() (channels []Channel, err error) {
channels, err = PrivateChannels(session, "@me")
body, err := Request(session, fmt.Sprintf("%s/%s", discordApi, fmt.Sprintf("users/@me/channels")))
err = json.Unmarshal(body, &channels)
return return
} }
// Servers returns an array of Server structures for all servers for the
// session authenticated user.
func (session *Session) Servers() (servers []Server, err error) { func (session *Session) Servers() (servers []Server, err error) {
servers, err = Servers(session, "@me")
body, err := Request(session, fmt.Sprintf("%s/%s", discordApi, fmt.Sprintf("users/@me/guilds")))
err = json.Unmarshal(body, &servers)
return
}
// Channels returns an array of Channel structures for all channels of a given
// server.
func (session *Session) Channels(serverId int) (channels []Channel, err error) {
body, err := Request(session, fmt.Sprintf("%s/%s", discordApi, fmt.Sprintf("guilds/%d/channels", serverId)))
err = json.Unmarshal(body, &channels)
return return
} }
// Close ends a session and logs out from the Discord REST API. // Close ends a session and logs out from the Discord REST API.
func (session *Session) Close() (err error) { func (session *Session) Close() (err error) {
req, err := http.NewRequest("POST", fmt.Sprintf("%s/%s", discordApi, fmt.Sprintf("auth/logout")), bytes.NewBuffer([]byte(fmt.Sprintf(``)))) err = Close(session)
if err != nil {
return
}
req.Header.Set("authorization", session.Token)
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: (20 * time.Second)}
resp, err := client.Do(req)
if err != nil {
return
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return
}
resp.Body.Close()
if resp.StatusCode != 204 && resp.StatusCode != 200 {
err = errors.New(fmt.Sprintf("StatusCode: %d, %s", resp.StatusCode, string(body)))
return
}
return return
} }

View file

@ -9,20 +9,6 @@ type User struct {
Discriminator string `json:"discriminator"` Discriminator string `json:"discriminator"`
} }
type Server struct {
Id int `json:"id,string"`
Name string `json:"name"`
Icon string `json:"icon"`
Region string `json:"region"`
Joined_at string `json:"joined_at"`
Afk_timeout int `json:"afk_timeout"`
Afk_channel_id int `json:"afk_channel_id"`
Embed_channel_id int `json:"embed_channel_id"`
Embed_enabled bool `json:"embed_enabled"`
Owner_id int `json:"owner_id,string"`
Roles []Role `json:"roles"`
}
type Role struct { type Role struct {
Id int `json:"id,string"` Id int `json:"id,string"`
Name string `json:"name"` Name string `json:"name"`
@ -33,18 +19,6 @@ type Role struct {
Permissions int `json:"permissions"` Permissions int `json:"permissions"`
} }
type Channel struct {
Server_id int `json:"guild_id,string,omitempty"`
Id int `json:"id,string"`
Name string `json:"name"`
Topic string `json:"topic"`
Position int `json:"position"`
Last_message_id int `json:"last_message_id,string"`
Type string `json:"type"`
Is_private bool `json:"is_private"`
Permission_overwrites string `json:"-"` // ignored for now
}
type Message struct { type Message struct {
Attachments []Attachment Attachments []Attachment
Tts bool Tts bool