diff --git a/Cargo.toml b/Cargo.toml index 7554e289..181ee42e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -starknet = "0.6.0" +starknet = { git = "https://github.com/xJonathanLEI/starknet-rs" } starknet-id = { git = "https://github.com/starknet-id/starknet-id.rs.git", branch = "master" } axum = "0.6.17" toml = "0.5.10" diff --git a/src/common/verify_has_root_or_braavos_domain.rs b/src/common/verify_has_root_or_braavos_domain.rs index 550d18ed..9d2f9e36 100644 --- a/src/common/verify_has_root_or_braavos_domain.rs +++ b/src/common/verify_has_root_or_braavos_domain.rs @@ -1,5 +1,4 @@ use std::{ - str::FromStr, sync::Arc, time::{SystemTime, UNIX_EPOCH}, }; diff --git a/src/models.rs b/src/models.rs index 9a7bac79..298f8160 100644 --- a/src/models.rs +++ b/src/models.rs @@ -38,6 +38,7 @@ pub_struct!(Debug, Serialize, Deserialize; QuestDocument { expiry_timestamp: Option, mandatory_domain: Option, expired: Option, + experience: i64, }); pub_struct!(Deserialize; CompletedTasks { @@ -97,7 +98,7 @@ pub_struct!(Debug, Serialize, Deserialize; AchievementDocument { done_title: String, done_desc: String, verify_type: String, - verify_endpoint: String, + experience:i64, }); pub_struct!(Debug, Serialize, Deserialize; AchievementCategoryDocument { @@ -118,7 +119,6 @@ pub struct UserAchievements { pub category_disabled: bool, achievements: Vec, } - pub fn default_category_disabled() -> bool { false } diff --git a/src/utils.rs b/src/utils.rs index 0d2df5df..e6498f05 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,3 +1,4 @@ +use futures::TryStreamExt; use crate::models::{AchievementDocument, AppState, CompletedTasks}; use async_trait::async_trait; use axum::{ @@ -17,6 +18,8 @@ use starknet::{ use std::fmt::Write; use std::result::Result; use std::str::FromStr; +use chrono::{Utc}; + #[macro_export] macro_rules! pub_struct { @@ -118,8 +121,129 @@ impl CompletedTasksTrait for AppState { let result = completed_tasks_collection .update_one(filter, update, options) - .await; - result + .await?; + + match &result.upserted_id { + Some(_id) => { + let pipeline = vec![ + doc! { + "$match": doc!{ + "address": addr.to_string(), + }, + }, + doc! { + "$lookup": doc! { + "from": "tasks", + "localField": "task_id", + "foreignField": "id", + "as": "associatedTask", + }, + }, + doc! { + "$unwind": "$associatedTask", + }, + doc! { + "$project": doc! { + "address": "$address", + "task_id": "$task_id", + "quest_id": "$associatedTask.quest_id", + }, + }, + doc! { + "$group": doc! { + "_id": "$quest_id", + "done": doc! { + "$sum": 1, + }, + }, + }, + doc! { + "$lookup": doc! { + "from": "tasks", + "localField": "_id", + "foreignField": "quest_id", + "as": "tasks", + }, + }, + doc! { + "$match": doc! { + "$expr": { + "$eq": [ + "$done", + { + "$size": "$tasks", + }, + ], + }, + }, + }, + doc! { + "$lookup": doc! { + "from": "quests", + "localField": "_id", + "foreignField": "id", + "as": "associatedQuests", + } + }, + doc! { + "$unwind": "$associatedQuests", + }, + doc! { + "$project": doc! { + "experience": "$associatedQuests.experience", + } + }, + doc! { + "$lookup": doc! { + "from": "tasks", + "localField": "_id", + "foreignField": "quest_id", + "as": "completedTasks", + }, + }, + doc! { + "$unwind": "$completedTasks", + }, + doc! { + "$match": { + "completedTasks.id": task_id, + }, + }, + doc! { + "$project": doc! { + "_id": 0, + "experience": 1, + }, + }, + ]; + match completed_tasks_collection.aggregate(pipeline, None).await { + Ok(mut cursor) => { + let mut experience = 0; + while let Some(response) = cursor.try_next().await.unwrap() { + experience = response.get("experience").unwrap().as_i32().unwrap(); + } + + // return result if experience is 0 (quest is not completed) + if experience == 0 { + return Ok(result); + } + + // save the user_exp document in the collection + let user_exp_collection = self.db.collection("user_exp"); + // add doc with address ,experience and timestamp + let timestamp = Utc::now().timestamp_millis(); + let document = doc! { "address": addr.to_string(), "experience":experience, "timestamp":timestamp}; + user_exp_collection.insert_one(document, None).await?; + } + Err(_e) => { + get_error("Error querying quests".to_string()); + } + } + } + None => {} + } + + Ok(result) } } @@ -162,8 +286,32 @@ impl AchievementsTrait for AppState { let result = achieved_collection .update_one(filter, update, options) - .await; - result + .await?; + + + match &result.upserted_id { + Some(_id) => { + // Check if the document was modified + let achievement_collection: Collection = self.db.collection("achievements"); + // Define a query using the `doc!` macro. + let query = doc! { "id": achievement_id }; + let mut experience: i32 = 0; + + let mut cursor = achievement_collection.find(query, None).await?; + // Iterate over the results. + while let Some(doc) = cursor.try_next().await? { + experience = doc.experience as i32; + } + + let user_exp_collection = self.db.collection("user_exp"); + // add doc with address ,experience and timestamp + let timestamp: f64 = Utc::now().timestamp_millis() as f64; + let document = doc! { "address": addr.to_string(), "experience":experience, "timestamp":timestamp}; + user_exp_collection.insert_one(document, None).await?; + } + None => {} + } + Ok(result) } async fn get_achievement(