Implement Observer for WebSocketEvents
This commit is contained in:
parent
8f97b48a09
commit
50b6029f54
|
@ -2,7 +2,7 @@
|
||||||
To learn more about the types implemented here, please visit
|
To learn more about the types implemented here, please visit
|
||||||
https://discord.com/developers/docs .
|
https://discord.com/developers/docs .
|
||||||
I do not feel like re-documenting all of this, as everything is already perfectly explained there.
|
I do not feel like re-documenting all of this, as everything is already perfectly explained there.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
@ -10,6 +10,8 @@ use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{api::limits::Limits, URLBundle};
|
use crate::{api::limits::Limits, URLBundle};
|
||||||
|
|
||||||
|
pub trait WebSocketEvent {}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct LoginResult {
|
pub struct LoginResult {
|
||||||
token: String,
|
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
|
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)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
struct PartialMessage {
|
struct PartialMessage {
|
||||||
id: Option<String>,
|
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
|
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)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
struct MessageDelete {
|
struct MessageDelete {
|
||||||
id: String,
|
id: String,
|
||||||
|
@ -300,6 +306,8 @@ struct MessageDelete {
|
||||||
guild_id: Option<String>,
|
guild_id: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl WebSocketEvent for MessageDelete {}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
struct MessageDeleteBulk {
|
struct MessageDeleteBulk {
|
||||||
ids: Vec<String>,
|
ids: Vec<String>,
|
||||||
|
@ -307,6 +315,8 @@ struct MessageDeleteBulk {
|
||||||
guild_id: Option<String>,
|
guild_id: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl WebSocketEvent for MessageDeleteBulk {}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
struct MessageReactionAdd {
|
struct MessageReactionAdd {
|
||||||
user_id: String,
|
user_id: String,
|
||||||
|
@ -317,6 +327,8 @@ struct MessageReactionAdd {
|
||||||
emoji: Emoji,
|
emoji: Emoji,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl WebSocketEvent for MessageReactionAdd {}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
struct MessageReactionRemove {
|
struct MessageReactionRemove {
|
||||||
user_id: String,
|
user_id: String,
|
||||||
|
@ -326,6 +338,8 @@ struct MessageReactionRemove {
|
||||||
emoji: Emoji,
|
emoji: Emoji,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl WebSocketEvent for MessageReactionRemove {}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
struct MessageReactionRemoveAll {
|
struct MessageReactionRemoveAll {
|
||||||
channel_id: String,
|
channel_id: String,
|
||||||
|
@ -333,6 +347,8 @@ struct MessageReactionRemoveAll {
|
||||||
guild_id: Option<String>,
|
guild_id: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl WebSocketEvent for MessageReactionRemoveAll {}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
struct MessageReactionRemoveEmoji {
|
struct MessageReactionRemoveEmoji {
|
||||||
channel_id: String,
|
channel_id: String,
|
||||||
|
@ -341,6 +357,8 @@ struct MessageReactionRemoveEmoji {
|
||||||
emoji: Emoji,
|
emoji: Emoji,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl WebSocketEvent for MessageReactionRemoveEmoji {}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
struct ChannelMention {
|
struct ChannelMention {
|
||||||
id: String,
|
id: String,
|
||||||
|
@ -689,6 +707,8 @@ struct TypingStartEvent {
|
||||||
member: Option<GuildMember>,
|
member: Option<GuildMember>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl WebSocketEvent for TypingStartEvent {}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
struct GatewayIdentifyPayload {
|
struct GatewayIdentifyPayload {
|
||||||
token: String,
|
token: String,
|
||||||
|
@ -700,6 +720,8 @@ struct GatewayIdentifyPayload {
|
||||||
intents: i32,
|
intents: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl WebSocketEvent for GatewayIdentifyPayload {}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
struct GatewayIdentifyConnectionProps {
|
struct GatewayIdentifyConnectionProps {
|
||||||
os: String,
|
os: String,
|
||||||
|
@ -715,6 +737,8 @@ struct PresenceUpdate {
|
||||||
afk: bool,
|
afk: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl WebSocketEvent for PresenceUpdate {}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
struct Activity {
|
struct Activity {
|
||||||
name: String,
|
name: String,
|
||||||
|
@ -770,8 +794,10 @@ struct ActivityButton {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
struct GatewayResume {
|
pub(crate) struct GatewayResume {
|
||||||
token: String,
|
pub(crate) token: String,
|
||||||
session_id: String,
|
pub(crate) session_id: String,
|
||||||
seq: String,
|
pub(crate) seq: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl WebSocketEvent for GatewayResume {}
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
use crate::errors::ObserverError;
|
use crate::{api::WebSocketEvent, errors::ObserverError};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Gateway {}
|
pub struct Gateway {}
|
||||||
|
|
||||||
pub trait Observer {
|
pub trait Observer<T: WebSocketEvent> {
|
||||||
fn update(&self, data: &str);
|
fn update(&self, data: &T);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct GatewayEvent<'a> {
|
pub struct GatewayEvent<'a, T: WebSocketEvent> {
|
||||||
observers: Vec<&'a dyn Observer>,
|
observers: Vec<&'a dyn Observer<T>>,
|
||||||
pub test_content: String,
|
pub event_data: T,
|
||||||
pub is_observed: bool,
|
pub is_observed: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> GatewayEvent<'a> {
|
impl<'a, T: WebSocketEvent> GatewayEvent<'a, T> {
|
||||||
fn new(test_content: String) -> Self {
|
fn new(event_data: T) -> Self {
|
||||||
Self {
|
Self {
|
||||||
is_observed: false,
|
is_observed: false,
|
||||||
observers: Vec::new(),
|
observers: Vec::new(),
|
||||||
test_content,
|
event_data,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ impl<'a> GatewayEvent<'a> {
|
||||||
self.is_observed
|
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 {
|
if self.is_observed {
|
||||||
return Some(ObserverError::AlreadySubscribedError);
|
return Some(ObserverError::AlreadySubscribedError);
|
||||||
}
|
}
|
||||||
|
@ -35,20 +35,65 @@ impl<'a> GatewayEvent<'a> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unsubscribe(&mut self, observable: &'a dyn Observer) {
|
pub fn unsubscribe(&mut self, observable: &'a dyn Observer<T>) {
|
||||||
self.observers.pop();
|
// .retain()'s closure retains only those elements of the vector, which have a different
|
||||||
self.is_observed = false;
|
// pointer value than observable.
|
||||||
|
self.observers.retain(|obs| !std::ptr::eq(*obs, observable));
|
||||||
|
self.is_observed = !self.observers.is_empty();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_data(&mut self, test_content: String) {
|
fn update_data(&mut self, new_event_data: T) {
|
||||||
self.test_content = test_content;
|
self.event_data = new_event_data;
|
||||||
self.notify();
|
self.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn notify(&self) {
|
fn notify(&self) {
|
||||||
for observer in &self.observers {
|
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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue