123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395 |
- /******************************************************************************
- Known API Commands:
- Login - POST http://discordapp.com/api/auth/login
- Send Message - POST http://discordapp.com/api/channels/107877361818570752/messages
- About Self - GET http://discordapp.com/api/users/@me
- Guild List - GET http://discordapp.com/api/users/90975935880241152/guilds
- Channel List - GET http://discordapp.com/api/guilds/107877361818570752/channels
- Get Messages - GET http://discordapp.com/api/channels/107877361818570752/messages
- Get PM Channels - GET http://discordapp.com/api/users/@me/channels
- Get Guild Members - GET http://discordapp.com/api/guilds/107877361818570752/members
- */
- package discordgo
- import (
- "bytes"
- "encoding/json"
- "errors"
- "fmt"
- "io/ioutil"
- "net/http"
- "time"
- )
- var discordUrl = "http://discordapp.com/api"
- type RestClient struct {
- Url string
- Session *Session
- client *http.Client
- Debug bool
- }
- type Session struct {
- Id string
- Email string
- Password string
- Token string
- }
- type Guild 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"`
- }
- type Role struct {
- Permissions int
- Id int `json:",string"`
- Name string
- }
- 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
- }
- type Message struct {
- Attachments []Attachment
- Tts bool
- Embeds []Embed
- Timestamp string
- Mention_everyone bool
- Id int `json:",string"`
- Edited_timestamp string
- Author *Author
- Content string
- Channel_id int `json:",string"`
- Mentions []Mention
- }
- type Mention struct {
- }
- type Attachment struct {
- }
- type Embed struct {
- }
- type Author struct {
- Username string
- Discriminator int `json:",string"`
- Id int `json:",string"`
- Avatar string
- }
- // Create takes an email and password then prepares a RestClient with the given data,
- // which is a simple object used for future requests.
- func Create(email string, password string) (restClient *RestClient, err error) {
- if len(email) < 3 {
- err = errors.New("email too short")
- return
- }
- if len(password) < 3 {
- err = errors.New("password too short")
- return
- }
- session := &Session{"0", email, password, ""}
- httpClient := &http.Client{Timeout: (20 * time.Second)}
- restClient = &RestClient{discordUrl, session, httpClient, false}
- restClient.Session.Token, err = requestToken(restClient)
- if err != nil {
- return
- }
- restClient.Session.Id, err = requestSelf(restClient)
- if err != nil {
- return
- }
- return
- }
- // RequestToken asks the Rest server for a token by provided email/password
- func requestToken(restClient *RestClient) (token string, err error) {
- if restClient == nil {
- err = errors.New("Empty restClient, Create() one first")
- return
- }
- if restClient.Session == nil || len(restClient.Session.Email) == 0 || len(restClient.Session.Password) == 0 {
- err = errors.New("Empty restClient.Session data, Create() to set email/password")
- return
- }
- var urlStr string = fmt.Sprintf("%s/%s", restClient.Url, "auth/login")
- req, err := http.NewRequest("POST", urlStr, bytes.NewBuffer([]byte(fmt.Sprintf(`{"email":"%s", "password":"%s"}`, restClient.Session.Email, restClient.Session.Password))))
- if err != nil {
- return
- }
- req.Header.Set("Content-Type", "application/json")
- resp, err := restClient.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
- }
- session := &Session{}
- err = json.Unmarshal(body, &session)
- token = session.Token
- return
- }
- // Identify user himself
- func requestSelf(restClient *RestClient) (clientId string, err error) {
- body, err := Request(restClient, fmt.Sprintf("%s/%s", restClient.Url, "users/@me"))
- session := &Session{} // what's this for?
- err = json.Unmarshal(body, &session)
- clientId = session.Id
- return
- }
- func ListGuilds(restClient *RestClient) (guilds []Guild, err error) {
- body, err := Request(restClient, fmt.Sprintf("%s/%s", restClient.Url, fmt.Sprintf("users/%s/guilds", restClient.Session.Id)))
- err = json.Unmarshal(body, &guilds)
- return
- }
- func ListChannels(restClient *RestClient, guildId int) (channels []Channel, err error) {
- body, err := Request(restClient, fmt.Sprintf("%s/%s", restClient.Url, fmt.Sprintf("guilds/%d/channels", guildId)))
- err = json.Unmarshal(body, &channels)
- body, err = Request(restClient, fmt.Sprintf("%s/%s", restClient.Url, fmt.Sprintf("users/@me/channels", guildId)))
- err = json.Unmarshal(body, &channels)
- return
- }
- func GetMessages(restClient *RestClient, channelId int, before int, limit int) (messages []Message, err error) {
- // var urlStr = fmt.Sprintf("%s/%s", restClient.Url, fmt.Sprintf("channels/%d/messages?limit=%d&after=%d", channelId,limit,before))
- var urlStr = fmt.Sprintf("%s/%s", restClient.Url, fmt.Sprintf("channels/%d/messages", channelId))
- if limit > 0 {
- urlStr = urlStr + fmt.Sprintf("?limit=%d", limit)
- } else {
- urlStr = urlStr + "?limit=1"
- }
- if before > 0 {
- urlStr = urlStr + fmt.Sprintf("&after=%d", before)
- }
- body, err := Request(restClient, urlStr)
- err = json.Unmarshal(body, &messages)
- return
- }
- func CreateChannelUser(restClient *RestClient, userId int) (channelId int, err error) {
- var urlStr string = fmt.Sprintf("%s/%s", restClient.Url, fmt.Sprintf("users/@me/channels"))
- req, err := http.NewRequest("POST", urlStr, bytes.NewBuffer([]byte(fmt.Sprintf(`{"recipient_id":"%d"}`, userId))))
- if err != nil {
- return
- }
- req.Header.Set("authorization", restClient.Session.Token)
- req.Header.Set("Content-Type", "application/json")
- resp, err := restClient.client.Do(req)
- if err != nil {
- return
- }
- body, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- return
- }
- resp.Body.Close()
- if resp.StatusCode != 200 {
- err = errors.New(fmt.Sprintf("StatusCode: %d, %s", resp.StatusCode, string(body)))
- return
- }
- // something something if 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()))
- // err = json.Unmarshal(body, &responseMessage)
- return
- return
- }
- func SendMessage(restClient *RestClient, channelId int, message string) (responseMessage Message, err error) {
- var urlStr string = fmt.Sprintf("%s/%s", restClient.Url, fmt.Sprintf("channels/%d/messages", channelId))
- req, err := http.NewRequest("POST", urlStr, bytes.NewBuffer([]byte(fmt.Sprintf(`{"content":"%s"}`, message))))
- if err != nil {
- return
- }
- req.Header.Set("authorization", restClient.Session.Token)
- req.Header.Set("Content-Type", "application/json")
- resp, err := restClient.client.Do(req)
- if err != nil {
- return
- }
- body, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- return
- }
- resp.Body.Close()
- if resp.StatusCode != 200 {
- err = errors.New(fmt.Sprintf("StatusCode: %d, %s", resp.StatusCode, string(body)))
- return
- }
- // something something if 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()))
- err = json.Unmarshal(body, &responseMessage)
- return
- }
- func Close(restClient *RestClient) (err error) {
- req, err := http.NewRequest("POST", fmt.Sprintf("%s/%s", restClient.Url, fmt.Sprintf("auth/logout")), bytes.NewBuffer([]byte(fmt.Sprintf(``))))
- if err != nil {
- return
- }
- req.Header.Set("authorization", restClient.Session.Token)
- req.Header.Set("Content-Type", "application/json")
- resp, err := restClient.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
- }
- func ReadLoop(restClient *RestClient, channelId int) {
- var lastMessageId int = 0
- var i int = 0
- for i < 1000 {
- messages, err := GetMessages(restClient, channelId, lastMessageId, 10)
- if err != nil {
- fmt.Println(err)
- return
- }
- var i int = len(messages) - 1
- // fmt.Println("loop ", i, " ", lastMessageId);
- if i > -1 { // seems poorly wrote..
- for i >= 0 {
- var message Message = messages[i]
- fmt.Println("\n", message.Id, ":", message.Timestamp, ":\n", message.Author.Username, " > ", message.Content)
- lastMessageId = message.Id
- i--
- }
- }
- time.Sleep(2000 * time.Millisecond)
- i++
- }
- }
- // 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(restClient *RestClient, 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", restClient.Session.Token)
- req.Header.Set("Content-Type", "application/json")
- resp, err := restClient.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 restClient.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
- }
|