csml_engine 1.11.2

The CSML Engine is a conversational engine designed to make it extremely easy to create rich and powerful chatbots.
Documentation
use crate::{
    encrypt::{decrypt_data, encrypt_data},
    EngineError, MongoDbClient,
};
use bson::{doc, Document};
use csml_interpreter::data::Client;

pub fn format_state_data(
    client: &Client,
    _type: &str,
    keys_values: Vec<(&str, &serde_json::Value)>,
    expires_at: Option<bson::DateTime>,
) -> Result<Vec<Document>, EngineError> {
    let client = bson::to_bson(client)?;

    keys_values.iter().fold(Ok(vec![]), |vec, (key, value)| {
        let time = bson::DateTime::from_chrono(chrono::Utc::now());

        let value = encrypt_data(value)?;
        let mut vec = vec?;

        vec.push(doc! {
            "client": client.clone(),
            "type": _type,
            "key": key,
            "value": value,
            "expires_at": expires_at,
            "created_at": time
        });
        Ok(vec)
    })
}

pub fn delete_state_key(
    client: &Client,
    _type: &str,
    key: &str,
    db: &MongoDbClient,
) -> Result<(), EngineError> {
    let state = db.client.collection::<Document>("state");

    let filter = doc! {
        "client": bson::to_bson(client)?,
        "type": _type,
        "key": key,
    };
    state.delete_one(filter, None)?;

    Ok(())
}

pub fn get_state_key(
    client: &Client,
    _type: &str,
    key: &str,
    db: &MongoDbClient,
) -> Result<Option<serde_json::Value>, EngineError> {
    let state = db.client.collection::<Document>("state");

    let filter = doc! {
        "client.bot_id": client.bot_id.to_owned(),
        "client.user_id": client.user_id.to_owned(),
        "client.channel_id": client.channel_id.to_owned(),
        "type": _type,
        "key": key,
    };

    match state.find_one(filter, None)? {
        Some(value) => {
            let state: serde_json::Value = bson::from_bson(bson::Bson::Document(value))?;
            let val = state["value"].as_str().unwrap().to_owned();
            Ok(Some(decrypt_data(val)?))
        }
        None => Ok(None),
    }
}

pub fn get_current_state(
    client: &Client,
    db: &MongoDbClient,
) -> Result<Option<serde_json::Value>, EngineError> {
    let state = db.client.collection::<Document>("state");

    let filter = doc! {
        "client.bot_id": client.bot_id.to_owned(),
        "client.user_id": client.user_id.to_owned(),
        "client.channel_id": client.channel_id.to_owned(),
        "type": "hold",
        "key": "position",
    };

    match state.find_one(filter, None)? {
        Some(doc) => {
            let state: serde_json::Value = bson::from_bson(bson::Bson::Document(doc))?;
            let value = state["value"].as_str().unwrap().to_owned();

            let current_state = serde_json::json!({
                "client": state["client"],
                "type": state["type"],
                "value": decrypt_data(value)?,
                "created_at": state["created_at"],
            });

            Ok(Some(current_state))
        }
        None => Ok(None),
    }
}

pub fn set_state_items(
    client: &Client,
    _type: &str,
    keys_values: Vec<(&str, &serde_json::Value)>,
    expires_at: Option<bson::DateTime>,
    db: &MongoDbClient,
) -> Result<(), EngineError> {
    if keys_values.len() == 0 {
        return Ok(());
    }

    let state_data = format_state_data(client, _type, keys_values, expires_at)?;
    let state = db.client.collection::<Document>("state");
    state.insert_many(state_data, None)?;

    Ok(())
}

pub fn delete_user_state(client: &Client, db: &MongoDbClient) -> Result<(), EngineError> {
    let collection = db.client.collection::<Document>("state");

    let filter = doc! {
        "client.bot_id": client.bot_id.to_owned(),
        "client.user_id": client.user_id.to_owned(),
        "client.channel_id": client.channel_id.to_owned(),
    };

    collection.delete_many(filter, None)?;

    Ok(())
}