lemmy/crates/api_common/src/build_response.rs
dullbananas 1d38aad9d3
Make functions work with both connection and pool (#3420)
* a lot

* merge

* Fix stuff broken by merge

* Get rid of repetitive `&mut *context.conn().await?`

* Add blank lines under each line with `conn =`

* Fix style mistakes (partial)

* Revert "Fix style mistakes (partial)"

This reverts commit 48a033b87f.

* Revert "Add blank lines under each line with `conn =`"

This reverts commit 773a6d3beb.

* Revert "Get rid of repetitive `&mut *context.conn().await?`"

This reverts commit d2c6263ea1.

* Use DbConn for CaptchaAnswer methods

* DbConn trait

* Remove more `&mut *`

* Fix stuff

* Re-run CI

* try to make ci start

* fix

* fix

* Fix api_common::utils

* Fix apub::activities::block

* Fix apub::api::resolve_object

* Fix some things

* Revert "Fix some things"

This reverts commit 2bf8574bc8.

* Revert "Fix apub::api::resolve_object"

This reverts commit 3e4059aabb.

* Revert "Fix apub::activities::block"

This reverts commit 3b02389abd.

* Revert "Fix api_common::utils"

This reverts commit 7dc73de613.

* Revert "Revert "Fix api_common::utils""

This reverts commit f740f115e5.

* Revert "Revert "Fix apub::activities::block""

This reverts commit 2ee206af7c.

* Revert "Revert "Fix apub::api::resolve_object""

This reverts commit 96ed8bf2e9.

* Fix fetch_local_site_data

* Fix get_comment_parent_creator

* Remove unused perma deleted text

* Fix routes::feeds

* Fix lib.rs

* Update lib.rs

* rerun ci

* Attempt to create custom GetConn and RunQueryDsl traits

* Start over

* Add GetConn trait

* aaaa

* Revert "aaaa"

This reverts commit acc9ca1aed.

* Revert "Revert "aaaa""

This reverts commit 443a2a00a5.

* still aaaaaaaaaaaaa

* Return to earlier thing

Revert "Add GetConn trait"

This reverts commit ab4e94aea5.

* Try to use DbPool enum

* Revert "Try to use DbPool enum"

This reverts commit e4d1712646.

* DbConn and DbPool enums (db_schema only fails to compile for tests)

* fmt

* Make functions take `&mut DbPool<'_>` and make db_schema tests compile

* Add try_join_with_pool macro and run fix-clippy on more crates

* Fix some errors

* I did it

* Remove function variants that take connection

* rerun ci

* rerun ci

* rerun ci
2023-07-11 09:09:59 -04:00

219 lines
7.1 KiB
Rust

use crate::{
comment::CommentResponse,
community::CommunityResponse,
context::LemmyContext,
post::PostResponse,
utils::{check_person_block, get_interface_language, is_mod_or_admin, send_email_to_user},
};
use actix_web::web::Data;
use lemmy_db_schema::{
newtypes::{CommentId, CommunityId, LocalUserId, PersonId, PostId},
source::{
actor_language::CommunityLanguage,
comment::Comment,
comment_reply::{CommentReply, CommentReplyInsertForm},
person::Person,
person_mention::{PersonMention, PersonMentionInsertForm},
post::Post,
},
traits::Crud,
};
use lemmy_db_views::structs::{CommentView, LocalUserView, PostView};
use lemmy_db_views_actor::structs::CommunityView;
use lemmy_utils::{error::LemmyError, utils::mention::MentionData};
pub async fn build_comment_response(
context: &Data<LemmyContext>,
comment_id: CommentId,
local_user_view: Option<LocalUserView>,
form_id: Option<String>,
recipient_ids: Vec<LocalUserId>,
) -> Result<CommentResponse, LemmyError> {
let person_id = local_user_view.map(|l| l.person.id);
let comment_view = CommentView::read(&mut context.pool(), comment_id, person_id).await?;
Ok(CommentResponse {
comment_view,
recipient_ids,
form_id,
})
}
pub async fn build_community_response(
context: &Data<LemmyContext>,
local_user_view: LocalUserView,
community_id: CommunityId,
) -> Result<CommunityResponse, LemmyError> {
let is_mod_or_admin =
is_mod_or_admin(&mut context.pool(), local_user_view.person.id, community_id)
.await
.is_ok();
let person_id = local_user_view.person.id;
let community_view = CommunityView::read(
&mut context.pool(),
community_id,
Some(person_id),
Some(is_mod_or_admin),
)
.await?;
let discussion_languages = CommunityLanguage::read(&mut context.pool(), community_id).await?;
Ok(CommunityResponse {
community_view,
discussion_languages,
})
}
pub async fn build_post_response(
context: &Data<LemmyContext>,
community_id: CommunityId,
person_id: PersonId,
post_id: PostId,
) -> Result<PostResponse, LemmyError> {
let is_mod_or_admin = is_mod_or_admin(&mut context.pool(), person_id, community_id)
.await
.is_ok();
let post_view = PostView::read(
&mut context.pool(),
post_id,
Some(person_id),
Some(is_mod_or_admin),
)
.await?;
Ok(PostResponse { post_view })
}
// TODO: this function is a mess and should be split up to handle email seperately
#[tracing::instrument(skip_all)]
pub async fn send_local_notifs(
mentions: Vec<MentionData>,
comment: &Comment,
person: &Person,
post: &Post,
do_send_email: bool,
context: &LemmyContext,
) -> Result<Vec<LocalUserId>, LemmyError> {
let mut recipient_ids = Vec::new();
let inbox_link = format!("{}/inbox", context.settings().get_protocol_and_hostname());
// Send the local mentions
for mention in mentions
.iter()
.filter(|m| m.is_local(&context.settings().hostname) && m.name.ne(&person.name))
{
let mention_name = mention.name.clone();
let user_view = LocalUserView::read_from_name(&mut context.pool(), &mention_name).await;
if let Ok(mention_user_view) = user_view {
// TODO
// At some point, make it so you can't tag the parent creator either
// This can cause two notifications, one for reply and the other for mention
recipient_ids.push(mention_user_view.local_user.id);
let user_mention_form = PersonMentionInsertForm {
recipient_id: mention_user_view.person.id,
comment_id: comment.id,
read: None,
};
// Allow this to fail softly, since comment edits might re-update or replace it
// Let the uniqueness handle this fail
PersonMention::create(&mut context.pool(), &user_mention_form)
.await
.ok();
// Send an email to those local users that have notifications on
if do_send_email {
let lang = get_interface_language(&mention_user_view);
send_email_to_user(
&mention_user_view,
&lang.notification_mentioned_by_subject(&person.name),
&lang.notification_mentioned_by_body(&comment.content, &inbox_link, &person.name),
context.settings(),
)
.await
}
}
}
// Send comment_reply to the parent commenter / poster
if let Some(parent_comment_id) = comment.parent_comment_id() {
let parent_comment = Comment::read(&mut context.pool(), parent_comment_id).await?;
// Get the parent commenter local_user
let parent_creator_id = parent_comment.creator_id;
// Only add to recipients if that person isn't blocked
let creator_blocked = check_person_block(person.id, parent_creator_id, &mut context.pool())
.await
.is_err();
// Don't send a notif to yourself
if parent_comment.creator_id != person.id && !creator_blocked {
let user_view = LocalUserView::read_person(&mut context.pool(), parent_creator_id).await;
if let Ok(parent_user_view) = user_view {
recipient_ids.push(parent_user_view.local_user.id);
let comment_reply_form = CommentReplyInsertForm {
recipient_id: parent_user_view.person.id,
comment_id: comment.id,
read: None,
};
// Allow this to fail softly, since comment edits might re-update or replace it
// Let the uniqueness handle this fail
CommentReply::create(&mut context.pool(), &comment_reply_form)
.await
.ok();
if do_send_email {
let lang = get_interface_language(&parent_user_view);
send_email_to_user(
&parent_user_view,
&lang.notification_comment_reply_subject(&person.name),
&lang.notification_comment_reply_body(&comment.content, &inbox_link, &person.name),
context.settings(),
)
.await
}
}
}
} else {
// If there's no parent, its the post creator
// Only add to recipients if that person isn't blocked
let creator_blocked = check_person_block(person.id, post.creator_id, &mut context.pool())
.await
.is_err();
if post.creator_id != person.id && !creator_blocked {
let creator_id = post.creator_id;
let parent_user = LocalUserView::read_person(&mut context.pool(), creator_id).await;
if let Ok(parent_user_view) = parent_user {
recipient_ids.push(parent_user_view.local_user.id);
let comment_reply_form = CommentReplyInsertForm {
recipient_id: parent_user_view.person.id,
comment_id: comment.id,
read: None,
};
// Allow this to fail softly, since comment edits might re-update or replace it
// Let the uniqueness handle this fail
CommentReply::create(&mut context.pool(), &comment_reply_form)
.await
.ok();
if do_send_email {
let lang = get_interface_language(&parent_user_view);
send_email_to_user(
&parent_user_view,
&lang.notification_post_reply_subject(&person.name),
&lang.notification_post_reply_body(&comment.content, &inbox_link, &person.name),
context.settings(),
)
.await
}
}
}
}
Ok(recipient_ids)
}