client.go 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. /******************************************************************************
  2. Known API Commands:
  3. Login - POST http://discordapp.com/api/auth/login
  4. Send Message - POST http://discordapp.com/api/channels/107877361818570752/messages
  5. About Self - GET http://discordapp.com/api/users/@me
  6. Guild List - GET http://discordapp.com/api/users/90975935880241152/guilds
  7. Channel List - GET http://discordapp.com/api/guilds/107877361818570752/channels
  8. Get Messages - GET http://discordapp.com/api/channels/107877361818570752/messages
  9. Get PM Channels - GET http://discordapp.com/api/users/@me/channels
  10. Get Guild Members - GET http://discordapp.com/api/guilds/107877361818570752/members
  11. */
  12. package discordgo
  13. import (
  14. "bytes"
  15. "encoding/json"
  16. "errors"
  17. "fmt"
  18. "io/ioutil"
  19. "net/http"
  20. "time"
  21. )
  22. var discordUrl = "http://discordapp.com/api"
  23. type RestClient struct {
  24. Url string
  25. Session *Session
  26. client *http.Client
  27. Debug bool
  28. }
  29. type Session struct {
  30. Id string
  31. Email string
  32. Password string
  33. Token string
  34. }
  35. type Guild struct {
  36. Afk_timeout int
  37. Joined_at string
  38. // Afk_channel_id int `json:",string"`
  39. Id int `json:",string"`
  40. Icon string
  41. Name string
  42. // Roles []Role
  43. Region string
  44. //Embed_channel_id int `json:",string"`
  45. // Embed_channel_id string
  46. // Embed_enabled bool
  47. Owner_id int `json:",string"`
  48. }
  49. type Role struct {
  50. Permissions int
  51. Id int `json:",string"`
  52. Name string
  53. }
  54. type Channel struct {
  55. Guild_id int `json:",string"`
  56. Id int `json:",string"`
  57. Name string
  58. Last_message_id string
  59. Is_private string
  60. // Permission_overwrites string
  61. // Position int `json:",string"`
  62. // Type string
  63. }
  64. type Message struct {
  65. Attachments []Attachment
  66. Tts bool
  67. Embeds []Embed
  68. Timestamp string
  69. Mention_everyone bool
  70. Id int `json:",string"`
  71. Edited_timestamp string
  72. Author *Author
  73. Content string
  74. Channel_id int `json:",string"`
  75. Mentions []Mention
  76. }
  77. type Mention struct {
  78. }
  79. type Attachment struct {
  80. }
  81. type Embed struct {
  82. }
  83. type Author struct {
  84. Username string
  85. Discriminator int `json:",string"`
  86. Id int `json:",string"`
  87. Avatar string
  88. }
  89. // Create takes an email and password then prepares a RestClient with the given data,
  90. // which is a simple object used for future requests.
  91. func Create(email string, password string) (restClient *RestClient, err error) {
  92. if len(email) < 3 {
  93. err = errors.New("email too short")
  94. return
  95. }
  96. if len(password) < 3 {
  97. err = errors.New("password too short")
  98. return
  99. }
  100. session := &Session{"0", email, password, ""}
  101. httpClient := &http.Client{Timeout: (20 * time.Second)}
  102. restClient = &RestClient{discordUrl, session, httpClient, false}
  103. restClient.Session.Token, err = requestToken(restClient)
  104. if err != nil {
  105. return
  106. }
  107. restClient.Session.Id, err = requestSelf(restClient)
  108. if err != nil {
  109. return
  110. }
  111. return
  112. }
  113. // RequestToken asks the Rest server for a token by provided email/password
  114. func requestToken(restClient *RestClient) (token string, err error) {
  115. if restClient == nil {
  116. err = errors.New("Empty restClient, Create() one first")
  117. return
  118. }
  119. if restClient.Session == nil || len(restClient.Session.Email) == 0 || len(restClient.Session.Password) == 0 {
  120. err = errors.New("Empty restClient.Session data, Create() to set email/password")
  121. return
  122. }
  123. var urlStr string = fmt.Sprintf("%s/%s", restClient.Url, "auth/login")
  124. req, err := http.NewRequest("POST", urlStr, bytes.NewBuffer([]byte(fmt.Sprintf(`{"email":"%s", "password":"%s"}`, restClient.Session.Email, restClient.Session.Password))))
  125. if err != nil {
  126. return
  127. }
  128. req.Header.Set("Content-Type", "application/json")
  129. resp, err := restClient.client.Do(req)
  130. if err != nil {
  131. return
  132. }
  133. defer resp.Body.Close()
  134. body, _ := ioutil.ReadAll(resp.Body)
  135. if resp.StatusCode != 200 {
  136. err = errors.New(fmt.Sprintf("StatusCode: %d, %s", resp.StatusCode, string(body)))
  137. return
  138. }
  139. session := &Session{}
  140. err = json.Unmarshal(body, &session)
  141. token = session.Token
  142. return
  143. }
  144. // Identify user himself
  145. func requestSelf(restClient *RestClient) (clientId string, err error) {
  146. body, err := Request(restClient, fmt.Sprintf("%s/%s", restClient.Url, "users/@me"))
  147. session := &Session{} // what's this for?
  148. err = json.Unmarshal(body, &session)
  149. clientId = session.Id
  150. return
  151. }
  152. func ListGuilds(restClient *RestClient) (guilds []Guild, err error) {
  153. body, err := Request(restClient, fmt.Sprintf("%s/%s", restClient.Url, fmt.Sprintf("users/%s/guilds", restClient.Session.Id)))
  154. err = json.Unmarshal(body, &guilds)
  155. return
  156. }
  157. func ListChannels(restClient *RestClient, guildId int) (channels []Channel, err error) {
  158. body, err := Request(restClient, fmt.Sprintf("%s/%s", restClient.Url, fmt.Sprintf("guilds/%d/channels", guildId)))
  159. err = json.Unmarshal(body, &channels)
  160. body, err = Request(restClient, fmt.Sprintf("%s/%s", restClient.Url, fmt.Sprintf("users/@me/channels", guildId)))
  161. err = json.Unmarshal(body, &channels)
  162. return
  163. }
  164. func GetMessages(restClient *RestClient, channelId int, before int, limit int) (messages []Message, err error) {
  165. // var urlStr = fmt.Sprintf("%s/%s", restClient.Url, fmt.Sprintf("channels/%d/messages?limit=%d&after=%d", channelId,limit,before))
  166. var urlStr = fmt.Sprintf("%s/%s", restClient.Url, fmt.Sprintf("channels/%d/messages", channelId))
  167. if limit > 0 {
  168. urlStr = urlStr + fmt.Sprintf("?limit=%d", limit)
  169. } else {
  170. urlStr = urlStr + "?limit=1"
  171. }
  172. if before > 0 {
  173. urlStr = urlStr + fmt.Sprintf("&after=%d", before)
  174. }
  175. body, err := Request(restClient, urlStr)
  176. err = json.Unmarshal(body, &messages)
  177. return
  178. }
  179. func CreateChannelUser(restClient *RestClient, userId int) (channelId int, err error) {
  180. var urlStr string = fmt.Sprintf("%s/%s", restClient.Url, fmt.Sprintf("users/@me/channels"))
  181. req, err := http.NewRequest("POST", urlStr, bytes.NewBuffer([]byte(fmt.Sprintf(`{"recipient_id":"%d"}`, userId))))
  182. if err != nil {
  183. return
  184. }
  185. req.Header.Set("authorization", restClient.Session.Token)
  186. req.Header.Set("Content-Type", "application/json")
  187. resp, err := restClient.client.Do(req)
  188. if err != nil {
  189. return
  190. }
  191. body, err := ioutil.ReadAll(resp.Body)
  192. if err != nil {
  193. return
  194. }
  195. resp.Body.Close()
  196. if resp.StatusCode != 200 {
  197. err = errors.New(fmt.Sprintf("StatusCode: %d, %s", resp.StatusCode, string(body)))
  198. return
  199. }
  200. // something something if debug
  201. var prettyJSON bytes.Buffer
  202. error := json.Indent(&prettyJSON, body, "", "\t")
  203. if error != nil {
  204. fmt.Print("JSON parse error: ", error)
  205. return
  206. }
  207. fmt.Println(urlStr+" Response:\n", string(prettyJSON.Bytes()))
  208. // err = json.Unmarshal(body, &responseMessage)
  209. return
  210. return
  211. }
  212. func SendMessage(restClient *RestClient, channelId int, message string) (responseMessage Message, err error) {
  213. var urlStr string = fmt.Sprintf("%s/%s", restClient.Url, fmt.Sprintf("channels/%d/messages", channelId))
  214. req, err := http.NewRequest("POST", urlStr, bytes.NewBuffer([]byte(fmt.Sprintf(`{"content":"%s"}`, message))))
  215. if err != nil {
  216. return
  217. }
  218. req.Header.Set("authorization", restClient.Session.Token)
  219. req.Header.Set("Content-Type", "application/json")
  220. resp, err := restClient.client.Do(req)
  221. if err != nil {
  222. return
  223. }
  224. body, err := ioutil.ReadAll(resp.Body)
  225. if err != nil {
  226. return
  227. }
  228. resp.Body.Close()
  229. if resp.StatusCode != 200 {
  230. err = errors.New(fmt.Sprintf("StatusCode: %d, %s", resp.StatusCode, string(body)))
  231. return
  232. }
  233. // something something if debug
  234. var prettyJSON bytes.Buffer
  235. error := json.Indent(&prettyJSON, body, "", "\t")
  236. if error != nil {
  237. fmt.Print("JSON parse error: ", error)
  238. return
  239. }
  240. fmt.Println(urlStr+" Response:\n", string(prettyJSON.Bytes()))
  241. err = json.Unmarshal(body, &responseMessage)
  242. return
  243. }
  244. func Close(restClient *RestClient) (err error) {
  245. req, err := http.NewRequest("POST", fmt.Sprintf("%s/%s", restClient.Url, fmt.Sprintf("auth/logout")), bytes.NewBuffer([]byte(fmt.Sprintf(``))))
  246. if err != nil {
  247. return
  248. }
  249. req.Header.Set("authorization", restClient.Session.Token)
  250. req.Header.Set("Content-Type", "application/json")
  251. resp, err := restClient.client.Do(req)
  252. if err != nil {
  253. return
  254. }
  255. body, err := ioutil.ReadAll(resp.Body)
  256. if err != nil {
  257. return
  258. }
  259. resp.Body.Close()
  260. if resp.StatusCode != 204 && resp.StatusCode != 200 {
  261. err = errors.New(fmt.Sprintf("StatusCode: %d, %s", resp.StatusCode, string(body)))
  262. return
  263. }
  264. return
  265. }
  266. func ReadLoop(restClient *RestClient, channelId int) {
  267. var lastMessageId int = 0
  268. var i int = 0
  269. for i < 1000 {
  270. messages, err := GetMessages(restClient, channelId, lastMessageId, 10)
  271. if err != nil {
  272. fmt.Println(err)
  273. return
  274. }
  275. var i int = len(messages) - 1
  276. // fmt.Println("loop ", i, " ", lastMessageId);
  277. if i > -1 { // seems poorly wrote..
  278. for i >= 0 {
  279. var message Message = messages[i]
  280. fmt.Println("\n", message.Id, ":", message.Timestamp, ":\n", message.Author.Username, " > ", message.Content)
  281. lastMessageId = message.Id
  282. i--
  283. }
  284. }
  285. time.Sleep(2000 * time.Millisecond)
  286. i++
  287. }
  288. }
  289. // Request makes a API GET Request. This is a general purpose function
  290. // and is used by all API functions. It is exposed currently so it can
  291. // also be used outside of this library.
  292. func Request(restClient *RestClient, urlStr string) (body []byte, err error) {
  293. req, err := http.NewRequest("GET", urlStr, bytes.NewBuffer([]byte(fmt.Sprintf(``))))
  294. if err != nil {
  295. return
  296. }
  297. req.Header.Set("authorization", restClient.Session.Token)
  298. req.Header.Set("Content-Type", "application/json")
  299. resp, err := restClient.client.Do(req)
  300. if err != nil {
  301. return
  302. }
  303. body, err = ioutil.ReadAll(resp.Body)
  304. resp.Body.Close()
  305. if err != nil {
  306. return
  307. }
  308. if resp.StatusCode != 200 {
  309. err = errors.New(fmt.Sprintf("StatusCode: %d, %s", resp.StatusCode, string(body)))
  310. return
  311. }
  312. if restClient.Debug {
  313. var prettyJSON bytes.Buffer
  314. error := json.Indent(&prettyJSON, body, "", "\t")
  315. if error != nil {
  316. fmt.Print("JSON parse error: ", error)
  317. return
  318. }
  319. fmt.Println(urlStr+" Response:\n", string(prettyJSON.Bytes()))
  320. }
  321. return
  322. }