From 3e0ff2f0210c588de0b849bcc713b6fd22ee1717 Mon Sep 17 00:00:00 2001 From: Igor Bubelov Date: Mon, 9 Sep 2024 18:31:42 +0700 Subject: [PATCH] Add get most commented countries RPC --- src/rpc/get_most_commented_countries.rs | 81 +++++++++++++++++++++++++ src/rpc/mod.rs | 1 + src/server/mod.rs | 1 + 3 files changed, 83 insertions(+) create mode 100644 src/rpc/get_most_commented_countries.rs diff --git a/src/rpc/get_most_commented_countries.rs b/src/rpc/get_most_commented_countries.rs new file mode 100644 index 0000000..d32a508 --- /dev/null +++ b/src/rpc/get_most_commented_countries.rs @@ -0,0 +1,81 @@ +use crate::{area::Area, auth::Token, element::Element, element_comment::ElementComment, Result}; +use deadpool_sqlite::Pool; +use jsonrpc_v2::{Data, Params}; +use rusqlite::Connection; +use serde::{Deserialize, Serialize}; +use std::{collections::HashMap, sync::Arc}; +use time::{format_description::well_known::Rfc3339, OffsetDateTime}; + +#[derive(Deserialize)] +pub struct Args { + pub token: String, + pub period_start: String, + pub period_end: String, +} + +#[derive(Serialize)] +pub struct Res { + id: i64, + name: String, + comments: i64, +} + +pub async fn run(Params(args): Params, pool: Data>) -> Result> { + pool.get() + .await? + .interact(move |conn| Token::select_by_secret(&args.token, conn)) + .await?? + .unwrap(); + let period_start = + OffsetDateTime::parse(&format!("{}T00:00:00Z", args.period_start), &Rfc3339).unwrap(); + let period_end = + OffsetDateTime::parse(&format!("{}T00:00:00Z", args.period_end), &Rfc3339).unwrap(); + pool.get() + .await? + .interact(move |conn| get_most_commented_countries(&period_start, &period_end, conn)) + .await? +} + +fn get_most_commented_countries( + period_start: &OffsetDateTime, + period_end: &OffsetDateTime, + conn: &Connection, +) -> Result> { + let comments = ElementComment::select_updated_since(period_start, None, conn)?; + let comments: Vec = comments + .into_iter() + .filter(|it| it.created_at < *period_end) + .collect(); + let mut areas_to_comments: HashMap> = HashMap::new(); + for comment in &comments { + let element = Element::select_by_id(comment.element_id, conn)?.unwrap(); + if element.tags.contains_key("areas") { + let areas = element.tag("areas").as_array().unwrap(); + for area in areas { + let area_id = area["id"].as_i64().unwrap(); + if !areas_to_comments.contains_key(&area_id) { + areas_to_comments.insert(area_id, vec![]); + } + let area_comments = areas_to_comments.get_mut(&area_id).unwrap(); + area_comments.push(comment); + } + } + } + let areas_to_comments: Vec<(Area, Vec<&ElementComment>)> = areas_to_comments + .into_iter() + .map(|(k, v)| (Area::select_by_id(k, conn).unwrap().unwrap(), v)) + .collect(); + let mut res: Vec = areas_to_comments + .iter() + .filter(|it| { + it.0.tags.contains_key("type") && it.0.tags["type"].as_str() == Some("country") + }) + .map(|it| Res { + id: it.0.id, + name: it.0.name(), + comments: it.1.len() as i64, + }) + .collect(); + res.sort_by(|x, y| y.comments.cmp(&x.comments)); + Ok(res) +} diff --git a/src/rpc/mod.rs b/src/rpc/mod.rs index 185d254..73545de 100644 --- a/src/rpc/mod.rs +++ b/src/rpc/mod.rs @@ -4,6 +4,7 @@ pub mod boost_element; pub mod generate_element_issues; pub mod get_area; pub mod get_element; +pub mod get_most_commented_countries; pub mod get_trending_communities; pub mod get_trending_countries; pub mod remove_area; diff --git a/src/server/mod.rs b/src/server/mod.rs index 3fa2496..7e4a727 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -92,6 +92,7 @@ pub async fn run() -> Result<()> { .with_method("setareatag", rpc::set_area_tag::run) .with_method("removeareatag", rpc::remove_area_tag::run) .with_method("gettrendingcountries", rpc::get_trending_countries::run) + .with_method("getmostcommentedcountries", rpc::get_most_commented_countries::run) .with_method("gettrendingcommunities", rpc::get_trending_communities::run) .with_method("removearea", rpc::remove_area::run) .finish()