diff --git a/apps/labrinth/src/routes/v3/analytics_get/mod.rs b/apps/labrinth/src/routes/v3/analytics_get/mod.rs index 71abe4689d..0df8fedf8d 100644 --- a/apps/labrinth/src/routes/v3/analytics_get/mod.rs +++ b/apps/labrinth/src/routes/v3/analytics_get/mod.rs @@ -18,6 +18,7 @@ use std::{ use crate::database::{PgPool, models::DBUserId}; use actix_web::{HttpRequest, post, web}; +use ariadne::ids::UserId; use chrono::{DateTime, TimeDelta, Utc}; use eyre::eyre; use serde::{Deserialize, Serialize}; @@ -43,7 +44,7 @@ use crate::{ projects::ProjectStatus, teams::ProjectPermissions, threads::MessageBody, - v3::{analytics::DownloadReason, projects::Project}, + v3::{analytics::DownloadReason, projects::Project, users::User}, }, queue::session::AuthQueue, routes::ApiError, @@ -131,6 +132,9 @@ pub struct GetResponse { /// Project metadata for projects referenced in the response metrics. #[serde(default)] pub projects: HashMap, + /// User metadata for users referenced in the response metrics. + #[serde(default)] + pub users: HashMap, /// List of events associated with projects that were requested. pub project_events: Vec, } @@ -422,10 +426,12 @@ pub async fn fetch_analytics( let projects = fetch_response_projects(&mut time_slices, &user, &pool, &redis).await?; + let users = fetch_response_users(&time_slices, &pool, &redis).await?; Ok(web::Json(GetResponse { metrics: time_slices, projects, + users, project_events, })) } @@ -545,6 +551,43 @@ async fn fetch_response_projects( .collect()) } +async fn fetch_response_users( + time_slices: &[TimeSlice], + pool: &PgPool, + redis: &RedisPool, +) -> Result, ApiError> { + let mut user_ids = HashSet::::new(); + + for time_slice in time_slices { + for data in &time_slice.0 { + let AnalyticsData::Project(project) = data else { + continue; + }; + + if let ProjectMetrics::Revenue(revenue) = &project.metrics + && let Some(user_id) = revenue.user_id + { + user_ids.insert(user_id.into()); + } + } + } + + let user_ids = user_ids.into_iter().collect::>(); + if user_ids.is_empty() { + return Ok(HashMap::new()); + } + + let users = DBUser::get_many_ids(&user_ids, pool, redis).await?; + + Ok(users + .into_iter() + .map(|user| { + let user_id = UserId::from(user.id); + (user_id, User::from(user)) + }) + .collect()) +} + fn filter_response_project_ids( time_slices: &mut [TimeSlice], visible_project_ids: &HashSet, @@ -993,6 +1036,7 @@ mod tests { })]), ], projects: HashMap::new(), + users: HashMap::new(), project_events: vec![], }; let target = json!({ @@ -1020,6 +1064,7 @@ mod tests { ] ], "projects": {}, + "users": {}, "project_events": [] });