this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Implement more of the gateway dispatch events and op codes, add a better README and do a little bit of cleanup

roufpup eaef784d e2dd5a0c

+350 -153
+1
.gitignore
··· 1 1 /target 2 2 .direnv/ 3 + .idea/
+1 -1
Cargo.lock
··· 338 338 339 339 [[package]] 340 340 name = "fluxer-rs" 341 - version = "0.1.0" 341 + version = "0.1.1" 342 342 dependencies = [ 343 343 "async-trait", 344 344 "ezsockets",
+7
README.md
··· 1 + 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. 2 + 3 + For opening issues and feature requests please head over to the MIRROR repo over on https://github.com/roufpup/colorbot 4 + 5 + Feel free to join me and chat on Fluxer in the fluxer-rs server https://fluxer.gg/YpAOaODV 6 + 7 + I will be doing my best to be implementing the API and gateway functionality as fast as i can so please bear with me.
+1 -1
fluxer-rs/Cargo.toml
··· 1 1 [package] 2 2 name = "fluxer-rs" 3 - version = "0.1.0" 3 + version = "0.1.1" 4 4 edition = "2024" 5 5 license = "MIT" 6 6 description = "A rust implementation of the fluxer api to be used on fluxer.app and other self hosted instances"
+4
fluxer-rs/README.md
··· 1 1 A rust implementation of the fluxer api to be used on fluxer.app and other self hosted instances 2 + 3 + For opening issues and feature requests please head over to the MIRROR repo over on https://github.com/roufpup/colorbot 4 + 5 + Feel free to join me and chat on Fluxer in the fluxer-rs server https://fluxer.gg/YpAOaODV
+3
fluxer-rs/src/api/handler.rs
··· 1 + pub struct FluxerApiHandler{ 2 + 3 + }
+1
fluxer-rs/src/api/mod.rs
··· 1 + pub mod handler;
+86
fluxer-rs/src/fluxerbot.rs
··· 1 + use crate::gateway::op_handlers::dispatch::{DispatchHandlerTrait, handle_dispatch_events}; 2 + use crate::gateway::op_handlers::heartbeat::{heartbeat_ack_handler, heartbeat_handler}; 3 + use crate::gateway::op_handlers::identify::auth_handler; 4 + use crate::gateway::serde::receive_serde::{ReceiveData, ReceiveDataType}; 5 + use async_trait::async_trait; 6 + use ezsockets::{Bytes, Client, ClientConfig, ClientExt, Error, Utf8Bytes, connect}; 7 + use log::{error, info}; 8 + 9 + pub struct FluxerBot<T: DispatchHandlerTrait + Send + Sync + 'static> { 10 + pub token: String, 11 + pub endpoint: String, 12 + pub dispatch_handler: T, 13 + pub ws_handle: Client<FluxerBot<T>>, 14 + } 15 + 16 + impl<T: DispatchHandlerTrait + Send + Sync + 'static> FluxerBot<T> { 17 + pub async fn start(token: String, endpoint: String, dispatch_handler: T) { 18 + info!("Init the bot"); 19 + 20 + let config: ClientConfig = ClientConfig::new(endpoint.as_str()); 21 + 22 + info!("Starting websocket"); 23 + let (_, future) = connect( 24 + |ws_handle| FluxerBot { 25 + ws_handle, 26 + token, 27 + dispatch_handler, 28 + endpoint, 29 + }, 30 + config, 31 + ) 32 + .await; 33 + let _ = future.await; 34 + } 35 + } 36 + 37 + impl<T> FluxerBot<T> where T: Send + Sync + DispatchHandlerTrait + 'static {} 38 + 39 + #[async_trait] 40 + impl<T: DispatchHandlerTrait + Send + Sync + 'static> ClientExt for FluxerBot<T> { 41 + type Call = (); 42 + 43 + async fn on_text(&mut self, text: Utf8Bytes) -> Result<(), Error> { 44 + let result: ReceiveData = match serde_json::from_slice(text.as_bytes()) { 45 + Ok(value) => value, 46 + Err(err) => { 47 + error!("Unhandled behavior: {err}"); 48 + error!("{}", text); 49 + panic!() 50 + } 51 + }; 52 + 53 + match result.d { 54 + ReceiveDataType::OP0(dispatch_event) => { 55 + handle_dispatch_events(dispatch_event, &self.dispatch_handler).await 56 + } 57 + ReceiveDataType::OP1(_op1_d) => heartbeat_handler(text, &self.ws_handle).await, 58 + ReceiveDataType::OP9(op9_d) => { 59 + if !op9_d { 60 + info!("-> {} Connection Invalid, Reauthenticating", text); 61 + auth_handler(self.token.clone(), &self.ws_handle).await 62 + } else { 63 + //TODO: Implement session resume 64 + info!("-> {} Connection Invalid, Resuming", text); 65 + panic!() 66 + } 67 + } 68 + ReceiveDataType::OP10(_data) => heartbeat_handler(text, &self.ws_handle).await, 69 + ReceiveDataType::OP11 => heartbeat_ack_handler::<T>(text).await, 70 + } 71 + Ok(()) 72 + } 73 + 74 + async fn on_binary(&mut self, _bytes: Bytes) -> Result<(), Error> { 75 + Ok(()) 76 + } 77 + 78 + async fn on_call(&mut self, _call: Self::Call) -> Result<(), Error> { 79 + Ok(()) 80 + } 81 + 82 + async fn on_connect(&mut self) -> Result<(), Error> { 83 + auth_handler(self.token.clone(), &self.ws_handle).await; 84 + Ok(()) 85 + } 86 + }
+9
fluxer-rs/src/gateway/dispatch_data/basic.rs
··· 1 + use serde::Deserialize; 2 + 3 + #[derive(Deserialize)] 4 + pub struct SessionReplaceData{ 5 + pub afk: bool, 6 + pub mobile: bool, 7 + pub session_id: String, 8 + pub status: String, 9 + }
+2 -2
fluxer-rs/src/gateway/dispatch_data/guild.rs
··· 1 - use crate::gateway::dispatch_data::types::{Channel, Member, Properties, Role}; 1 + use crate::gateway::dispatch_data::types::{Channel, Member, GuildProperties, Role}; 2 2 use serde::Deserialize; 3 3 use serde_json::Value; 4 4 ··· 19 19 pub members: Vec<Member>, 20 20 pub online_count: i64, 21 21 pub presences: Vec<Value>, 22 - pub properties: Properties, 22 + pub properties: GuildProperties, 23 23 pub roles: Vec<Role>, 24 24 pub stickers: Vec<Value>, 25 25 pub voice_states: Vec<Value>,
+23 -13
fluxer-rs/src/gateway/dispatch_data/message.rs
··· 1 1 use serde::Deserialize; 2 2 use serde_json::Value; 3 3 4 - use crate::gateway::dispatch_data::types::{Author, Member}; 4 + use crate::gateway::dispatch_data::types::{Author, Emoji, Member}; 5 5 6 6 #[derive(Deserialize)] 7 7 pub struct MessageEventData { 8 - pub attachments: Vec<Value>, 9 - pub author: Author, 8 + pub attachments: Option<Vec<Value>>, 9 + pub author: Option<Author>, 10 10 pub channel_id: String, 11 - pub channel_type: i64, 11 + pub channel_type: Option<i64>, 12 12 pub content: String, 13 - pub edited_timestamp: Value, 14 - pub embeds: Vec<Value>, 15 - pub flags: i64, 13 + pub edited_timestamp: Option<Value>, 14 + pub embeds: Option<Vec<Value>>, 15 + pub flags: Option<i64>, 16 16 pub guild_id: String, 17 17 pub id: String, 18 18 pub member: Member, 19 - pub mention_everyone: bool, 20 - pub nonce: String, 21 - pub pinned: bool, 22 - pub stickers: Vec<Value>, 23 - pub timestamp: String, 19 + pub mention_everyone: Option<bool>, 20 + pub nonce: Option<String>, 21 + pub pinned: Option<bool>, 22 + pub stickers: Option<Vec<Value>>, 23 + pub timestamp: Option<String>, 24 24 #[serde(rename = "type")] 25 - pub message_type: i64, 25 + pub message_type: Option<i64>, 26 26 } 27 27 28 28 #[derive(Deserialize)] ··· 33 33 pub timestamp: i64, 34 34 pub user_id: String, 35 35 } 36 + 37 + #[derive(Deserialize)] 38 + pub struct MessageReactData { 39 + pub channel_id: String, 40 + pub emoji: Emoji, 41 + pub guild_id: String, 42 + pub member: Member, 43 + pub message_id: String, 44 + pub user_id: String, 45 + }
+3 -1
fluxer-rs/src/gateway/dispatch_data/mod.rs
··· 1 1 pub mod guild; 2 2 pub mod message; 3 - pub mod types; 3 + pub mod types; 4 + pub mod basic; 5 + pub mod ready;
+88
fluxer-rs/src/gateway/dispatch_data/ready.rs
··· 1 + use serde::Deserialize; 2 + use serde_json::Value; 3 + 4 + #[derive(Deserialize)] 5 + pub struct ReadyData { 6 + pub country_code: String, 7 + pub favorite_memes: Vec<Value>, 8 + pub guilds: Vec<Value>, 9 + pub notes: Notes, 10 + pub pinned_dms: Vec<Value>, 11 + pub presences: Vec<Value>, 12 + pub private_channels: Vec<Value>, 13 + pub read_states: Vec<Value>, 14 + pub relationships: Vec<Value>, 15 + pub rtc_regions: Vec<RtcRegion>, 16 + pub session_id: String, 17 + pub sessions: Vec<Session>, 18 + pub user: LoggedInUser, 19 + pub user_guild_settings: Vec<Value>, 20 + pub user_settings: Value, 21 + pub users: Vec<Value>, 22 + pub version: i64, 23 + } 24 + 25 + #[derive(Deserialize)] 26 + pub struct Session { 27 + pub afk: bool, 28 + pub mobile: bool, 29 + pub session_id: String, 30 + pub status: String, 31 + } 32 + 33 + #[derive(Deserialize)] 34 + pub struct LoggedInUser { 35 + pub accent_color: Value, 36 + pub acls: Vec<Value>, 37 + pub authenticator_types: Vec<i64>, 38 + pub avatar: Value, 39 + pub avatar_color: Value, 40 + pub banner: Value, 41 + pub banner_color: Value, 42 + pub bio: Value, 43 + pub bot: bool, 44 + pub discriminator: String, 45 + pub email: Value, 46 + pub email_bounced: bool, 47 + pub flags: i64, 48 + pub global_name: Value, 49 + pub has_dismissed_premium_onboarding: bool, 50 + pub has_ever_purchased: bool, 51 + pub has_unread_gift_inventory: bool, 52 + pub id: String, 53 + pub is_staff: bool, 54 + pub mfa_enabled: bool, 55 + pub nsfw_allowed: bool, 56 + pub password_last_changed_at: Value, 57 + pub pending_bulk_message_deletion: Value, 58 + pub phone: Value, 59 + pub premium_badge_hidden: bool, 60 + pub premium_badge_masked: bool, 61 + pub premium_badge_sequence_hidden: bool, 62 + pub premium_badge_timestamp_hidden: bool, 63 + pub premium_billing_cycle: Value, 64 + pub premium_enabled_override: bool, 65 + pub premium_lifetime_sequence: Value, 66 + pub premium_purchase_disabled: bool, 67 + pub premium_since: Value, 68 + pub premium_type: i64, 69 + pub premium_until: Value, 70 + pub premium_will_cancel: bool, 71 + pub pronouns: Value, 72 + pub required_actions: Value, 73 + pub traits: Vec<Value>, 74 + pub unread_gift_inventory_count: i64, 75 + pub used_mobile_client: bool, 76 + pub username: String, 77 + pub verified: bool, 78 + } 79 + 80 + #[derive(Deserialize)] 81 + pub struct RtcRegion { 82 + pub emoji: String, 83 + pub id: String, 84 + pub name: String, 85 + } 86 + 87 + #[derive(Deserialize)] 88 + pub struct Notes {}
+8 -1
fluxer-rs/src/gateway/dispatch_data/types.rs
··· 49 49 } 50 50 51 51 #[derive(Deserialize)] 52 - pub struct Properties { 52 + pub struct GuildProperties { 53 53 pub afk_channel_id: Value, 54 54 pub afk_timeout: i64, 55 55 pub banner: Value, ··· 102 102 pub id: String, 103 103 pub username: String, 104 104 } 105 + 106 + #[derive(Deserialize)] 107 + pub struct Emoji { 108 + pub name: String, 109 + } 110 + 111 +
+52 -11
fluxer-rs/src/gateway/op_handlers/dispatch.rs
··· 1 1 use log::info; 2 2 3 + use crate::gateway::dispatch_data::basic::SessionReplaceData; 4 + use crate::gateway::dispatch_data::message::MessageReactData; 5 + use crate::gateway::dispatch_data::ready::ReadyData; 3 6 use crate::gateway::dispatch_data::{ 4 7 guild::{GuildCreateData, GuildDeleteData}, 5 8 message::{MessageEventData, TypingEventData}, 6 9 }; 7 10 8 11 pub enum DispatchEvent { 9 - Ready, 12 + Ready(ReadyData), 10 13 GuildDelete(GuildDeleteData), 11 14 GuildCreate(Box<GuildCreateData>), 12 15 MessageCreate(MessageEventData), 13 16 MessageDelete(MessageEventData), 17 + MessageUpdate(MessageEventData), 14 18 TypingStart(TypingEventData), 15 19 TypingStop(TypingEventData), 20 + ReactionAdd(MessageReactData), 21 + ReactionRemove(MessageReactData), 22 + SessionReplace(Vec<SessionReplaceData>), 16 23 } 17 24 18 25 pub trait DispatchHandlerTrait { 19 - fn handle_ready_dispatch(&self) { 20 - info!("-> [DISPATCH::READY]") 26 + fn handle_ready_dispatch(&self, data: ReadyData) { 27 + info!("-> [DISPATCH::READY] BOT_NAME: {}", data.user.username) 21 28 } 29 + 22 30 fn handle_guild_delete_dispatch(&self, data: GuildDeleteData) { 23 31 info!( 24 32 "-> [DISPATCH::GUILD_DELETE] ID: {}, Unavailable: {}", 25 33 data.guild_id, data.unavailable 26 34 ) 27 35 } 36 + 28 37 fn handle_guild_create_dispatch(&self, data: Box<GuildCreateData>) { 29 38 info!("-> [DISPATCH::GUILD_CREATE] ID: {}", data.id) 30 39 } 40 + 31 41 fn handle_message_create_dispatch(&self, data: MessageEventData) { 32 42 info!("-> [DISPATCH::MESSAGE_CREATE] CONTENT: {}", data.content) 33 43 } 44 + 34 45 fn handle_message_delete_dispatch(&self, data: MessageEventData) { 35 46 info!("-> [DISPATCH::MESSAGE_DELETE] CONTENT: {}", data.content) 36 47 } 48 + 49 + fn handle_message_update_dispatch(&self, data: MessageEventData) { 50 + info!("-> [DISPATCH::MESSAGE_UPDATE] CONTENT: {}", data.content) 51 + } 52 + 37 53 fn handle_typing_start_dispatch(&self, data: TypingEventData) { 38 54 info!( 39 55 "-> [DISPATCH::TYPING_START] GUILD: {}, CHANNEL: {}", 40 56 data.guild_id, data.channel_id 41 57 ) 42 58 } 59 + 43 60 fn handle_typing_stop_dispatch(&self, data: TypingEventData) { 44 61 info!( 45 62 "-> [DISPATCH::TYPING_STOP] GUILD: {}, CHANNEL: {}", 46 63 data.guild_id, data.channel_id 47 64 ) 48 65 } 66 + 67 + fn handle_message_reaction_add_dispatch(&self, data: MessageReactData) { 68 + info!( 69 + "-> [DISPATCH::MESSAGE_REACTION_ADD] MESSAGE: {}, EMOJI: {}", 70 + data.message_id, data.emoji.name 71 + ) 72 + } 73 + 74 + fn handle_message_reaction_remove_dispatch(&self, data: MessageReactData) { 75 + info!( 76 + "-> [DISPATCH::MESSAGE_REACTION_REMOVE] MESSAGE: {}, EMOJI: {}", 77 + data.message_id, data.emoji.name 78 + ) 79 + } 80 + 81 + fn handle_session_replace_dispatch(&self, _data: Vec<SessionReplaceData>) { 82 + info!("-> [DISPATCH::SESSION_REPLACE]",) 83 + } 49 84 } 50 85 51 86 #[derive(Default)] ··· 54 89 55 90 pub async fn handle_dispatch_events<T: DispatchHandlerTrait + Send + Sync + 'static>( 56 91 dispatch_event: Box<DispatchEvent>, 57 - dispatcher: &T, 92 + handler: &T, 58 93 ) { 59 94 match *dispatch_event { 60 - DispatchEvent::Ready => dispatcher.handle_ready_dispatch(), 61 - DispatchEvent::GuildDelete(data) => dispatcher.handle_guild_delete_dispatch(data), 62 - DispatchEvent::GuildCreate(data) => dispatcher.handle_guild_create_dispatch(data), 63 - DispatchEvent::MessageCreate(data) => dispatcher.handle_message_create_dispatch(data), 64 - DispatchEvent::MessageDelete(data) => dispatcher.handle_message_delete_dispatch(data), 65 - DispatchEvent::TypingStart(data) => dispatcher.handle_typing_start_dispatch(data), 66 - DispatchEvent::TypingStop(data) => dispatcher.handle_typing_stop_dispatch(data), 95 + DispatchEvent::Ready(data) => handler.handle_ready_dispatch(data), 96 + DispatchEvent::GuildDelete(data) => handler.handle_guild_delete_dispatch(data), 97 + DispatchEvent::GuildCreate(data) => handler.handle_guild_create_dispatch(data), 98 + DispatchEvent::MessageCreate(data) => handler.handle_message_create_dispatch(data), 99 + DispatchEvent::MessageDelete(data) => handler.handle_message_delete_dispatch(data), 100 + DispatchEvent::MessageUpdate(data) => handler.handle_message_update_dispatch(data), 101 + DispatchEvent::TypingStart(data) => handler.handle_typing_start_dispatch(data), 102 + DispatchEvent::TypingStop(data) => handler.handle_typing_stop_dispatch(data), 103 + DispatchEvent::ReactionAdd(data) => handler.handle_message_reaction_add_dispatch(data), 104 + DispatchEvent::ReactionRemove(data) => { 105 + handler.handle_message_reaction_remove_dispatch(data) 106 + } 107 + DispatchEvent::SessionReplace(data) => handler.handle_session_replace_dispatch(data), 67 108 } 68 109 }
+5 -33
fluxer-rs/src/gateway/op_handlers/heartbeat.rs
··· 1 1 use ezsockets::{Client, Utf8Bytes}; 2 2 use log::info; 3 3 4 - use crate::{ 5 - FluxerBot, 6 - gateway::{ 7 - op_handlers::dispatch::DispatchHandlerTrait, 8 - serde::send_serde::{OP2D, OP2DProps, SendData, SendDataType}, 9 - }, 4 + use crate::fluxerbot::FluxerBot; 5 + use crate::gateway::{ 6 + op_handlers::dispatch::DispatchHandlerTrait, 7 + serde::send_serde::{SendData, SendDataType}, 10 8 }; 11 9 12 10 pub async fn heartbeat_handler<T: DispatchHandlerTrait + Send + Sync + 'static>( ··· 28 26 29 27 pub async fn heartbeat_ack_handler<T: DispatchHandlerTrait + Send + Sync + 'static>( 30 28 text: Utf8Bytes, 31 - token: String, 32 - heartbeat_ack: bool, 33 - client_handle: &Client<FluxerBot<T>>, 34 - ) -> bool { 29 + ) { 35 30 info!("-> {} Heartbeat acknowledged", text); 36 - if !heartbeat_ack { 37 - let auth_string = serde_json::to_string(&SendData { 38 - d: SendDataType::OP2(OP2D { 39 - token, 40 - properties: OP2DProps { 41 - os: "Linux".to_string(), 42 - browser: "Fluxer-rs".to_string(), 43 - device: "x64".to_string(), 44 - }, 45 - }), 46 - op: 2, 47 - }) 48 - .unwrap(); 49 - 50 - match client_handle.text(auth_string) { 51 - Ok(_) => {} 52 - Err(err) => { 53 - panic!("{err}") 54 - } 55 - }; 56 - return true; 57 - } 58 - false 59 31 }
+25
fluxer-rs/src/gateway/op_handlers/identify.rs
··· 1 + use ezsockets::Client; 2 + use crate::fluxerbot::FluxerBot; 3 + use crate::gateway::op_handlers::dispatch::DispatchHandlerTrait; 4 + use crate::gateway::serde::send_serde::{OP2DProps, SendData, SendDataType, OP2D}; 5 + 6 + pub async fn auth_handler<T: DispatchHandlerTrait + Send + Sync + 'static> (token: String, client_handle: &Client<FluxerBot<T>>){ 7 + let auth_string = serde_json::to_string(&SendData { 8 + d: SendDataType::OP2(OP2D { 9 + token, 10 + properties: OP2DProps { 11 + os: "Linux".to_string(), 12 + browser: "Fluxer-rs".to_string(), 13 + device: "x64".to_string(), 14 + }, 15 + }), 16 + op: 2, 17 + }).unwrap(); 18 + 19 + match client_handle.text(auth_string) { 20 + Ok(_) => {} 21 + Err(err) => { 22 + panic!("{err}") 23 + } 24 + }; 25 + }
+2 -1
fluxer-rs/src/gateway/op_handlers/mod.rs
··· 1 1 pub mod heartbeat; 2 - pub mod dispatch; 2 + pub mod dispatch; 3 + pub mod identify;
+25 -1
fluxer-rs/src/gateway/serde/receive_serde.rs
··· 1 + use log::info; 1 2 use serde::{Deserialize, Serialize, de}; 2 3 use serde_json::Value; 3 4 5 + use crate::gateway::dispatch_data::basic::SessionReplaceData; 6 + use crate::gateway::dispatch_data::message::MessageReactData; 7 + use crate::gateway::dispatch_data::ready::ReadyData; 4 8 use crate::gateway::{ 5 9 dispatch_data::{ 6 10 guild::{GuildCreateData, GuildDeleteData}, ··· 17 21 pub enum ReceiveDataType { 18 22 OP0(Box<DispatchEvent>), 19 23 OP1(Option<u32>), 24 + OP9(bool), 20 25 OP10(OP10D), 21 26 OP11, 22 27 } ··· 36 41 let d = match op { 37 42 0 => { 38 43 let dispatch_event = match value["t"].as_str().unwrap() { 39 - "READY" => DispatchEvent::Ready, 44 + "READY" => DispatchEvent::Ready( 45 + ReadyData::deserialize(&value["d"]).map_err(de::Error::custom)?, 46 + ), 40 47 "GUILD_DELETE" => DispatchEvent::GuildDelete( 41 48 GuildDeleteData::deserialize(&value["d"]).map_err(de::Error::custom)?, 42 49 ), ··· 49 56 "MESSAGE_DELETE" => DispatchEvent::MessageDelete( 50 57 MessageEventData::deserialize(&value["d"]).map_err(de::Error::custom)?, 51 58 ), 59 + "MESSAGE_UPDATE" => DispatchEvent::MessageUpdate( 60 + MessageEventData::deserialize(&value["d"]).map_err(de::Error::custom)?, 61 + ), 52 62 "TYPING_START" => DispatchEvent::TypingStart( 53 63 TypingEventData::deserialize(&value["d"]).map_err(de::Error::custom)?, 54 64 ), 55 65 "TYPING_STOP" => DispatchEvent::TypingStop( 56 66 TypingEventData::deserialize(&value["d"]).map_err(de::Error::custom)?, 57 67 ), 68 + "MESSAGE_REACTION_ADD" => DispatchEvent::ReactionAdd( 69 + MessageReactData::deserialize(&value["d"]).map_err(de::Error::custom)?, 70 + ), 71 + "MESSAGE_REACTION_REMOVE" => DispatchEvent::ReactionRemove( 72 + MessageReactData::deserialize(&value["d"]).map_err(de::Error::custom)?, 73 + ), 74 + "SESSION_REPLACE" => DispatchEvent::SessionReplace( 75 + Vec::<SessionReplaceData>::deserialize(&value["d"]) 76 + .map_err(de::Error::custom)?, 77 + ), 58 78 _ => panic!("Unimplemented dispatch event: {}", value), 59 79 }; 60 80 ReceiveDataType::OP0(Box::new(dispatch_event)) ··· 63 83 let inner: Option<u32> = 64 84 Option::deserialize(&value["d"]).map_err(de::Error::custom)?; 65 85 ReceiveDataType::OP1(inner) 86 + } 87 + 9 => { 88 + let inner = bool::deserialize(&value["d"]).map_err(de::Error::custom)?; 89 + ReceiveDataType::OP9(inner) 66 90 } 67 91 10 => { 68 92 let inner = OP10D::deserialize(&value["d"]).map_err(de::Error::custom)?;
+2 -87
fluxer-rs/src/lib.rs
··· 1 - use async_trait::async_trait; 2 - use ezsockets::{Bytes, Client, ClientConfig, ClientExt, Utf8Bytes, connect}; 3 - use log::{error, info}; 4 - 5 - use crate::gateway::{ 6 - op_handlers::{ 7 - dispatch::{DispatchHandlerTrait, handle_dispatch_events}, 8 - heartbeat::{heartbeat_ack_handler, heartbeat_handler}, 9 - }, 10 - serde::receive_serde::{ReceiveData, ReceiveDataType}, 11 - }; 12 - 13 1 pub mod gateway; 14 - 15 - pub struct FluxerBot<T: DispatchHandlerTrait + Send + Sync + 'static> { 16 - pub token: String, 17 - pub endpoint: String, 18 - pub dispatch_handler: T, 19 - pub ws_handle: Client<FluxerBot<T>>, 20 - pub heartbeat_ack: bool, 21 - } 22 - 23 - impl<T: DispatchHandlerTrait + Send + Sync + 'static> FluxerBot<T> { 24 - pub async fn start(token: String, endpoint: String, dispatch_handler: T) { 25 - info!("Init the bot"); 26 - 27 - let config: ClientConfig = ClientConfig::new(endpoint.as_str()); 28 - 29 - info!("Starting websocket"); 30 - let (_, future) = connect( 31 - |ws_handle| FluxerBot { 32 - ws_handle, 33 - token, 34 - heartbeat_ack: false, 35 - dispatch_handler, 36 - endpoint, 37 - }, 38 - config, 39 - ) 40 - .await; 41 - let _ = future.await; 42 - } 43 - } 44 - 45 - impl<T> FluxerBot<T> where T: Send + Sync + DispatchHandlerTrait + 'static {} 46 - 47 - #[async_trait] 48 - impl<T: DispatchHandlerTrait + Send + Sync + 'static> ClientExt for FluxerBot<T> { 49 - type Call = (); 50 - 51 - async fn on_text(&mut self, text: Utf8Bytes) -> Result<(), ezsockets::Error> { 52 - let result: ReceiveData = match serde_json::from_slice(text.as_bytes()) { 53 - Ok(value) => value, 54 - Err(err) => { 55 - error!("Unhandled behavior: {err}"); 56 - error!("{}", text); 57 - panic!() 58 - } 59 - }; 60 - 61 - match result.d { 62 - ReceiveDataType::OP10(_data) => heartbeat_handler(text, &__self.ws_handle).await, 63 - ReceiveDataType::OP11 => { 64 - //TODO: Implement the check whether this is the first heartbeat a bit better 65 - self.heartbeat_ack = heartbeat_ack_handler( 66 - text, 67 - __self.token.clone(), 68 - __self.heartbeat_ack, 69 - &__self.ws_handle, 70 - ) 71 - .await 72 - } 73 - ReceiveDataType::OP1(_op1_d) => heartbeat_handler(text, &__self.ws_handle).await, 74 - ReceiveDataType::OP0(dispatch_event) => { 75 - handle_dispatch_events(dispatch_event, &self.dispatch_handler).await 76 - } 77 - } 78 - Ok(()) 79 - } 80 - 81 - async fn on_binary(&mut self, _bytes: Bytes) -> Result<(), ezsockets::Error> { 82 - Ok(()) 83 - } 84 - 85 - async fn on_call(&mut self, _call: Self::Call) -> Result<(), ezsockets::Error> { 86 - Ok(()) 87 - } 88 - } 2 + pub mod fluxerbot; 3 + pub mod api;
+2 -1
src/main.rs
··· 1 - use fluxer_rs::{FluxerBot, gateway::op_handlers::dispatch::DispatchHandler}; 1 + use fluxer_rs::fluxerbot::FluxerBot; 2 + use fluxer_rs::gateway::op_handlers::dispatch::DispatchHandler; 2 3 3 4 #[tokio::main] 4 5 async fn main() {