use crate::CommunityFollowerView;
use chrono::Utc;
use diesel::{
ExpressionMethods,
JoinOnDsl,
QueryDsl,
SelectableHelper,
dsl::{count_star, exists, not},
select,
};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::newtypes::CommunityId;
use lemmy_db_schema_file::{
InstanceId,
PersonId,
enums::CommunityFollowerState,
schema::{community, community_actions, person},
};
use lemmy_diesel_utils::{
connection::{DbPool, get_conn},
dburl::DbUrl,
utils::functions::lower,
};
use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult};
impl CommunityFollowerView {
#[diesel::dsl::auto_type(no_type_alias)]
fn joins() -> _ {
community_actions::table
.inner_join(community::table)
.inner_join(person::table.on(community_actions::person_id.eq(person::id)))
.filter(community_actions::followed_at.is_not_null())
}
pub async fn get_instance_followed_community_inboxes(
pool: &mut DbPool<'_>,
instance_id: InstanceId,
published_since: chrono::DateTime<Utc>,
) -> LemmyResult<Vec<(CommunityId, DbUrl)>> {
let conn = &mut get_conn(pool).await?;
Self::joins()
.filter(person::instance_id.eq(instance_id))
.filter(community::local) .filter(not(person::local))
.filter(community_actions::followed_at.gt(published_since.naive_utc()))
.select((community::id, person::inbox_url))
.distinct() .load::<(CommunityId, DbUrl)>(conn)
.await
.with_lemmy_type(LemmyErrorType::NotFound)
}
pub async fn count_community_followers(
pool: &mut DbPool<'_>,
community_id: CommunityId,
) -> LemmyResult<i32> {
let conn = &mut get_conn(pool).await?;
Self::joins()
.filter(community_actions::community_id.eq(community_id))
.select(count_star())
.first::<i64>(conn)
.await
.map(i32::try_from)?
.with_lemmy_type(LemmyErrorType::NotFound)
}
pub async fn for_person(pool: &mut DbPool<'_>, person_id: PersonId) -> LemmyResult<Vec<Self>> {
let conn = &mut get_conn(pool).await?;
Self::joins()
.filter(community_actions::person_id.eq(person_id))
.filter(community::deleted.eq(false))
.filter(community::removed.eq(false))
.filter(community::local_removed.eq(false))
.filter(community_actions::follow_state.ne(CommunityFollowerState::ApprovalRequired))
.filter(community_actions::follow_state.ne(CommunityFollowerState::Denied))
.select(Self::as_select())
.order_by(lower(community::title))
.load::<CommunityFollowerView>(conn)
.await
.with_lemmy_type(LemmyErrorType::NotFound)
}
pub async fn is_follower(
community_id: CommunityId,
instance_id: InstanceId,
pool: &mut DbPool<'_>,
) -> LemmyResult<()> {
let conn = &mut get_conn(pool).await?;
select(exists(
Self::joins()
.filter(community_actions::community_id.eq(community_id))
.filter(person::instance_id.eq(instance_id))
.filter(community_actions::follow_state.eq(CommunityFollowerState::Accepted)),
))
.get_result::<bool>(conn)
.await?
.then_some(())
.ok_or(LemmyErrorType::NotFound.into())
}
}