From 06f0e536b149c17398af31e33d3c5036e3ffa314 Mon Sep 17 00:00:00 2001 From: SeanOMik Date: Sat, 20 Jun 2020 13:59:49 -0500 Subject: [PATCH] Send files --- src/channel.nim | 35 +++++++++++++++++++++++++++++++++-- src/client.nim | 26 +++++++++++++++++++++++++- src/message.nim | 4 ++-- 3 files changed, 60 insertions(+), 5 deletions(-) diff --git a/src/channel.nim b/src/channel.nim index d65834b..422d323 100644 --- a/src/channel.nim +++ b/src/channel.nim @@ -1,4 +1,4 @@ -import json, discordobject, user, options, nimcordutils, message, httpcore, asyncdispatch, asyncfutures, permission, embed +import json, discordobject, user, options, nimcordutils, message, httpcore, asyncdispatch, asyncfutures, permission, embed, httpclient, streams type ChannelType* = enum @@ -60,6 +60,13 @@ type temporary*: bool ## Whether this invite only grants temporary membership createdAt: string ## When this invite was created + DiscordFile* = ref object + ## This type is used for sending files. + ## It stores the file name, and the file path. + ## Nimcord will read the file contents itself. + fileName*: string + filePath*: string + proc newChannel*(channel: JsonNode): Channel {.inline.} = ## Parses the channel from json. var chan = Channel( @@ -132,13 +139,37 @@ proc newInvite*(json: JsonNode): Invite {.inline.} = return invite #TODO: Files -proc sendMessage*(channel: Channel, content: string, tts: bool = false, embed: Embed = nil): Message = +proc sendMessage*(channel: Channel, content: string, tts: bool = false, embed: Embed = nil, files: seq[DiscordFile] = @[]): Message = ## Send a message through the channel. var messagePayload = %*{"content": content, "tts": tts} if (not embed.isNil()): messagePayload.add("embed", embed.embedJson) + if (files.len != 0): + var client = newHttpClient() + let endpoint = endpoint("/channels/" & $channel.id & "/messages") + var multipart = newMultipartData() + # Add headers + client.headers = defaultHeaders(newHttpHeaders({"Content-Type": "multipart/form-data"})) + + for index, file in files: + var imageStream = newFileStream(file.filePath, fmRead) + if (not isNil(imageStream)): + let data = imageStream.readALL() + multipart.add("file" & $index, data, file.fileName, "application/octet-stream", false) + + imageStream.close() + else: + raise newException(IOError, "Failed to open file for sending: " & file.filePath) + multipart.add("payload_json", $messagePayload, "", "application/json", false) + + echo "Sending POST request, URL: ", endpoint, ", headers: ", client.headers, " payload_json: ", messagePayload + + waitForRateLimits(channel.id, RateLimitBucketType.channel) + let response: Response = client.post(endpoint, "", multipart) + return newMessage(handleResponse(response, channel.id, RateLimitBucketType.channel)) + return newMessage(sendRequest(endpoint("/channels/" & $channel.id & "/messages"), HttpPost, defaultHeaders(newHttpHeaders({"Content-Type": "application/json"})), channel.id, RateLimitBucketType.channel, messagePayload)) diff --git a/src/client.nim b/src/client.nim index e33d2b1..40dfb27 100644 --- a/src/client.nim +++ b/src/client.nim @@ -1,6 +1,6 @@ import websocket, asyncdispatch, json, httpClient, eventdispatcher, strformat import eventhandler, streams, nimcordutils, discordobject, user, cache, clientobjects -import strutils, channel, options, message, emoji, guild, embed +import strutils, channel, options, message, emoji, guild, embed, os const nimcordMajor = 0 @@ -185,6 +185,30 @@ registerEventListener(EventType.evtMessageCreate, proc(bEvt: BaseEvent) = embed.addField("Inline-1", "This is an inline field 1", true) embed.setColor(0xffb900) discard channel.sendMessage("", false, embed) + elif (event.message.content.startsWith("?sendFile")): + var channel: Channel = event.message.getMessageChannel(event.client.cache) + if (channel != nil): + let filePath = event.message.content.substr(10) + + let splitFile = splitFile(filePath) + let fileName = splitFile.name & splitFile.ext + + let file = DiscordFile(filePath: filePath, fileName: fileName) + discard channel.sendMessage("", false, nil, @[file]) + elif (event.message.content.startsWith("?sendImage")): + var channel: Channel = event.message.getMessageChannel(event.client.cache) + if (channel != nil): + let filePath = event.message.content.substr(11) + + let splitFile = splitFile(filePath) + let fileName = splitFile.name & splitFile.ext + + let file = DiscordFile(filePath: filePath, fileName: fileName) + + var embed = Embed() + embed.setTitle("Image attachment test.") + embed.setImage("attachment://" & fileName) + discard channel.sendMessage("", false, embed, @[file]) ) waitFor bot.startConnection() \ No newline at end of file diff --git a/src/message.nim b/src/message.nim index b7e9819..b28c1fd 100644 --- a/src/message.nim +++ b/src/message.nim @@ -135,8 +135,8 @@ proc newMessage*(messageJson: JsonNode): Message = size: uint(attachment["size"].getInt()), url: attachment["url"].getStr(), proxyURL: attachment["proxy_url"].getStr(), - height: attachment["height"].getInt(), - width: attachment["width"].getInt() + height: attachment{"height"}.getInt(), + width: attachment{"width"}.getInt() )) for embed in messageJson["embeds"]: