From 132af64a6ec2cc25b2aaff1552d6b0df693ac8c9 Mon Sep 17 00:00:00 2001 From: sup39 Date: Sun, 9 Jun 2024 16:34:58 +0800 Subject: [PATCH] refactor (backend-rs): create all_texts macro --- .../backend-rs/src/misc/check_word_mute.rs | 10 +- .../backend-rs/src/misc/get_note_all_texts.rs | 126 ++++++++++++------ .../src/service/antenna/process_new_note.rs | 10 +- 3 files changed, 87 insertions(+), 59 deletions(-) diff --git a/packages/backend-rs/src/misc/check_word_mute.rs b/packages/backend-rs/src/misc/check_word_mute.rs index 6777f05728..6faf9352ec 100644 --- a/packages/backend-rs/src/misc/check_word_mute.rs +++ b/packages/backend-rs/src/misc/check_word_mute.rs @@ -59,15 +59,7 @@ pub async fn check_word_mute( Ok(false) } else { Ok(check_word_mute_impl( - &all_texts( - note.file_ids, - note.text, - note.cw, - note.renote_id, - note.reply_id, - true, - ) - .await?, + &all_texts!(note, true).await?, muted_words, muted_patterns, )) diff --git a/packages/backend-rs/src/misc/get_note_all_texts.rs b/packages/backend-rs/src/misc/get_note_all_texts.rs index 57a3444430..8db5fbc8f3 100644 --- a/packages/backend-rs/src/misc/get_note_all_texts.rs +++ b/packages/backend-rs/src/misc/get_note_all_texts.rs @@ -6,18 +6,20 @@ use sea_orm::{prelude::*, QuerySelect}; /// Returns [`Vec`] containing the post text, content warning, /// those of the "parent" (replied/quoted) posts, and alt texts of attached files. +/// Consider using [`all_texts`] macro instead +/// when dealing with a note ([`note::Model`])-like instance. /// /// # Arguments /// /// * `file_ids` : IDs of attached files ([`drive_file::Model`]) /// * `text`, `cw`, `renote_id`, `reply_id` : note ([`note::Model`]) fields /// * `include_parent` : whether to take the reply-to post and quoted post into account -pub async fn all_texts( - file_ids: Vec, +pub async fn all_texts_impl( + file_ids: &[String], text: Option, cw: Option, - renote_id: Option, - reply_id: Option, + renote_id: &Option, + reply_id: &Option, include_parent: bool, ) -> Result, DbErr> { let db = db_conn().await?; @@ -26,10 +28,10 @@ pub async fn all_texts( let is_renote = text.is_none(); if let Some(text) = text { - texts.push(text) + texts.push(text); } if let Some(cw) = cw { - texts.push(cw) + texts.push(cw); } texts.extend( @@ -44,45 +46,87 @@ pub async fn all_texts( .flatten(), ); - if renote_id.is_some() && (include_parent || is_renote) { - let renote_id = renote_id.unwrap(); - - if let Some((text, cw)) = note::Entity::find_by_id(&renote_id) - .select_only() - .columns([note::Column::Text, note::Column::Cw]) - .into_tuple::<(Option, Option)>() - .one(db) - .await? - { - if let Some(t) = text { - texts.push(t); - } - if let Some(c) = cw { - texts.push(c); - } - } else { - tracing::warn!("nonexistent renote id: {}", renote_id); + let mut query_note_ids = Vec::<&str>::with_capacity(2); + if let Some(renote_id) = renote_id { + if include_parent || is_renote { + query_note_ids.push(renote_id); } } - - if include_parent && reply_id.is_some() { - if let Some((text, cw)) = note::Entity::find_by_id(reply_id.as_ref().unwrap()) - .select_only() - .columns([note::Column::Text, note::Column::Cw]) - .into_tuple::<(Option, Option)>() - .one(db) - .await? - { - if let Some(t) = text { - texts.push(t); - } - if let Some(c) = cw { - texts.push(c); - } - } else { - tracing::warn!("nonexistent reply id: {}", reply_id.unwrap()); + if let Some(reply_id) = reply_id { + if include_parent { + query_note_ids.push(reply_id); } } + if !query_note_ids.is_empty() { + texts.extend( + note::Entity::find() + .filter(note::Column::Id.is_in(query_note_ids)) + .select_only() + .columns([note::Column::Text, note::Column::Cw]) + .into_tuple::<(Option, Option)>() + .one(db) + .await? + .into_iter() + .flat_map(|(text, cw)| [text, cw]) + .flatten(), + ); + } Ok(texts) } + +/// Returns [`Vec`] containing the post text, content warning, +/// those of the "parent" (replied/quoted) posts, and alt texts of attached files. +/// +/// # Arguments +/// +/// * `note_like` : a note ([`note::Model`])-like instance containing +/// `file_ids`, `text`, `cw`, `renote_id`, `reply_id` fields +/// * `include_parent` ([bool]) : whether to take the reply-to post and quoted post into account +/// +/// # Caveats +/// +/// The `note_like` argument should not contain function calls +/// (e.g., `all_texts!(note.clone(), false)`) +/// since the function will be called multiple times after macro expansion. +/// +/// # Examples +/// +/// ``` +/// # use backend_rs::misc::get_note_all_texts::all_texts; +/// // note-like struct +/// struct SomeNoteLikeStruct { +/// // required fields +/// file_ids: Vec, +/// text: Option, +/// cw: Option, +/// renote_id: Option, +/// reply_id: Option, +/// // arbitrary extra fields +/// extra_field_1: u32, +/// extra_field_2: Vec, +/// } +/// +/// async fn all_texts_from_some_note_like_struct( +/// note_like: &SomeNoteLikeStruct, +/// include_parent: bool, +/// ) -> Result, sea_orm::DbErr> { +/// all_texts!(note_like, include_parent).await +/// } +/// ``` +#[doc(hidden)] // hide the macro in the top doc page +#[macro_export] +macro_rules! all_texts { + ($note_like:expr, $include_parent:expr) => { + $crate::misc::get_note_all_texts::all_texts_impl( + &$note_like.file_ids, + $note_like.text.clone(), + $note_like.cw.clone(), + &$note_like.renote_id, + &$note_like.reply_id, + $include_parent, + ) + }; +} +#[doc(inline)] // show the macro in the module doc page +pub use all_texts; diff --git a/packages/backend-rs/src/service/antenna/process_new_note.rs b/packages/backend-rs/src/service/antenna/process_new_note.rs index 2d1f818afc..f4ec336681 100644 --- a/packages/backend-rs/src/service/antenna/process_new_note.rs +++ b/packages/backend-rs/src/service/antenna/process_new_note.rs @@ -41,15 +41,7 @@ pub async fn update_antennas_on_new_note( note_author: &Acct, note_muted_users: &[String], ) -> Result<(), Error> { - let note_all_texts = all_texts( - note.file_ids.to_owned(), - note.text.to_owned(), - note.cw.to_owned(), - note.renote_id.to_owned(), - note.reply_id.to_owned(), - false, - ) - .await?; + let note_all_texts = all_texts!(note, false).await?; // TODO: do this in parallel for antenna in antenna::cache::get().await?.iter() {