* Ignore old federated post edits (ref #4529) * use filter on insert * coalesce(updated, published) * avoid comment conflict clause --------- Co-authored-by: SleeplessOne1917 <28871516+SleeplessOne1917@users.noreply.github.com>
This commit is contained in:
parent
99d585b7be
commit
0203b62a6d
8 changed files with 136 additions and 42 deletions
|
@ -29,6 +29,7 @@ use lemmy_db_schema::{
|
|||
post::Post,
|
||||
},
|
||||
traits::Crud,
|
||||
utils::naive_now,
|
||||
};
|
||||
use lemmy_utils::{
|
||||
error::{LemmyError, LemmyErrorType},
|
||||
|
@ -141,6 +142,7 @@ impl Object for ApubComment {
|
|||
check_apub_id_valid_with_strictness(note.id.inner(), community.local, context).await?;
|
||||
verify_is_remote_object(note.id.inner(), context.settings())?;
|
||||
verify_person_in_community(¬e.attributed_to, &community, context).await?;
|
||||
|
||||
let (post, _) = note.get_parents(context).await?;
|
||||
let creator = note.attributed_to.dereference(context).await?;
|
||||
let is_mod_or_admin = is_mod_or_admin(&mut context.pool(), &creator, community.id)
|
||||
|
@ -184,7 +186,14 @@ impl Object for ApubComment {
|
|||
language_id,
|
||||
};
|
||||
let parent_comment_path = parent_comment.map(|t| t.0.path);
|
||||
let comment = Comment::create(&mut context.pool(), &form, parent_comment_path.as_ref()).await?;
|
||||
let timestamp: DateTime<Utc> = note.updated.or(note.published).unwrap_or_else(naive_now);
|
||||
let comment = Comment::insert_apub(
|
||||
&mut context.pool(),
|
||||
Some(timestamp),
|
||||
&form,
|
||||
parent_comment_path.as_ref(),
|
||||
)
|
||||
.await?;
|
||||
Ok(comment.into())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -175,7 +175,8 @@ impl Object for ApubCommunity {
|
|||
let languages =
|
||||
LanguageTag::to_language_id_multiple(group.language, &mut context.pool()).await?;
|
||||
|
||||
let community = Community::create(&mut context.pool(), &form).await?;
|
||||
let timestamp = group.updated.or(group.published).unwrap_or_else(naive_now);
|
||||
let community = Community::insert_apub(&mut context.pool(), timestamp, &form).await?;
|
||||
CommunityLanguage::update(&mut context.pool(), languages, community.id).await?;
|
||||
|
||||
let community: ApubCommunity = community.into();
|
||||
|
|
|
@ -41,6 +41,7 @@ use lemmy_db_schema::{
|
|||
post::{Post, PostInsertForm, PostUpdateForm},
|
||||
},
|
||||
traits::Crud,
|
||||
utils::naive_now,
|
||||
};
|
||||
use lemmy_db_views_actor::structs::CommunityModeratorView;
|
||||
use lemmy_utils::{
|
||||
|
@ -270,7 +271,8 @@ impl Object for ApubPost {
|
|||
.build()
|
||||
};
|
||||
|
||||
let post = Post::create(&mut context.pool(), &form).await?;
|
||||
let timestamp = page.updated.or(page.published).unwrap_or_else(naive_now);
|
||||
let post = Post::insert_apub(&mut context.pool(), timestamp, &form).await?;
|
||||
|
||||
generate_post_link_metadata(
|
||||
post.clone(),
|
||||
|
|
|
@ -23,6 +23,7 @@ use lemmy_db_schema::{
|
|||
private_message::{PrivateMessage, PrivateMessageInsertForm},
|
||||
},
|
||||
traits::Crud,
|
||||
utils::naive_now,
|
||||
};
|
||||
use lemmy_utils::{
|
||||
error::{LemmyError, LemmyErrorType},
|
||||
|
@ -142,7 +143,8 @@ impl Object for ApubPrivateMessage {
|
|||
ap_id: Some(note.id.into()),
|
||||
local: Some(false),
|
||||
};
|
||||
let pm = PrivateMessage::create(&mut context.pool(), &form).await?;
|
||||
let timestamp = note.updated.or(note.published).unwrap_or_else(naive_now);
|
||||
let pm = PrivateMessage::insert_apub(&mut context.pool(), timestamp, &form).await?;
|
||||
Ok(pm.into())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use crate::{
|
||||
diesel::DecoratableTarget,
|
||||
newtypes::{CommentId, DbUrl, PersonId},
|
||||
schema::comment,
|
||||
source::comment::{
|
||||
|
@ -11,8 +12,9 @@ use crate::{
|
|||
CommentUpdateForm,
|
||||
},
|
||||
traits::{Crud, Likeable, Saveable},
|
||||
utils::{get_conn, naive_now, DbPool, DELETED_REPLACEMENT_TEXT},
|
||||
utils::{functions::coalesce, get_conn, naive_now, DbPool, DELETED_REPLACEMENT_TEXT},
|
||||
};
|
||||
use chrono::{DateTime, Utc};
|
||||
use diesel::{
|
||||
dsl::{insert_into, sql_query},
|
||||
result::Error,
|
||||
|
@ -59,6 +61,15 @@ impl Comment {
|
|||
pool: &mut DbPool<'_>,
|
||||
comment_form: &CommentInsertForm,
|
||||
parent_path: Option<&Ltree>,
|
||||
) -> Result<Comment, Error> {
|
||||
Self::insert_apub(pool, None, comment_form, parent_path).await
|
||||
}
|
||||
|
||||
pub async fn insert_apub(
|
||||
pool: &mut DbPool<'_>,
|
||||
timestamp: Option<DateTime<Utc>>,
|
||||
comment_form: &CommentInsertForm,
|
||||
parent_path: Option<&Ltree>,
|
||||
) -> Result<Comment, Error> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
|
||||
|
@ -67,13 +78,21 @@ impl Comment {
|
|||
.run(|conn| {
|
||||
Box::pin(async move {
|
||||
// Insert, to get the id
|
||||
let inserted_comment = insert_into(comment::table)
|
||||
let inserted_comment = if let Some(timestamp) = timestamp {
|
||||
insert_into(comment::table)
|
||||
.values(comment_form)
|
||||
.on_conflict(comment::ap_id)
|
||||
.filter_target(coalesce(comment::updated, comment::published).lt(timestamp))
|
||||
.do_update()
|
||||
.set(comment_form)
|
||||
.get_result::<Self>(conn)
|
||||
.await?;
|
||||
.await?
|
||||
} else {
|
||||
insert_into(comment::table)
|
||||
.values(comment_form)
|
||||
.get_result::<Self>(conn)
|
||||
.await?
|
||||
};
|
||||
|
||||
let comment_id = inserted_comment.id;
|
||||
|
||||
|
@ -129,6 +148,7 @@ where ca.comment_id = c.id"
|
|||
})
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn read_from_apub_id(
|
||||
pool: &mut DbPool<'_>,
|
||||
object_id: Url,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use crate::{
|
||||
diesel::DecoratableTarget,
|
||||
newtypes::{CommunityId, DbUrl, PersonId},
|
||||
schema::{community, community_follower, instance},
|
||||
source::{
|
||||
|
@ -17,9 +18,14 @@ use crate::{
|
|||
post::Post,
|
||||
},
|
||||
traits::{ApubActor, Bannable, Crud, Followable, Joinable},
|
||||
utils::{functions::lower, get_conn, DbPool},
|
||||
utils::{
|
||||
functions::{coalesce, lower},
|
||||
get_conn,
|
||||
DbPool,
|
||||
},
|
||||
SubscribedType,
|
||||
};
|
||||
use chrono::{DateTime, Utc};
|
||||
use diesel::{
|
||||
deserialize,
|
||||
dsl,
|
||||
|
@ -44,25 +50,15 @@ impl Crud for Community {
|
|||
type IdType = CommunityId;
|
||||
|
||||
async fn create(pool: &mut DbPool<'_>, form: &Self::InsertForm) -> Result<Self, Error> {
|
||||
let is_new_community = match &form.actor_id {
|
||||
Some(id) => Community::read_from_apub_id(pool, id).await?.is_none(),
|
||||
None => true,
|
||||
};
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
|
||||
// Can't do separate insert/update commands because InsertForm/UpdateForm aren't convertible
|
||||
let community_ = insert_into(community::table)
|
||||
.values(form)
|
||||
.on_conflict(community::actor_id)
|
||||
.do_update()
|
||||
.set(form)
|
||||
.get_result::<Self>(conn)
|
||||
.await?;
|
||||
|
||||
// Initialize languages for new community
|
||||
if is_new_community {
|
||||
CommunityLanguage::update(pool, vec![], community_.id).await?;
|
||||
}
|
||||
|
||||
Ok(community_)
|
||||
}
|
||||
|
@ -116,6 +112,35 @@ pub enum CollectionType {
|
|||
}
|
||||
|
||||
impl Community {
|
||||
pub async fn insert_apub(
|
||||
pool: &mut DbPool<'_>,
|
||||
timestamp: DateTime<Utc>,
|
||||
form: &CommunityInsertForm,
|
||||
) -> Result<Self, Error> {
|
||||
let is_new_community = match &form.actor_id {
|
||||
Some(id) => Community::read_from_apub_id(pool, id).await?.is_none(),
|
||||
None => true,
|
||||
};
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
|
||||
// Can't do separate insert/update commands because InsertForm/UpdateForm aren't convertible
|
||||
let community_ = insert_into(community::table)
|
||||
.values(form)
|
||||
.on_conflict(community::actor_id)
|
||||
.filter_target(coalesce(community::updated, community::published).lt(timestamp))
|
||||
.do_update()
|
||||
.set(form)
|
||||
.get_result::<Self>(conn)
|
||||
.await?;
|
||||
|
||||
// Initialize languages for new community
|
||||
if is_new_community {
|
||||
CommunityLanguage::update(pool, vec![], community_.id).await?;
|
||||
}
|
||||
|
||||
Ok(community_)
|
||||
}
|
||||
|
||||
/// Get the community which has a given moderators or featured url, also return the collection type
|
||||
pub async fn get_by_collection_url(
|
||||
pool: &mut DbPool<'_>,
|
||||
|
|
|
@ -27,8 +27,15 @@ use crate::{
|
|||
},
|
||||
};
|
||||
use ::url::Url;
|
||||
use chrono::Utc;
|
||||
use diesel::{dsl::insert_into, result::Error, ExpressionMethods, QueryDsl, TextExpressionMethods};
|
||||
use chrono::{DateTime, Utc};
|
||||
use diesel::{
|
||||
dsl::insert_into,
|
||||
result::Error,
|
||||
DecoratableTarget,
|
||||
ExpressionMethods,
|
||||
QueryDsl,
|
||||
TextExpressionMethods,
|
||||
};
|
||||
use diesel_async::RunQueryDsl;
|
||||
use std::collections::HashSet;
|
||||
|
||||
|
@ -42,9 +49,6 @@ impl Crud for Post {
|
|||
let conn = &mut get_conn(pool).await?;
|
||||
insert_into(post::table)
|
||||
.values(form)
|
||||
.on_conflict(post::ap_id)
|
||||
.do_update()
|
||||
.set(form)
|
||||
.get_result::<Self>(conn)
|
||||
.await
|
||||
}
|
||||
|
@ -63,6 +67,22 @@ impl Crud for Post {
|
|||
}
|
||||
|
||||
impl Post {
|
||||
pub async fn insert_apub(
|
||||
pool: &mut DbPool<'_>,
|
||||
timestamp: DateTime<Utc>,
|
||||
form: &PostInsertForm,
|
||||
) -> Result<Self, Error> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
insert_into(post::table)
|
||||
.values(form)
|
||||
.on_conflict(post::ap_id)
|
||||
.filter_target(coalesce(post::updated, post::published).lt(timestamp))
|
||||
.do_update()
|
||||
.set(form)
|
||||
.get_result::<Self>(conn)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn list_for_community(
|
||||
pool: &mut DbPool<'_>,
|
||||
the_community_id: CommunityId,
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
use crate::{
|
||||
diesel::DecoratableTarget,
|
||||
newtypes::{DbUrl, PersonId, PrivateMessageId},
|
||||
schema::private_message::dsl::{ap_id, private_message, read, recipient_id},
|
||||
schema::private_message,
|
||||
source::private_message::{PrivateMessage, PrivateMessageInsertForm, PrivateMessageUpdateForm},
|
||||
traits::Crud,
|
||||
utils::{get_conn, DbPool},
|
||||
utils::{functions::coalesce, get_conn, DbPool},
|
||||
};
|
||||
use chrono::{DateTime, Utc};
|
||||
use diesel::{dsl::insert_into, result::Error, ExpressionMethods, QueryDsl};
|
||||
use diesel_async::RunQueryDsl;
|
||||
use lemmy_utils::error::LemmyError;
|
||||
|
@ -18,11 +20,8 @@ impl Crud for PrivateMessage {
|
|||
|
||||
async fn create(pool: &mut DbPool<'_>, form: &Self::InsertForm) -> Result<Self, Error> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
insert_into(private_message)
|
||||
insert_into(private_message::table)
|
||||
.values(form)
|
||||
.on_conflict(ap_id)
|
||||
.do_update()
|
||||
.set(form)
|
||||
.get_result::<Self>(conn)
|
||||
.await
|
||||
}
|
||||
|
@ -33,7 +32,7 @@ impl Crud for PrivateMessage {
|
|||
form: &Self::UpdateForm,
|
||||
) -> Result<Self, Error> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
diesel::update(private_message.find(private_message_id))
|
||||
diesel::update(private_message::table.find(private_message_id))
|
||||
.set(form)
|
||||
.get_result::<Self>(conn)
|
||||
.await
|
||||
|
@ -41,17 +40,33 @@ impl Crud for PrivateMessage {
|
|||
}
|
||||
|
||||
impl PrivateMessage {
|
||||
pub async fn insert_apub(
|
||||
pool: &mut DbPool<'_>,
|
||||
timestamp: DateTime<Utc>,
|
||||
form: &PrivateMessageInsertForm,
|
||||
) -> Result<Self, Error> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
insert_into(private_message::table)
|
||||
.values(form)
|
||||
.on_conflict(private_message::ap_id)
|
||||
.filter_target(coalesce(private_message::updated, private_message::published).lt(timestamp))
|
||||
.do_update()
|
||||
.set(form)
|
||||
.get_result::<Self>(conn)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn mark_all_as_read(
|
||||
pool: &mut DbPool<'_>,
|
||||
for_recipient_id: PersonId,
|
||||
) -> Result<Vec<PrivateMessage>, Error> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
diesel::update(
|
||||
private_message
|
||||
.filter(recipient_id.eq(for_recipient_id))
|
||||
.filter(read.eq(false)),
|
||||
private_message::table
|
||||
.filter(private_message::recipient_id.eq(for_recipient_id))
|
||||
.filter(private_message::read.eq(false)),
|
||||
)
|
||||
.set(read.eq(true))
|
||||
.set(private_message::read.eq(true))
|
||||
.get_results::<Self>(conn)
|
||||
.await
|
||||
}
|
||||
|
@ -63,8 +78,8 @@ impl PrivateMessage {
|
|||
let conn = &mut get_conn(pool).await?;
|
||||
let object_id: DbUrl = object_id.into();
|
||||
Ok(
|
||||
private_message
|
||||
.filter(ap_id.eq(object_id))
|
||||
private_message::table
|
||||
.filter(private_message::ap_id.eq(object_id))
|
||||
.first::<PrivateMessage>(conn)
|
||||
.await
|
||||
.ok()
|
||||
|
|
Loading…
Reference in a new issue