Implement Observer for WebSocketEvents

This commit is contained in:
bitfl0wer 2023-04-28 12:31:59 +02:00
parent caafb9a620
commit 3099a0165b
2 changed files with 92 additions and 21 deletions

View File

@ -10,6 +10,8 @@ use serde::{Deserialize, Serialize};
use crate::{api::limits::Limits, URLBundle};
pub trait WebSocketEvent {}
#[derive(Debug, Serialize, Deserialize)]
pub struct LoginResult {
token: String,
@ -246,6 +248,8 @@ struct MessageCreate {
mentions: Vec<(UserObject, GuildMember)>, // Not sure if this is correct: https://discord.com/developers/docs/topics/gateway-events#message-create
}
impl WebSocketEvent for MessageCreate {}
#[derive(Debug, Serialize, Deserialize)]
struct PartialMessage {
id: Option<String>,
@ -293,6 +297,8 @@ struct MessageUpdate {
mentions: Vec<(UserObject, GuildMember)>, // Not sure if this is correct: https://discord.com/developers/docs/topics/gateway-events#message-create
}
impl WebSocketEvent for MessageUpdate {}
#[derive(Debug, Serialize, Deserialize)]
struct MessageDelete {
id: String,
@ -300,6 +306,8 @@ struct MessageDelete {
guild_id: Option<String>,
}
impl WebSocketEvent for MessageDelete {}
#[derive(Debug, Serialize, Deserialize)]
struct MessageDeleteBulk {
ids: Vec<String>,
@ -307,6 +315,8 @@ struct MessageDeleteBulk {
guild_id: Option<String>,
}
impl WebSocketEvent for MessageDeleteBulk {}
#[derive(Debug, Serialize, Deserialize)]
struct MessageReactionAdd {
user_id: String,
@ -317,6 +327,8 @@ struct MessageReactionAdd {
emoji: Emoji,
}
impl WebSocketEvent for MessageReactionAdd {}
#[derive(Debug, Serialize, Deserialize)]
struct MessageReactionRemove {
user_id: String,
@ -326,6 +338,8 @@ struct MessageReactionRemove {
emoji: Emoji,
}
impl WebSocketEvent for MessageReactionRemove {}
#[derive(Debug, Serialize, Deserialize)]
struct MessageReactionRemoveAll {
channel_id: String,
@ -333,6 +347,8 @@ struct MessageReactionRemoveAll {
guild_id: Option<String>,
}
impl WebSocketEvent for MessageReactionRemoveAll {}
#[derive(Debug, Serialize, Deserialize)]
struct MessageReactionRemoveEmoji {
channel_id: String,
@ -341,6 +357,8 @@ struct MessageReactionRemoveEmoji {
emoji: Emoji,
}
impl WebSocketEvent for MessageReactionRemoveEmoji {}
#[derive(Debug, Serialize, Deserialize)]
struct ChannelMention {
id: String,
@ -689,6 +707,8 @@ struct TypingStartEvent {
member: Option<GuildMember>,
}
impl WebSocketEvent for TypingStartEvent {}
#[derive(Debug, Deserialize, Serialize)]
struct GatewayIdentifyPayload {
token: String,
@ -700,6 +720,8 @@ struct GatewayIdentifyPayload {
intents: i32,
}
impl WebSocketEvent for GatewayIdentifyPayload {}
#[derive(Debug, Deserialize, Serialize)]
struct GatewayIdentifyConnectionProps {
os: String,
@ -715,6 +737,8 @@ struct PresenceUpdate {
afk: bool,
}
impl WebSocketEvent for PresenceUpdate {}
#[derive(Debug, Deserialize, Serialize)]
struct Activity {
name: String,
@ -770,8 +794,10 @@ struct ActivityButton {
}
#[derive(Debug, Deserialize, Serialize)]
struct GatewayResume {
token: String,
session_id: String,
seq: String,
pub(crate) struct GatewayResume {
pub(crate) token: String,
pub(crate) session_id: String,
pub(crate) seq: String,
}
impl WebSocketEvent for GatewayResume {}

View File

@ -1,24 +1,24 @@
use crate::errors::ObserverError;
use crate::{api::WebSocketEvent, errors::ObserverError};
#[derive(Debug)]
pub struct Gateway {}
pub trait Observer {
fn update(&self, data: &str);
pub trait Observer<T: WebSocketEvent> {
fn update(&self, data: &T);
}
pub struct GatewayEvent<'a> {
observers: Vec<&'a dyn Observer>,
pub test_content: String,
pub struct GatewayEvent<'a, T: WebSocketEvent> {
observers: Vec<&'a dyn Observer<T>>,
pub event_data: T,
pub is_observed: bool,
}
impl<'a> GatewayEvent<'a> {
fn new(test_content: String) -> Self {
impl<'a, T: WebSocketEvent> GatewayEvent<'a, T> {
fn new(event_data: T) -> Self {
Self {
is_observed: false,
observers: Vec::new(),
test_content,
event_data,
}
}
@ -26,7 +26,7 @@ impl<'a> GatewayEvent<'a> {
self.is_observed
}
pub fn subscribe(&mut self, observable: &'a dyn Observer) -> Option<ObserverError> {
pub fn subscribe(&mut self, observable: &'a dyn Observer<T>) -> Option<ObserverError> {
if self.is_observed {
return Some(ObserverError::AlreadySubscribedError);
}
@ -35,20 +35,65 @@ impl<'a> GatewayEvent<'a> {
None
}
pub fn unsubscribe(&mut self, observable: &'a dyn Observer) {
self.observers.pop();
self.is_observed = false;
pub fn unsubscribe(&mut self, observable: &'a dyn Observer<T>) {
// .retain()'s closure retains only those elements of the vector, which have a different
// pointer value than observable.
self.observers.retain(|obs| !std::ptr::eq(*obs, observable));
self.is_observed = !self.observers.is_empty();
return;
}
fn update_data(&mut self, test_content: String) {
self.test_content = test_content;
fn update_data(&mut self, new_event_data: T) {
self.event_data = new_event_data;
self.notify();
}
fn notify(&self) {
for observer in &self.observers {
observer.update(&self.test_content);
observer.update(&self.event_data);
}
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::api::types::GatewayResume;
struct Consumer;
impl Observer<GatewayResume> for Consumer {
fn update(&self, data: &GatewayResume) {
println!("{}", data.token)
}
}
#[test]
fn test_observer_behaviour() {
let mut event = GatewayEvent::new(GatewayResume {
token: "start".to_string(),
session_id: "start".to_string(),
seq: "start".to_string(),
});
let new_data = GatewayResume {
token: "token_3276ha37am3".to_string(),
session_id: "89346671230".to_string(),
seq: "3".to_string(),
};
let consumer = Consumer;
event.subscribe(&consumer);
event.notify();
event.update_data(new_data);
let second_consumer = Consumer;
match event.subscribe(&second_consumer) {
None => return,
Some(err) => println!("You cannot subscribe twice: {}", err),
}
}
}