Skip to content

Commit

Permalink
Merge pull request #332 from SYLVIANNORUKA/fix-325
Browse files Browse the repository at this point in the history
Fix: Implement get_quest_participants admin route
  • Loading branch information
Marchand-Nicolas authored Nov 29, 2024
2 parents e9a4d32 + 36a612b commit 80ee4f4
Show file tree
Hide file tree
Showing 19 changed files with 129 additions and 20 deletions.
101 changes: 101 additions & 0 deletions src/endpoints/admin/quest/get_quest_participants.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
use std::sync::Arc;

use axum::{
extract::{Extension, Query, State},
http::StatusCode,
response::{IntoResponse, Json},
};
use axum_auto_routes::route;
use futures::StreamExt;
use mongodb::bson::doc;
use serde::Deserialize;
use serde_json::json;
use starknet::core::types::FieldElement;

use crate::{middleware::auth::auth_middleware, utils::to_hex};
use crate::{
models::{AppState, CompletedTaskDocument, QuestTaskDocument},
utils::get_error,
};

pub_struct!(Deserialize; GetQuestParticipantsParams {
quest_id: i64,
});

#[route(get, "/admin/quests/get_quest_participants", auth_middleware)]
pub async fn get_quest_participants_handler(
State(state): State<Arc<AppState>>,
Extension(_sub): Extension<String>,
Query(params): Query<GetQuestParticipantsParams>,
) -> impl IntoResponse {
let tasks_collection = state.db.collection::<QuestTaskDocument>("tasks");
let completed_tasks_collection = state
.db
.collection::<CompletedTaskDocument>("completed_tasks");

// Fetch all task IDs for the given quest_id
let task_filter = doc! { "quest_id": params.quest_id };
let task_ids: Vec<i32> = match tasks_collection.find(task_filter, None).await {
Ok(mut cursor) => {
let mut ids = Vec::new();
while let Some(doc) = cursor.next().await {
match doc {
Ok(task) => ids.push(task.id),
Err(e) => return get_error(format!("Error processing tasks: {}", e)),
}
}
ids
}
Err(e) => return get_error(format!("Error fetching tasks: {}", e)),
};

if task_ids.is_empty() {
return get_error(format!("No tasks found for quest_id {}", params.quest_id));
}

// Use aggregation pipeline to fetch completed tasks and group by address
let pipeline = vec![
doc! { "$match": { "task_id": { "$in": &task_ids } } },
doc! { "$group": {
"_id": "$address",
"task_ids": { "$addToSet": "$task_id" }
}},
doc! { "$project": {
"address": "$_id",
"tasks_completed_count": { "$size": "$task_ids" }
}},
];

let mut cursor = match completed_tasks_collection.aggregate(pipeline, None).await {
Ok(cursor) => cursor,
Err(e) => return get_error(format!("Error aggregating completed tasks: {}", e)),
};

let total_tasks = task_ids.len();
let mut participants = Vec::new();

while let Some(doc) = cursor.next().await {
match doc {
Ok(doc) => {
// Get the decimal address and convert it to a hex string
let address: String = match doc.get_str("address") {
Ok(addr) => to_hex(FieldElement::from_dec_str(addr).unwrap()),
Err(_) => continue, // Skip invalid documents
};

let tasks_completed_count: usize = match doc.get_i32("tasks_completed_count") {
Ok(count) => count as usize,
Err(_) => continue, // Skip invalid documents
};

if tasks_completed_count == total_tasks {
participants.push(address);
}
}
Err(e) => return get_error(format!("Error processing aggregation results: {}", e)),
}
}

let participants_json = json!({ "participants": participants });
(StatusCode::OK, Json(participants_json)).into_response()
}
1 change: 1 addition & 0 deletions src/endpoints/admin/quest/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pub mod create_quest;
mod get_quest;
pub mod get_quest_participants;
pub mod get_quests;
pub mod get_tasks;
pub mod update_quest;
3 changes: 2 additions & 1 deletion src/endpoints/admin/quiz/create_question.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ pub async fn handler(

let mut state_last_id = state.last_question_id.lock().await;

let next_quiz_question_id = get_next_question_id(&quiz_questions_collection, state_last_id.clone()).await;
let next_quiz_question_id =
get_next_question_id(&quiz_questions_collection, state_last_id.clone()).await;

*state_last_id = next_quiz_question_id;

Expand Down
7 changes: 5 additions & 2 deletions src/endpoints/admin/quiz/delete_question.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,15 @@ pub async fn handler(
"id": &body.id,
};

return match quiz_questions_collection.delete_one(question_filter, None).await {
return match quiz_questions_collection
.delete_one(question_filter, None)
.await
{
Ok(_) => (
StatusCode::OK,
Json(json!({"message": "deleted successfully"})),
)
.into_response(),
Err(_e) => get_error("error deleting question".to_string()),
};
}
}
2 changes: 1 addition & 1 deletion src/endpoints/admin/quiz/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pub mod create_question;
pub mod create_quiz;
pub mod delete_question;
pub mod get_quiz;
pub mod update_question;
pub mod update_quiz;
pub mod delete_question;
2 changes: 1 addition & 1 deletion src/endpoints/defi/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1 @@
pub mod rewards;
pub mod rewards;
2 changes: 1 addition & 1 deletion src/endpoints/get_boosted_quests.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use crate::{models::AppState, utils::get_error};
use axum::{extract::State, response::IntoResponse, Json};

use axum::http::StatusCode;
use axum_auto_routes::route;
use futures::TryStreamExt;
use mongodb::bson::{doc, Document};
use axum::http::StatusCode;
use std::sync::Arc;

#[route(get, "/get_boosted_quests")]
Expand Down
2 changes: 1 addition & 1 deletion src/endpoints/get_completed_quests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ use axum::{
Json,
};

use axum::http::StatusCode;
use axum_auto_routes::route;
use futures::TryStreamExt;
use mongodb::bson::{doc, Document};
use axum::http::StatusCode;
use serde::{Deserialize, Serialize};
use starknet::core::types::FieldElement;
use std::sync::Arc;
Expand Down
2 changes: 1 addition & 1 deletion src/endpoints/get_quest_participants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ use axum::{
Json,
};

use axum::http::StatusCode;
use axum_auto_routes::route;
use futures::StreamExt;
use mongodb::bson::{doc, Document};
use axum::http::StatusCode;
use serde::{Deserialize, Serialize};
use std::sync::Arc;

Expand Down
2 changes: 1 addition & 1 deletion src/endpoints/get_trending_quests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::{
models::{AppState, QuestDocument},
utils::get_error,
};
use axum::http::StatusCode;
use axum::{
extract::{Query, State},
response::IntoResponse,
Expand All @@ -10,7 +11,6 @@ use axum::{
use axum_auto_routes::route;
use futures::StreamExt;
use mongodb::bson::{doc, from_document};
use axum::http::StatusCode;
use serde::{Deserialize, Serialize};
use starknet::core::types::FieldElement;
use std::sync::Arc;
Expand Down
2 changes: 1 addition & 1 deletion src/endpoints/has_completed_quest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ use axum::{
Json,
};

use axum::http::StatusCode;
use axum_auto_routes::route;
use futures::TryStreamExt;
use mongodb::bson::{doc, Document};
use axum::http::StatusCode;
use serde::{Deserialize, Serialize};
use starknet::core::types::FieldElement;
use std::sync::Arc;
Expand Down
2 changes: 1 addition & 1 deletion src/endpoints/leaderboard/get_ranking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ use axum::{
use axum_auto_routes::route;

use crate::utils::get_timestamp_from_days;
use axum::http::StatusCode;
use axum::http::{header, Response};
use chrono::Utc;
use futures::TryStreamExt;
use mongodb::bson::{doc, Document};
use mongodb::Collection;
use axum::http::StatusCode;
use serde::{Deserialize, Serialize};
use std::sync::Arc;

Expand Down
2 changes: 1 addition & 1 deletion src/endpoints/leaderboard/get_static_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ use axum_auto_routes::route;

use crate::utils::get_timestamp_from_days;
use axum::http::header;
use axum::http::StatusCode;
use axum::response::Response;
use chrono::Utc;
use futures::TryStreamExt;
use mongodb::bson::{doc, Document};
use axum::http::StatusCode;
use serde::{Deserialize, Serialize};
use std::sync::Arc;

Expand Down
2 changes: 1 addition & 1 deletion src/endpoints/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
pub mod achievements;
pub mod admin;
pub mod analytics;
pub mod defi;
pub mod discover;
pub mod get_boosted_quests;
pub mod get_completed_quests;
Expand All @@ -17,4 +18,3 @@ pub mod leaderboard;
pub mod quest_boost;
pub mod quests;
pub mod unique_page_visit;
pub mod defi;
2 changes: 1 addition & 1 deletion src/endpoints/quest_boost/get_claim_params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ use axum_auto_routes::route;
use std::str::FromStr;

use crate::utils::to_hex;
use mongodb::bson::{doc, Bson, Document};
use axum::http::StatusCode;
use mongodb::bson::{doc, Bson, Document};
use serde::{Deserialize, Serialize};
use serde_json::json;
use starknet::core::crypto::ecdsa_sign;
Expand Down
2 changes: 1 addition & 1 deletion src/endpoints/quest_boost/get_completed_boosts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ use axum::{
Json,
};

use axum::http::StatusCode;
use axum_auto_routes::route;
use futures::TryStreamExt;
use mongodb::bson::{doc, Document};
use axum::http::StatusCode;
use serde::{Deserialize, Serialize};
use starknet::core::types::FieldElement;
use std::sync::Arc;
Expand Down
2 changes: 1 addition & 1 deletion src/endpoints/quests/claimable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ use axum::{

use crate::models::{Reward, RewardResponse};
use crate::utils::get_nft;
use axum::http::StatusCode;
use axum_auto_routes::route;
use futures::TryStreamExt;
use mongodb::bson::{doc, Document};
use axum::http::StatusCode;
use serde::{Deserialize, Serialize};
use starknet::core::types::FieldElement;
use starknet::signers::{LocalWallet, SigningKey};
Expand Down
1 change: 0 additions & 1 deletion src/logger.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use chrono::Utc;
use reqwest;
use serde_derive::Serialize;
use std::borrow::Cow;
use std::sync::Arc;
Expand Down
10 changes: 7 additions & 3 deletions src/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,9 @@ pub_struct!(Deserialize; CompletedTasks {

#[derive(Debug, Serialize, Deserialize)]
pub struct CompletedTaskDocument {
address: String,
task_id: u32,
timestamp: i64,
pub address: String,
pub task_id: u32,
pub timestamp: i64,
}

impl CompletedTaskDocument {
Expand Down Expand Up @@ -522,3 +522,7 @@ pub struct DefiReward {
pub amount: FieldElement,
pub token_symbol: String,
}

pub_struct!(Deserialize; GetQuestParticipantsParams {
quest_id: i64,
});

0 comments on commit 80ee4f4

Please sign in to comment.