use std::any::Any;
use std::sync::Arc;
use crate::action::{ChatAction, ChatActionGuard, ChatActionSender};
#[cfg(not(target_arch = "wasm32"))]
pub trait ContextDataBounds: Send + Sync {}
#[cfg(not(target_arch = "wasm32"))]
impl<T: Send + Sync + ?Sized> ContextDataBounds for T {}
#[cfg(target_arch = "wasm32")]
pub trait ContextDataBounds {}
#[cfg(target_arch = "wasm32")]
impl<T: ?Sized> ContextDataBounds for T {}
#[derive(Clone)]
pub struct Context {
inner: Arc<dyn ContextData>,
}
impl Context {
pub fn new<T: ContextData>(data: T) -> Self {
Self {
inner: Arc::new(data),
}
}
pub fn channel_id(&self) -> &str {
self.inner.channel_id()
}
pub fn user_id(&self) -> &str {
self.inner.user_id()
}
pub fn user_name(&self) -> &str {
self.inner.user_name()
}
pub fn command_name(&self) -> Option<&str> {
self.inner.command_name()
}
pub fn command_args(&self) -> Option<&str> {
self.inner.command_args()
}
pub fn option(&self, name: &str) -> Option<OptionValue> {
self.inner.option(name)
}
pub fn button_id(&self) -> Option<&str> {
self.inner.button_id()
}
pub fn message_content(&self) -> Option<&str> {
self.inner.message_content()
}
pub fn platform<T: 'static>(&self) -> Option<&T> {
self.inner.as_any().downcast_ref::<T>()
}
pub fn data(&self) -> &dyn ContextData {
&*self.inner
}
pub fn typing(&self) -> Option<ChatActionGuard> {
self.send_action(ChatAction::Typing)
}
pub(crate) fn send_action(&self, action: ChatAction) -> Option<ChatActionGuard> {
let sender = self.inner.action_sender()?;
Some(ChatActionGuard::start(sender, action))
}
}
#[derive(Debug, Clone)]
pub enum OptionValue {
String(String),
Integer(i64),
Boolean(bool),
Number(f64),
}
impl OptionValue {
pub fn as_str(&self) -> Option<&str> {
match self {
Self::String(s) => Some(s),
_ => None,
}
}
pub fn as_i64(&self) -> Option<i64> {
match self {
Self::Integer(i) => Some(*i),
_ => None,
}
}
pub fn as_bool(&self) -> Option<bool> {
match self {
Self::Boolean(b) => Some(*b),
_ => None,
}
}
pub fn as_f64(&self) -> Option<f64> {
match self {
Self::Number(n) => Some(*n),
_ => None,
}
}
}
pub trait ContextData: ContextDataBounds + 'static {
fn channel_id(&self) -> &str;
fn user_id(&self) -> &str;
fn user_name(&self) -> &str;
fn command_name(&self) -> Option<&str>;
fn command_args(&self) -> Option<&str>;
fn option(&self, name: &str) -> Option<OptionValue>;
fn button_id(&self) -> Option<&str>;
fn message_content(&self) -> Option<&str>;
fn as_any(&self) -> &dyn Any;
fn action_sender(&self) -> Option<Box<dyn ChatActionSender>> {
None
}
}