Преглед на файлове

Initial add of client.go

Bruce Marriner преди 9 години
родител
ревизия
1e1ad5940b
променени са 1 файла, в които са добавени 395 реда и са изтрити 0 реда
  1. 395 0
      client.go

+ 395 - 0
client.go

@@ -0,0 +1,395 @@
+/******************************************************************************
+
+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
+}