botx_api_framework/handlers/
internal_bot_notification.rs

1use std::{any::{Any, TypeId}, marker::PhantomData, ops::Deref};
2
3use anthill_di::{*, types::BuildDependencyResult};
4use serde::Deserialize;
5
6use crate::{contexts::RequestContext, results::CommandResult};
7
8pub struct InternalBotNotificationHandlerTypeId(pub TypeId);
9
10impl Deref for InternalBotNotificationHandlerTypeId {
11    type Target = TypeId;
12
13    fn deref(&self) -> &Self::Target { &self.0 }
14}
15
16#[async_trait_with_sync::async_trait]
17pub trait IInternalBotNotificationHandler: Send + Sync {
18    type TData: Sync + Send + for<'de> Deserialize<'de> + 'static;
19    type TOptions: Sync + Send + for<'de> Deserialize<'de> + 'static;
20
21    async fn handle(&mut self, data: Self::TData, options: Self::TOptions, request_context: RequestContext) -> CommandResult;
22}
23
24pub trait IInternalBotNotificationDataProcessor: Sync + Send {
25    fn get_data(&self, data: &serde_json::Value) -> Option<Box<dyn Any + Sync + Send>>;
26    fn get_options(&self, options: &serde_json::Value) -> Option<Box<dyn Any + Sync + Send>>;
27    fn get_handler_type_id(&self) -> InternalBotNotificationHandlerTypeId;
28}
29
30/// Десериализует данные и если удалось возвращает не типизированную ссылку на данные
31pub struct InternalBotNotificationDataProcessor<THandler: IInternalBotNotificationHandler + 'static> {
32    handler_pd: PhantomData<THandler>
33}
34
35impl<THandler: IInternalBotNotificationHandler + 'static> IInternalBotNotificationDataProcessor for InternalBotNotificationDataProcessor<THandler> {
36    fn get_data(&self, data: &serde_json::Value) -> Option<Box<dyn Any + Sync + Send>> {
37        serde_json::value::from_value::<THandler::TData>(data.clone())
38            .map(|x| Box::new(x) as Box<dyn Any + Sync + Send>)
39            .ok()
40    }
41
42    fn get_options(&self, options: &serde_json::Value) -> Option<Box<dyn Any + Sync + Send>> {
43        serde_json::value::from_value::<THandler::TOptions>(options.clone())
44            .map(|x| Box::new(x) as Box<dyn Any + Sync + Send>)
45            .ok()
46    }
47
48    fn get_handler_type_id(&self) -> InternalBotNotificationHandlerTypeId {
49        InternalBotNotificationHandlerTypeId(TypeId::of::<THandler>())
50    }
51}
52
53#[async_trait_with_sync::async_trait(Sync)]
54impl<THandler: IInternalBotNotificationHandler + 'static> Constructor for InternalBotNotificationDataProcessor<THandler> {
55    async fn ctor(_: DependencyContext) -> BuildDependencyResult<Self> {
56        Ok(Self { handler_pd: Default::default() })
57    }
58}
59
60/// Возвращает тип данным и вызывает обработчик
61#[async_trait_with_sync::async_trait]
62pub trait IInternalBotNotificationCallProducer: Send + Sync {
63    async fn handle(&mut self, data: Box<dyn Any + Sync + Send>, options: Box<dyn Any + Sync + Send>, request_context: RequestContext) -> CommandResult;
64}
65
66#[async_trait_with_sync::async_trait]
67impl<T: IInternalBotNotificationHandler + 'static> IInternalBotNotificationCallProducer for T
68{
69    async fn handle(&mut self, data: Box<dyn Any + Sync + Send>, options: Box<dyn Any + Sync + Send>, request_context: RequestContext) -> CommandResult {
70        let data = unsafe {
71            *data.downcast_unchecked::<T::TData>()
72        };
73
74        let options = unsafe {
75            *options.downcast_unchecked::<T::TOptions>()
76        };
77
78        T::handle(self, data, options, request_context).await
79    }
80}