diff --git a/src/endpoints/admin/balance/create_balance.rs b/src/endpoints/admin/balance/create_balance.rs index 4de3928..7436259 100644 --- a/src/endpoints/admin/balance/create_balance.rs +++ b/src/endpoints/admin/balance/create_balance.rs @@ -72,6 +72,8 @@ pub async fn handler( discord_guild_id: None, quiz_name: None, contracts: Some(parsed_contracts), + api_url: None, + regex: None, }; // insert document to boost collection diff --git a/src/endpoints/admin/custom/create_custom.rs b/src/endpoints/admin/custom/create_custom.rs index 2180d7e..08155f3 100644 --- a/src/endpoints/admin/custom/create_custom.rs +++ b/src/endpoints/admin/custom/create_custom.rs @@ -63,6 +63,8 @@ pub async fn handler( discord_guild_id: None, quiz_name: None, contracts: None, + api_url: None, + regex: None, }; // insert document to boost collection diff --git a/src/endpoints/admin/discord/create_discord.rs b/src/endpoints/admin/discord/create_discord.rs index 6f6c7ef..895ec26 100644 --- a/src/endpoints/admin/discord/create_discord.rs +++ b/src/endpoints/admin/discord/create_discord.rs @@ -62,6 +62,8 @@ pub async fn handler( quiz_name: None, verify_redirect: None, contracts: None, + api_url: None, + regex: None, }; // insert document to boost collection diff --git a/src/endpoints/admin/domain/create_domain.rs b/src/endpoints/admin/domain/create_domain.rs index 586e1fb..0080f4d 100644 --- a/src/endpoints/admin/domain/create_domain.rs +++ b/src/endpoints/admin/domain/create_domain.rs @@ -59,6 +59,8 @@ pub async fn handler( quiz_name: None, verify_redirect: None, contracts: None, + api_url: None, + regex: None, }; // insert document to boost collection diff --git a/src/endpoints/admin/quiz/create_quiz.rs b/src/endpoints/admin/quiz/create_quiz.rs index 4f9b41e..d382e2b 100644 --- a/src/endpoints/admin/quiz/create_quiz.rs +++ b/src/endpoints/admin/quiz/create_quiz.rs @@ -90,6 +90,8 @@ pub async fn handler( discord_guild_id: None, verify_redirect: None, contracts: None, + api_url: None, + regex: None, }; return match tasks_collection.insert_one(new_document, None).await { diff --git a/src/endpoints/admin/twitter/create_twitter_fw.rs b/src/endpoints/admin/twitter/create_twitter_fw.rs index a2348a6..5337c05 100644 --- a/src/endpoints/admin/twitter/create_twitter_fw.rs +++ b/src/endpoints/admin/twitter/create_twitter_fw.rs @@ -63,6 +63,8 @@ pub async fn handler( discord_guild_id: None, quiz_name: None, contracts: None, + api_url: None, + regex: None, }; // insert document to boost collection diff --git a/src/endpoints/admin/twitter/create_twitter_rw.rs b/src/endpoints/admin/twitter/create_twitter_rw.rs index 8b1106e..99b2312 100644 --- a/src/endpoints/admin/twitter/create_twitter_rw.rs +++ b/src/endpoints/admin/twitter/create_twitter_rw.rs @@ -61,6 +61,8 @@ pub async fn handler( discord_guild_id: None, quiz_name: None, contracts: None, + api_url: None, + regex: None, }; // insert document to boost collection diff --git a/src/endpoints/quests/mod.rs b/src/endpoints/quests/mod.rs index 3338ed1..5e52e46 100644 --- a/src/endpoints/quests/mod.rs +++ b/src/endpoints/quests/mod.rs @@ -10,6 +10,7 @@ pub mod starknet; pub mod starknetid; pub mod uri; pub mod verify_balance; +pub mod verify_custom_api; pub mod verify_quiz; pub mod verify_twitter_fw; pub mod verify_twitter_rw; diff --git a/src/endpoints/quests/verify_custom_api.rs b/src/endpoints/quests/verify_custom_api.rs new file mode 100644 index 0000000..bda30a1 --- /dev/null +++ b/src/endpoints/quests/verify_custom_api.rs @@ -0,0 +1,78 @@ +use std::{sync::Arc, str::FromStr}; +use crate::{ + models::{AppState, QuestTaskDocument}, + utils::{get_error, CompletedTasksTrait}, +}; +use axum::{ + extract::{Query, State}, + http::StatusCode, + response::IntoResponse, + Json, +}; +use axum_auto_routes::route; +use mongodb::bson::doc; +use serde::{Deserialize, Serialize}; +use serde_json::json; +use regex::Regex; +use reqwest::get; +use starknet::core::types::FieldElement; + +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct VerifyCustomApiQuery { + pub addr: String, + pub task_id: u32, +} + +#[route(get, "/quests/verify_custom_api")] +pub async fn handler( + State(state): State>, + Query(query): Query, +) -> impl IntoResponse { + let task_id = query.task_id; + + // Get task in db + let task_collection = state.db.collection("tasks"); + let task: QuestTaskDocument = task_collection + .find_one(doc! {"id": task_id}, None) + .await + .unwrap() + .unwrap(); + + // Check if the task type is "custom_api" + if task.task_type != Some("custom_api".to_string()) { + return get_error("Invalid task type.".to_string()); + } + + // Check if the task has the required fields (api_url and regex) + let api_url = match &task.api_url { + Some(url) => url, + None => return get_error("API URL not found.".to_string()), + }; + + let regex_str = match &task.regex { + Some(rgx) => rgx, + None => return get_error("Regex not found.".to_string()), + }; + + // Call the specified API + let response = get(api_url).await; + + match response { + Ok(res) => { + let res_text = res.text().await.unwrap(); + + // Check response against the regex + let re = Regex::new(regex_str).unwrap(); + if re.is_match(&res_text) { + // Mark the task as completed + match state.upsert_completed_task(FieldElement::from_str(&query.addr).unwrap(), task_id).await { + Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), + Err(e) => get_error(format!("{}", e)), + } + } else { + get_error("Response did not match the required pattern.".to_string()) + } + } + Err(e) => get_error(format!("Failed to fetch API: {}", e)), + } +} diff --git a/src/models.rs b/src/models.rs index 9451b66..07ffdd7 100644 --- a/src/models.rs +++ b/src/models.rs @@ -118,6 +118,8 @@ pub struct QuestTaskDocument { pub verify_endpoint: String, pub href: String, pub verify_endpoint_type: String, + pub api_url: Option, + pub regex: Option, #[serde(default)] pub verify_redirect: Option, #[serde(default)]