mirror of
https://github.com/LemmyNet/lemmy.git
synced 2025-09-03 03:33:50 +00:00
Adding Modlog RSS feed. (#5708)
* Adding Modlog RSS feed. - Fixes #3179 * Addressing PR comments * Fixing clippy. * Fixing markdown test. * Creating common format_actor_url function. * Clippy * Adding boolean strings for remove/restore * Addressing PR comments
This commit is contained in:
parent
ced74b40cc
commit
079ca69312
11 changed files with 413 additions and 74 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -3860,6 +3860,7 @@ dependencies = [
|
|||
"lemmy_db_schema_file",
|
||||
"lemmy_db_views_inbox_combined",
|
||||
"lemmy_db_views_local_user",
|
||||
"lemmy_db_views_modlog_combined",
|
||||
"lemmy_db_views_person_content_combined",
|
||||
"lemmy_db_views_post",
|
||||
"lemmy_db_views_site",
|
||||
|
|
|
@ -82,7 +82,7 @@ pub async fn create_community(
|
|||
check_community_visibility_allowed(data.visibility, &local_user_view)?;
|
||||
|
||||
// Double check for duplicate community actor_ids
|
||||
let community_ap_id = Community::local_url(&data.name, context.settings())?;
|
||||
let community_ap_id = Community::generate_local_actor_url(&data.name, context.settings())?;
|
||||
let community_dupe = Community::read_from_apub_id(&mut context.pool(), &community_ap_id).await?;
|
||||
if community_dupe.is_some() {
|
||||
Err(LemmyErrorType::CommunityAlreadyExists)?
|
||||
|
|
|
@ -29,7 +29,7 @@ use lemmy_db_schema::{
|
|||
person::{Person, PersonInsertForm},
|
||||
registration_application::{RegistrationApplication, RegistrationApplicationInsertForm},
|
||||
},
|
||||
traits::Crud,
|
||||
traits::{ApubActor, Crud},
|
||||
utils::get_conn,
|
||||
};
|
||||
use lemmy_db_schema_file::enums::RegistrationMode;
|
||||
|
@ -443,7 +443,7 @@ async fn create_person(
|
|||
conn: &mut AsyncPgConnection,
|
||||
) -> Result<Person, LemmyError> {
|
||||
is_valid_actor_name(&username, site_view.local_site.actor_name_max_length)?;
|
||||
let ap_id = Person::local_url(&username, context.settings())?;
|
||||
let ap_id = Person::generate_local_actor_url(&username, context.settings())?;
|
||||
|
||||
// Register the new person
|
||||
let person_form = PersonInsertForm {
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
use crate::objects::{PostOrComment, SearchableObjects, UserOrCommunity};
|
||||
use activitypub_federation::{config::Data, fetch::object_id::ObjectId};
|
||||
use lemmy_api_common::context::LemmyContext;
|
||||
use lemmy_db_schema::{newtypes::InstanceId, source::instance::Instance};
|
||||
use lemmy_utils::{
|
||||
error::LemmyResult,
|
||||
utils::markdown::image_links::{markdown_find_links, markdown_handle_title},
|
||||
};
|
||||
use lemmy_db_schema::traits::ApubActor;
|
||||
use lemmy_utils::utils::markdown::image_links::{markdown_find_links, markdown_handle_title};
|
||||
use url::Url;
|
||||
|
||||
pub async fn markdown_rewrite_remote_links_opt(
|
||||
|
@ -51,7 +48,8 @@ pub async fn markdown_rewrite_remote_links(
|
|||
pub(crate) async fn to_local_url(url: &str, context: &Data<LemmyContext>) -> Option<Url> {
|
||||
let local_domain = &context.settings().get_protocol_and_hostname();
|
||||
let object_id = ObjectId::<SearchableObjects>::parse(url).ok()?;
|
||||
if object_id.inner().domain() == Some(local_domain) {
|
||||
let object_domain = object_id.inner().domain();
|
||||
if object_domain == Some(local_domain) {
|
||||
return None;
|
||||
}
|
||||
let dereferenced = object_id.dereference_local(context).await.ok()?;
|
||||
|
@ -63,49 +61,27 @@ pub(crate) async fn to_local_url(url: &str, context: &Data<LemmyContext>) -> Opt
|
|||
.ok()
|
||||
.map(Into::into),
|
||||
SearchableObjects::Right(pc) => match pc {
|
||||
UserOrCommunity::Left(user) => {
|
||||
format_actor_url(&user.name, "u", user.instance_id, context).await
|
||||
}
|
||||
UserOrCommunity::Right(community) => {
|
||||
format_actor_url(&community.name, "c", community.instance_id, context).await
|
||||
}
|
||||
UserOrCommunity::Left(user) => user.actor_url(context.settings()),
|
||||
UserOrCommunity::Right(community) => community.actor_url(context.settings()),
|
||||
}
|
||||
.ok(),
|
||||
}
|
||||
}
|
||||
|
||||
async fn format_actor_url(
|
||||
name: &str,
|
||||
kind: &str,
|
||||
instance_id: InstanceId,
|
||||
context: &LemmyContext,
|
||||
) -> LemmyResult<Url> {
|
||||
let local_protocol_and_hostname = context.settings().get_protocol_and_hostname();
|
||||
let local_hostname = &context.settings().hostname;
|
||||
let instance = Instance::read(&mut context.pool(), instance_id).await?;
|
||||
let url = if &instance.domain != local_hostname {
|
||||
format!(
|
||||
"{local_protocol_and_hostname}/{kind}/{name}@{}",
|
||||
instance.domain
|
||||
)
|
||||
} else {
|
||||
format!("{local_protocol_and_hostname}/{kind}/{name}")
|
||||
};
|
||||
Ok(Url::parse(&url)?)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use lemmy_db_schema::{
|
||||
source::{
|
||||
community::{Community, CommunityInsertForm},
|
||||
instance::Instance,
|
||||
post::{Post, PostInsertForm},
|
||||
},
|
||||
traits::Crud,
|
||||
};
|
||||
use lemmy_db_views_local_user::LocalUserView;
|
||||
use lemmy_db_views_site::impls::create_test_instance;
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
use pretty_assertions::assert_eq;
|
||||
use serial_test::serial;
|
||||
|
||||
|
@ -114,16 +90,16 @@ mod tests {
|
|||
async fn test_markdown_rewrite_remote_links() -> LemmyResult<()> {
|
||||
let context = LemmyContext::init_test_context().await;
|
||||
let instance = create_test_instance(&mut context.pool()).await?;
|
||||
let community = Community::create(
|
||||
&mut context.pool(),
|
||||
&CommunityInsertForm::new(
|
||||
let community_form = CommunityInsertForm {
|
||||
ap_id: Some(Url::parse("https://example.com/c/my_community")?.into()),
|
||||
..CommunityInsertForm::new(
|
||||
instance.id,
|
||||
"my_community".to_string(),
|
||||
"My Community".to_string(),
|
||||
"pubkey".to_string(),
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
)
|
||||
};
|
||||
let community = Community::create(&mut context.pool(), &community_form).await?;
|
||||
let user =
|
||||
LocalUserView::create_test_user(&mut context.pool(), "garda", "garda bio", false).await?;
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ use crate::{
|
|||
},
|
||||
traits::{ApubActor, Bannable, Blockable, Crud, Followable, Joinable},
|
||||
utils::{
|
||||
format_actor_url,
|
||||
functions::{coalesce, coalesce_2_nullable, lower, random_smallint},
|
||||
get_conn,
|
||||
uplete,
|
||||
|
@ -277,11 +278,6 @@ impl Community {
|
|||
Ok(Url::parse(&format!("{}/tag/{}", self.ap_id, &id_slug))?.into())
|
||||
}
|
||||
|
||||
pub fn local_url(name: &str, settings: &Settings) -> LemmyResult<DbUrl> {
|
||||
let domain = settings.get_protocol_and_hostname();
|
||||
Ok(Url::parse(&format!("{domain}/c/{name}"))?.into())
|
||||
}
|
||||
|
||||
pub async fn update_federated_followers(
|
||||
pool: &mut DbPool<'_>,
|
||||
for_community_id: CommunityId,
|
||||
|
@ -651,6 +647,21 @@ impl ApubActor for Community {
|
|||
.optional()
|
||||
.with_lemmy_type(LemmyErrorType::NotFound)
|
||||
}
|
||||
|
||||
fn actor_url(&self, settings: &Settings) -> LemmyResult<Url> {
|
||||
let domain = self
|
||||
.ap_id
|
||||
.inner()
|
||||
.domain()
|
||||
.ok_or(LemmyErrorType::NotFound)?;
|
||||
|
||||
format_actor_url(&self.name, domain, 'c', settings)
|
||||
}
|
||||
|
||||
fn generate_local_actor_url(name: &str, settings: &Settings) -> LemmyResult<DbUrl> {
|
||||
let domain = settings.get_protocol_and_hostname();
|
||||
Ok(Url::parse(&format!("{domain}/c/{name}"))?.into())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -10,7 +10,7 @@ use crate::{
|
|||
PersonUpdateForm,
|
||||
},
|
||||
traits::{ApubActor, Blockable, Crud, Followable},
|
||||
utils::{functions::lower, get_conn, uplete, DbPool},
|
||||
utils::{format_actor_url, functions::lower, get_conn, uplete, DbPool},
|
||||
};
|
||||
use chrono::Utc;
|
||||
use diesel::{
|
||||
|
@ -146,11 +146,6 @@ impl Person {
|
|||
.then_some(())
|
||||
.ok_or(LemmyErrorType::UsernameAlreadyExists.into())
|
||||
}
|
||||
|
||||
pub fn local_url(name: &str, settings: &Settings) -> LemmyResult<DbUrl> {
|
||||
let domain = settings.get_protocol_and_hostname();
|
||||
Ok(Url::parse(&format!("{domain}/u/{name}"))?.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl PersonInsertForm {
|
||||
|
@ -210,6 +205,21 @@ impl ApubActor for Person {
|
|||
.optional()
|
||||
.with_lemmy_type(LemmyErrorType::NotFound)
|
||||
}
|
||||
|
||||
fn actor_url(&self, settings: &Settings) -> LemmyResult<Url> {
|
||||
let domain = self
|
||||
.ap_id
|
||||
.inner()
|
||||
.domain()
|
||||
.ok_or(LemmyErrorType::NotFound)?;
|
||||
|
||||
format_actor_url(&self.name, domain, 'u', settings)
|
||||
}
|
||||
|
||||
fn generate_local_actor_url(name: &str, settings: &Settings) -> LemmyResult<DbUrl> {
|
||||
let domain = settings.get_protocol_and_hostname();
|
||||
Ok(Url::parse(&format!("{domain}/u/{name}"))?.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl Followable for PersonActions {
|
||||
|
|
|
@ -14,8 +14,12 @@ use diesel_async::{
|
|||
AsyncPgConnection,
|
||||
RunQueryDsl,
|
||||
};
|
||||
use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult};
|
||||
use lemmy_utils::{
|
||||
error::{LemmyErrorExt, LemmyErrorType, LemmyResult},
|
||||
settings::structs::Settings,
|
||||
};
|
||||
use std::future::Future;
|
||||
use url::Url;
|
||||
|
||||
/// Returned by `diesel::delete`
|
||||
pub type Delete<T> = DeleteStatement<<T as HasTable>::Table, <T as IntoUpdateTarget>::WhereClause>;
|
||||
|
@ -326,6 +330,9 @@ pub trait ApubActor {
|
|||
) -> impl Future<Output = LemmyResult<Option<Self>>> + Send
|
||||
where
|
||||
Self: Sized;
|
||||
|
||||
fn generate_local_actor_url(name: &str, settings: &Settings) -> LemmyResult<DbUrl>;
|
||||
fn actor_url(&self, settings: &Settings) -> LemmyResult<Url>;
|
||||
}
|
||||
|
||||
pub trait InternalToCombinedView {
|
||||
|
|
|
@ -35,7 +35,7 @@ use i_love_jesus::{CursorKey, PaginatedQueryBuilder, SortDirection};
|
|||
use lemmy_db_schema_file::schema_setup;
|
||||
use lemmy_utils::{
|
||||
error::{LemmyError, LemmyErrorExt, LemmyErrorType, LemmyResult},
|
||||
settings::SETTINGS,
|
||||
settings::{structs::Settings, SETTINGS},
|
||||
utils::validation::clean_url,
|
||||
};
|
||||
use regex::Regex;
|
||||
|
@ -624,6 +624,22 @@ pub fn paginate<Q, C>(
|
|||
query
|
||||
}
|
||||
|
||||
pub(crate) fn format_actor_url(
|
||||
name: &str,
|
||||
domain: &str,
|
||||
prefix: char,
|
||||
settings: &Settings,
|
||||
) -> LemmyResult<Url> {
|
||||
let local_protocol_and_hostname = settings.get_protocol_and_hostname();
|
||||
let local_hostname = &settings.hostname;
|
||||
let url = if domain != local_hostname {
|
||||
format!("{local_protocol_and_hostname}/{prefix}/{name}@{domain}",)
|
||||
} else {
|
||||
format!("{local_protocol_and_hostname}/{prefix}/{name}")
|
||||
};
|
||||
Ok(Url::parse(&url)?)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
@ -19,6 +19,7 @@ workspace = true
|
|||
lemmy_db_views_post = { workspace = true, features = ["full"] }
|
||||
lemmy_db_views_local_user = { workspace = true, features = ["full"] }
|
||||
lemmy_db_views_inbox_combined = { workspace = true, features = ["full"] }
|
||||
lemmy_db_views_modlog_combined = { workspace = true, features = ["full"] }
|
||||
lemmy_db_views_person_content_combined = { workspace = true, features = [
|
||||
"full",
|
||||
] }
|
||||
|
|
|
@ -12,6 +12,7 @@ use lemmy_db_schema::{
|
|||
};
|
||||
use lemmy_db_schema_file::enums::{ListingType, PostSortType};
|
||||
use lemmy_db_views_inbox_combined::{impls::InboxCombinedQuery, InboxCombinedView};
|
||||
use lemmy_db_views_modlog_combined::{impls::ModlogCombinedQuery, ModlogCombinedView};
|
||||
use lemmy_db_views_person_content_combined::impls::PersonContentCombinedQuery;
|
||||
use lemmy_db_views_post::{impls::PostQuery, PostView};
|
||||
use lemmy_db_views_site::SiteView;
|
||||
|
@ -58,6 +59,7 @@ enum RequestType {
|
|||
User,
|
||||
Front,
|
||||
Inbox,
|
||||
Modlog,
|
||||
}
|
||||
|
||||
pub fn config(cfg: &mut web::ServiceConfig) {
|
||||
|
@ -169,6 +171,7 @@ async fn get_feed(
|
|||
"c" => RequestType::Community,
|
||||
"front" => RequestType::Front,
|
||||
"inbox" => RequestType::Inbox,
|
||||
"modlog" => RequestType::Modlog,
|
||||
_ => return Err(ErrorBadRequest(LemmyError::from(anyhow!("wrong_type")))),
|
||||
};
|
||||
|
||||
|
@ -181,6 +184,7 @@ async fn get_feed(
|
|||
get_feed_front(&context, &info.sort_type()?, &info.get_limit(), ¶m).await
|
||||
}
|
||||
RequestType::Inbox => get_feed_inbox(&context, ¶m).await,
|
||||
RequestType::Modlog => get_feed_modlog(&context, ¶m).await,
|
||||
}
|
||||
.map_err(ErrorBadRequest)?;
|
||||
|
||||
|
@ -331,7 +335,7 @@ async fn get_feed_inbox(context: &LemmyContext, jwt: &str) -> LemmyResult<Channe
|
|||
.await?;
|
||||
|
||||
let protocol_and_hostname = context.settings().get_protocol_and_hostname();
|
||||
let items = create_reply_and_mention_items(inbox, &protocol_and_hostname, context)?;
|
||||
let items = create_reply_and_mention_items(inbox, context)?;
|
||||
|
||||
let mut channel = Channel {
|
||||
namespaces: RSS_NAMESPACE.clone(),
|
||||
|
@ -348,9 +352,41 @@ async fn get_feed_inbox(context: &LemmyContext, jwt: &str) -> LemmyResult<Channe
|
|||
Ok(channel)
|
||||
}
|
||||
|
||||
/// Gets your ModeratorView modlog
|
||||
async fn get_feed_modlog(context: &LemmyContext, jwt: &str) -> LemmyResult<Channel> {
|
||||
let site_view = SiteView::read_local(&mut context.pool()).await?;
|
||||
let local_user = local_user_view_from_jwt(jwt, context).await?;
|
||||
check_private_instance(&Some(local_user.clone()), &site_view.local_site)?;
|
||||
|
||||
let modlog = ModlogCombinedQuery {
|
||||
listing_type: Some(ListingType::ModeratorView),
|
||||
local_user: Some(&local_user.local_user),
|
||||
hide_modlog_names: Some(false),
|
||||
..Default::default()
|
||||
}
|
||||
.list(&mut context.pool())
|
||||
.await?;
|
||||
|
||||
let protocol_and_hostname = context.settings().get_protocol_and_hostname();
|
||||
let items = create_modlog_items(modlog, context.settings())?;
|
||||
|
||||
let mut channel = Channel {
|
||||
namespaces: RSS_NAMESPACE.clone(),
|
||||
title: format!("{} - Modlog", local_user.person.name),
|
||||
link: format!("{protocol_and_hostname}/modlog"),
|
||||
items,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
if let Some(site_desc) = site_view.site.description {
|
||||
channel.set_description(&site_desc);
|
||||
}
|
||||
|
||||
Ok(channel)
|
||||
}
|
||||
|
||||
fn create_reply_and_mention_items(
|
||||
inbox: Vec<InboxCombinedView>,
|
||||
protocol_and_hostname: &str,
|
||||
context: &LemmyContext,
|
||||
) -> LemmyResult<Vec<Item>> {
|
||||
let reply_items: Vec<Item> = inbox
|
||||
|
@ -359,41 +395,41 @@ fn create_reply_and_mention_items(
|
|||
InboxCombinedView::CommentReply(v) => {
|
||||
let reply_url = v.comment.local_url(context.settings())?;
|
||||
build_item(
|
||||
&v.creator.name,
|
||||
&v.creator,
|
||||
&v.comment.published,
|
||||
reply_url.as_str(),
|
||||
&v.comment.content,
|
||||
protocol_and_hostname,
|
||||
context.settings(),
|
||||
)
|
||||
}
|
||||
InboxCombinedView::CommentMention(v) => {
|
||||
let mention_url = v.comment.local_url(context.settings())?;
|
||||
build_item(
|
||||
&v.creator.name,
|
||||
&v.creator,
|
||||
&v.comment.published,
|
||||
mention_url.as_str(),
|
||||
&v.comment.content,
|
||||
protocol_and_hostname,
|
||||
context.settings(),
|
||||
)
|
||||
}
|
||||
InboxCombinedView::PostMention(v) => {
|
||||
let mention_url = v.post.local_url(context.settings())?;
|
||||
build_item(
|
||||
&v.creator.name,
|
||||
&v.creator,
|
||||
&v.post.published,
|
||||
mention_url.as_str(),
|
||||
&v.post.body.clone().unwrap_or_default(),
|
||||
protocol_and_hostname,
|
||||
context.settings(),
|
||||
)
|
||||
}
|
||||
InboxCombinedView::PrivateMessage(v) => {
|
||||
let inbox_url = format!("{}/inbox", protocol_and_hostname);
|
||||
let inbox_url = format!("{}/inbox", context.settings().get_protocol_and_hostname());
|
||||
build_item(
|
||||
&v.creator.name,
|
||||
&v.creator,
|
||||
&v.private_message.published,
|
||||
&inbox_url,
|
||||
&v.private_message.content,
|
||||
protocol_and_hostname,
|
||||
context.settings(),
|
||||
)
|
||||
}
|
||||
})
|
||||
|
@ -402,12 +438,292 @@ fn create_reply_and_mention_items(
|
|||
Ok(reply_items)
|
||||
}
|
||||
|
||||
fn create_modlog_items(
|
||||
modlog: Vec<ModlogCombinedView>,
|
||||
settings: &Settings,
|
||||
) -> LemmyResult<Vec<Item>> {
|
||||
// All of these go to your modlog url
|
||||
let modlog_url = format!(
|
||||
"{}/modlog?listing_type=ModeratorView",
|
||||
settings.get_protocol_and_hostname()
|
||||
);
|
||||
|
||||
let modlog_items: Vec<Item> = modlog
|
||||
.iter()
|
||||
.map(|r| match r {
|
||||
ModlogCombinedView::AdminAllowInstance(v) => build_modlog_item(
|
||||
&v.admin,
|
||||
&v.admin_allow_instance.published,
|
||||
&modlog_url,
|
||||
&format!(
|
||||
"Admin {} instance - {}",
|
||||
if v.admin_allow_instance.allowed {
|
||||
"allowed"
|
||||
} else {
|
||||
"disallowed"
|
||||
},
|
||||
&v.instance.domain
|
||||
),
|
||||
&v.admin_allow_instance.reason,
|
||||
settings,
|
||||
),
|
||||
ModlogCombinedView::AdminBlockInstance(v) => build_modlog_item(
|
||||
&v.admin,
|
||||
&v.admin_block_instance.published,
|
||||
&modlog_url,
|
||||
&format!(
|
||||
"Admin {} instance - {}",
|
||||
if v.admin_block_instance.blocked {
|
||||
"blocked"
|
||||
} else {
|
||||
"unblocked"
|
||||
},
|
||||
&v.instance.domain
|
||||
),
|
||||
&v.admin_block_instance.reason,
|
||||
settings,
|
||||
),
|
||||
ModlogCombinedView::AdminPurgeComment(v) => build_modlog_item(
|
||||
&v.admin,
|
||||
&v.admin_purge_comment.published,
|
||||
&modlog_url,
|
||||
"Admin purged comment",
|
||||
&v.admin_purge_comment.reason,
|
||||
settings,
|
||||
),
|
||||
ModlogCombinedView::AdminPurgeCommunity(v) => build_modlog_item(
|
||||
&v.admin,
|
||||
&v.admin_purge_community.published,
|
||||
&modlog_url,
|
||||
"Admin purged community",
|
||||
&v.admin_purge_community.reason,
|
||||
settings,
|
||||
),
|
||||
ModlogCombinedView::AdminPurgePerson(v) => build_modlog_item(
|
||||
&v.admin,
|
||||
&v.admin_purge_person.published,
|
||||
&modlog_url,
|
||||
"Admin purged person",
|
||||
&v.admin_purge_person.reason,
|
||||
settings,
|
||||
),
|
||||
ModlogCombinedView::AdminPurgePost(v) => build_modlog_item(
|
||||
&v.admin,
|
||||
&v.admin_purge_post.published,
|
||||
&modlog_url,
|
||||
"Admin purged post",
|
||||
&v.admin_purge_post.reason,
|
||||
settings,
|
||||
),
|
||||
ModlogCombinedView::ModAdd(v) => build_modlog_item(
|
||||
&v.moderator,
|
||||
&v.mod_add.published,
|
||||
&modlog_url,
|
||||
&format!(
|
||||
"{} admin {}",
|
||||
removed_added_str(v.mod_add.removed),
|
||||
&v.other_person.name
|
||||
),
|
||||
&None,
|
||||
settings,
|
||||
),
|
||||
ModlogCombinedView::ModAddCommunity(v) => build_modlog_item(
|
||||
&v.moderator,
|
||||
&v.mod_add_community.published,
|
||||
&modlog_url,
|
||||
&format!(
|
||||
"{} mod {} to /c/{}",
|
||||
removed_added_str(v.mod_add_community.removed),
|
||||
&v.other_person.name,
|
||||
&v.community.name
|
||||
),
|
||||
&None,
|
||||
settings,
|
||||
),
|
||||
ModlogCombinedView::ModBan(v) => build_modlog_item(
|
||||
&v.moderator,
|
||||
&v.mod_ban.published,
|
||||
&modlog_url,
|
||||
&format!(
|
||||
"{} {}",
|
||||
banned_unbanned_str(v.mod_ban.banned),
|
||||
&v.other_person.name
|
||||
),
|
||||
&v.mod_ban.reason,
|
||||
settings,
|
||||
),
|
||||
ModlogCombinedView::ModBanFromCommunity(v) => build_modlog_item(
|
||||
&v.moderator,
|
||||
&v.mod_ban_from_community.published,
|
||||
&modlog_url,
|
||||
&format!(
|
||||
"{} {} from /c/{}",
|
||||
banned_unbanned_str(v.mod_ban_from_community.banned),
|
||||
&v.other_person.name,
|
||||
&v.community.name
|
||||
),
|
||||
&v.mod_ban_from_community.reason,
|
||||
settings,
|
||||
),
|
||||
ModlogCombinedView::ModFeaturePost(v) => build_modlog_item(
|
||||
&v.moderator,
|
||||
&v.mod_feature_post.published,
|
||||
&modlog_url,
|
||||
&format!(
|
||||
"{} post {}",
|
||||
if v.mod_feature_post.featured {
|
||||
"Featured"
|
||||
} else {
|
||||
"Unfeatured"
|
||||
},
|
||||
&v.post.name
|
||||
),
|
||||
&None,
|
||||
settings,
|
||||
),
|
||||
ModlogCombinedView::ModChangeCommunityVisibility(v) => build_modlog_item(
|
||||
&v.moderator,
|
||||
&v.mod_change_community_visibility.published,
|
||||
&modlog_url,
|
||||
&format!(
|
||||
"Changed /c/{} visibility to {}",
|
||||
&v.community.name, &v.mod_change_community_visibility.visibility
|
||||
),
|
||||
&None,
|
||||
settings,
|
||||
),
|
||||
ModlogCombinedView::ModLockPost(v) => build_modlog_item(
|
||||
&v.moderator,
|
||||
&v.mod_lock_post.published,
|
||||
&modlog_url,
|
||||
&format!(
|
||||
"{} post {}",
|
||||
if v.mod_lock_post.locked {
|
||||
"Locked"
|
||||
} else {
|
||||
"Unlocked"
|
||||
},
|
||||
&v.post.name
|
||||
),
|
||||
&v.mod_lock_post.reason,
|
||||
settings,
|
||||
),
|
||||
ModlogCombinedView::ModRemoveComment(v) => build_modlog_item(
|
||||
&v.moderator,
|
||||
&v.mod_remove_comment.published,
|
||||
&modlog_url,
|
||||
&format!(
|
||||
"{} comment {}",
|
||||
removed_restored_str(v.mod_remove_comment.removed),
|
||||
&v.comment.content
|
||||
),
|
||||
&v.mod_remove_comment.reason,
|
||||
settings,
|
||||
),
|
||||
ModlogCombinedView::ModRemoveCommunity(v) => build_modlog_item(
|
||||
&v.moderator,
|
||||
&v.mod_remove_community.published,
|
||||
&modlog_url,
|
||||
&format!(
|
||||
"{} community /c/{}",
|
||||
removed_restored_str(v.mod_remove_community.removed),
|
||||
&v.community.name
|
||||
),
|
||||
&v.mod_remove_community.reason,
|
||||
settings,
|
||||
),
|
||||
ModlogCombinedView::ModRemovePost(v) => build_modlog_item(
|
||||
&v.moderator,
|
||||
&v.mod_remove_post.published,
|
||||
&modlog_url,
|
||||
&format!(
|
||||
"{} post {}",
|
||||
removed_restored_str(v.mod_remove_post.removed),
|
||||
&v.post.name
|
||||
),
|
||||
&v.mod_remove_post.reason,
|
||||
settings,
|
||||
),
|
||||
ModlogCombinedView::ModTransferCommunity(v) => build_modlog_item(
|
||||
&v.moderator,
|
||||
&v.mod_transfer_community.published,
|
||||
&modlog_url,
|
||||
&format!(
|
||||
"Tranferred /c/{} to /u/{}",
|
||||
&v.community.name, &v.other_person.name
|
||||
),
|
||||
&None,
|
||||
settings,
|
||||
),
|
||||
})
|
||||
.collect::<LemmyResult<Vec<Item>>>()?;
|
||||
|
||||
Ok(modlog_items)
|
||||
}
|
||||
|
||||
fn removed_added_str(removed: bool) -> &'static str {
|
||||
if removed {
|
||||
"Removed"
|
||||
} else {
|
||||
"Added"
|
||||
}
|
||||
}
|
||||
|
||||
fn banned_unbanned_str(banned: bool) -> &'static str {
|
||||
if banned {
|
||||
"Banned"
|
||||
} else {
|
||||
"Unbanned"
|
||||
}
|
||||
}
|
||||
|
||||
fn removed_restored_str(removed: bool) -> &'static str {
|
||||
if removed {
|
||||
"Removed"
|
||||
} else {
|
||||
"Restored"
|
||||
}
|
||||
}
|
||||
|
||||
fn build_modlog_item(
|
||||
mod_: &Option<Person>,
|
||||
published: &DateTime<Utc>,
|
||||
url: &str,
|
||||
action: &str,
|
||||
reason: &Option<String>,
|
||||
settings: &Settings,
|
||||
) -> LemmyResult<Item> {
|
||||
let guid = Some(Guid {
|
||||
permalink: true,
|
||||
value: action.to_owned(),
|
||||
});
|
||||
let author = if let Some(mod_) = mod_ {
|
||||
Some(format!(
|
||||
"/u/{} <a href=\"{}\">(link)</a>",
|
||||
mod_.name,
|
||||
mod_.actor_url(settings)?
|
||||
))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(Item {
|
||||
title: Some(action.to_string()),
|
||||
author,
|
||||
pub_date: Some(published.to_rfc2822()),
|
||||
link: Some(url.to_owned()),
|
||||
guid,
|
||||
description: reason.clone(),
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
|
||||
fn build_item(
|
||||
creator_name: &str,
|
||||
creator: &Person,
|
||||
published: &DateTime<Utc>,
|
||||
url: &str,
|
||||
content: &str,
|
||||
protocol_and_hostname: &str,
|
||||
settings: &Settings,
|
||||
) -> LemmyResult<Item> {
|
||||
// TODO add images
|
||||
let guid = Some(Guid {
|
||||
|
@ -417,10 +733,11 @@ fn build_item(
|
|||
let description = Some(markdown_to_html(content));
|
||||
|
||||
Ok(Item {
|
||||
title: Some(format!("Reply from {creator_name}")),
|
||||
title: Some(format!("Reply from {}", creator.name)),
|
||||
author: Some(format!(
|
||||
"/u/{creator_name} <a href=\"{}\">(link)</a>",
|
||||
format_args!("{protocol_and_hostname}/u/{creator_name}")
|
||||
"/u/{} <a href=\"{}\">(link)</a>",
|
||||
creator.name,
|
||||
creator.actor_url(settings)?
|
||||
)),
|
||||
pub_date: Some(published.to_rfc2822()),
|
||||
comments: Some(url.to_owned()),
|
||||
|
@ -436,7 +753,7 @@ fn create_post_items(posts: Vec<PostView>, settings: &Settings) -> LemmyResult<V
|
|||
|
||||
for p in posts {
|
||||
let post_url = p.post.local_url(settings)?;
|
||||
let community_url = Community::local_url(&p.community.name, settings)?;
|
||||
let community_url = &p.community.actor_url(settings)?;
|
||||
let dublin_core_ext = Some(DublinCoreExtension {
|
||||
creators: vec![p.creator.ap_id.to_string()],
|
||||
..DublinCoreExtension::default()
|
||||
|
@ -446,7 +763,7 @@ fn create_post_items(posts: Vec<PostView>, settings: &Settings) -> LemmyResult<V
|
|||
value: post_url.to_string(),
|
||||
});
|
||||
let mut description = format!("submitted by <a href=\"{}\">{}</a> to <a href=\"{}\">{}</a><br>{} points | <a href=\"{}\">{} comments</a>",
|
||||
p.creator.ap_id,
|
||||
p.creator.actor_url(settings)?,
|
||||
&p.creator.name,
|
||||
community_url,
|
||||
&p.community.name,
|
||||
|
|
|
@ -10,7 +10,7 @@ use lemmy_db_schema::{
|
|||
person::{Person, PersonInsertForm},
|
||||
site::{Site, SiteInsertForm},
|
||||
},
|
||||
traits::Crud,
|
||||
traits::{ApubActor, Crud},
|
||||
utils::DbPool,
|
||||
};
|
||||
use lemmy_db_views_site::SiteView;
|
||||
|
@ -37,7 +37,7 @@ pub async fn setup_local_site(pool: &mut DbPool<'_>, settings: &Settings) -> Lem
|
|||
|
||||
if let Some(setup) = &settings.setup {
|
||||
let person_keypair = generate_actor_keypair()?;
|
||||
let person_ap_id = Person::local_url(&setup.admin_username, settings)?;
|
||||
let person_ap_id = Person::generate_local_actor_url(&setup.admin_username, settings)?;
|
||||
|
||||
// Register the user if there's a site setup
|
||||
let person_form = PersonInsertForm {
|
||||
|
|
Loading…
Reference in a new issue