Merge pull request #33 from polyphony-chat/feature/sending-messages

Bring main up-to-date
This commit is contained in:
Flori 2023-05-09 19:47:18 +02:00 committed by GitHub
commit 83cedc21ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 207 additions and 147 deletions

View File

@ -8,11 +8,11 @@ pub mod login {
use crate::errors::InstanceServerError;
use crate::instance::Instance;
impl<'a> Instance<'a> {
impl Instance {
pub async fn login_account(
&mut self,
login_schema: &LoginSchema,
) -> Result<LoginResult, InstanceServerError> {
) -> Result<crate::api::types::User, InstanceServerError> {
let requester = &mut self.requester;
let json_schema = json!(login_schema);
let client = Client::new();
@ -49,9 +49,21 @@ pub mod login {
return Err(InstanceServerError::InvalidFormBodyError { error_type, error });
}
let cloned_limits = self.limits.clone();
let login_result: LoginResult = from_str(&response_text_string).unwrap();
let object = self
.get_user(login_result.token.clone(), None)
.await
.unwrap();
let user = crate::api::types::User::new(
self,
login_result.token,
cloned_limits,
login_result.settings,
Some(object),
);
Ok(login_result)
Ok(user)
}
}
}
@ -104,6 +116,5 @@ mod test {
.login_account(&login_schema.unwrap())
.await
.unwrap();
println!("{:?}", login_result);
}
}*/

View File

@ -1,14 +1,14 @@
pub mod register {
use reqwest::Client;
use serde_json::json;
use serde_json::{from_str, json};
use crate::{
api::{limits::LimitType, schemas::RegisterSchema, types::ErrorResponse},
api::{limits::LimitType, schemas::RegisterSchema, types::ErrorResponse, Token},
errors::InstanceServerError,
instance::{Instance, Token},
instance::Instance,
};
impl<'a> Instance<'a> {
impl Instance {
/**
Registers a new user on the Spacebar server.
# Arguments
@ -19,7 +19,7 @@ pub mod register {
pub async fn register_account(
&mut self,
register_schema: &RegisterSchema,
) -> Result<Token, InstanceServerError> {
) -> Result<crate::api::types::User, InstanceServerError> {
let json_schema = json!(register_schema);
let limited_requester = &mut self.requester;
let client = Client::new();
@ -43,9 +43,12 @@ pub mod register {
let response_unwrap = response.unwrap();
let status = response_unwrap.status();
let response_text_string = response_unwrap.text().await.unwrap();
let response_unwrap_text = response_unwrap.text().await.unwrap();
println!("{}", response_unwrap_text);
let token = from_str::<Token>(&response_unwrap_text).unwrap();
let token = token.token;
if status.is_client_error() {
let json: ErrorResponse = serde_json::from_str(&response_text_string).unwrap();
let json: ErrorResponse = serde_json::from_str(&token).unwrap();
let error_type = json.errors.errors.iter().next().unwrap().0.to_owned();
let mut error = "".to_string();
for (_, value) in json.errors.errors.iter() {
@ -55,9 +58,22 @@ pub mod register {
}
return Err(InstanceServerError::InvalidFormBodyError { error_type, error });
}
Ok(Token {
token: response_text_string,
})
let user_object = self.get_user(token.clone(), None).await.unwrap();
let settings = crate::api::types::User::get_settings(
&token,
&self.urls.get_api().to_string(),
&mut self.limits,
)
.await
.unwrap();
let user: crate::api::types::User = crate::api::types::User::new(
self,
token.clone(),
cloned_limits,
settings,
Some(user_object),
);
Ok(user)
}
}
}
@ -65,42 +81,9 @@ pub mod register {
#[cfg(test)]
mod test {
use crate::api::schemas::{AuthEmail, AuthPassword, AuthUsername, RegisterSchema};
use crate::errors::InstanceServerError;
use crate::instance::Instance;
use crate::limit::LimitedRequester;
use crate::URLBundle;
#[tokio::test]
async fn test_incomplete_registration() {
let urls = URLBundle::new(
"http://localhost:3001/api".to_string(),
"http://localhost:3001".to_string(),
"http://localhost:3001".to_string(),
);
let limited_requester = LimitedRequester::new().await;
let mut test_instance = Instance::new(urls.clone(), limited_requester)
.await
.unwrap();
let reg = RegisterSchema::new(
AuthUsername::new("hiiii".to_string()).unwrap(),
None,
true,
Some(AuthEmail::new("me@mail.xy".to_string()).unwrap()),
None,
None,
None,
None,
None,
None,
)
.unwrap();
assert_eq!(
InstanceServerError::InvalidFormBodyError {
error_type: "date_of_birth".to_string(),
error: "This field is required (BASE_TYPE_REQUIRED)".to_string()
},
test_instance.register_account(&reg).await.err().unwrap()
);
}
#[tokio::test]
async fn test_registration() {
@ -117,7 +100,7 @@ mod test {
AuthUsername::new("Hiiii".to_string()).unwrap(),
Some(AuthPassword::new("mysupersecurepass123!".to_string()).unwrap()),
true,
Some(AuthEmail::new("random978234@aaaa.xyz".to_string()).unwrap()),
Some(AuthEmail::new("four7@aaaa.xyz".to_string()).unwrap()),
None,
None,
Some("2000-01-01".to_string()),
@ -127,6 +110,5 @@ mod test {
)
.unwrap();
let token = test_instance.register_account(&reg).await.unwrap().token;
println!("{}", token);
}
}

View File

@ -2,7 +2,6 @@ pub mod messages {
use reqwest::Client;
use serde_json::to_string;
use crate::api::limits::Limits;
use crate::api::types::{Message, PartialDiscordFileAttachment, User};
use crate::limit::LimitedRequester;
@ -45,10 +44,10 @@ pub mod messages {
)
.await
} else {
return Err(crate::errors::InstanceServerError::InvalidFormBodyError {
Err(crate::errors::InstanceServerError::InvalidFormBodyError {
error_type: "Not implemented".to_string(),
error: "Not implemented".to_string(),
});
})
}
}
}
@ -56,7 +55,7 @@ pub mod messages {
impl<'a> User<'a> {
pub async fn send_message(
&mut self,
mut message: &mut crate::api::schemas::MessageSendSchema,
message: &mut crate::api::schemas::MessageSendSchema,
channel_id: &String,
files: Option<Vec<PartialDiscordFileAttachment>>,
) -> Result<reqwest::Response, crate::errors::InstanceServerError> {
@ -64,7 +63,7 @@ pub mod messages {
Message::send(
&self.belongs_to.urls.get_api().to_string(),
channel_id,
&mut message,
message,
files,
&token,
self,
@ -77,13 +76,11 @@ pub mod messages {
#[cfg(test)]
mod test {
use crate::{
api::{AuthUsername, LoginSchema, MessageSendSchema, UserObject},
api::{AuthUsername, LoginSchema},
instance::Instance,
limit::LimitedRequester,
};
use super::*;
#[tokio::test]
async fn send_message() {
let channel_id = "1104413094102290492".to_string();
@ -123,12 +120,10 @@ mod test {
let token = login_result.token;
let settings = login_result.settings;
let limits = instance.limits.clone();
let mut user =
crate::api::types::User::new(true, &mut instance, token, limits, settings, None);
let mut user = crate::api::types::User::new(&mut instance, token, limits, settings, None);
let response = user
.send_message(&mut message, &channel_id, None)
.await
.unwrap();
println!("{:?}", response);
}
}

View File

@ -1,11 +1,10 @@
use reqwest::Client;
use serde_json::from_str;
use crate::errors::InstanceServerError;
use crate::{api::types::InstancePolicies, instance::Instance};
impl<'a> Instance<'a> {
impl Instance {
/**
Gets the instance policies schema.
# Errors
@ -53,6 +52,5 @@ mod instance_policies_schema_test {
.unwrap();
let schema = test_instance.instance_policies_schema().await.unwrap();
println!("{:?}", schema);
}
}

View File

@ -1,16 +1,17 @@
pub mod limits {
use std::collections::HashMap;
use std::{collections::HashMap};
use reqwest::Client;
use serde::{Deserialize, Serialize};
use serde_json::from_str;
#[derive(Clone, Copy, Eq, Hash, PartialEq, Debug)]
#[derive(Clone, Copy, Eq, Hash, PartialEq, Debug, Default)]
pub enum LimitType {
AuthRegister,
AuthLogin,
AbsoluteMessage,
AbsoluteRegister,
#[default]
Global,
Ip,
Channel,
@ -19,23 +20,6 @@ pub mod limits {
Webhook,
}
impl std::fmt::Display for LimitType {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
LimitType::AuthRegister => write!(f, "auth_register"),
LimitType::AuthLogin => write!(f, "auth_login"),
LimitType::AbsoluteMessage => write!(f, "absolute_message"),
LimitType::AbsoluteRegister => write!(f, "absolute_register"),
LimitType::Global => write!(f, "global"),
LimitType::Ip => write!(f, "ip"),
LimitType::Channel => write!(f, "channel"),
LimitType::Error => write!(f, "error"),
LimitType::Guild => write!(f, "guild"),
LimitType::Webhook => write!(f, "webhook"),
}
}
}
#[derive(Debug, Deserialize, Serialize)]
#[allow(non_snake_case)]
pub struct User {
@ -134,7 +118,7 @@ pub mod limits {
pub absoluteRate: AbsoluteRate,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
pub struct Limit {
pub bucket: LimitType,
pub limit: u64,
@ -146,7 +130,7 @@ pub mod limits {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"Bucket: {}, Limit: {}, Remaining: {}, Reset: {}",
"Bucket: {:?}, Limit: {}, Remaining: {}, Reset: {}",
self.bucket, self.limit, self.remaining, self.reset
)
}
@ -229,7 +213,7 @@ pub mod limits {
}
}
#[derive(Debug, Clone)]
#[derive(Debug, Clone, Default)]
pub struct Limits {
pub limit_absolute_messages: Limit,
pub limit_absolute_register: Limit,

View File

@ -1,11 +1,11 @@
use std::{collections::HashMap, io::Bytes};
use std::{collections::HashMap};
use regex::Regex;
use serde::{ser::SerializeMap, Deserialize, Serialize, Serializer};
use serde::{Deserialize, Serialize};
use crate::errors::FieldFormatError;
use super::{DiscordFileAttachment, Embed};
use super::{Embed};
/**
A struct that represents a well-formed email address.

View File

@ -4,8 +4,6 @@ https://discord.com/developers/docs .
I do not feel like re-documenting all of this, as everything is already perfectly explained there.
*/
use std::{collections::HashMap, fs::File};
use serde::{Deserialize, Serialize};
use crate::{api::limits::Limits, instance::Instance};
@ -136,40 +134,44 @@ pub struct Error {
#[derive(Serialize, Deserialize, Debug, Default)]
pub struct UserObject {
id: String,
pub id: String,
username: String,
discriminator: String,
avatar: Option<String>,
bot: Option<bool>,
bot: bool,
system: Option<bool>,
mfa_enabled: Option<bool>,
banner: Option<bool>,
accent_color: Option<String>,
locale: String,
locale: Option<String>,
verified: Option<bool>,
email: Option<String>,
flags: i8,
premium_type: Option<i8>,
flags: String,
premium_since: Option<String>,
premium_type: i8,
pronouns: Option<String>,
public_flags: Option<i8>,
banner: Option<String>,
bio: String,
theme_colors: Option<Vec<i32>>,
phone: Option<String>,
nsfw_allowed: bool,
premium: bool,
purchased_flags: i32,
premium_usage_flags: i32,
disabled: bool,
}
#[derive(Debug)]
pub struct User<'a> {
pub logged_in: bool,
pub belongs_to: &'a mut Instance<'a>,
token: String,
pub belongs_to: &'a mut Instance,
pub token: String,
pub limits: Limits,
pub settings: UserSettings,
pub object: Option<UserObject>,
}
impl<'a> User<'a> {
pub fn is_logged_in(&self) -> bool {
self.logged_in
}
pub fn belongs_to(&mut self) -> &mut Instance<'a> {
pub fn belongs_to(&mut self) -> &mut Instance {
self.belongs_to
}
@ -177,24 +179,18 @@ impl<'a> User<'a> {
self.token.clone()
}
pub fn set_logged_in(&mut self, bool: bool) {
self.logged_in = bool;
}
pub fn set_token(&mut self, token: String) {
self.token = token;
}
pub fn new(
logged_in: bool,
belongs_to: &'a mut Instance<'a>,
belongs_to: &'a mut Instance,
token: String,
limits: Limits,
settings: UserSettings,
object: Option<UserObject>,
) -> User<'a> {
User {
logged_in,
belongs_to,
token,
limits,
@ -877,3 +873,8 @@ pub enum AllowedMentionType {
Users,
Everyone,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Token {
pub token: String,
}

View File

@ -1 +1,112 @@
pub fn doathing() {}
use reqwest::Client;
use crate::{
api::{
limits::Limits,
types::{User, UserObject},
UserSettings,
},
errors::InstanceServerError,
instance::Instance,
};
impl<'a> User<'a> {
/**
Get a user object by id, or get the current user.
# Arguments
* `token` - A valid access token for the API.
* `url_api` - The URL to the API.
* `id` - The id of the user that will be retrieved. If this is None, the current user will be retrieved.
* `instance_limits` - The [`Limits`] of the instance.
# Errors
* [`InstanceServerError`] - If the request fails.
*/
pub async fn get(
token: &String,
url_api: &String,
id: Option<&String>,
instance_limits: &mut Limits,
) -> Result<UserObject, InstanceServerError> {
let url: String;
if id.is_none() {
url = format!("{}/users/@me/", url_api);
} else {
url = format!("{}/users/{}", url_api, id.unwrap());
}
let request = reqwest::Client::new().get(url).bearer_auth(token);
let mut requester = crate::limit::LimitedRequester::new().await;
let mut cloned_limits = instance_limits.clone();
match requester
.send_request(
request,
crate::api::limits::LimitType::Ip,
instance_limits,
&mut cloned_limits,
)
.await
{
Ok(result) => {
let result_text = result.text().await.unwrap();
Ok(serde_json::from_str::<UserObject>(&result_text).unwrap())
}
Err(e) => Err(e),
}
}
pub async fn get_settings(
token: &String,
url_api: &String,
instance_limits: &mut Limits,
) -> Result<UserSettings, InstanceServerError> {
let request: reqwest::RequestBuilder = Client::new()
.get(format!("{}/users/@me/settings/", url_api))
.bearer_auth(token);
let mut cloned_limits = instance_limits.clone();
let mut requester = crate::limit::LimitedRequester::new().await;
match requester
.send_request(
request,
crate::api::limits::LimitType::Ip,
instance_limits,
&mut cloned_limits,
)
.await
{
Ok(result) => Ok(serde_json::from_str(&result.text().await.unwrap()).unwrap()),
Err(e) => Err(e),
}
}
}
impl Instance {
/**
Get a user object by id, or get the current user.
# Arguments
* `token` - A valid access token for the API.
* `id` - The id of the user that will be retrieved. If this is None, the current user will be retrieved.
# Errors
* [`InstanceServerError`] - If the request fails.
# Notes
This function is a wrapper around [`User::get`].
*/
pub async fn get_user(
&mut self,
token: String,
id: Option<&String>,
) -> Result<UserObject, InstanceServerError> {
User::get(
&token,
&self.urls.get_api().to_string(),
id,
&mut self.limits,
)
.await
}
}
#[cfg(test)]
mod test {
#[tokio::test]
async fn get_user() {}
}

View File

@ -3,23 +3,6 @@ use crate::api::WebSocketEvent;
use crate::errors::ObserverError;
use crate::gateway::events::Events;
/**
Represents a Gateway connection. A Gateway connection will create observable
[`GatewayEvents`](GatewayEvent), which you can subscribe to. Gateway events include all currently
@ -36,11 +19,11 @@ impl<'a> Gateway<'a> {
websocket_url: String,
token: String,
) -> Result<Gateway<'a>, tokio_tungstenite::tungstenite::Error> {
return Ok(Gateway {
Ok(Gateway {
url: websocket_url,
token,
events: Events::default(),
});
})
}
}

View File

@ -1,26 +1,25 @@
use crate::api::limits::Limits;
use crate::api::types::{InstancePolicies, User};
use crate::api::types::{InstancePolicies};
use crate::errors::{FieldFormatError, InstanceServerError};
use crate::limit::LimitedRequester;
use crate::URLBundle;
use std::collections::HashMap;
use std::fmt;
#[derive(Debug)]
/**
The [`Instance`] what you will be using to perform all sorts of actions on the Spacebar server.
*/
pub struct Instance<'a> {
pub struct Instance {
pub urls: URLBundle,
pub instance_info: InstancePolicies,
pub requester: LimitedRequester,
pub limits: Limits,
//pub gateway: Gateway,
pub users: HashMap<Token, User<'a>>,
}
impl<'a> Instance<'a> {
impl Instance {
/// Creates a new [`Instance`].
/// # Arguments
/// * `urls` - The [`URLBundle`] that contains all the URLs that are needed to connect to the Spacebar server.
@ -30,8 +29,7 @@ impl<'a> Instance<'a> {
pub async fn new(
urls: URLBundle,
requester: LimitedRequester,
) -> Result<Instance<'a>, InstanceServerError> {
let users: HashMap<Token, User> = HashMap::new();
) -> Result<Instance, InstanceServerError> {
let mut instance = Instance {
urls: urls.clone(),
instance_info: InstancePolicies::new(
@ -47,7 +45,6 @@ impl<'a> Instance<'a> {
),
limits: Limits::check_limits(urls.api).await,
requester,
users,
};
instance.instance_info = match instance.instance_policies_schema().await {
Ok(schema) => schema,

View File

@ -1,9 +1,9 @@
mod api;
mod errors;
mod gateway;
mod instance;
mod limit;
mod voice;
pub mod api;
pub mod errors;
pub mod gateway;
pub mod instance;
pub mod limit;
pub mod voice;
use url::{ParseError, Url};
#[derive(Clone, Default, Debug, PartialEq, Eq)]
@ -30,7 +30,6 @@ impl URLBundle {
/// # Example:
/// ```rs
/// let url = parse_url("localhost:3000");
/// println!("{}", url);
/// ```
/// `-> Outputs "http://localhost:3000".`
pub fn parse_url(url: String) -> String {

View File

@ -330,6 +330,5 @@ mod rate_limit {
Err(_) => panic!("Request failed"),
};
let config: Config = from_str(result.text().await.unwrap().as_str()).unwrap();
println!("{:?}", config);
}
}