From c0f68b4bd5ef42271a21081e62d7273ad2376adf Mon Sep 17 00:00:00 2001 From: Bruce Marriner Date: Mon, 2 Nov 2015 16:43:10 -0600 Subject: [PATCH] Refactoring stuff, moved things around :) --- discord.go | 52 ++++++++++++++++++++ session.go | 141 +++++++++++++++++++++++++++++++++++++++++++++++++++++ structs.go | 63 ++++++++++++++---------- 3 files changed, 229 insertions(+), 27 deletions(-) create mode 100644 discord.go create mode 100644 session.go diff --git a/discord.go b/discord.go new file mode 100644 index 0000000..8ef436d --- /dev/null +++ b/discord.go @@ -0,0 +1,52 @@ +/****************************************************************************** + * Discordgo v0 by Bruce Marriner + * A DiscordApp API for Golang. + * + * Currently only the REST API is functional. I will add on the websocket + * layer once I get the API section where I want it. + * + */ + +package discordgo + +// Define known API URL paths as global constants +const ( + discordUrl = "http://discordapp.com" + discordApi = discordUrl + "/api/" + servers = discordApi + "guilds" + channels = discordApi + "channels" + users = discordApi + "users" +) + +// possible all-inclusive strut.. +type Discord struct { + Session + User User + Servers []Server +} + +// Create a new connection to Discord API. Returns a client session handle. +// this is a all inclusive type of easy setup command that will return +// a connection, user information, and available channels. +// This is probably the most common way to use the library but you +// can use the "manual" functions below instead. +func New(email string, password string) (discord *Discord, err error) { + + session := Session{} + + session.Token, err = session.RequestToken(email, password) + if err != nil { + return + } + + user, err := session.Self() + if err != nil { + return + } + + servers, err := session.Servers() + + discord = &Discord{session, user, servers} + + return +} diff --git a/session.go b/session.go new file mode 100644 index 0000000..c3eae3c --- /dev/null +++ b/session.go @@ -0,0 +1,141 @@ +/****************************************************************************** + * Discordgo v0 by Bruce Marriner + * A DiscordApp API for Golang. + * + * Currently only the REST API is functional. I will add on the websocket + * layer once I get the API section where I want it. + * + */ + +package discordgo + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "io/ioutil" + "net/http" + "time" +) + +// Represents a session connection to the Discord REST API. +// I suspect I'll be adding more to this later :) +type Session struct { + Token string + Debug bool +} + +// RequestToken asks the Rest server for a token by provided email/password +func (session *Session) RequestToken(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 +} + +// Identify session user +func (session *Session) Self() (user User, err error) { + + body, err := Request(session, fmt.Sprintf("%s/%s", discordApi, "users/@me")) + err = json.Unmarshal(body, &user) + + return +} + +// Request makes a API GET Request. This is a general purpose function +// and is used by all API functions. It is exposed currently so it can +// also be used outside of this library. +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 +} + +func (session *Session) Servers() (servers []Server, err error) { + + body, err := Request(session, fmt.Sprintf("%s/%s", discordApi, fmt.Sprintf("users/@me/guilds"))) + //body, err := Request(session, fmt.Sprintf("%s/%s", discordApi, fmt.Sprintf("users/%s/guilds", session.Id))) + err = json.Unmarshal(body, &servers) + + return +} + +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 +} + +func (session *Session) PrivateChannels() (channels []Channel, err error) { + + body, err := Request(session, fmt.Sprintf("%s/%s", discordApi, fmt.Sprintf("users/@me/channels"))) + err = json.Unmarshal(body, &channels) + + return +} diff --git a/structs.go b/structs.go index 7a28778..c78b329 100644 --- a/structs.go +++ b/structs.go @@ -1,36 +1,48 @@ package discordgo +type User struct { + Id int `json:"id,string"` + Email string `json:"email"` + Username string `json:"username"` + Avatar string `json:"Avatar"` + Verified bool `json:"verified"` + Discriminator string `json:"discriminator"` +} + type Server struct { - Afk_timeout int - Joined_at string - // Afk_channel_id int `json:",string"` - Id int `json:",string"` - Icon string - Name string - // Roles []Role - Region string - //Embed_channel_id int `json:",string"` - // Embed_channel_id string - // Embed_enabled bool - Owner_id int `json:",string"` + 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 { - Permissions int - Id int `json:",string"` - Name string + Id int `json:"id,string"` + Name string `json:"name"` + Managed bool `json:"managed"` + Color int `json:"color"` + Hoist bool `json:"hoist"` + Position int `json:"position"` + Permissions int `json:"permissions"` } type Channel struct { - Guild_id int `json:",string"` - Id int `json:",string"` - Name string - Last_message_id string - Is_private string - - // Permission_overwrites string - // Position int `json:",string"` - // Type string + 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 { @@ -62,6 +74,3 @@ type Author struct { Id int `json:",string"` Avatar string } - -type User struct { -}