From 5bf09a997c56117f9979a3b97e5f664cbda9b820 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Fri, 5 May 2023 14:16:09 +0200 Subject: [PATCH 01/10] Add new() DiscordFileAttachment --- src/api/types.rs | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/api/types.rs b/src/api/types.rs index 0fa51f2..f993fbe 100644 --- a/src/api/types.rs +++ b/src/api/types.rs @@ -4,7 +4,7 @@ https://discord.com/developers/docs . I do not feel like re-documenting all of this, as everything is already perfectly explained there. */ -use std::fs::File; +use std::{collections::HashMap, fs::File}; use serde::{Deserialize, Serialize}; @@ -849,20 +849,24 @@ pub struct DiscordFileAttachment { } impl DiscordFileAttachment { - pub fn new(filenames: &Vec, files: Vec) { - //-> Vec { - if filenames.len() != files.len() { - panic!("Your 'filenames' Vector has either more or less elements than your 'files' Vector.") - } + /** + Returns a [`Vec`], where [`DiscordFileAttachment`] represents a file + attachment according to Discord API spec (Unique name, filename and File). + # Arguments + * filename_file_map: A [`HashMap`], where + * key ([`String`]): Filename of the file + * value ([`File`]): A [`File`] object. + */ + pub fn new(filename_file_map: HashMap) -> Vec { let mut return_vec: Vec = Vec::new(); let mut counter = 0; - /*for _ in 0..files.len() { + for (filename, file) in filename_file_map { return_vec.push(DiscordFileAttachment { name: format!("files[{}]", counter.to_string()), - filename: filenames.iter().next().unwrap().to_string(), - file: files.get(0).unwrap(), + filename, + file, }); } - return_vec*/ + return_vec } } From 164bd627b0ae1a0a79d5ae445b85bb4771196aac Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Fri, 5 May 2023 14:18:59 +0200 Subject: [PATCH 02/10] Change HashMap to Map Filenames can be non-unique, which could not be accurately represented using a HashMap. --- src/api/types.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/api/types.rs b/src/api/types.rs index f993fbe..828f907 100644 --- a/src/api/types.rs +++ b/src/api/types.rs @@ -853,14 +853,14 @@ impl DiscordFileAttachment { Returns a [`Vec`], where [`DiscordFileAttachment`] represents a file attachment according to Discord API spec (Unique name, filename and File). # Arguments - * filename_file_map: A [`HashMap`], where - * key ([`String`]): Filename of the file - * value ([`File`]): A [`File`] object. + * filename_file_map: A [`Vec`], where + * [`String`]: Filename of the file + * [`File`]: A [`File`] object. */ - pub fn new(filename_file_map: HashMap) -> Vec { + pub fn new(filename_file_vec: Vec<(String, File)>) -> Vec { let mut return_vec: Vec = Vec::new(); let mut counter = 0; - for (filename, file) in filename_file_map { + for (filename, file) in filename_file_vec { return_vec.push(DiscordFileAttachment { name: format!("files[{}]", counter.to_string()), filename, From 2940b50f1b67458afefece082a3a3315d7da2d91 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Fri, 5 May 2023 14:19:38 +0200 Subject: [PATCH 03/10] Fix counter not being incremented --- src/api/types.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/api/types.rs b/src/api/types.rs index 828f907..3f52618 100644 --- a/src/api/types.rs +++ b/src/api/types.rs @@ -866,6 +866,7 @@ impl DiscordFileAttachment { filename, file, }); + counter += 1; } return_vec } From 3236d462ff179ce598be3b18049e78063a2111cd Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Fri, 5 May 2023 14:38:05 +0200 Subject: [PATCH 04/10] Add multipart feature --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 22d8f0b..8e9652b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ edition = "2021" tokio = {version = "1.27.0", features = ["rt", "macros", "rt-multi-thread"]} serde = {version = "1.0.159", features = ["derive"]} serde_json = "1.0.95" -reqwest = "0.11.16" +reqwest = {version = "0.11.16", features = ["multipart"]} url = "2.3.1" chrono = "0.4.24" regex = "1.7.3" From e749251529e4f9fb39fd3591dc150fb5db03e831 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Fri, 5 May 2023 14:38:22 +0200 Subject: [PATCH 05/10] change name type from String to i16 --- src/api/types.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/api/types.rs b/src/api/types.rs index 3f52618..1059d62 100644 --- a/src/api/types.rs +++ b/src/api/types.rs @@ -843,7 +843,7 @@ pub struct GatewayPayload { impl WebSocketEvent for GatewayPayload {} pub struct DiscordFileAttachment { - pub name: String, + pub name: i16, pub filename: String, pub file: File, } @@ -862,7 +862,7 @@ impl DiscordFileAttachment { let mut counter = 0; for (filename, file) in filename_file_vec { return_vec.push(DiscordFileAttachment { - name: format!("files[{}]", counter.to_string()), + name: counter, filename, file, }); From cdc3836177b0c8cdc9a9a8ca04eb0127347634ed Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Fri, 5 May 2023 14:38:37 +0200 Subject: [PATCH 06/10] handle attachment-messages seperately --- src/api/channels/messages.rs | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/api/channels/messages.rs b/src/api/channels/messages.rs index 668e150..0c5f637 100644 --- a/src/api/channels/messages.rs +++ b/src/api/channels/messages.rs @@ -29,14 +29,24 @@ pub mod messages { limits_instance: &mut Limits, requester: &mut LimitedRequester, ) -> Result { - let mut request = Client::new() + if files.is_some() { + return Self::send_with_attachments( + url_api, + token, + message, + files, + limits_user, + limits_instance, + requester, + ); + } + let request = Client::new() .post(format!( "{}/channels/{}/messages", url_api, message.channel_id )) .body(to_string(message).unwrap()) .bearer_auth(token); - if files.is_some() {} match requester .send_request( request, @@ -50,6 +60,18 @@ pub mod messages { Err(e) => Err(e), } } + + fn send_with_attachments( + url_api: &String, + token: &String, + message: &Message, + files: Option>, + limits_user: &mut Limits, + limits_instance: &mut Limits, + requester: &mut LimitedRequester, + ) -> Result { + let form = reqwest::multipart::Form::new(); + } } impl<'a> User<'a> { From 7a8eedd4c0dfd6adb7737212a7737bcf233b5209 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Fri, 5 May 2023 21:52:27 +0200 Subject: [PATCH 07/10] Add MessageSendSchema --- src/api/schemas.rs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/api/schemas.rs b/src/api/schemas.rs index 08425a3..7672e55 100644 --- a/src/api/schemas.rs +++ b/src/api/schemas.rs @@ -1,8 +1,12 @@ +use std::{collections::HashMap, io::Bytes}; + use regex::Regex; -use serde::{Deserialize, Serialize}; +use serde::{ser::SerializeMap, Deserialize, Serialize, Serializer}; use crate::errors::FieldFormatError; +use super::{DiscordFileAttachment, Embed}; + /** A struct that represents a well-formed email address. */ @@ -240,6 +244,24 @@ pub struct TotpSchema { login_source: Option, } +#[derive(Debug, Deserialize)] +#[serde(rename_all = "snake_case")] +pub struct MessageSendSchema { + #[serde(rename = "type")] + message_type: i32, + content: Option, + nonce: Option, + tts: Option, + embeds: Option>, + allowed_mentions: Option, + message_reference: Option, + components: Option>, + sticker_ids: Option>, + #[serde(flatten)] + files: Option>>, + attachments: Option>, +} + // I know that some of these tests are... really really basic and unneccessary, but sometimes, I // just feel like writing tests, so there you go :) -@bitfl0wer #[cfg(test)] From 1076c23403a43151f03ec7cd052cea3fdc48f6e4 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Fri, 5 May 2023 21:53:00 +0200 Subject: [PATCH 08/10] Add DiscordFileAttachment, change visibilities --- src/api/types.rs | 79 ++++++++++++++++++++++++++++++------------------ 1 file changed, 49 insertions(+), 30 deletions(-) diff --git a/src/api/types.rs b/src/api/types.rs index 1059d62..3683bda 100644 --- a/src/api/types.rs +++ b/src/api/types.rs @@ -216,7 +216,7 @@ pub struct Message { mentions: Vec, mention_roles: Vec, mention_channels: Option>, - attachments: Vec, + pub attachments: Vec, embeds: Vec, reactions: Option>, nonce: Option, @@ -386,7 +386,7 @@ struct Attachment { /** Represents an Embed. [See the Discord Documentation](https://discord.com/developers/docs/resources/channel#embed-object). */ -struct Embed { +pub struct Embed { title: Option, #[serde(rename = "type")] embed_type: Option, @@ -539,9 +539,9 @@ struct InstallParams { } #[derive(Debug, Serialize, Deserialize)] -struct MessageReference { - message_id: Option, - channel_id: Option, +pub struct MessageReference { + message_id: String, + channel_id: String, guild_id: Option, fail_if_not_exists: Option, } @@ -655,7 +655,7 @@ struct DefaultReaction { } #[derive(Debug, Serialize, Deserialize)] -enum Component { +pub enum Component { ActionRow = 1, Button = 2, StringSelect = 3, @@ -842,32 +842,51 @@ pub struct GatewayPayload { impl WebSocketEvent for GatewayPayload {} +#[derive(Debug, Serialize, Deserialize)] pub struct DiscordFileAttachment { - pub name: i16, + pub id: i16, pub filename: String, - pub file: File, + description: Option, + content_type: Option, + size: i64, + url: String, + proxy_url: String, + height: Option, + width: Option, + ephemeral: Option, + duration_secs: Option, + waveform: Option, } -impl DiscordFileAttachment { - /** - Returns a [`Vec`], where [`DiscordFileAttachment`] represents a file - attachment according to Discord API spec (Unique name, filename and File). - # Arguments - * filename_file_map: A [`Vec`], where - * [`String`]: Filename of the file - * [`File`]: A [`File`] object. - */ - pub fn new(filename_file_vec: Vec<(String, File)>) -> Vec { - let mut return_vec: Vec = Vec::new(); - let mut counter = 0; - for (filename, file) in filename_file_vec { - return_vec.push(DiscordFileAttachment { - name: counter, - filename, - file, - }); - counter += 1; - } - return_vec - } +#[derive(Debug, Serialize, Deserialize)] + +pub struct PartialDiscordFileAttachment { + pub id: Option, + pub filename: Option, + description: Option, + content_type: Option, + size: Option, + url: Option, + proxy_url: Option, + height: Option, + width: Option, + ephemeral: Option, + duration_secs: Option, + waveform: Option, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct AllowedMention { + parse: Vec, + roles: Vec, + users: Vec, + replied_user: bool, +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum AllowedMentionType { + Roles, + Users, + Everyone, } From bae45254fee30c10b0b887c907ef64c2d3de7f7a Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Fri, 5 May 2023 21:53:23 +0200 Subject: [PATCH 09/10] start re-doing send() --- src/api/channels/messages.rs | 78 +++++------------------------------- 1 file changed, 9 insertions(+), 69 deletions(-) diff --git a/src/api/channels/messages.rs b/src/api/channels/messages.rs index 0c5f637..357e245 100644 --- a/src/api/channels/messages.rs +++ b/src/api/channels/messages.rs @@ -1,11 +1,6 @@ pub mod messages { - use reqwest::{Client, Response}; - use serde_json::to_string; - use std::io::Read; - use crate::api::limits::Limits; - use crate::api::types::{DiscordFileAttachment, Message, User}; - use crate::errors::InstanceServerError; + use crate::api::types::{Message, PartialDiscordFileAttachment, User}; use crate::limit::LimitedRequester; impl Message { @@ -20,76 +15,21 @@ pub mod messages { # Errors * [`InstanceServerError`] - If the message cannot be sent. */ - pub async fn send( - url_api: &String, - token: &String, - message: &Message, - files: Option>, - limits_user: &mut Limits, - limits_instance: &mut Limits, - requester: &mut LimitedRequester, - ) -> Result { - if files.is_some() { - return Self::send_with_attachments( - url_api, - token, - message, - files, - limits_user, - limits_instance, - requester, - ); - } - let request = Client::new() - .post(format!( - "{}/channels/{}/messages", - url_api, message.channel_id - )) - .body(to_string(message).unwrap()) - .bearer_auth(token); - match requester - .send_request( - request, - crate::api::limits::LimitType::Channel, - limits_instance, - limits_user, - ) - .await - { - Ok(result) => Ok(result), - Err(e) => Err(e), - } - } - fn send_with_attachments( + pub async fn send<'a>( url_api: &String, - token: &String, - message: &Message, - files: Option>, - limits_user: &mut Limits, + message: &mut Message, + files: Option>, + user: &mut User<'a>, limits_instance: &mut Limits, requester: &mut LimitedRequester, - ) -> Result { - let form = reqwest::multipart::Form::new(); + ) { + let token = user.token(); + let mut limits = &mut user.rate_limits; } } impl<'a> User<'a> { - pub async fn send_message( - &mut self, - message: &Message, - files: Option>, - ) -> Result { - Message::send( - &self.belongs_to().urls.get_api().to_string(), - &self.token(), - message, - files, - self.rate_limits.get_as_mut(), - &mut self.belongs_to.limits.get_as_mut(), - &mut LimitedRequester::new().await, - ) - .await - } + pub async fn send_message() {} } } From fa0d74e9dd69c6de4d273d605a95dfcc04314a65 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Fri, 5 May 2023 22:00:37 +0200 Subject: [PATCH 10/10] remove redundant code --- src/api/types.rs | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/src/api/types.rs b/src/api/types.rs index 3683bda..0cb7ba0 100644 --- a/src/api/types.rs +++ b/src/api/types.rs @@ -216,7 +216,7 @@ pub struct Message { mentions: Vec, mention_roles: Vec, mention_channels: Option>, - pub attachments: Vec, + pub attachments: Vec, embeds: Vec, reactions: Option>, nonce: Option, @@ -263,7 +263,7 @@ struct PartialMessage { mentions: Option>, mention_roles: Option>, mention_channels: Option>, - attachments: Option>, + attachments: Option>, embeds: Option>, reactions: Option>, nonce: Option, @@ -368,20 +368,6 @@ struct ChannelMention { name: String, } -#[derive(Debug, Serialize, Deserialize)] -struct Attachment { - id: String, - filename: String, - description: Option, - content_type: Option, - size: i64, - url: String, - proxy_url: String, - height: Option, - width: Option, - ephemeral: Option, -} - #[derive(Debug, Serialize, Deserialize)] /** Represents an Embed. [See the Discord Documentation](https://discord.com/developers/docs/resources/channel#embed-object).