zero4rs 2.0.0

zero4rs is a powerful, pragmatic, and extremely fast web framework for Rust
Documentation
use lazy_static::lazy_static;

pub mod comments;
pub mod models;

pub use comments::*;

use mongodb::bson::doc;
use mongodb::bson::oid::ObjectId;

use crate::core::auth0::UserDetails;
use crate::core::auth0::UserId;
use crate::core::mongo;

use crate::commons::timestamp_millis;

use self::models::FetchFeeds;
use self::models::UserFeeds;
use self::models::UserFeedsSave;
use self::models::UserFeedsVo;

use crate::core::error2::Error;
use crate::core::error2::Result;

lazy_static! {
    pub static ref FEEDS_DB: &'static str = "feeds_db";
    pub static ref FEEDS_COL: &'static str = "t_user_feeds";
}

pub async fn save_feeds(
    client: &mongo::MongoClient,
    record: models::FeedsCreateFormData,
    _user_id: UserId,
    curr_user: &UserDetails,
) -> Result<String> {
    let user_feeds_record = UserFeedsSave::from(&record, curr_user);

    client
        .insert_one(*FEEDS_DB, *FEEDS_COL, user_feeds_record)
        .await
        .map_err(Error::run_time)
}

pub async fn query_feeds_count(client: &mongo::MongoClient) -> Result<u64> {
    let count = client.count(*FEEDS_DB, *FEEDS_COL).await?;

    Ok(count)
}

pub async fn select_feeds(
    client: &mongo::MongoClient,
    input: FetchFeeds,
) -> Result<Vec<UserFeedsVo>> {
    let _filter = doc! {};
    let _sort = doc! {"created_at": -1};

    let list = client
        .select::<UserFeeds>(
            *FEEDS_DB,
            *FEEDS_COL,
            _filter,
            _sort,
            (input.skip.unwrap_or(0), input.limit.unwrap_or(15)),
        )
        .await?
        .into_iter()
        .map(|r| UserFeedsVo::from(&r))
        .collect();

    Ok(list)
}

pub async fn feeds_thumb_ups_count(client: &mongo::MongoClient, feed_id: &str) -> Result<i32> {
    let pipeline = vec![
        doc! { "$match": { "_id": ObjectId::parse_str(feed_id).unwrap() } },
        doc! { "$unwind": "$thumb_ups" },
        doc! {
            "$group": {
                "_id": "$_id",
                "_cnt": { "$sum": 1 }
            }
        },
    ];

    let result = client.pipeline(*FEEDS_DB, *FEEDS_COL, pipeline).await?;

    if !result.is_empty() {
        Ok(result[0].1)
    } else {
        Ok(0)
    }
}

// 点赞
pub async fn feeds_thumb_up(
    client: &mongo::MongoClient,
    feed_id: &str,
    user_id: UserId,
) -> Result<i32> {
    if let Ok(result) = feeds_thumb_up_exists(client, feed_id, &user_id.0).await {
        if result {
            // 取消点赞
            let _pull_update = doc! { "$pull": { "thumb_ups": { "user_id": &user_id.0 } }};

            let _ = client
                .update_one(*FEEDS_DB, *FEEDS_COL, feed_id, _pull_update)
                .await?;

            return feeds_thumb_ups_count(client, feed_id).await;
        }
    }

    let _push_update = doc! { "$push": { "thumb_ups": { "user_id": &user_id.0, "created_time": timestamp_millis() } }};

    let _ = client
        .update_one(*FEEDS_DB, *FEEDS_COL, feed_id, _push_update)
        .await?;

    feeds_thumb_ups_count(client, feed_id).await
}

// 查询指定用户是否点赞过
pub async fn feeds_thumb_up_exists(
    client: &mongo::MongoClient,
    feed_id: &str,
    user_id: &str,
) -> Result<bool> {
    let filter = doc! {
      "_id": ObjectId::parse_str(feed_id).unwrap(),
      "thumb_ups": {
        "$elemMatch": {
          "user_id": user_id
        }
      },
      "thumb_ups.user_id": {
        "$exists": true
      }
    };

    let options = doc! {
      "_id": 0,
      "thumb_ups.$": 1
    };

    client
        .exists_by_sub_match(*FEEDS_DB, *FEEDS_COL, filter, options)
        .await
        .map_err(Error::run_time)
}