1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
use crate::{
    session::{namespace_from_update, Session},
    store::SessionStore,
};
use carapax::prelude::*;
use std::sync::Arc;

/// A session handler for carapax
///
/// This handler sets Session to context,
/// so you can use it in your handlers:
///
/// ```
/// # #[cfg(feature = "redis-store")]
/// # mod session_example {
/// use carapax::prelude::*;
/// use carapax_session::{store::redis::RedisSessionStore, Session};
///
/// fn handler(context: &mut Context, message: &Message) -> HandlerFuture {
///     let session = context.get::<Session<RedisSessionStore>>();
///     // do something with session...
///     HandlerResult::Continue.into()
/// }
/// # }
/// # fn main() {}
/// ```
pub struct SessionHandler<S> {
    store: Arc<S>,
}

impl<S> SessionHandler<S>
where
    S: SessionStore,
{
    /// Creates a new handler with given store
    pub fn new(store: S) -> Self {
        Self { store: Arc::new(store) }
    }
}

impl<S> Handler for SessionHandler<S>
where
    S: SessionStore + Send + Sync + 'static,
{
    type Input = Update;
    type Output = ();

    fn handle(&self, context: &mut Context, update: Self::Input) -> Self::Output {
        let namespace = namespace_from_update(&update);
        context.set(Session::new(namespace, self.store.clone()));
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::SessionKey;
    use failure::Error;
    use futures::Future;
    use serde::{de::DeserializeOwned, Serialize};

    struct Store;

    impl SessionStore for Store {
        fn get<O>(&self, _key: SessionKey) -> Box<dyn Future<Item = Option<O>, Error = Error> + Send>
        where
            O: DeserializeOwned + Send + 'static,
        {
            unimplemented!()
        }

        fn set<I>(&self, _key: SessionKey, _val: &I) -> Box<dyn Future<Item = (), Error = Error> + Send>
        where
            I: Serialize,
        {
            unimplemented!()
        }

        fn expire(&self, _key: SessionKey, _seconds: usize) -> Box<dyn Future<Item = (), Error = Error> + Send> {
            unimplemented!()
        }

        fn del(&self, _key: SessionKey) -> Box<dyn Future<Item = (), Error = Error> + Send> {
            unimplemented!()
        }
    }

    #[test]
    fn handler() {
        let mut context = Context::default();
        let update: Update = serde_json::from_value(serde_json::json!(
            {
                "update_id": 1,
                "message": {
                    "message_id": 1,
                    "date": 0,
                    "from": {"id": 1, "is_bot": false, "first_name": "test", "username": "username1"},
                    "chat": {"id": 1, "type": "private", "first_name": "test", "username": "username1"},
                    "text": "test middleware"
                }
            }
        ))
        .unwrap();
        let handler = SessionHandler::new(Store);
        handler.handle(&mut context, update);
        assert!(context.get_opt::<Session<Store>>().is_some());
    }
}