From eaef784deb83fb1db99377cb8cc8658dc093782c Mon Sep 17 00:00:00 2001 From: roufpup Date: Wed, 18 Feb 2026 17:33:05 +0200 Subject: [PATCH] Implement more of the gateway dispatch events and op codes, add a better README and do a little bit of cleanup --- .gitignore | 1 + Cargo.lock | 2 +- README.md | 7 ++ fluxer-rs/Cargo.toml | 2 +- fluxer-rs/README.md | 4 + fluxer-rs/src/api/handler.rs | 3 + fluxer-rs/src/api/mod.rs | 1 + fluxer-rs/src/fluxerbot.rs | 86 ++++++++++++++++++ fluxer-rs/src/gateway/dispatch_data/basic.rs | 9 ++ fluxer-rs/src/gateway/dispatch_data/guild.rs | 4 +- .../src/gateway/dispatch_data/message.rs | 36 +++++--- fluxer-rs/src/gateway/dispatch_data/mod.rs | 4 +- fluxer-rs/src/gateway/dispatch_data/ready.rs | 88 ++++++++++++++++++ fluxer-rs/src/gateway/dispatch_data/types.rs | 9 +- fluxer-rs/src/gateway/op_handlers/dispatch.rs | 63 ++++++++++--- .../src/gateway/op_handlers/heartbeat.rs | 38 ++------ fluxer-rs/src/gateway/op_handlers/identify.rs | 25 ++++++ fluxer-rs/src/gateway/op_handlers/mod.rs | 3 +- fluxer-rs/src/gateway/serde/receive_serde.rs | 26 +++++- fluxer-rs/src/lib.rs | 89 +------------------ src/main.rs | 3 +- 21 files changed, 350 insertions(+), 153 deletions(-) create mode 100644 README.md create mode 100644 fluxer-rs/src/api/handler.rs create mode 100644 fluxer-rs/src/api/mod.rs create mode 100644 fluxer-rs/src/fluxerbot.rs create mode 100644 fluxer-rs/src/gateway/dispatch_data/basic.rs create mode 100644 fluxer-rs/src/gateway/dispatch_data/ready.rs create mode 100644 fluxer-rs/src/gateway/op_handlers/identify.rs diff --git a/.gitignore b/.gitignore index 0e71e34..3fac59b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target .direnv/ +.idea/ \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index d5c05fb..23bd4d8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -338,7 +338,7 @@ checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" [[package]] name = "fluxer-rs" -version = "0.1.0" +version = "0.1.1" dependencies = [ "async-trait", "ezsockets", diff --git a/README.md b/README.md new file mode 100644 index 0000000..4d2bbc8 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +This repository is facilitating the code for both fluxer-rs a very experimental and still work in progress rust library that interacts with the fluxer social media platform and the bot colorbot which will utilize fluxer-rs. + +For opening issues and feature requests please head over to the MIRROR repo over on https://github.com/roufpup/colorbot + +Feel free to join me and chat on Fluxer in the fluxer-rs server https://fluxer.gg/YpAOaODV + +I will be doing my best to be implementing the API and gateway functionality as fast as i can so please bear with me. diff --git a/fluxer-rs/Cargo.toml b/fluxer-rs/Cargo.toml index b3b9545..9b49b36 100644 --- a/fluxer-rs/Cargo.toml +++ b/fluxer-rs/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fluxer-rs" -version = "0.1.0" +version = "0.1.1" edition = "2024" license = "MIT" description = "A rust implementation of the fluxer api to be used on fluxer.app and other self hosted instances" diff --git a/fluxer-rs/README.md b/fluxer-rs/README.md index b46ef49..efd8039 100644 --- a/fluxer-rs/README.md +++ b/fluxer-rs/README.md @@ -1 +1,5 @@ A rust implementation of the fluxer api to be used on fluxer.app and other self hosted instances + +For opening issues and feature requests please head over to the MIRROR repo over on https://github.com/roufpup/colorbot + +Feel free to join me and chat on Fluxer in the fluxer-rs server https://fluxer.gg/YpAOaODV diff --git a/fluxer-rs/src/api/handler.rs b/fluxer-rs/src/api/handler.rs new file mode 100644 index 0000000..6e29f4e --- /dev/null +++ b/fluxer-rs/src/api/handler.rs @@ -0,0 +1,3 @@ +pub struct FluxerApiHandler{ + +} \ No newline at end of file diff --git a/fluxer-rs/src/api/mod.rs b/fluxer-rs/src/api/mod.rs new file mode 100644 index 0000000..ef7d850 --- /dev/null +++ b/fluxer-rs/src/api/mod.rs @@ -0,0 +1 @@ +pub mod handler; \ No newline at end of file diff --git a/fluxer-rs/src/fluxerbot.rs b/fluxer-rs/src/fluxerbot.rs new file mode 100644 index 0000000..3fa0b7c --- /dev/null +++ b/fluxer-rs/src/fluxerbot.rs @@ -0,0 +1,86 @@ +use crate::gateway::op_handlers::dispatch::{DispatchHandlerTrait, handle_dispatch_events}; +use crate::gateway::op_handlers::heartbeat::{heartbeat_ack_handler, heartbeat_handler}; +use crate::gateway::op_handlers::identify::auth_handler; +use crate::gateway::serde::receive_serde::{ReceiveData, ReceiveDataType}; +use async_trait::async_trait; +use ezsockets::{Bytes, Client, ClientConfig, ClientExt, Error, Utf8Bytes, connect}; +use log::{error, info}; + +pub struct FluxerBot { + pub token: String, + pub endpoint: String, + pub dispatch_handler: T, + pub ws_handle: Client>, +} + +impl FluxerBot { + pub async fn start(token: String, endpoint: String, dispatch_handler: T) { + info!("Init the bot"); + + let config: ClientConfig = ClientConfig::new(endpoint.as_str()); + + info!("Starting websocket"); + let (_, future) = connect( + |ws_handle| FluxerBot { + ws_handle, + token, + dispatch_handler, + endpoint, + }, + config, + ) + .await; + let _ = future.await; + } +} + +impl FluxerBot where T: Send + Sync + DispatchHandlerTrait + 'static {} + +#[async_trait] +impl ClientExt for FluxerBot { + type Call = (); + + async fn on_text(&mut self, text: Utf8Bytes) -> Result<(), Error> { + let result: ReceiveData = match serde_json::from_slice(text.as_bytes()) { + Ok(value) => value, + Err(err) => { + error!("Unhandled behavior: {err}"); + error!("{}", text); + panic!() + } + }; + + match result.d { + ReceiveDataType::OP0(dispatch_event) => { + handle_dispatch_events(dispatch_event, &self.dispatch_handler).await + } + ReceiveDataType::OP1(_op1_d) => heartbeat_handler(text, &self.ws_handle).await, + ReceiveDataType::OP9(op9_d) => { + if !op9_d { + info!("-> {} Connection Invalid, Reauthenticating", text); + auth_handler(self.token.clone(), &self.ws_handle).await + } else { + //TODO: Implement session resume + info!("-> {} Connection Invalid, Resuming", text); + panic!() + } + } + ReceiveDataType::OP10(_data) => heartbeat_handler(text, &self.ws_handle).await, + ReceiveDataType::OP11 => heartbeat_ack_handler::(text).await, + } + Ok(()) + } + + async fn on_binary(&mut self, _bytes: Bytes) -> Result<(), Error> { + Ok(()) + } + + async fn on_call(&mut self, _call: Self::Call) -> Result<(), Error> { + Ok(()) + } + + async fn on_connect(&mut self) -> Result<(), Error> { + auth_handler(self.token.clone(), &self.ws_handle).await; + Ok(()) + } +} diff --git a/fluxer-rs/src/gateway/dispatch_data/basic.rs b/fluxer-rs/src/gateway/dispatch_data/basic.rs new file mode 100644 index 0000000..54a305c --- /dev/null +++ b/fluxer-rs/src/gateway/dispatch_data/basic.rs @@ -0,0 +1,9 @@ +use serde::Deserialize; + +#[derive(Deserialize)] +pub struct SessionReplaceData{ + pub afk: bool, + pub mobile: bool, + pub session_id: String, + pub status: String, +} \ No newline at end of file diff --git a/fluxer-rs/src/gateway/dispatch_data/guild.rs b/fluxer-rs/src/gateway/dispatch_data/guild.rs index efca6d3..8c0ccbe 100644 --- a/fluxer-rs/src/gateway/dispatch_data/guild.rs +++ b/fluxer-rs/src/gateway/dispatch_data/guild.rs @@ -1,4 +1,4 @@ -use crate::gateway::dispatch_data::types::{Channel, Member, Properties, Role}; +use crate::gateway::dispatch_data::types::{Channel, Member, GuildProperties, Role}; use serde::Deserialize; use serde_json::Value; @@ -19,7 +19,7 @@ pub struct GuildCreateData { pub members: Vec, pub online_count: i64, pub presences: Vec, - pub properties: Properties, + pub properties: GuildProperties, pub roles: Vec, pub stickers: Vec, pub voice_states: Vec, diff --git a/fluxer-rs/src/gateway/dispatch_data/message.rs b/fluxer-rs/src/gateway/dispatch_data/message.rs index 1c40eb4..5451a0d 100644 --- a/fluxer-rs/src/gateway/dispatch_data/message.rs +++ b/fluxer-rs/src/gateway/dispatch_data/message.rs @@ -1,28 +1,28 @@ use serde::Deserialize; use serde_json::Value; -use crate::gateway::dispatch_data::types::{Author, Member}; +use crate::gateway::dispatch_data::types::{Author, Emoji, Member}; #[derive(Deserialize)] pub struct MessageEventData { - pub attachments: Vec, - pub author: Author, + pub attachments: Option>, + pub author: Option, pub channel_id: String, - pub channel_type: i64, + pub channel_type: Option, pub content: String, - pub edited_timestamp: Value, - pub embeds: Vec, - pub flags: i64, + pub edited_timestamp: Option, + pub embeds: Option>, + pub flags: Option, pub guild_id: String, pub id: String, pub member: Member, - pub mention_everyone: bool, - pub nonce: String, - pub pinned: bool, - pub stickers: Vec, - pub timestamp: String, + pub mention_everyone: Option, + pub nonce: Option, + pub pinned: Option, + pub stickers: Option>, + pub timestamp: Option, #[serde(rename = "type")] - pub message_type: i64, + pub message_type: Option, } #[derive(Deserialize)] @@ -33,3 +33,13 @@ pub struct TypingEventData { pub timestamp: i64, pub user_id: String, } + +#[derive(Deserialize)] +pub struct MessageReactData { + pub channel_id: String, + pub emoji: Emoji, + pub guild_id: String, + pub member: Member, + pub message_id: String, + pub user_id: String, +} \ No newline at end of file diff --git a/fluxer-rs/src/gateway/dispatch_data/mod.rs b/fluxer-rs/src/gateway/dispatch_data/mod.rs index 83111fa..8069ef0 100644 --- a/fluxer-rs/src/gateway/dispatch_data/mod.rs +++ b/fluxer-rs/src/gateway/dispatch_data/mod.rs @@ -1,3 +1,5 @@ pub mod guild; pub mod message; -pub mod types; \ No newline at end of file +pub mod types; +pub mod basic; +pub mod ready; \ No newline at end of file diff --git a/fluxer-rs/src/gateway/dispatch_data/ready.rs b/fluxer-rs/src/gateway/dispatch_data/ready.rs new file mode 100644 index 0000000..2e83288 --- /dev/null +++ b/fluxer-rs/src/gateway/dispatch_data/ready.rs @@ -0,0 +1,88 @@ +use serde::Deserialize; +use serde_json::Value; + +#[derive(Deserialize)] +pub struct ReadyData { + pub country_code: String, + pub favorite_memes: Vec, + pub guilds: Vec, + pub notes: Notes, + pub pinned_dms: Vec, + pub presences: Vec, + pub private_channels: Vec, + pub read_states: Vec, + pub relationships: Vec, + pub rtc_regions: Vec, + pub session_id: String, + pub sessions: Vec, + pub user: LoggedInUser, + pub user_guild_settings: Vec, + pub user_settings: Value, + pub users: Vec, + pub version: i64, +} + +#[derive(Deserialize)] +pub struct Session { + pub afk: bool, + pub mobile: bool, + pub session_id: String, + pub status: String, +} + +#[derive(Deserialize)] +pub struct LoggedInUser { + pub accent_color: Value, + pub acls: Vec, + pub authenticator_types: Vec, + pub avatar: Value, + pub avatar_color: Value, + pub banner: Value, + pub banner_color: Value, + pub bio: Value, + pub bot: bool, + pub discriminator: String, + pub email: Value, + pub email_bounced: bool, + pub flags: i64, + pub global_name: Value, + pub has_dismissed_premium_onboarding: bool, + pub has_ever_purchased: bool, + pub has_unread_gift_inventory: bool, + pub id: String, + pub is_staff: bool, + pub mfa_enabled: bool, + pub nsfw_allowed: bool, + pub password_last_changed_at: Value, + pub pending_bulk_message_deletion: Value, + pub phone: Value, + pub premium_badge_hidden: bool, + pub premium_badge_masked: bool, + pub premium_badge_sequence_hidden: bool, + pub premium_badge_timestamp_hidden: bool, + pub premium_billing_cycle: Value, + pub premium_enabled_override: bool, + pub premium_lifetime_sequence: Value, + pub premium_purchase_disabled: bool, + pub premium_since: Value, + pub premium_type: i64, + pub premium_until: Value, + pub premium_will_cancel: bool, + pub pronouns: Value, + pub required_actions: Value, + pub traits: Vec, + pub unread_gift_inventory_count: i64, + pub used_mobile_client: bool, + pub username: String, + pub verified: bool, +} + +#[derive(Deserialize)] +pub struct RtcRegion { + pub emoji: String, + pub id: String, + pub name: String, +} + +#[derive(Deserialize)] +pub struct Notes {} diff --git a/fluxer-rs/src/gateway/dispatch_data/types.rs b/fluxer-rs/src/gateway/dispatch_data/types.rs index 866e014..63acf99 100644 --- a/fluxer-rs/src/gateway/dispatch_data/types.rs +++ b/fluxer-rs/src/gateway/dispatch_data/types.rs @@ -49,7 +49,7 @@ pub struct User { } #[derive(Deserialize)] -pub struct Properties { +pub struct GuildProperties { pub afk_channel_id: Value, pub afk_timeout: i64, pub banner: Value, @@ -102,3 +102,10 @@ pub struct Author { pub id: String, pub username: String, } + +#[derive(Deserialize)] +pub struct Emoji { + pub name: String, +} + + diff --git a/fluxer-rs/src/gateway/op_handlers/dispatch.rs b/fluxer-rs/src/gateway/op_handlers/dispatch.rs index de434cb..4d75f90 100644 --- a/fluxer-rs/src/gateway/op_handlers/dispatch.rs +++ b/fluxer-rs/src/gateway/op_handlers/dispatch.rs @@ -1,51 +1,86 @@ use log::info; +use crate::gateway::dispatch_data::basic::SessionReplaceData; +use crate::gateway::dispatch_data::message::MessageReactData; +use crate::gateway::dispatch_data::ready::ReadyData; use crate::gateway::dispatch_data::{ guild::{GuildCreateData, GuildDeleteData}, message::{MessageEventData, TypingEventData}, }; pub enum DispatchEvent { - Ready, + Ready(ReadyData), GuildDelete(GuildDeleteData), GuildCreate(Box), MessageCreate(MessageEventData), MessageDelete(MessageEventData), + MessageUpdate(MessageEventData), TypingStart(TypingEventData), TypingStop(TypingEventData), + ReactionAdd(MessageReactData), + ReactionRemove(MessageReactData), + SessionReplace(Vec), } pub trait DispatchHandlerTrait { - fn handle_ready_dispatch(&self) { - info!("-> [DISPATCH::READY]") + fn handle_ready_dispatch(&self, data: ReadyData) { + info!("-> [DISPATCH::READY] BOT_NAME: {}", data.user.username) } + fn handle_guild_delete_dispatch(&self, data: GuildDeleteData) { info!( "-> [DISPATCH::GUILD_DELETE] ID: {}, Unavailable: {}", data.guild_id, data.unavailable ) } + fn handle_guild_create_dispatch(&self, data: Box) { info!("-> [DISPATCH::GUILD_CREATE] ID: {}", data.id) } + fn handle_message_create_dispatch(&self, data: MessageEventData) { info!("-> [DISPATCH::MESSAGE_CREATE] CONTENT: {}", data.content) } + fn handle_message_delete_dispatch(&self, data: MessageEventData) { info!("-> [DISPATCH::MESSAGE_DELETE] CONTENT: {}", data.content) } + + fn handle_message_update_dispatch(&self, data: MessageEventData) { + info!("-> [DISPATCH::MESSAGE_UPDATE] CONTENT: {}", data.content) + } + fn handle_typing_start_dispatch(&self, data: TypingEventData) { info!( "-> [DISPATCH::TYPING_START] GUILD: {}, CHANNEL: {}", data.guild_id, data.channel_id ) } + fn handle_typing_stop_dispatch(&self, data: TypingEventData) { info!( "-> [DISPATCH::TYPING_STOP] GUILD: {}, CHANNEL: {}", data.guild_id, data.channel_id ) } + + fn handle_message_reaction_add_dispatch(&self, data: MessageReactData) { + info!( + "-> [DISPATCH::MESSAGE_REACTION_ADD] MESSAGE: {}, EMOJI: {}", + data.message_id, data.emoji.name + ) + } + + fn handle_message_reaction_remove_dispatch(&self, data: MessageReactData) { + info!( + "-> [DISPATCH::MESSAGE_REACTION_REMOVE] MESSAGE: {}, EMOJI: {}", + data.message_id, data.emoji.name + ) + } + + fn handle_session_replace_dispatch(&self, _data: Vec) { + info!("-> [DISPATCH::SESSION_REPLACE]",) + } } #[derive(Default)] @@ -54,15 +89,21 @@ impl DispatchHandlerTrait for DispatchHandler {} pub async fn handle_dispatch_events( dispatch_event: Box, - dispatcher: &T, + handler: &T, ) { match *dispatch_event { - DispatchEvent::Ready => dispatcher.handle_ready_dispatch(), - DispatchEvent::GuildDelete(data) => dispatcher.handle_guild_delete_dispatch(data), - DispatchEvent::GuildCreate(data) => dispatcher.handle_guild_create_dispatch(data), - DispatchEvent::MessageCreate(data) => dispatcher.handle_message_create_dispatch(data), - DispatchEvent::MessageDelete(data) => dispatcher.handle_message_delete_dispatch(data), - DispatchEvent::TypingStart(data) => dispatcher.handle_typing_start_dispatch(data), - DispatchEvent::TypingStop(data) => dispatcher.handle_typing_stop_dispatch(data), + DispatchEvent::Ready(data) => handler.handle_ready_dispatch(data), + DispatchEvent::GuildDelete(data) => handler.handle_guild_delete_dispatch(data), + DispatchEvent::GuildCreate(data) => handler.handle_guild_create_dispatch(data), + DispatchEvent::MessageCreate(data) => handler.handle_message_create_dispatch(data), + DispatchEvent::MessageDelete(data) => handler.handle_message_delete_dispatch(data), + DispatchEvent::MessageUpdate(data) => handler.handle_message_update_dispatch(data), + DispatchEvent::TypingStart(data) => handler.handle_typing_start_dispatch(data), + DispatchEvent::TypingStop(data) => handler.handle_typing_stop_dispatch(data), + DispatchEvent::ReactionAdd(data) => handler.handle_message_reaction_add_dispatch(data), + DispatchEvent::ReactionRemove(data) => { + handler.handle_message_reaction_remove_dispatch(data) + } + DispatchEvent::SessionReplace(data) => handler.handle_session_replace_dispatch(data), } } diff --git a/fluxer-rs/src/gateway/op_handlers/heartbeat.rs b/fluxer-rs/src/gateway/op_handlers/heartbeat.rs index ae50792..e2818ca 100644 --- a/fluxer-rs/src/gateway/op_handlers/heartbeat.rs +++ b/fluxer-rs/src/gateway/op_handlers/heartbeat.rs @@ -1,12 +1,10 @@ use ezsockets::{Client, Utf8Bytes}; use log::info; -use crate::{ - FluxerBot, - gateway::{ - op_handlers::dispatch::DispatchHandlerTrait, - serde::send_serde::{OP2D, OP2DProps, SendData, SendDataType}, - }, +use crate::fluxerbot::FluxerBot; +use crate::gateway::{ + op_handlers::dispatch::DispatchHandlerTrait, + serde::send_serde::{SendData, SendDataType}, }; pub async fn heartbeat_handler( @@ -28,32 +26,6 @@ pub async fn heartbeat_handler( pub async fn heartbeat_ack_handler( text: Utf8Bytes, - token: String, - heartbeat_ack: bool, - client_handle: &Client>, -) -> bool { +) { info!("-> {} Heartbeat acknowledged", text); - if !heartbeat_ack { - let auth_string = serde_json::to_string(&SendData { - d: SendDataType::OP2(OP2D { - token, - properties: OP2DProps { - os: "Linux".to_string(), - browser: "Fluxer-rs".to_string(), - device: "x64".to_string(), - }, - }), - op: 2, - }) - .unwrap(); - - match client_handle.text(auth_string) { - Ok(_) => {} - Err(err) => { - panic!("{err}") - } - }; - return true; - } - false } diff --git a/fluxer-rs/src/gateway/op_handlers/identify.rs b/fluxer-rs/src/gateway/op_handlers/identify.rs new file mode 100644 index 0000000..3b5aa6e --- /dev/null +++ b/fluxer-rs/src/gateway/op_handlers/identify.rs @@ -0,0 +1,25 @@ +use ezsockets::Client; +use crate::fluxerbot::FluxerBot; +use crate::gateway::op_handlers::dispatch::DispatchHandlerTrait; +use crate::gateway::serde::send_serde::{OP2DProps, SendData, SendDataType, OP2D}; + +pub async fn auth_handler (token: String, client_handle: &Client>){ + let auth_string = serde_json::to_string(&SendData { + d: SendDataType::OP2(OP2D { + token, + properties: OP2DProps { + os: "Linux".to_string(), + browser: "Fluxer-rs".to_string(), + device: "x64".to_string(), + }, + }), + op: 2, + }).unwrap(); + + match client_handle.text(auth_string) { + Ok(_) => {} + Err(err) => { + panic!("{err}") + } + }; +} \ No newline at end of file diff --git a/fluxer-rs/src/gateway/op_handlers/mod.rs b/fluxer-rs/src/gateway/op_handlers/mod.rs index 7b35b65..e1c1f97 100644 --- a/fluxer-rs/src/gateway/op_handlers/mod.rs +++ b/fluxer-rs/src/gateway/op_handlers/mod.rs @@ -1,2 +1,3 @@ pub mod heartbeat; -pub mod dispatch; \ No newline at end of file +pub mod dispatch; +pub mod identify; \ No newline at end of file diff --git a/fluxer-rs/src/gateway/serde/receive_serde.rs b/fluxer-rs/src/gateway/serde/receive_serde.rs index ee90ada..244cc19 100644 --- a/fluxer-rs/src/gateway/serde/receive_serde.rs +++ b/fluxer-rs/src/gateway/serde/receive_serde.rs @@ -1,6 +1,10 @@ +use log::info; use serde::{Deserialize, Serialize, de}; use serde_json::Value; +use crate::gateway::dispatch_data::basic::SessionReplaceData; +use crate::gateway::dispatch_data::message::MessageReactData; +use crate::gateway::dispatch_data::ready::ReadyData; use crate::gateway::{ dispatch_data::{ guild::{GuildCreateData, GuildDeleteData}, @@ -17,6 +21,7 @@ pub struct ReceiveData { pub enum ReceiveDataType { OP0(Box), OP1(Option), + OP9(bool), OP10(OP10D), OP11, } @@ -36,7 +41,9 @@ impl<'de> Deserialize<'de> for ReceiveData { let d = match op { 0 => { let dispatch_event = match value["t"].as_str().unwrap() { - "READY" => DispatchEvent::Ready, + "READY" => DispatchEvent::Ready( + ReadyData::deserialize(&value["d"]).map_err(de::Error::custom)?, + ), "GUILD_DELETE" => DispatchEvent::GuildDelete( GuildDeleteData::deserialize(&value["d"]).map_err(de::Error::custom)?, ), @@ -49,12 +56,25 @@ impl<'de> Deserialize<'de> for ReceiveData { "MESSAGE_DELETE" => DispatchEvent::MessageDelete( MessageEventData::deserialize(&value["d"]).map_err(de::Error::custom)?, ), + "MESSAGE_UPDATE" => DispatchEvent::MessageUpdate( + MessageEventData::deserialize(&value["d"]).map_err(de::Error::custom)?, + ), "TYPING_START" => DispatchEvent::TypingStart( TypingEventData::deserialize(&value["d"]).map_err(de::Error::custom)?, ), "TYPING_STOP" => DispatchEvent::TypingStop( TypingEventData::deserialize(&value["d"]).map_err(de::Error::custom)?, ), + "MESSAGE_REACTION_ADD" => DispatchEvent::ReactionAdd( + MessageReactData::deserialize(&value["d"]).map_err(de::Error::custom)?, + ), + "MESSAGE_REACTION_REMOVE" => DispatchEvent::ReactionRemove( + MessageReactData::deserialize(&value["d"]).map_err(de::Error::custom)?, + ), + "SESSION_REPLACE" => DispatchEvent::SessionReplace( + Vec::::deserialize(&value["d"]) + .map_err(de::Error::custom)?, + ), _ => panic!("Unimplemented dispatch event: {}", value), }; ReceiveDataType::OP0(Box::new(dispatch_event)) @@ -64,6 +84,10 @@ impl<'de> Deserialize<'de> for ReceiveData { Option::deserialize(&value["d"]).map_err(de::Error::custom)?; ReceiveDataType::OP1(inner) } + 9 => { + let inner = bool::deserialize(&value["d"]).map_err(de::Error::custom)?; + ReceiveDataType::OP9(inner) + } 10 => { let inner = OP10D::deserialize(&value["d"]).map_err(de::Error::custom)?; ReceiveDataType::OP10(inner) diff --git a/fluxer-rs/src/lib.rs b/fluxer-rs/src/lib.rs index 85e8cbb..7866ec2 100644 --- a/fluxer-rs/src/lib.rs +++ b/fluxer-rs/src/lib.rs @@ -1,88 +1,3 @@ -use async_trait::async_trait; -use ezsockets::{Bytes, Client, ClientConfig, ClientExt, Utf8Bytes, connect}; -use log::{error, info}; - -use crate::gateway::{ - op_handlers::{ - dispatch::{DispatchHandlerTrait, handle_dispatch_events}, - heartbeat::{heartbeat_ack_handler, heartbeat_handler}, - }, - serde::receive_serde::{ReceiveData, ReceiveDataType}, -}; - pub mod gateway; - -pub struct FluxerBot { - pub token: String, - pub endpoint: String, - pub dispatch_handler: T, - pub ws_handle: Client>, - pub heartbeat_ack: bool, -} - -impl FluxerBot { - pub async fn start(token: String, endpoint: String, dispatch_handler: T) { - info!("Init the bot"); - - let config: ClientConfig = ClientConfig::new(endpoint.as_str()); - - info!("Starting websocket"); - let (_, future) = connect( - |ws_handle| FluxerBot { - ws_handle, - token, - heartbeat_ack: false, - dispatch_handler, - endpoint, - }, - config, - ) - .await; - let _ = future.await; - } -} - -impl FluxerBot where T: Send + Sync + DispatchHandlerTrait + 'static {} - -#[async_trait] -impl ClientExt for FluxerBot { - type Call = (); - - async fn on_text(&mut self, text: Utf8Bytes) -> Result<(), ezsockets::Error> { - let result: ReceiveData = match serde_json::from_slice(text.as_bytes()) { - Ok(value) => value, - Err(err) => { - error!("Unhandled behavior: {err}"); - error!("{}", text); - panic!() - } - }; - - match result.d { - ReceiveDataType::OP10(_data) => heartbeat_handler(text, &__self.ws_handle).await, - ReceiveDataType::OP11 => { - //TODO: Implement the check whether this is the first heartbeat a bit better - self.heartbeat_ack = heartbeat_ack_handler( - text, - __self.token.clone(), - __self.heartbeat_ack, - &__self.ws_handle, - ) - .await - } - ReceiveDataType::OP1(_op1_d) => heartbeat_handler(text, &__self.ws_handle).await, - ReceiveDataType::OP0(dispatch_event) => { - handle_dispatch_events(dispatch_event, &self.dispatch_handler).await - } - } - Ok(()) - } - - async fn on_binary(&mut self, _bytes: Bytes) -> Result<(), ezsockets::Error> { - Ok(()) - } - - async fn on_call(&mut self, _call: Self::Call) -> Result<(), ezsockets::Error> { - Ok(()) - } -} +pub mod fluxerbot; +pub mod api; \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 9703758..c0710f6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,5 @@ -use fluxer_rs::{FluxerBot, gateway::op_handlers::dispatch::DispatchHandler}; +use fluxer_rs::fluxerbot::FluxerBot; +use fluxer_rs::gateway::op_handlers::dispatch::DispatchHandler; #[tokio::main] async fn main() { -- 2.51.2