refactor (backend-rs): create all_texts macro
This commit is contained in:
parent
09d975bdce
commit
132af64a6e
3 changed files with 87 additions and 59 deletions
|
@ -59,15 +59,7 @@ pub async fn check_word_mute(
|
||||||
Ok(false)
|
Ok(false)
|
||||||
} else {
|
} else {
|
||||||
Ok(check_word_mute_impl(
|
Ok(check_word_mute_impl(
|
||||||
&all_texts(
|
&all_texts!(note, true).await?,
|
||||||
note.file_ids,
|
|
||||||
note.text,
|
|
||||||
note.cw,
|
|
||||||
note.renote_id,
|
|
||||||
note.reply_id,
|
|
||||||
true,
|
|
||||||
)
|
|
||||||
.await?,
|
|
||||||
muted_words,
|
muted_words,
|
||||||
muted_patterns,
|
muted_patterns,
|
||||||
))
|
))
|
||||||
|
|
|
@ -6,18 +6,20 @@ use sea_orm::{prelude::*, QuerySelect};
|
||||||
|
|
||||||
/// Returns [`Vec<String>`] containing the post text, content warning,
|
/// Returns [`Vec<String>`] containing the post text, content warning,
|
||||||
/// those of the "parent" (replied/quoted) posts, and alt texts of attached files.
|
/// 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
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// * `file_ids` : IDs of attached files ([`drive_file::Model`])
|
/// * `file_ids` : IDs of attached files ([`drive_file::Model`])
|
||||||
/// * `text`, `cw`, `renote_id`, `reply_id` : note ([`note::Model`]) fields
|
/// * `text`, `cw`, `renote_id`, `reply_id` : note ([`note::Model`]) fields
|
||||||
/// * `include_parent` : whether to take the reply-to post and quoted post into account
|
/// * `include_parent` : whether to take the reply-to post and quoted post into account
|
||||||
pub async fn all_texts(
|
pub async fn all_texts_impl(
|
||||||
file_ids: Vec<String>,
|
file_ids: &[String],
|
||||||
text: Option<String>,
|
text: Option<String>,
|
||||||
cw: Option<String>,
|
cw: Option<String>,
|
||||||
renote_id: Option<String>,
|
renote_id: &Option<String>,
|
||||||
reply_id: Option<String>,
|
reply_id: &Option<String>,
|
||||||
include_parent: bool,
|
include_parent: bool,
|
||||||
) -> Result<Vec<String>, DbErr> {
|
) -> Result<Vec<String>, DbErr> {
|
||||||
let db = db_conn().await?;
|
let db = db_conn().await?;
|
||||||
|
@ -26,10 +28,10 @@ pub async fn all_texts(
|
||||||
let is_renote = text.is_none();
|
let is_renote = text.is_none();
|
||||||
|
|
||||||
if let Some(text) = text {
|
if let Some(text) = text {
|
||||||
texts.push(text)
|
texts.push(text);
|
||||||
}
|
}
|
||||||
if let Some(cw) = cw {
|
if let Some(cw) = cw {
|
||||||
texts.push(cw)
|
texts.push(cw);
|
||||||
}
|
}
|
||||||
|
|
||||||
texts.extend(
|
texts.extend(
|
||||||
|
@ -44,45 +46,87 @@ pub async fn all_texts(
|
||||||
.flatten(),
|
.flatten(),
|
||||||
);
|
);
|
||||||
|
|
||||||
if renote_id.is_some() && (include_parent || is_renote) {
|
let mut query_note_ids = Vec::<&str>::with_capacity(2);
|
||||||
let renote_id = renote_id.unwrap();
|
if let Some(renote_id) = renote_id {
|
||||||
|
if include_parent || is_renote {
|
||||||
if let Some((text, cw)) = note::Entity::find_by_id(&renote_id)
|
query_note_ids.push(renote_id);
|
||||||
.select_only()
|
|
||||||
.columns([note::Column::Text, note::Column::Cw])
|
|
||||||
.into_tuple::<(Option<String>, Option<String>)>()
|
|
||||||
.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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let Some(reply_id) = reply_id {
|
||||||
if include_parent && reply_id.is_some() {
|
if include_parent {
|
||||||
if let Some((text, cw)) = note::Entity::find_by_id(reply_id.as_ref().unwrap())
|
query_note_ids.push(reply_id);
|
||||||
.select_only()
|
|
||||||
.columns([note::Column::Text, note::Column::Cw])
|
|
||||||
.into_tuple::<(Option<String>, Option<String>)>()
|
|
||||||
.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 !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<String>, Option<String>)>()
|
||||||
|
.one(db)
|
||||||
|
.await?
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(|(text, cw)| [text, cw])
|
||||||
|
.flatten(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(texts)
|
Ok(texts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns [`Vec<String>`] 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<String>,
|
||||||
|
/// text: Option<String>,
|
||||||
|
/// cw: Option<String>,
|
||||||
|
/// renote_id: Option<String>,
|
||||||
|
/// reply_id: Option<String>,
|
||||||
|
/// // arbitrary extra fields
|
||||||
|
/// extra_field_1: u32,
|
||||||
|
/// extra_field_2: Vec<String>,
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// async fn all_texts_from_some_note_like_struct(
|
||||||
|
/// note_like: &SomeNoteLikeStruct,
|
||||||
|
/// include_parent: bool,
|
||||||
|
/// ) -> Result<Vec<String>, 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;
|
||||||
|
|
|
@ -41,15 +41,7 @@ pub async fn update_antennas_on_new_note(
|
||||||
note_author: &Acct,
|
note_author: &Acct,
|
||||||
note_muted_users: &[String],
|
note_muted_users: &[String],
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let note_all_texts = all_texts(
|
let note_all_texts = all_texts!(note, false).await?;
|
||||||
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?;
|
|
||||||
|
|
||||||
// TODO: do this in parallel
|
// TODO: do this in parallel
|
||||||
for antenna in antenna::cache::get().await?.iter() {
|
for antenna in antenna::cache::get().await?.iter() {
|
||||||
|
|
Loading…
Reference in a new issue