structural refactor and codebase improvements
This commit is contained in:
89
crates/application/src/users/get_federated_profile_stats.rs
Normal file
89
crates/application/src/users/get_federated_profile_stats.rs
Normal file
@@ -0,0 +1,89 @@
|
||||
//! The federated half of the former `get_profile` (ADR-0004's closed wart).
|
||||
//! `build_federated_profile_response` (`handlers/users.rs`) calls this with a
|
||||
//! synthetic `user_id` that has no row in the local `users` table — a federated
|
||||
//! actor's identity is built entirely from the resolved `FederatedProfile`, so
|
||||
//! this type carries no `identity` field at all: the old `get_profile` computed
|
||||
//! one for this path anyway, filled with empty-string sentinels for `username`/
|
||||
//! `handle`, and the handler never read it (see the closed wart paragraph in
|
||||
//! `docs/adr/0004-instance-identity.md`). No type here can represent that
|
||||
//! sentinel, because there is nothing to fill in.
|
||||
//!
|
||||
//! A federated actor also has no local pending-follow-request concept, so unlike
|
||||
//! `get_local_profile` this never computes `pending_followers` — it would always
|
||||
//! be empty here regardless of `is_own_profile`.
|
||||
|
||||
use crate::users::{
|
||||
deps::GetFederatedProfileStatsDeps,
|
||||
diary_filter::{feed_sort_to_direction, paged_user_filter},
|
||||
queries::{GetUserProfileQuery, ProfileView},
|
||||
};
|
||||
use domain::{
|
||||
errors::DomainError,
|
||||
models::{DiaryEntry, UserStats, UserTrends, collections::Paginated},
|
||||
value_objects::UserId,
|
||||
};
|
||||
|
||||
pub struct FederatedProfileStats {
|
||||
pub stats: UserStats,
|
||||
pub entries: Option<Paginated<DiaryEntry>>,
|
||||
pub history: Option<Vec<DiaryEntry>>,
|
||||
pub trends: Option<UserTrends>,
|
||||
pub following_count: usize,
|
||||
pub followers_count: usize,
|
||||
}
|
||||
|
||||
pub async fn execute(
|
||||
deps: &GetFederatedProfileStatsDeps,
|
||||
query: GetUserProfileQuery,
|
||||
) -> Result<FederatedProfileStats, DomainError> {
|
||||
let user_id = UserId::from_uuid(query.user_id);
|
||||
let stats = deps.stats.get_user_stats(&user_id).await?;
|
||||
|
||||
let following_count = deps
|
||||
.social_query
|
||||
.count_following(&user_id)
|
||||
.await
|
||||
.unwrap_or(0);
|
||||
let followers_count = deps
|
||||
.social_query
|
||||
.count_followers(&user_id)
|
||||
.await
|
||||
.unwrap_or(0);
|
||||
|
||||
let base = |entries, history, trends| FederatedProfileStats {
|
||||
stats,
|
||||
entries,
|
||||
history,
|
||||
trends,
|
||||
following_count,
|
||||
followers_count,
|
||||
};
|
||||
|
||||
match query.view {
|
||||
ProfileView::History => {
|
||||
let all_entries = deps.diary.get_user_history(&user_id).await?;
|
||||
Ok(base(None, Some(all_entries), None))
|
||||
}
|
||||
ProfileView::Trends => {
|
||||
let trends = deps.stats.get_user_trends(&user_id).await?;
|
||||
Ok(base(None, None, Some(trends)))
|
||||
}
|
||||
ProfileView::Ratings | ProfileView::Recent => {
|
||||
let sort_direction = feed_sort_to_direction(query.sort_by);
|
||||
let filter = paged_user_filter(
|
||||
user_id,
|
||||
sort_direction,
|
||||
query.limit,
|
||||
query.offset,
|
||||
query.search.clone(),
|
||||
query.include_remote,
|
||||
)?;
|
||||
let entries = deps.diary.query_diary(&filter).await?;
|
||||
Ok(base(Some(entries), None, None))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "tests/get_federated_profile_stats.rs"]
|
||||
mod tests;
|
||||
Reference in New Issue
Block a user