Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ pub mod private_message;
pub mod private_message_report;
pub mod site;
pub mod sitemap;
pub mod vote_analytics;

/// Converts the captcha to a base64 encoded wav audio file
pub(crate) fn captcha_as_wav_base64(captcha: &Captcha) -> LemmyResult<String> {
Expand Down
46 changes: 46 additions & 0 deletions crates/api/src/vote_analytics/given_by_person.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use activitypub_federation::config::Data;
use actix_web::web::{Json, Query};
use chrono::{TimeZone, Utc};
use lemmy_api_common::{context::LemmyContext, person::GetVoteAnalyticsByPerson, utils::is_admin};
use lemmy_db_views::structs::LocalUserView;
use lemmy_db_views_actor::structs::VoteAnalyticsGivenByPersonView;
use lemmy_utils::{error::LemmyResult, LemmyErrorType};

#[tracing::instrument(skip(context))]
pub async fn get_vote_analytics_given_by_person(
data: Query<GetVoteAnalyticsByPerson>,
context: Data<LemmyContext>,
local_user_view: LocalUserView,
) -> LemmyResult<Json<VoteAnalyticsGivenByPersonView>> {
is_admin(&local_user_view)?;

let since = match data.start_time {
Some(t) => Some(
Utc
.timestamp_opt(t, 0)
.single()
.ok_or(LemmyErrorType::InvalidUnixTime)?,
),
_ => None,
};
let until = match data.end_time {
Some(t) => Some(
Utc
.timestamp_opt(t, 0)
.single()
.ok_or(LemmyErrorType::InvalidUnixTime)?,
),
_ => None,
};

let view = VoteAnalyticsGivenByPersonView::read(
&mut context.pool(),
data.person_id,
since,
until,
data.limit,
)
.await?;

Ok(Json(view))
}
1 change: 1 addition & 0 deletions crates/api/src/vote_analytics/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod given_by_person;
10 changes: 10 additions & 0 deletions crates/api_common/src/person.rs
Original file line number Diff line number Diff line change
Expand Up @@ -441,3 +441,13 @@ pub struct ListMedia {
pub struct ListMediaResponse {
pub images: Vec<LocalImageView>,
}

#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "full", derive(TS))]
#[cfg_attr(feature = "full", ts(export))]
pub struct GetVoteAnalyticsByPerson {
pub person_id: PersonId,
pub start_time: Option<i64>,
pub end_time: Option<i64>,
pub limit: Option<i64>,
}
21 changes: 21 additions & 0 deletions crates/db_schema/src/impls/community.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ use diesel::{
};
use diesel_async::RunQueryDsl;
use lemmy_utils::error::{LemmyErrorType, LemmyResult};
use std::collections::HashMap;

#[async_trait]
impl Crud for Community {
Expand Down Expand Up @@ -147,6 +148,26 @@ impl Community {
Ok(community_)
}

pub async fn read_many(
pool: &mut DbPool<'_>,
community_ids: &[CommunityId],
is_admin: bool,
) -> Result<HashMap<CommunityId, Community>, Error> {
let conn = &mut get_conn(pool).await?;
let mut query = community::table
.filter(community::id.eq_any(community_ids))
.into_boxed();
if !is_admin {
query = query
.filter(community::deleted.eq(false))
.filter(community::removed.eq(false));
}
let communities: Vec<Community> = query.get_results(conn).await?;
Ok(HashMap::from_iter(
communities.iter().map(|c| (c.id, c.clone())),
))
}

/// Get the community which has a given moderators or featured url, also return the collection
/// type
pub async fn get_by_collection_url(
Expand Down
19 changes: 19 additions & 0 deletions crates/db_schema/src/impls/person.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use diesel::{
QueryDsl,
};
use diesel_async::RunQueryDsl;
use std::collections::HashMap;

#[async_trait]
impl Crud for Person {
Expand Down Expand Up @@ -97,6 +98,24 @@ impl Person {
.await
}

pub async fn read_many(
pool: &mut DbPool<'_>,
person_ids: &[PersonId],
is_admin: bool,
) -> Result<HashMap<PersonId, Person>, Error> {
let conn = &mut get_conn(pool).await?;
let mut query = person::table
.filter(person::id.eq_any(person_ids))
.into_boxed();
if !is_admin {
query = query.filter(person::deleted.eq(false));
}
let persons: Vec<Person> = query.get_results(conn).await?;
Ok(HashMap::from_iter(
persons.iter().map(|p| (p.id, p.clone())),
))
}

/// Lists local community ids for all posts and comments for a given creator.
pub async fn list_local_community_ids(
pool: &mut DbPool<'_>,
Expand Down
2 changes: 2 additions & 0 deletions crates/db_views_actor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@ pub mod person_mention_view;
#[cfg(feature = "full")]
pub mod person_view;
pub mod structs;
#[cfg(feature = "full")]
mod vote_analytics_given_by_view;
40 changes: 40 additions & 0 deletions crates/db_views_actor/src/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,43 @@ pub struct PersonView {
pub counts: PersonAggregates,
pub is_admin: bool,
}

#[derive(Debug, Serialize)]
#[cfg_attr(feature = "full", derive(TS))]
#[cfg_attr(feature = "full", ts(export))]
pub struct VoteAnalyticsByPerson {
pub creator: Person,
pub total_votes: i64,
pub upvotes: i64,
pub downvotes: i64,
pub upvote_percentage: f64,
}

#[derive(Debug, Serialize)]
#[cfg_attr(feature = "full", derive(TS))]
#[cfg_attr(feature = "full", ts(export))]
pub struct VoteAnalyticsByCommunity {
pub community: Community,
pub total_votes: i64,
pub upvotes: i64,
pub downvotes: i64,
pub upvote_percentage: f64,
}

#[derive(Debug, Serialize)]
#[cfg_attr(feature = "full", derive(TS))]
#[cfg_attr(feature = "full", ts(export))]
pub struct VoteAnalyticsGivenByPersonView {
pub post_votes_total_votes: i64,
pub post_votes_total_upvotes: i64,
pub post_votes_total_downvotes: i64,
pub post_votes_total_upvote_percentage: f64,
pub post_votes_by_target_user: Vec<VoteAnalyticsByPerson>,
pub post_votes_by_target_community: Vec<VoteAnalyticsByCommunity>,
pub comment_votes_total_votes: i64,
pub comment_votes_total_upvotes: i64,
pub comment_votes_total_downvotes: i64,
pub comment_votes_total_upvote_percentage: f64,
pub comment_votes_by_target_user: Vec<VoteAnalyticsByPerson>,
pub comment_votes_by_target_community: Vec<VoteAnalyticsByCommunity>,
}
Loading