mirror of
https://example.com
synced 2024-11-22 14:06:39 +09:00
refactor (backend-rs): check_word_mute
Co-authored-by: naskya <m@naskya.net>
This commit is contained in:
parent
a7fc8f22c1
commit
9cd3d474ae
1 changed files with 58 additions and 65 deletions
|
@ -1,10 +1,10 @@
|
|||
use crate::database::JsDbConn;
|
||||
use crate::model::entity::{drive_file, note};
|
||||
use crate::prelude::*;
|
||||
use once_cell::sync::Lazy;
|
||||
use regex::Regex;
|
||||
use sea_orm::prelude::*;
|
||||
|
||||
// FIXME: remove this type
|
||||
#[napi_derive::napi(object)]
|
||||
pub struct NoteLike {
|
||||
pub file_ids: Vec<String>,
|
||||
|
@ -15,82 +15,76 @@ pub struct NoteLike {
|
|||
pub reply_id: Option<String>,
|
||||
}
|
||||
|
||||
async fn full_text(conn: &JsDbConn, note: NoteLike) -> String {
|
||||
let mut to_return = format!(
|
||||
"{}\n{}\n",
|
||||
note.text.unwrap_or_default(),
|
||||
note.cw.unwrap_or_default(),
|
||||
);
|
||||
async fn all_texts(conn: &JsDbConn, note: NoteLike) -> napi::Result<Vec<String>> {
|
||||
let mut texts: Vec<String> = vec![];
|
||||
|
||||
if let Some(text) = note.text {
|
||||
texts.push(text);
|
||||
}
|
||||
if let Some(cw) = note.cw {
|
||||
texts.push(cw);
|
||||
}
|
||||
|
||||
for file_id in note.file_ids {
|
||||
if let Some(alt_text) = drive_file::Entity::find_by_id(file_id)
|
||||
.one(conn.inner())
|
||||
.await
|
||||
.expect("Failed to connect to the database")
|
||||
.expect("file_id is invalid")
|
||||
.map_err(to_napi_error)?
|
||||
.ok_or_else(|| to_napi_error("file_id is invalid"))?
|
||||
.comment
|
||||
{
|
||||
to_return.push_str(alt_text.as_str());
|
||||
to_return.push('\n');
|
||||
texts.push(alt_text);
|
||||
}
|
||||
}
|
||||
|
||||
if note.renote_id.is_some() {
|
||||
to_return.push_str(
|
||||
note::Entity::find_by_id(note.renote_id.unwrap())
|
||||
.one(conn.inner())
|
||||
.await
|
||||
.expect("Failed to connect to the database")
|
||||
.expect("renote_id is invalid")
|
||||
.text
|
||||
.unwrap_or_default()
|
||||
.as_str(),
|
||||
);
|
||||
to_return.push('\n');
|
||||
if let Some(renote_id) = note.renote_id {
|
||||
if let Some(text) = note::Entity::find_by_id(renote_id)
|
||||
.one(conn.inner())
|
||||
.await
|
||||
.map_err(to_napi_error)?
|
||||
.ok_or_else(|| to_napi_error("renote_id is invalid"))?
|
||||
.text
|
||||
{
|
||||
texts.push(text);
|
||||
}
|
||||
}
|
||||
|
||||
if note.reply_id.is_some() {
|
||||
to_return.push_str(
|
||||
note::Entity::find_by_id(note.reply_id.unwrap())
|
||||
.one(conn.inner())
|
||||
.await
|
||||
.expect("Failed to connect to the database")
|
||||
.expect("reply_id is invalid")
|
||||
.text
|
||||
.unwrap_or_default()
|
||||
.as_str(),
|
||||
);
|
||||
if let Some(reply_id) = note.reply_id {
|
||||
if let Some(text) = note::Entity::find_by_id(reply_id)
|
||||
.one(conn.inner())
|
||||
.await
|
||||
.map_err(to_napi_error)?
|
||||
.ok_or_else(|| to_napi_error("reply_id is invalid"))?
|
||||
.text
|
||||
{
|
||||
texts.push(text);
|
||||
}
|
||||
}
|
||||
|
||||
to_return.trim().to_owned()
|
||||
Ok(texts)
|
||||
}
|
||||
|
||||
// FIXME: remove this funtion
|
||||
fn convert_regex(js_regex: String) -> String {
|
||||
fn convert_regex(js_regex: &str) -> String {
|
||||
static RE: Lazy<Regex> = Lazy::new(|| Regex::new(r"^/(.+)/(.*)$").unwrap());
|
||||
RE.replace(&js_regex, "(?$2)$1").to_string()
|
||||
RE.replace(js_regex, "(?$2)$1").to_string()
|
||||
}
|
||||
|
||||
async fn check_word_mute_impl(
|
||||
text: String,
|
||||
muted_word_lists: Vec<Vec<String>>,
|
||||
muted_patterns: Vec<String>,
|
||||
fn check_word_mute_impl(
|
||||
texts: &[String],
|
||||
muted_word_lists: &[Vec<String>],
|
||||
muted_patterns: &[String],
|
||||
) -> bool {
|
||||
if text.is_empty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
let text_lowercase = text.to_lowercase();
|
||||
|
||||
muted_word_lists.into_iter().any(|muted_word_list| {
|
||||
muted_word_list
|
||||
.into_iter()
|
||||
.all(|muted_word| text_lowercase.contains(&muted_word.to_lowercase()))
|
||||
}) || muted_patterns.into_iter().any(|muted_patten| {
|
||||
match Regex::new(convert_regex(muted_patten).as_str()) {
|
||||
Ok(re) => re.is_match(&text),
|
||||
Err(_) => false,
|
||||
}
|
||||
muted_word_lists.iter().any(|muted_word_list| {
|
||||
texts.iter().any(|text| {
|
||||
let text_lower = text.to_lowercase();
|
||||
muted_word_list
|
||||
.iter()
|
||||
.all(|muted_word| text_lower.contains(muted_word))
|
||||
})
|
||||
}) || muted_patterns.iter().any(|muted_pattern| {
|
||||
Regex::new(convert_regex(muted_pattern).as_str())
|
||||
.map(|re| texts.iter().any(|text| re.is_match(text)))
|
||||
.unwrap_or(false)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -100,15 +94,14 @@ pub async fn check_word_mute(
|
|||
note: NoteLike,
|
||||
muted_word_lists: Vec<Vec<String>>,
|
||||
muted_patterns: Vec<String>,
|
||||
) -> bool {
|
||||
) -> napi::Result<bool> {
|
||||
if muted_word_lists.is_empty() && muted_patterns.is_empty() {
|
||||
false
|
||||
Ok(false)
|
||||
} else {
|
||||
check_word_mute_impl(
|
||||
full_text(conn, note).await,
|
||||
muted_word_lists,
|
||||
muted_patterns,
|
||||
)
|
||||
.await
|
||||
Ok(check_word_mute_impl(
|
||||
&all_texts(conn, note).await?,
|
||||
&muted_word_lists,
|
||||
&muted_patterns,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue