traits::{Actor, Object},
};
use chrono::NaiveDateTime;
-use itertools::Itertools;
use lemmy_api_common::{
context::LemmyContext,
utils::{generate_featured_url, generate_moderators_url, generate_outbox_url},
let id = self.id;
let local_site_data = local_site_data_cached(context.pool()).await?;
- let follows = CommunityFollowerView::for_community(context.pool(), id).await?;
+ let follows = CommunityFollowerView::get_community_follower_inboxes(context.pool(), id).await?;
+
let inboxes: Vec<Url> = follows
.into_iter()
- .filter(|f| !f.follower.local)
- .map(|f| {
- f.follower
- .shared_inbox_url
- .unwrap_or(f.follower.inbox_url)
- .into()
- })
- .unique()
+ .map(Into::into)
.filter(|inbox: &Url| inbox.host_str() != Some(&context.settings().hostname))
// Don't send to blocked instances
.filter(|inbox| check_apub_id_valid(inbox, &local_site_data).is_ok())
) -> Result<GroupFollowers, LemmyError> {
let community_id = community.id;
let community_followers =
- CommunityFollowerView::for_community(context.pool(), community_id).await?;
+ CommunityFollowerView::count_community_followers(context.pool(), community_id).await?;
Ok(GroupFollowers {
id: generate_followers_url(&community.actor_id)?.into(),
r#type: CollectionType::Collection,
- total_items: community_followers.len() as i32,
+ total_items: community_followers as i32,
items: vec![],
})
}
use crate::structs::CommunityFollowerView;
-use diesel::{result::Error, ExpressionMethods, QueryDsl};
+use diesel::{
+ dsl::{count_star, not},
+ result::Error,
+ sql_function,
+ ExpressionMethods,
+ QueryDsl,
+};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::{
- newtypes::{CommunityId, PersonId},
+ newtypes::{CommunityId, DbUrl, PersonId},
schema::{community, community_follower, person},
source::{community::Community, person::Person},
traits::JoinView,
type CommunityFollowerViewTuple = (Community, Person);
+sql_function!(fn coalesce(x: diesel::sql_types::Nullable<diesel::sql_types::Text>, y: diesel::sql_types::Text) -> diesel::sql_types::Text);
+
impl CommunityFollowerView {
- pub async fn for_community(pool: &DbPool, community_id: CommunityId) -> Result<Vec<Self>, Error> {
+ pub async fn get_community_follower_inboxes(
+ pool: &DbPool,
+ community_id: CommunityId,
+ ) -> Result<Vec<DbUrl>, Error> {
let conn = &mut get_conn(pool).await?;
let res = community_follower::table
- .inner_join(community::table)
+ .filter(community_follower::community_id.eq(community_id))
+ .filter(not(person::local))
.inner_join(person::table)
- .select((community::all_columns, person::all_columns))
+ .select(coalesce(person::shared_inbox_url, person::inbox_url))
+ .distinct()
+ .load::<DbUrl>(conn)
+ .await?;
+
+ Ok(res)
+ }
+ pub async fn count_community_followers(
+ pool: &DbPool,
+ community_id: CommunityId,
+ ) -> Result<i64, Error> {
+ let conn = &mut get_conn(pool).await?;
+ let res = community_follower::table
.filter(community_follower::community_id.eq(community_id))
- .order_by(community::title)
- .load::<CommunityFollowerViewTuple>(conn)
+ .select(count_star())
+ .first::<i64>(conn)
.await?;
- Ok(res.into_iter().map(Self::from_tuple).collect())
+ Ok(res)
}
pub async fn for_person(pool: &DbPool, person_id: PersonId) -> Result<Vec<Self>, Error> {