start porting over new types folder

This commit is contained in:
bitfl0wer 2023-05-25 23:09:18 +02:00
parent 48113825b8
commit f74b9c4c0d
9 changed files with 430 additions and 259 deletions

View File

@ -1,11 +1,7 @@
use reqwest::Client; use reqwest::Client;
use serde_json::from_str; use serde_json::from_str;
use crate::{ use crate::{api::limits::Limits, errors::InstanceServerError, limit::LimitedRequester};
api::{limits::Limits, types},
errors::InstanceServerError,
limit::LimitedRequester,
};
impl types::Channel { impl types::Channel {
pub async fn get( pub async fn get(
@ -14,7 +10,7 @@ impl types::Channel {
channel_id: &str, channel_id: &str,
limits_user: &mut Limits, limits_user: &mut Limits,
limits_instance: &mut Limits, limits_instance: &mut Limits,
) -> Result<types::Channel, InstanceServerError> { ) -> Result<Channel, InstanceServerError> {
let request = Client::new() let request = Client::new()
.get(format!("{}/channels/{}/", url_api, channel_id)) .get(format!("{}/channels/{}/", url_api, channel_id))
.bearer_auth(token); .bearer_auth(token);

View File

@ -2,13 +2,9 @@ pub mod auth;
pub mod channels; pub mod channels;
pub mod guilds; pub mod guilds;
pub mod policies; pub mod policies;
pub mod schemas;
pub mod types;
pub mod users; pub mod users;
pub use channels::messages::*; pub use channels::messages::*;
pub use guilds::*; pub use guilds::*;
pub use policies::instance::instance::*; pub use policies::instance::instance::*;
pub use policies::instance::limits::*; pub use policies::instance::limits::*;
pub use schemas::*;
pub use types::*;

View File

@ -2,7 +2,8 @@ use reqwest::Client;
use serde_json::from_str; use serde_json::from_str;
use crate::errors::InstanceServerError; use crate::errors::InstanceServerError;
use crate::{api::types::InstancePolicies, instance::Instance}; use crate::instance::Instance;
use crate::types::GeneralConfiguration;
impl Instance { impl Instance {
/** /**
@ -10,7 +11,9 @@ impl Instance {
# Errors # Errors
[`InstanceServerError`] - If the request fails. [`InstanceServerError`] - If the request fails.
*/ */
pub async fn instance_policies_schema(&self) -> Result<InstancePolicies, InstanceServerError> { pub async fn general_configuration_schema(
&self,
) -> Result<GeneralConfiguration, InstanceServerError> {
let client = Client::new(); let client = Client::new();
let endpoint_url = self.urls.get_api().to_string() + "/policies/instance/"; let endpoint_url = self.urls.get_api().to_string() + "/policies/instance/";
let request = match client.get(&endpoint_url).send().await { let request = match client.get(&endpoint_url).send().await {
@ -30,7 +33,7 @@ impl Instance {
} }
let body = request.text().await.unwrap(); let body = request.text().await.unwrap();
let instance_policies_schema: InstancePolicies = from_str(&body).unwrap(); let instance_policies_schema: GeneralConfiguration = from_str(&body).unwrap();
Ok(instance_policies_schema) Ok(instance_policies_schema)
} }
} }
@ -49,6 +52,6 @@ mod instance_policies_schema_test {
let limited_requester = LimitedRequester::new().await; let limited_requester = LimitedRequester::new().await;
let test_instance = Instance::new(urls.clone()).await.unwrap(); let test_instance = Instance::new(urls.clone()).await.unwrap();
let _schema = test_instance.instance_policies_schema().await.unwrap(); let _schema = test_instance.general_configuration_schema().await.unwrap();
} }
} }

View File

@ -2,17 +2,14 @@ use reqwest::Client;
use serde_json::{from_str, to_string}; use serde_json::{from_str, to_string};
use crate::{ use crate::{
api::{ api::limits::Limits,
limits::Limits,
types::{User, UserObject},
UserModifySchema, UserSettings,
},
errors::InstanceServerError, errors::InstanceServerError,
instance::Instance, instance::{Instance, UserMeta},
limit::LimitedRequester, limit::LimitedRequester,
types::{User, UserModifySchema},
}; };
impl User { impl UserMeta {
/** /**
Get a user object by id, or get the current user. Get a user object by id, or get the current user.
# Arguments # Arguments
@ -28,7 +25,7 @@ impl User {
url_api: &String, url_api: &String,
id: Option<&String>, id: Option<&String>,
instance_limits: &mut Limits, instance_limits: &mut Limits,
) -> Result<UserObject, InstanceServerError> { ) -> Result<User, InstanceServerError> {
let url: String; let url: String;
if id.is_none() { if id.is_none() {
url = format!("{}/users/@me/", url_api); url = format!("{}/users/@me/", url_api);
@ -49,7 +46,7 @@ impl User {
{ {
Ok(result) => { Ok(result) => {
let result_text = result.text().await.unwrap(); let result_text = result.text().await.unwrap();
Ok(serde_json::from_str::<UserObject>(&result_text).unwrap()) Ok(serde_json::from_str::<User>(&result_text).unwrap())
} }
Err(e) => Err(e), Err(e) => Err(e),
} }
@ -59,7 +56,7 @@ impl User {
token: &String, token: &String,
url_api: &String, url_api: &String,
instance_limits: &mut Limits, instance_limits: &mut Limits,
) -> Result<UserSettings, InstanceServerError> { ) -> Result<User, InstanceServerError> {
let request: reqwest::RequestBuilder = Client::new() let request: reqwest::RequestBuilder = Client::new()
.get(format!("{}/users/@me/settings/", url_api)) .get(format!("{}/users/@me/settings/", url_api))
.bearer_auth(token); .bearer_auth(token);
@ -91,7 +88,7 @@ impl User {
pub async fn modify( pub async fn modify(
&mut self, &mut self,
modify_schema: UserModifySchema, modify_schema: UserModifySchema,
) -> Result<UserObject, InstanceServerError> { ) -> Result<User, InstanceServerError> {
if modify_schema.new_password.is_some() if modify_schema.new_password.is_some()
|| modify_schema.email.is_some() || modify_schema.email.is_some()
|| modify_schema.code.is_some() || modify_schema.code.is_some()
@ -118,7 +115,7 @@ impl User {
Ok(response) => response, Ok(response) => response,
Err(e) => return Err(e), Err(e) => return Err(e),
}; };
let user_updated: UserObject = from_str(&result.text().await.unwrap()).unwrap(); let user_updated: User = from_str(&result.text().await.unwrap()).unwrap();
let _ = std::mem::replace( let _ = std::mem::replace(
&mut self.object.as_mut().unwrap(), &mut self.object.as_mut().unwrap(),
&mut user_updated.clone(), &mut user_updated.clone(),
@ -171,8 +168,8 @@ impl Instance {
&mut self, &mut self,
token: String, token: String,
id: Option<&String>, id: Option<&String>,
) -> Result<UserObject, InstanceServerError> { ) -> Result<User, InstanceServerError> {
User::get( UserMeta::get(
&token, &token,
&self.urls.get_api().to_string(), &self.urls.get_api().to_string(),
id, id,

View File

@ -1,12 +1,46 @@
use std::sync::Arc;
use crate::api::types::*;
use crate::api::WebSocketEvent;
use crate::errors::ObserverError; use crate::errors::ObserverError;
use crate::gateway::events::Events; use crate::gateway::events::Events;
use crate::types::Channel;
use crate::types::ChannelCreate;
use crate::types::ChannelDelete;
use crate::types::ChannelPinsUpdate;
use crate::types::ChannelUpdate;
use crate::types::GatewayHeartbeat;
use crate::types::GatewayIdentifyPayload;
use crate::types::GatewayPayload;
use crate::types::GatewayReady;
use crate::types::GatewayRequestGuildMembers;
use crate::types::GatewayResume;
use crate::types::GatewayVoiceStateUpdate;
use crate::types::GuildBanAdd;
use crate::types::GuildBanRemove;
use crate::types::GuildCreate;
use crate::types::HelloData;
use crate::types::MessageCreate;
use crate::types::MessageDelete;
use crate::types::MessageDeleteBulk;
use crate::types::MessageReactionAdd;
use crate::types::MessageReactionRemove;
use crate::types::MessageReactionRemoveAll;
use crate::types::MessageReactionRemoveEmoji;
use crate::types::MessageUpdate;
use crate::types::PresenceUpdate;
use crate::types::ThreadCreate;
use crate::types::ThreadDelete;
use crate::types::ThreadListSync;
use crate::types::ThreadMemberUpdate;
use crate::types::ThreadMembersUpdate;
use crate::types::ThreadUpdate;
use crate::types::TypingStartEvent;
use crate::types::UnavailableGuild;
use crate::types::User;
use crate::types::UserUpdate;
use crate::types::WebSocketEvent;
use futures_util::stream::SplitSink;
use futures_util::SinkExt; use futures_util::SinkExt;
use futures_util::StreamExt; use futures_util::StreamExt;
use futures_util::stream::SplitSink;
use native_tls::TlsConnector; use native_tls::TlsConnector;
use std::sync::Arc;
use tokio::net::TcpStream; use tokio::net::TcpStream;
use tokio::sync::mpsc; use tokio::sync::mpsc;
use tokio::sync::mpsc::error::TryRecvError; use tokio::sync::mpsc::error::TryRecvError;
@ -16,7 +50,7 @@ use tokio::task;
use tokio::time; use tokio::time;
use tokio::time::Instant; use tokio::time::Instant;
use tokio_tungstenite::MaybeTlsStream; use tokio_tungstenite::MaybeTlsStream;
use tokio_tungstenite::{WebSocketStream, Connector, connect_async_tls_with_config}; use tokio_tungstenite::{connect_async_tls_with_config, Connector, WebSocketStream};
#[derive(Debug)] #[derive(Debug)]
/** /**
@ -28,14 +62,25 @@ Using this handle you can also send Gateway Events directly.
pub struct GatewayHandle { pub struct GatewayHandle {
pub url: String, pub url: String,
pub events: Arc<Mutex<Events>>, pub events: Arc<Mutex<Events>>,
pub websocket_tx: Arc<Mutex<SplitSink<WebSocketStream<MaybeTlsStream<TcpStream>>, tokio_tungstenite::tungstenite::Message>>>, pub websocket_tx: Arc<
Mutex<
SplitSink<
WebSocketStream<MaybeTlsStream<TcpStream>>,
tokio_tungstenite::tungstenite::Message,
>,
>,
>,
} }
impl GatewayHandle { impl GatewayHandle {
/// Sends json to the gateway with an opcode /// Sends json to the gateway with an opcode
async fn send_json_event(&self, op: u8, to_send: serde_json::Value) { async fn send_json_event(&self, op: u8, to_send: serde_json::Value) {
let gateway_payload = GatewayPayload {
let gateway_payload = GatewayPayload { op, d: Some(to_send), s: None, t: None }; op,
d: Some(to_send),
s: None,
t: None,
};
let payload_json = serde_json::to_string(&gateway_payload).unwrap(); let payload_json = serde_json::to_string(&gateway_payload).unwrap();
@ -46,7 +91,6 @@ impl GatewayHandle {
/// Sends an identify event to the gateway /// Sends an identify event to the gateway
pub async fn send_identify(&self, to_send: GatewayIdentifyPayload) { pub async fn send_identify(&self, to_send: GatewayIdentifyPayload) {
let to_send_value = serde_json::to_value(&to_send).unwrap(); let to_send_value = serde_json::to_value(&to_send).unwrap();
println!("GW: Sending Identify.."); println!("GW: Sending Identify..");
@ -56,7 +100,6 @@ impl GatewayHandle {
/// Sends a resume event to the gateway /// Sends a resume event to the gateway
pub async fn send_resume(&self, to_send: GatewayResume) { pub async fn send_resume(&self, to_send: GatewayResume) {
let to_send_value = serde_json::to_value(&to_send).unwrap(); let to_send_value = serde_json::to_value(&to_send).unwrap();
println!("GW: Sending Resume.."); println!("GW: Sending Resume..");
@ -66,7 +109,6 @@ impl GatewayHandle {
/// Sends an update presence event to the gateway /// Sends an update presence event to the gateway
pub async fn send_update_presence(&self, to_send: PresenceUpdate) { pub async fn send_update_presence(&self, to_send: PresenceUpdate) {
let to_send_value = serde_json::to_value(&to_send).unwrap(); let to_send_value = serde_json::to_value(&to_send).unwrap();
println!("GW: Sending Presence Update.."); println!("GW: Sending Presence Update..");
@ -76,7 +118,6 @@ impl GatewayHandle {
/// Sends a Request Guild Members to the server /// Sends a Request Guild Members to the server
pub async fn send_request_guild_members(&self, to_send: GatewayRequestGuildMembers) { pub async fn send_request_guild_members(&self, to_send: GatewayRequestGuildMembers) {
let to_send_value = serde_json::to_value(&to_send).unwrap(); let to_send_value = serde_json::to_value(&to_send).unwrap();
println!("GW: Sending Request Guild Members.."); println!("GW: Sending Request Guild Members..");
@ -86,7 +127,6 @@ impl GatewayHandle {
/// Sends a Request Guild Members to the server /// Sends a Request Guild Members to the server
pub async fn send_update_voice_state(&self, to_send: GatewayVoiceStateUpdate) { pub async fn send_update_voice_state(&self, to_send: GatewayVoiceStateUpdate) {
let to_send_value = serde_json::to_value(&to_send).unwrap(); let to_send_value = serde_json::to_value(&to_send).unwrap();
println!("GW: Sending Voice State Update.."); println!("GW: Sending Voice State Update..");
@ -98,14 +138,20 @@ impl GatewayHandle {
pub struct Gateway { pub struct Gateway {
pub events: Arc<Mutex<Events>>, pub events: Arc<Mutex<Events>>,
heartbeat_handler: Option<HeartbeatHandler>, heartbeat_handler: Option<HeartbeatHandler>,
pub websocket_tx: Arc<Mutex<SplitSink<WebSocketStream<MaybeTlsStream<TcpStream>>, tokio_tungstenite::tungstenite::Message>>> pub websocket_tx: Arc<
Mutex<
SplitSink<
WebSocketStream<MaybeTlsStream<TcpStream>>,
tokio_tungstenite::tungstenite::Message,
>,
>,
>,
} }
impl Gateway { impl Gateway {
pub async fn new( pub async fn new(
websocket_url: String, websocket_url: String,
) -> Result<GatewayHandle, tokio_tungstenite::tungstenite::Error> { ) -> Result<GatewayHandle, tokio_tungstenite::tungstenite::Error> {
let (ws_stream, _) = match connect_async_tls_with_config( let (ws_stream, _) = match connect_async_tls_with_config(
&websocket_url, &websocket_url,
None, None,
@ -123,7 +169,11 @@ impl Gateway {
let shared_tx = Arc::new(Mutex::new(ws_tx)); let shared_tx = Arc::new(Mutex::new(ws_tx));
let mut gateway = Gateway { events: Arc::new(Mutex::new(Events::default())), heartbeat_handler: None, websocket_tx: shared_tx.clone() }; let mut gateway = Gateway {
events: Arc::new(Mutex::new(Events::default())),
heartbeat_handler: None,
websocket_tx: shared_tx.clone(),
};
let shared_events = gateway.events.clone(); let shared_events = gateway.events.clone();
@ -134,13 +184,20 @@ impl Gateway {
if gateway_payload.op != 10 { if gateway_payload.op != 10 {
println!("Recieved non hello on gateway init, what is happening?"); println!("Recieved non hello on gateway init, what is happening?");
return Err(tokio_tungstenite::tungstenite::Error::Protocol(tokio_tungstenite::tungstenite::error::ProtocolError::InvalidOpcode(gateway_payload.op))) return Err(tokio_tungstenite::tungstenite::Error::Protocol(
tokio_tungstenite::tungstenite::error::ProtocolError::InvalidOpcode(
gateway_payload.op,
),
));
} }
println!("GW: Received Hello"); println!("GW: Received Hello");
let gateway_hello: HelloData = serde_json::from_value(gateway_payload.d.unwrap()).unwrap(); let gateway_hello: HelloData = serde_json::from_value(gateway_payload.d.unwrap()).unwrap();
gateway.heartbeat_handler = Some(HeartbeatHandler::new(gateway_hello.heartbeat_interval, shared_tx.clone())); gateway.heartbeat_handler = Some(HeartbeatHandler::new(
gateway_hello.heartbeat_interval,
shared_tx.clone(),
));
// Now we can continously check for messages in a different task, since we aren't going to receive another hello // Now we can continously check for messages in a different task, since we aren't going to receive another hello
task::spawn(async move { task::spawn(async move {
@ -162,7 +219,6 @@ impl Gateway {
/// This handles a message as a websocket event and updates its events along with the events' observers /// This handles a message as a websocket event and updates its events along with the events' observers
pub async fn handle_event(&mut self, msg: tokio_tungstenite::tungstenite::Message) { pub async fn handle_event(&mut self, msg: tokio_tungstenite::tungstenite::Message) {
if msg.to_string() == String::new() { if msg.to_string() == String::new() {
return; return;
} }
@ -183,7 +239,8 @@ impl Gateway {
// See https://discord.com/developers/docs/topics/gateway-events#receive-events // See https://discord.com/developers/docs/topics/gateway-events#receive-events
match gateway_payload_t.as_str() { match gateway_payload_t.as_str() {
"READY" => { "READY" => {
let _data: GatewayReady = serde_json::from_value(gateway_payload.d.unwrap()).unwrap(); let _data: GatewayReady =
serde_json::from_value(gateway_payload.d.unwrap()).unwrap();
} }
"RESUMED" => {} "RESUMED" => {}
"APPLICATION_COMMAND_PERMISSIONS_UPDATE" => {} "APPLICATION_COMMAND_PERMISSIONS_UPDATE" => {}
@ -192,65 +249,144 @@ impl Gateway {
"AUTO_MODERATION_RULE_DELETE" => {} "AUTO_MODERATION_RULE_DELETE" => {}
"AUTO_MODERATION_ACTION_EXECUTION" => {} "AUTO_MODERATION_ACTION_EXECUTION" => {}
"CHANNEL_CREATE" => { "CHANNEL_CREATE" => {
let channel: Channel = serde_json::from_value(gateway_payload.d.unwrap()).unwrap(); let channel: Channel =
let new_data = ChannelCreate {channel}; serde_json::from_value(gateway_payload.d.unwrap()).unwrap();
self.events.lock().await.channel.create.update_data(new_data).await; let new_data = ChannelCreate { channel };
self.events
.lock()
.await
.channel
.create
.update_data(new_data)
.await;
} }
"CHANNEL_UPDATE" => { "CHANNEL_UPDATE" => {
let channel: Channel = serde_json::from_value(gateway_payload.d.unwrap()).unwrap(); let channel: Channel =
let new_data = ChannelUpdate {channel}; serde_json::from_value(gateway_payload.d.unwrap()).unwrap();
self.events.lock().await.channel.update.update_data(new_data).await; let new_data = ChannelUpdate { channel };
self.events
.lock()
.await
.channel
.update
.update_data(new_data)
.await;
} }
"CHANNEL_DELETE" => { "CHANNEL_DELETE" => {
let channel: Channel = serde_json::from_value(gateway_payload.d.unwrap()).unwrap(); let channel: Channel =
let new_data = ChannelDelete {channel}; serde_json::from_value(gateway_payload.d.unwrap()).unwrap();
self.events.lock().await.channel.delete.update_data(new_data).await; let new_data = ChannelDelete { channel };
self.events
.lock()
.await
.channel
.delete
.update_data(new_data)
.await;
} }
"CHANNEL_PINS_UPDATE" => { "CHANNEL_PINS_UPDATE" => {
let new_data: ChannelPinsUpdate = serde_json::from_value(gateway_payload.d.unwrap()).unwrap(); let new_data: ChannelPinsUpdate =
self.events.lock().await.channel.pins_update.update_data(new_data).await; serde_json::from_value(gateway_payload.d.unwrap()).unwrap();
self.events
.lock()
.await
.channel
.pins_update
.update_data(new_data)
.await;
} }
"THREAD_CREATE" => { "THREAD_CREATE" => {
let thread: Channel = serde_json::from_value(gateway_payload.d.unwrap()).unwrap(); let thread: Channel =
let new_data = ThreadCreate {thread}; serde_json::from_value(gateway_payload.d.unwrap()).unwrap();
self.events.lock().await.thread.create.update_data(new_data).await; let new_data = ThreadCreate { thread };
self.events
.lock()
.await
.thread
.create
.update_data(new_data)
.await;
} }
"THREAD_UPDATE" => { "THREAD_UPDATE" => {
let thread: Channel = serde_json::from_value(gateway_payload.d.unwrap()).unwrap(); let thread: Channel =
let new_data = ThreadUpdate {thread}; serde_json::from_value(gateway_payload.d.unwrap()).unwrap();
self.events.lock().await.thread.update.update_data(new_data).await; let new_data = ThreadUpdate { thread };
self.events
.lock()
.await
.thread
.update
.update_data(new_data)
.await;
} }
"THREAD_DELETE" => { "THREAD_DELETE" => {
let thread: Channel = serde_json::from_value(gateway_payload.d.unwrap()).unwrap(); let thread: Channel =
let new_data = ThreadDelete {thread}; serde_json::from_value(gateway_payload.d.unwrap()).unwrap();
self.events.lock().await.thread.delete.update_data(new_data).await; let new_data = ThreadDelete { thread };
self.events
.lock()
.await
.thread
.delete
.update_data(new_data)
.await;
} }
"THREAD_LIST_SYNC" => { "THREAD_LIST_SYNC" => {
let new_data: ThreadListSync = serde_json::from_value(gateway_payload.d.unwrap()).unwrap(); let new_data: ThreadListSync =
self.events.lock().await.thread.list_sync.update_data(new_data).await; serde_json::from_value(gateway_payload.d.unwrap()).unwrap();
self.events
.lock()
.await
.thread
.list_sync
.update_data(new_data)
.await;
} }
"THREAD_MEMBER_UPDATE" => { "THREAD_MEMBER_UPDATE" => {
let new_data: ThreadMemberUpdate = serde_json::from_value(gateway_payload.d.unwrap()).unwrap(); let new_data: ThreadMemberUpdate =
self.events.lock().await.thread.member_update.update_data(new_data).await; serde_json::from_value(gateway_payload.d.unwrap()).unwrap();
self.events
.lock()
.await
.thread
.member_update
.update_data(new_data)
.await;
} }
"THREAD_MEMBERS_UPDATE" => { "THREAD_MEMBERS_UPDATE" => {
let new_data: ThreadMembersUpdate = serde_json::from_value(gateway_payload.d.unwrap()).unwrap(); let new_data: ThreadMembersUpdate =
self.events.lock().await.thread.members_update.update_data(new_data).await; serde_json::from_value(gateway_payload.d.unwrap()).unwrap();
self.events
.lock()
.await
.thread
.members_update
.update_data(new_data)
.await;
} }
"GUILD_CREATE" => { "GUILD_CREATE" => {
let new_data: GuildCreate = serde_json::from_str(&msg_string).unwrap(); let new_data: GuildCreate = serde_json::from_str(&msg_string).unwrap();
self.events.lock().await.guild.create.update_data(new_data).await; self.events
.lock()
.await
.guild
.create
.update_data(new_data)
.await;
} }
"GUILD_UPDATE" => {} "GUILD_UPDATE" => {}
"GUILD_DELETE" => { "GUILD_DELETE" => {
let _new_data: UnavailableGuild = serde_json::from_value(gateway_payload.d.unwrap()).unwrap(); let _new_data: UnavailableGuild =
serde_json::from_value(gateway_payload.d.unwrap()).unwrap();
} }
"GUILD_AUDIT_LOG_ENTRY_CREATE" => {} "GUILD_AUDIT_LOG_ENTRY_CREATE" => {}
"GUILD_BAN_ADD" => { "GUILD_BAN_ADD" => {
let _new_data: GuildBanAdd = serde_json::from_value(gateway_payload.d.unwrap()).unwrap(); let _new_data: GuildBanAdd =
serde_json::from_value(gateway_payload.d.unwrap()).unwrap();
} }
"GUILD_BAN_REMOVE" => { "GUILD_BAN_REMOVE" => {
let _new_data: GuildBanRemove = serde_json::from_value(gateway_payload.d.unwrap()).unwrap(); let _new_data: GuildBanRemove =
serde_json::from_value(gateway_payload.d.unwrap()).unwrap();
} }
"GUILD_EMOJIS_UPDATE" => {} "GUILD_EMOJIS_UPDATE" => {}
"GUILD_STICKERS_UPDATE" => {} "GUILD_STICKERS_UPDATE" => {}
@ -274,40 +410,103 @@ impl Gateway {
"INVITE_CREATE" => {} "INVITE_CREATE" => {}
"INVITE_DELETE" => {} "INVITE_DELETE" => {}
"MESSAGE_CREATE" => { "MESSAGE_CREATE" => {
let new_data: MessageCreate = serde_json::from_value(gateway_payload.d.unwrap()).unwrap(); let new_data: MessageCreate =
self.events.lock().await.message.create.update_data(new_data).await; serde_json::from_value(gateway_payload.d.unwrap()).unwrap();
self.events
.lock()
.await
.message
.create
.update_data(new_data)
.await;
} }
"MESSAGE_UPDATE" => { "MESSAGE_UPDATE" => {
let new_data: MessageUpdate = serde_json::from_value(gateway_payload.d.unwrap()).unwrap(); let new_data: MessageUpdate =
self.events.lock().await.message.update.update_data(new_data).await; serde_json::from_value(gateway_payload.d.unwrap()).unwrap();
self.events
.lock()
.await
.message
.update
.update_data(new_data)
.await;
} }
"MESSAGE_DELETE" => { "MESSAGE_DELETE" => {
let new_data: MessageDelete = serde_json::from_value(gateway_payload.d.unwrap()).unwrap(); let new_data: MessageDelete =
self.events.lock().await.message.delete.update_data(new_data).await; serde_json::from_value(gateway_payload.d.unwrap()).unwrap();
self.events
.lock()
.await
.message
.delete
.update_data(new_data)
.await;
} }
"MESSAGE_DELETE_BULK" => { "MESSAGE_DELETE_BULK" => {
let new_data: MessageDeleteBulk = serde_json::from_value(gateway_payload.d.unwrap()).unwrap(); let new_data: MessageDeleteBulk =
self.events.lock().await.message.delete_bulk.update_data(new_data).await; serde_json::from_value(gateway_payload.d.unwrap()).unwrap();
self.events
.lock()
.await
.message
.delete_bulk
.update_data(new_data)
.await;
} }
"MESSAGE_REACTION_ADD" => { "MESSAGE_REACTION_ADD" => {
let new_data: MessageReactionAdd = serde_json::from_value(gateway_payload.d.unwrap()).unwrap(); let new_data: MessageReactionAdd =
self.events.lock().await.message.reaction_add.update_data(new_data).await; serde_json::from_value(gateway_payload.d.unwrap()).unwrap();
self.events
.lock()
.await
.message
.reaction_add
.update_data(new_data)
.await;
} }
"MESSAGE_REACTION_REMOVE" => { "MESSAGE_REACTION_REMOVE" => {
let new_data: MessageReactionRemove = serde_json::from_value(gateway_payload.d.unwrap()).unwrap(); let new_data: MessageReactionRemove =
self.events.lock().await.message.reaction_remove.update_data(new_data).await; serde_json::from_value(gateway_payload.d.unwrap()).unwrap();
self.events
.lock()
.await
.message
.reaction_remove
.update_data(new_data)
.await;
} }
"MESSAGE_REACTION_REMOVE_ALL" => { "MESSAGE_REACTION_REMOVE_ALL" => {
let new_data: MessageReactionRemoveAll = serde_json::from_value(gateway_payload.d.unwrap()).unwrap(); let new_data: MessageReactionRemoveAll =
self.events.lock().await.message.reaction_remove_all.update_data(new_data).await; serde_json::from_value(gateway_payload.d.unwrap()).unwrap();
self.events
.lock()
.await
.message
.reaction_remove_all
.update_data(new_data)
.await;
} }
"MESSAGE_REACTION_REMOVE_EMOJI" => { "MESSAGE_REACTION_REMOVE_EMOJI" => {
let new_data: MessageReactionRemoveEmoji= serde_json::from_value(gateway_payload.d.unwrap()).unwrap(); let new_data: MessageReactionRemoveEmoji =
self.events.lock().await.message.reaction_remove_emoji.update_data(new_data).await; serde_json::from_value(gateway_payload.d.unwrap()).unwrap();
self.events
.lock()
.await
.message
.reaction_remove_emoji
.update_data(new_data)
.await;
} }
"PRESENCE_UPDATE" => { "PRESENCE_UPDATE" => {
let new_data: PresenceUpdate = serde_json::from_value(gateway_payload.d.unwrap()).unwrap(); let new_data: PresenceUpdate =
self.events.lock().await.user.presence_update.update_data(new_data).await; serde_json::from_value(gateway_payload.d.unwrap()).unwrap();
self.events
.lock()
.await
.user
.presence_update
.update_data(new_data)
.await;
} }
"STAGE_INSTANCE_CREATE" => {} "STAGE_INSTANCE_CREATE" => {}
"STAGE_INSTANCE_UPDATE" => {} "STAGE_INSTANCE_UPDATE" => {}
@ -315,27 +514,47 @@ impl Gateway {
// Not documented in discord docs, I assume this isnt for bots / apps but is for users? // Not documented in discord docs, I assume this isnt for bots / apps but is for users?
"SESSIONS_REPLACE" => {} "SESSIONS_REPLACE" => {}
"TYPING_START" => { "TYPING_START" => {
let new_data: TypingStartEvent = serde_json::from_value(gateway_payload.d.unwrap()).unwrap(); let new_data: TypingStartEvent =
self.events.lock().await.user.typing_start_event.update_data(new_data).await; serde_json::from_value(gateway_payload.d.unwrap()).unwrap();
self.events
.lock()
.await
.user
.typing_start_event
.update_data(new_data)
.await;
} }
"USER_UPDATE" => { "USER_UPDATE" => {
let user: UserObject = serde_json::from_value(gateway_payload.d.unwrap()).unwrap(); let user: User =
let new_data = UserUpdate {user}; serde_json::from_value(gateway_payload.d.unwrap()).unwrap();
self.events.lock().await.user.update.update_data(new_data).await; let new_data = UserUpdate { user };
self.events
.lock()
.await
.user
.update
.update_data(new_data)
.await;
} }
"VOICE_STATE_UPDATE" => {} "VOICE_STATE_UPDATE" => {}
"VOICE_SERVER_UPDATE" => {} "VOICE_SERVER_UPDATE" => {}
"WEBHOOKS_UPDATE" => {} "WEBHOOKS_UPDATE" => {}
_ => {panic!("Invalid gateway event ({})", &gateway_payload_t)} _ => {
panic!("Invalid gateway event ({})", &gateway_payload_t)
}
} }
} }
// Heartbeat // Heartbeat
// We received a heartbeat from the server // We received a heartbeat from the server
1 => {} 1 => {}
// Reconnect // Reconnect
7 => {todo!()} 7 => {
todo!()
}
// Invalid Session // Invalid Session
9 => {todo!()} 9 => {
todo!()
}
// Hello // Hello
// Starts our heartbeat // Starts our heartbeat
// We should have already handled this in gateway init // We should have already handled this in gateway init
@ -346,17 +565,32 @@ impl Gateway {
11 => { 11 => {
println!("GW: Received Heartbeat ACK"); println!("GW: Received Heartbeat ACK");
} }
2 | 3 | 4 | 6 | 8 => {panic!("Received Gateway op code that's meant to be sent, not received ({})", gateway_payload.op)} 2 | 3 | 4 | 6 | 8 => {
_ => {panic!("Received Invalid Gateway op code ({})", gateway_payload.op)} panic!(
"Received Gateway op code that's meant to be sent, not received ({})",
gateway_payload.op
)
}
_ => {
panic!("Received Invalid Gateway op code ({})", gateway_payload.op)
}
} }
// If we have an active heartbeat thread and we received a seq number we should let it know // If we have an active heartbeat thread and we received a seq number we should let it know
if gateway_payload.s.is_some() { if gateway_payload.s.is_some() {
if self.heartbeat_handler.is_some() { if self.heartbeat_handler.is_some() {
let heartbeat_communication = HeartbeatThreadCommunication {
op: gateway_payload.op,
d: gateway_payload.s.unwrap(),
};
let heartbeat_communication = HeartbeatThreadCommunication { op: gateway_payload.op, d: gateway_payload.s.unwrap() }; self.heartbeat_handler
.as_mut()
self.heartbeat_handler.as_mut().unwrap().tx.send(heartbeat_communication).await.unwrap(); .unwrap()
.tx
.send(heartbeat_communication)
.await
.unwrap();
} }
} }
} }
@ -372,7 +606,17 @@ struct HeartbeatHandler {
} }
impl HeartbeatHandler { impl HeartbeatHandler {
pub fn new(heartbeat_interval: u128, websocket_tx: Arc<Mutex<SplitSink<WebSocketStream<MaybeTlsStream<TcpStream>>, tokio_tungstenite::tungstenite::Message>>>) -> HeartbeatHandler { pub fn new(
heartbeat_interval: u128,
websocket_tx: Arc<
Mutex<
SplitSink<
WebSocketStream<MaybeTlsStream<TcpStream>>,
tokio_tungstenite::tungstenite::Message,
>,
>,
>,
) -> HeartbeatHandler {
let (tx, mut rx) = mpsc::channel(32); let (tx, mut rx) = mpsc::channel(32);
task::spawn(async move { task::spawn(async move {
@ -380,37 +624,36 @@ impl HeartbeatHandler {
let mut last_seq_number: Option<u64> = None; let mut last_seq_number: Option<u64> = None;
loop { loop {
// If we received a seq number update, use that as the last seq number // If we received a seq number update, use that as the last seq number
let hb_communication: Result<HeartbeatThreadCommunication, TryRecvError> = rx.try_recv(); let hb_communication: Result<HeartbeatThreadCommunication, TryRecvError> =
rx.try_recv();
if hb_communication.is_ok() { if hb_communication.is_ok() {
last_seq_number = Some(hb_communication.unwrap().d); last_seq_number = Some(hb_communication.unwrap().d);
} }
if last_heartbeat.elapsed().as_millis() > heartbeat_interval { if last_heartbeat.elapsed().as_millis() > heartbeat_interval {
println!("GW: Sending Heartbeat.."); println!("GW: Sending Heartbeat..");
let heartbeat = GatewayHeartbeat { let heartbeat = GatewayHeartbeat {
op: 1, op: 1,
d: last_seq_number d: last_seq_number,
}; };
let heartbeat_json = serde_json::to_string(&heartbeat).unwrap(); let heartbeat_json = serde_json::to_string(&heartbeat).unwrap();
let msg = tokio_tungstenite::tungstenite::Message::text(heartbeat_json); let msg = tokio_tungstenite::tungstenite::Message::text(heartbeat_json);
websocket_tx.lock().await websocket_tx.lock().await.send(msg).await.unwrap();
.send(msg)
.await
.unwrap();
last_heartbeat = time::Instant::now(); last_heartbeat = time::Instant::now();
} }
} }
}); });
Self { heartbeat_interval, tx } Self {
heartbeat_interval,
tx,
}
} }
} }
@ -423,7 +666,7 @@ struct HeartbeatThreadCommunication {
/// An opcode for the communication we received /// An opcode for the communication we received
op: u8, op: u8,
/// The sequence number we got from discord /// The sequence number we got from discord
d: u64 d: u64,
} }
/** /**
@ -469,7 +712,10 @@ impl<T: WebSocketEvent> GatewayEvent<T> {
Returns an error if the GatewayEvent is already observed. Returns an error if the GatewayEvent is already observed.
Error type: [`ObserverError::AlreadySubscribedError`] Error type: [`ObserverError::AlreadySubscribedError`]
*/ */
pub fn subscribe(&mut self, observable: Arc<Mutex<dyn Observer<T> + Sync + Send>>) -> Option<ObserverError> { pub fn subscribe(
&mut self,
observable: Arc<Mutex<dyn Observer<T> + Sync + Send>>,
) -> Option<ObserverError> {
if self.is_observed { if self.is_observed {
return Some(ObserverError::AlreadySubscribedError); return Some(ObserverError::AlreadySubscribedError);
} }
@ -486,7 +732,8 @@ impl<T: WebSocketEvent> GatewayEvent<T> {
// pointer value than observable. // pointer value than observable.
// The usage of the debug format to compare the generic T of observers is quite stupid, but the only thing to compare between them is T and if T == T they are the same // The usage of the debug format to compare the generic T of observers is quite stupid, but the only thing to compare between them is T and if T == T they are the same
// anddd there is no way to do that without using format // anddd there is no way to do that without using format
self.observers.retain(|obs| !(format!("{:?}", obs) == format!("{:?}", &observable))); self.observers
.retain(|obs| !(format!("{:?}", obs) == format!("{:?}", &observable)));
self.is_observed = !self.observers.is_empty(); self.is_observed = !self.observers.is_empty();
} }
@ -545,7 +792,7 @@ mod events {
pub create: GatewayEvent<ChannelCreate>, pub create: GatewayEvent<ChannelCreate>,
pub update: GatewayEvent<ChannelUpdate>, pub update: GatewayEvent<ChannelUpdate>,
pub delete: GatewayEvent<ChannelDelete>, pub delete: GatewayEvent<ChannelDelete>,
pub pins_update: GatewayEvent<ChannelPinsUpdate> pub pins_update: GatewayEvent<ChannelPinsUpdate>,
} }
#[derive(Default, Debug)] #[derive(Default, Debug)]
@ -587,7 +834,6 @@ mod events {
#[cfg(test)] #[cfg(test)]
mod example { mod example {
use super::*; use super::*;
use crate::api::types::GatewayResume;
#[derive(Debug)] #[derive(Debug)]
struct Consumer; struct Consumer;
@ -634,7 +880,6 @@ mod example {
None => assert!(true), None => assert!(true),
Some(_) => assert!(false), Some(_) => assert!(false),
} }
} }
#[tokio::test] #[tokio::test]

View File

@ -1,9 +1,11 @@
use crate::api::limits::Limits; use crate::api::limits::Limits;
use crate::api::types::InstancePolicies;
use crate::errors::{FieldFormatError, InstanceServerError}; use crate::errors::{FieldFormatError, InstanceServerError};
use crate::types::{GeneralConfiguration, User, UserSettings};
use crate::URLBundle; use crate::URLBundle;
use std::cell::RefCell;
use std::fmt; use std::fmt;
use std::rc::Rc;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
/** /**
@ -11,7 +13,7 @@ The [`Instance`] what you will be using to perform all sorts of actions on the S
*/ */
pub struct Instance { pub struct Instance {
pub urls: URLBundle, pub urls: URLBundle,
pub instance_info: InstancePolicies, pub instance_info: GeneralConfiguration,
pub limits: Limits, pub limits: Limits,
} }
@ -25,7 +27,7 @@ impl Instance {
pub async fn new(urls: URLBundle) -> Result<Instance, InstanceServerError> { pub async fn new(urls: URLBundle) -> Result<Instance, InstanceServerError> {
let mut instance = Instance { let mut instance = Instance {
urls: urls.clone(), urls: urls.clone(),
instance_info: InstancePolicies::new( instance_info: GeneralConfiguration::new(
// This is okay, because the instance_info will be overwritten by the instance_policies_schema() function. // This is okay, because the instance_info will be overwritten by the instance_policies_schema() function.
"".to_string(), "".to_string(),
None, None,
@ -38,7 +40,7 @@ impl Instance {
), ),
limits: Limits::check_limits(urls.api).await, limits: Limits::check_limits(urls.api).await,
}; };
instance.instance_info = match instance.instance_policies_schema().await { instance.instance_info = match instance.general_configuration_schema().await {
Ok(schema) => schema, Ok(schema) => schema,
Err(e) => { Err(e) => {
return Err(InstanceServerError::CantGetInfoError { return Err(InstanceServerError::CantGetInfoError {
@ -79,3 +81,38 @@ impl Username {
Ok(Username { username }) Ok(Username { username })
} }
} }
#[derive(Debug)]
pub struct UserMeta {
pub belongs_to: Rc<RefCell<Instance>>,
pub token: String,
pub limits: Limits,
pub settings: UserSettings,
pub object: Option<User>,
}
impl UserMeta {
pub fn token(&self) -> String {
self.token.clone()
}
pub fn set_token(&mut self, token: String) {
self.token = token;
}
pub fn new(
belongs_to: Rc<RefCell<Instance>>,
token: String,
limits: Limits,
settings: UserSettings,
object: Option<User>,
) -> UserMeta {
UserMeta {
belongs_to,
token,
limits,
settings,
object,
}
}
}

View File

@ -13,7 +13,6 @@ pub struct GeneralConfiguration {
pub correspondence_user_id: Option<String>, pub correspondence_user_id: Option<String>,
pub image: Option<String>, pub image: Option<String>,
pub instance_id: Option<Snowflake>, pub instance_id: Option<Snowflake>,
pub auto_create_bot_users: Option<bool>,
} }
impl Default for GeneralConfiguration { impl Default for GeneralConfiguration {
@ -29,7 +28,30 @@ impl Default for GeneralConfiguration {
correspondence_user_id: None, correspondence_user_id: None,
image: None, image: None,
instance_id: Some(Snowflake::generate()), instance_id: Some(Snowflake::generate()),
auto_create_bot_users: Some(false), }
}
}
impl GeneralConfiguration {
pub fn new(
instance_name: String,
instance_description: Option<String>,
front_page: Option<String>,
tos_page: Option<String>,
correspondence_email: Option<String>,
correspondence_user_id: Option<String>,
image: Option<String>,
instance_id: Option<Snowflake>,
) -> Self {
Self {
instance_name,
instance_description,
front_page,
tos_page,
correspondence_email,
correspondence_user_id,
image,
instance_id,
} }
} }
} }

View File

@ -1,4 +1,5 @@
pub use config::*; pub use config::*;
pub use entities::*;
pub use errors::*; pub use errors::*;
pub use events::*; pub use events::*;
pub use interfaces::*; pub use interfaces::*;

View File

@ -9,63 +9,6 @@ use crate::{
utils::Snowflake, //util::{email::adjust_email, entities::user_setting::UserSettings}, utils::Snowflake, //util::{email::adjust_email, entities::user_setting::UserSettings},
}; };
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "sqlx", derive(FromRow))]
pub struct User {
pub id: Snowflake,
pub username: String,
pub discriminator: String,
pub avatar: Option<String>,
pub accent_color: Option<u8>,
pub banner: Option<String>,
pub theme_colors: Option<Vec<u8>>,
pub pronouns: Option<String>,
pub phone: Option<String>,
pub desktop: bool,
pub mobile: bool,
pub premium: bool,
pub premium_type: u8,
pub bot: bool,
pub bio: String,
pub system: bool,
pub nsfw_allowed: bool,
pub mfa_enabled: bool,
pub webauthn_enabled: bool,
#[serde(skip)]
pub totp_secret: Option<String>,
#[serde(skip)]
pub totp_last_ticket: Option<String>,
pub created_at: DateTime<Utc>,
pub premium_since: Option<DateTime<Utc>>,
pub verified: bool,
pub disabled: bool,
pub deleted: bool,
pub email: Option<String>,
pub flags: String,
pub public_flags: u16,
pub purchased_flags: u16,
pub premium_usage_flags: u16,
pub rights: String,
#[cfg(feature = "sqlx")]
pub relationship_ids: sqlx::types::Json<Vec<String>>,
#[cfg(not(feature = "sqlx"))]
pub relationship_ids: Vec<String>,
#[cfg(feature = "sqlx")]
pub connected_account_ids: sqlx::types::Json<Vec<String>>,
#[cfg(not(feature = "sqlx"))]
pub connected_account_ids: Vec<String>,
#[cfg(feature = "sqlx")]
pub data: sqlx::types::Json<UserData>,
#[cfg(not(feature = "sqlx"))]
pub data: UserData,
#[cfg(feature = "sqlx")]
pub fingerprints: sqlx::types::Json<Vec<String>>,
#[cfg(not(feature = "sqlx"))]
pub fingerprints: Vec<String>,
// pub settings: UserSettings,
pub extended_settings: Value,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
#[cfg_attr(feature = "sqlx", derive(Type))] #[cfg_attr(feature = "sqlx", derive(Type))]
pub struct UserData { pub struct UserData {
@ -73,77 +16,8 @@ pub struct UserData {
pub hash: Option<String>, pub hash: Option<String>,
} }
impl Default for User {
fn default() -> Self {
Self {
id: Snowflake::generate(),
username: String::new(),
discriminator: String::new(),
avatar: None,
accent_color: None,
banner: None,
theme_colors: None,
pronouns: None,
phone: None,
desktop: false,
mobile: false,
premium: false,
premium_type: 0,
bot: false,
bio: String::new(),
system: false,
nsfw_allowed: false,
mfa_enabled: false,
webauthn_enabled: false,
totp_secret: None,
totp_last_ticket: None,
created_at: Utc::now(),
premium_since: None,
verified: false,
disabled: false,
deleted: false,
email: None,
flags: String::from("0"),
public_flags: 0,
purchased_flags: 0,
premium_usage_flags: 0,
rights: String::new(),
relationship_ids: Default::default(),
connected_account_ids: Default::default(),
data: Default::default(),
fingerprints: Default::default(),
//settings: UserSettings::default(),
extended_settings: Value::Object(Map::new()),
}
}
}
impl User {
pub fn validate(&mut self) -> Result<(), Error> {
/*if let Some(email) = self.email.as_ref() {
self.email = Some(adjust_email(email)?);
}
if self.discriminator.len() < 4 {
self.discriminator = format!("{:0>4}", self.discriminator);
}
Ok(())*/
todo!()
}
pub async fn generate_discriminator(_username: &str) -> Result<String, Error> {
todo!()
}
}
impl User {
pub fn to_public_user(self) -> PublicUser {
PublicUser::from(self)
}
}
#[derive(Serialize, Deserialize, Debug, Default, Clone)] #[derive(Serialize, Deserialize, Debug, Default, Clone)]
pub struct PrivateUser { pub struct User {
pub id: String, pub id: String,
username: String, username: String,
discriminator: String, discriminator: String,
@ -172,7 +46,7 @@ pub struct PrivateUser {
} }
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PublicUser { pub struct User {
pub id: Snowflake, pub id: Snowflake,
pub username: String, pub username: String,
pub discriminator: String, pub discriminator: String,