chore (backend-rs): rename modules to more comfortable names
This commit is contained in:
parent
132af64a6e
commit
679749a2cc
11 changed files with 193 additions and 133 deletions
8
packages/backend-rs/index.d.ts
vendored
8
packages/backend-rs/index.d.ts
vendored
|
@ -419,19 +419,13 @@ export interface ImageSize {
|
|||
height: number
|
||||
}
|
||||
export function getImageSizeFromUrl(url: string): Promise<ImageSize>
|
||||
export interface PartialNoteToSummarize {
|
||||
fileIds: Array<string>
|
||||
text: string | null
|
||||
cw: string | null
|
||||
hasPoll: boolean
|
||||
}
|
||||
export function getNoteSummary(note: PartialNoteToSummarize): string
|
||||
export function isQuote(note: Note): boolean
|
||||
export function isSafeUrl(url: string): boolean
|
||||
/** Returns the latest Firefish version. */
|
||||
export function latestVersion(): Promise<string>
|
||||
export function toMastodonId(firefishId: string): string | null
|
||||
export function fromMastodonId(mastodonId: string): string | null
|
||||
export function getNoteSummary(fileIds: Array<string>, text: string | undefined | null, cw: string | undefined | null, hasPoll: boolean): string
|
||||
/**
|
||||
* Converts the given text into the cat language.
|
||||
*
|
||||
|
|
|
@ -310,7 +310,7 @@ if (!nativeBinding) {
|
|||
throw new Error(`Failed to load native binding`)
|
||||
}
|
||||
|
||||
const { SECOND, MINUTE, HOUR, DAY, USER_ONLINE_THRESHOLD, USER_ACTIVE_THRESHOLD, FILE_TYPE_BROWSERSAFE, fetchMeta, updateMetaCache, metaToPugArgs, loadConfig, stringToAcct, acctToString, fetchNodeinfo, nodeinfo_2_1, nodeinfo_2_0, updateNodeinfoCache, Protocol, Inbound, Outbound, greet, initializeRustLogger, showServerInfo, isBlockedServer, isSilencedServer, isAllowedServer, checkWordMute, getFullApAccount, isSelfHost, isSameOrigin, extractHost, toPuny, isUnicodeEmoji, sqlLikeEscape, safeForSql, formatMilliseconds, getImageSizeFromUrl, getNoteSummary, isQuote, isSafeUrl, latestVersion, toMastodonId, fromMastodonId, nyaify, hashPassword, verifyPassword, isOldPasswordAlgorithm, decodeReaction, countReactions, toDbReaction, removeOldAttestationChallenges, cpuInfo, cpuUsage, memoryUsage, storageUsage, AntennaSrc, DriveFileUsageHint, MutedNoteReason, NoteVisibility, NotificationType, PageVisibility, PollNoteVisibility, RelayStatus, UserEmojiModPerm, UserProfileFfvisibility, UserProfileMutingNotificationTypes, updateAntennasOnNewNote, updateAntennaCache, watchNote, unwatchNote, PushNotificationKind, sendPushNotification, publishToChannelStream, publishToChatStream, ChatIndexEvent, publishToChatIndexStream, publishToBroadcastStream, publishToGroupChatStream, publishToModerationStream, ChatEvent, getTimestamp, genId, genIdAt, generateSecureRandomString, generateUserToken } = nativeBinding
|
||||
const { SECOND, MINUTE, HOUR, DAY, USER_ONLINE_THRESHOLD, USER_ACTIVE_THRESHOLD, FILE_TYPE_BROWSERSAFE, fetchMeta, updateMetaCache, metaToPugArgs, loadConfig, stringToAcct, acctToString, fetchNodeinfo, nodeinfo_2_1, nodeinfo_2_0, updateNodeinfoCache, Protocol, Inbound, Outbound, greet, initializeRustLogger, showServerInfo, isBlockedServer, isSilencedServer, isAllowedServer, checkWordMute, getFullApAccount, isSelfHost, isSameOrigin, extractHost, toPuny, isUnicodeEmoji, sqlLikeEscape, safeForSql, formatMilliseconds, getImageSizeFromUrl, isQuote, isSafeUrl, latestVersion, toMastodonId, fromMastodonId, getNoteSummary, nyaify, hashPassword, verifyPassword, isOldPasswordAlgorithm, decodeReaction, countReactions, toDbReaction, removeOldAttestationChallenges, cpuInfo, cpuUsage, memoryUsage, storageUsage, AntennaSrc, DriveFileUsageHint, MutedNoteReason, NoteVisibility, NotificationType, PageVisibility, PollNoteVisibility, RelayStatus, UserEmojiModPerm, UserProfileFfvisibility, UserProfileMutingNotificationTypes, updateAntennasOnNewNote, updateAntennaCache, watchNote, unwatchNote, PushNotificationKind, sendPushNotification, publishToChannelStream, publishToChatStream, ChatIndexEvent, publishToChatIndexStream, publishToBroadcastStream, publishToGroupChatStream, publishToModerationStream, ChatEvent, getTimestamp, genId, genIdAt, generateSecureRandomString, generateUserToken } = nativeBinding
|
||||
|
||||
module.exports.SECOND = SECOND
|
||||
module.exports.MINUTE = MINUTE
|
||||
|
@ -349,12 +349,12 @@ module.exports.sqlLikeEscape = sqlLikeEscape
|
|||
module.exports.safeForSql = safeForSql
|
||||
module.exports.formatMilliseconds = formatMilliseconds
|
||||
module.exports.getImageSizeFromUrl = getImageSizeFromUrl
|
||||
module.exports.getNoteSummary = getNoteSummary
|
||||
module.exports.isQuote = isQuote
|
||||
module.exports.isSafeUrl = isSafeUrl
|
||||
module.exports.latestVersion = latestVersion
|
||||
module.exports.toMastodonId = toMastodonId
|
||||
module.exports.fromMastodonId = fromMastodonId
|
||||
module.exports.getNoteSummary = getNoteSummary
|
||||
module.exports.nyaify = nyaify
|
||||
module.exports.hashPassword = hashPassword
|
||||
module.exports.verifyPassword = verifyPassword
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::misc::get_note_all_texts::all_texts;
|
||||
use crate::misc::note::elaborate;
|
||||
use once_cell::sync::Lazy;
|
||||
use regex::Regex;
|
||||
use sea_orm::DbErr;
|
||||
|
@ -59,7 +59,7 @@ pub async fn check_word_mute(
|
|||
Ok(false)
|
||||
} else {
|
||||
Ok(check_word_mute_impl(
|
||||
&all_texts!(note, true).await?,
|
||||
&elaborate!(note, true).await?,
|
||||
muted_words,
|
||||
muted_patterns,
|
||||
))
|
||||
|
|
|
@ -1,93 +0,0 @@
|
|||
use serde::Deserialize;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[crate::export(object)]
|
||||
pub struct PartialNoteToSummarize {
|
||||
pub file_ids: Vec<String>,
|
||||
pub text: Option<String>,
|
||||
pub cw: Option<String>,
|
||||
pub has_poll: bool,
|
||||
}
|
||||
|
||||
#[crate::export]
|
||||
pub fn get_note_summary(note: PartialNoteToSummarize) -> String {
|
||||
let mut buf: Vec<String> = vec![];
|
||||
|
||||
if let Some(cw) = note.cw {
|
||||
buf.push(cw)
|
||||
} else if let Some(text) = note.text {
|
||||
buf.push(text)
|
||||
}
|
||||
|
||||
match note.file_ids.len() {
|
||||
0 => (),
|
||||
1 => buf.push("📎".to_string()),
|
||||
n => buf.push(format!("📎 ({})", n)),
|
||||
};
|
||||
|
||||
if note.has_poll {
|
||||
buf.push("📊".to_string())
|
||||
}
|
||||
|
||||
buf.join(" ")
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod unit_test {
|
||||
use super::{get_note_summary, PartialNoteToSummarize};
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[test]
|
||||
fn test_note_summary() {
|
||||
let note = PartialNoteToSummarize {
|
||||
file_ids: vec![],
|
||||
text: Some("Hello world!".to_string()),
|
||||
cw: None,
|
||||
has_poll: false,
|
||||
};
|
||||
assert_eq!(get_note_summary(note), "Hello world!");
|
||||
|
||||
let note_with_cw = PartialNoteToSummarize {
|
||||
file_ids: vec![],
|
||||
text: Some("Hello world!".to_string()),
|
||||
cw: Some("Content warning".to_string()),
|
||||
has_poll: false,
|
||||
};
|
||||
assert_eq!(get_note_summary(note_with_cw), "Content warning");
|
||||
|
||||
let note_with_file_and_cw = PartialNoteToSummarize {
|
||||
file_ids: vec!["9s7fmcqogiq4igin".to_string()],
|
||||
text: None,
|
||||
cw: Some("Selfie, no ec".to_string()),
|
||||
has_poll: false,
|
||||
};
|
||||
assert_eq!(get_note_summary(note_with_file_and_cw), "Selfie, no ec 📎");
|
||||
|
||||
let note_with_files_only = PartialNoteToSummarize {
|
||||
file_ids: vec![
|
||||
"9s7fmcqogiq4igin".to_string(),
|
||||
"9s7qrld5u14cey98".to_string(),
|
||||
"9s7gebs5zgts4kca".to_string(),
|
||||
"9s5z3e4vefqd29ee".to_string(),
|
||||
],
|
||||
text: None,
|
||||
cw: None,
|
||||
has_poll: false,
|
||||
};
|
||||
assert_eq!(get_note_summary(note_with_files_only), "📎 (4)");
|
||||
|
||||
let note_all = PartialNoteToSummarize {
|
||||
file_ids: vec![
|
||||
"9s7fmcqogiq4igin".to_string(),
|
||||
"9s7qrld5u14cey98".to_string(),
|
||||
"9s7gebs5zgts4kca".to_string(),
|
||||
"9s5z3e4vefqd29ee".to_string(),
|
||||
],
|
||||
text: Some("Hello world!".to_string()),
|
||||
cw: Some("Content warning".to_string()),
|
||||
has_poll: true,
|
||||
};
|
||||
assert_eq!(get_note_summary(note_all), "Content warning 📎 (4) 📊");
|
||||
}
|
||||
}
|
|
@ -7,12 +7,11 @@ pub mod emoji;
|
|||
pub mod escape_sql;
|
||||
pub mod format_milliseconds;
|
||||
pub mod get_image_size;
|
||||
pub mod get_note_all_texts;
|
||||
pub mod get_note_summary;
|
||||
pub mod is_quote;
|
||||
pub mod is_safe_url;
|
||||
pub mod latest_version;
|
||||
pub mod mastodon_id;
|
||||
pub mod note;
|
||||
pub mod nyaify;
|
||||
pub mod password;
|
||||
pub mod reaction;
|
||||
|
|
|
@ -6,7 +6,7 @@ use sea_orm::{prelude::*, QuerySelect};
|
|||
|
||||
/// Returns [`Vec<String>`] 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
|
||||
/// Consider using [`elaborate`] macro instead
|
||||
/// when dealing with a note ([`note::Model`])-like instance.
|
||||
///
|
||||
/// # Arguments
|
||||
|
@ -14,7 +14,7 @@ use sea_orm::{prelude::*, QuerySelect};
|
|||
/// * `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_impl(
|
||||
pub async fn elaborate_impl(
|
||||
file_ids: &[String],
|
||||
text: Option<String>,
|
||||
cw: Option<String>,
|
||||
|
@ -87,15 +87,15 @@ pub async fn all_texts_impl(
|
|||
/// # Caveats
|
||||
///
|
||||
/// The `note_like` argument should not contain function calls
|
||||
/// (e.g., `all_texts!(note.clone(), false)`)
|
||||
/// (e.g., `elaborate!(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;
|
||||
/// # use backend_rs::misc::note::elaborate;
|
||||
/// // note-like struct
|
||||
/// struct SomeNoteLikeStruct {
|
||||
/// struct NoteLike {
|
||||
/// // required fields
|
||||
/// file_ids: Vec<String>,
|
||||
/// text: Option<String>,
|
||||
|
@ -107,18 +107,19 @@ pub async fn all_texts_impl(
|
|||
/// 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
|
||||
/// async fn print_all_related_texts(
|
||||
/// note: &NoteLike
|
||||
/// ) -> Result<(), sea_orm::DbErr> {
|
||||
/// let all_texts = elaborate!(note, true).await?;
|
||||
/// all_texts.iter().map(|text| println!("{}", text));
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[doc(hidden)] // hide the macro in the top doc page
|
||||
#[macro_export]
|
||||
macro_rules! all_texts {
|
||||
macro_rules! elaborate {
|
||||
($note_like:expr, $include_parent:expr) => {
|
||||
$crate::misc::get_note_all_texts::all_texts_impl(
|
||||
$crate::misc::note::elaborate::elaborate_impl(
|
||||
&$note_like.file_ids,
|
||||
$note_like.text.clone(),
|
||||
$note_like.cw.clone(),
|
||||
|
@ -128,5 +129,6 @@ macro_rules! all_texts {
|
|||
)
|
||||
};
|
||||
}
|
||||
|
||||
#[doc(inline)] // show the macro in the module doc page
|
||||
pub use all_texts;
|
||||
pub use elaborate;
|
5
packages/backend-rs/src/misc/note/mod.rs
Normal file
5
packages/backend-rs/src/misc/note/mod.rs
Normal file
|
@ -0,0 +1,5 @@
|
|||
pub use elaborate::elaborate;
|
||||
pub use summarize::summarize;
|
||||
|
||||
pub mod elaborate;
|
||||
pub mod summarize;
|
145
packages/backend-rs/src/misc/note/summarize.rs
Normal file
145
packages/backend-rs/src/misc/note/summarize.rs
Normal file
|
@ -0,0 +1,145 @@
|
|||
#[crate::export(js_name = "getNoteSummary")]
|
||||
pub fn summarize_impl(
|
||||
file_ids: &[String],
|
||||
text: Option<String>,
|
||||
cw: Option<String>,
|
||||
has_poll: bool,
|
||||
) -> String {
|
||||
let mut buf: Vec<String> = vec![];
|
||||
|
||||
if let Some(cw) = cw {
|
||||
buf.push(cw)
|
||||
} else if let Some(text) = text {
|
||||
buf.push(text)
|
||||
}
|
||||
|
||||
match file_ids.len() {
|
||||
0 => (),
|
||||
1 => buf.push("📎".to_string()),
|
||||
n => buf.push(format!("📎 ({})", n)),
|
||||
};
|
||||
|
||||
if has_poll {
|
||||
buf.push("📊".to_string())
|
||||
}
|
||||
|
||||
buf.join(" ")
|
||||
}
|
||||
|
||||
/// Returns the summary of a post, which can be used to display posts in small spaces
|
||||
/// such as push notifications.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `note_like` : a note ([`crate::model::entity::note::Model`])-like instance containing
|
||||
/// `file_ids`, `text`, `cw`, `has_poll` fields
|
||||
///
|
||||
/// # Caveats
|
||||
///
|
||||
/// The `note_like` argument should not contain function calls
|
||||
/// (e.g., `summarize!(note.clone())`)
|
||||
/// since the function will be called multiple times after macro expansion.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use backend_rs::misc::note::summarize;
|
||||
/// // note-like struct
|
||||
/// struct NoteLike {
|
||||
/// // required fields
|
||||
/// file_ids: Vec<String>,
|
||||
/// text: Option<String>,
|
||||
/// cw: Option<String>,
|
||||
/// has_poll: bool,
|
||||
/// // arbitrary extra fields
|
||||
/// renote_id: Option<String>,
|
||||
/// reply_id: Option<String>,
|
||||
/// extra_field_1: u32,
|
||||
/// extra_field_2: Vec<String>,
|
||||
/// }
|
||||
///
|
||||
/// fn print_note_summary(note: &NoteLike) {
|
||||
/// println!("{}", summarize!(note));
|
||||
/// }
|
||||
/// ```
|
||||
#[doc(hidden)] // hide the macro in the top doc page
|
||||
#[macro_export]
|
||||
macro_rules! summarize {
|
||||
($note_like:expr) => {
|
||||
$crate::misc::note::summarize::summarize_impl(
|
||||
&$note_like.file_ids,
|
||||
$note_like.text.to_owned(),
|
||||
$note_like.cw.to_owned(),
|
||||
$note_like.has_poll.to_owned(),
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
#[doc(inline)] // show the macro in the module doc page
|
||||
pub use summarize;
|
||||
|
||||
#[cfg(test)]
|
||||
mod unit_test {
|
||||
use super::summarize;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
struct NoteLike {
|
||||
file_ids: Vec<String>,
|
||||
text: Option<String>,
|
||||
cw: Option<String>,
|
||||
has_poll: bool,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn summarize() {
|
||||
let note = NoteLike {
|
||||
file_ids: vec![],
|
||||
text: Some("Hello world!".to_string()),
|
||||
cw: None,
|
||||
has_poll: false,
|
||||
};
|
||||
assert_eq!(summarize!(note), "Hello world!");
|
||||
|
||||
let note_with_cw = NoteLike {
|
||||
file_ids: vec![],
|
||||
text: Some("Hello world!".to_string()),
|
||||
cw: Some("Content warning".to_string()),
|
||||
has_poll: false,
|
||||
};
|
||||
assert_eq!(summarize!(note_with_cw), "Content warning");
|
||||
|
||||
let note_with_file_and_cw = NoteLike {
|
||||
file_ids: vec!["9s7fmcqogiq4igin".to_string()],
|
||||
text: None,
|
||||
cw: Some("Selfie, no ec".to_string()),
|
||||
has_poll: false,
|
||||
};
|
||||
assert_eq!(summarize!(note_with_file_and_cw), "Selfie, no ec 📎");
|
||||
|
||||
let note_with_files_only = NoteLike {
|
||||
file_ids: vec![
|
||||
"9s7fmcqogiq4igin".to_string(),
|
||||
"9s7qrld5u14cey98".to_string(),
|
||||
"9s7gebs5zgts4kca".to_string(),
|
||||
"9s5z3e4vefqd29ee".to_string(),
|
||||
],
|
||||
text: None,
|
||||
cw: None,
|
||||
has_poll: false,
|
||||
};
|
||||
assert_eq!(summarize!(note_with_files_only), "📎 (4)");
|
||||
|
||||
let note_all = NoteLike {
|
||||
file_ids: vec![
|
||||
"9s7fmcqogiq4igin".to_string(),
|
||||
"9s7qrld5u14cey98".to_string(),
|
||||
"9s7gebs5zgts4kca".to_string(),
|
||||
"9s5z3e4vefqd29ee".to_string(),
|
||||
],
|
||||
text: Some("Hello world!".to_string()),
|
||||
cw: Some("Content warning".to_string()),
|
||||
has_poll: true,
|
||||
};
|
||||
assert_eq!(summarize!(note_all), "Content warning 📎 (4) 📊");
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{
|
||||
database::{cache, redis_conn, redis_key, RedisConnError},
|
||||
federation::acct::Acct,
|
||||
misc::get_note_all_texts::all_texts,
|
||||
misc::note::elaborate,
|
||||
model::entity::note,
|
||||
service::{
|
||||
antenna,
|
||||
|
@ -41,7 +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, false).await?;
|
||||
let note_all_texts = elaborate!(note, false).await?;
|
||||
|
||||
// TODO: do this in parallel
|
||||
for antenna in antenna::cache::get().await?.iter() {
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
use crate::{
|
||||
config::local_server_info,
|
||||
database::db_conn,
|
||||
misc::get_note_summary::{get_note_summary, PartialNoteToSummarize},
|
||||
model::entity::sw_subscription,
|
||||
util::http_client,
|
||||
config::local_server_info, database::db_conn, misc::note::summarize,
|
||||
model::entity::sw_subscription, util::http_client,
|
||||
};
|
||||
use once_cell::sync::OnceCell;
|
||||
use sea_orm::prelude::*;
|
||||
use serde::Deserialize;
|
||||
use web_push::*;
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
|
@ -72,8 +70,18 @@ fn compact_content(mut content: serde_json::Value) -> Result<serde_json::Value,
|
|||
));
|
||||
}
|
||||
|
||||
let note_like: PartialNoteToSummarize = serde_json::from_value(note.clone())?;
|
||||
let text = get_note_summary(note_like);
|
||||
// TODO: get rid of this struct
|
||||
#[derive(Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct PartialNote {
|
||||
file_ids: Vec<String>,
|
||||
text: Option<String>,
|
||||
cw: Option<String>,
|
||||
has_poll: bool,
|
||||
}
|
||||
|
||||
let note_like: PartialNote = serde_json::from_value(note.clone())?;
|
||||
let text = summarize!(note_like);
|
||||
|
||||
let note_object = note.as_object_mut().unwrap();
|
||||
|
||||
|
|
|
@ -540,7 +540,7 @@ router.get("/notes/:note", async (ctx, next) => {
|
|||
await Users.findOneByOrFail({ id: note.userId }),
|
||||
),
|
||||
// TODO: Let locale changeable by instance setting
|
||||
summary: getNoteSummary(note),
|
||||
summary: getNoteSummary(note.fileIds, note.text, note.cw, note.hasPoll),
|
||||
});
|
||||
|
||||
ctx.set("Cache-Control", "public, max-age=15");
|
||||
|
@ -562,19 +562,19 @@ router.get("/posts/:note", async (ctx, next) => {
|
|||
visibility: In(["public", "home"]),
|
||||
});
|
||||
|
||||
if (note) {
|
||||
const _note = await Notes.pack(note);
|
||||
if (note != null) {
|
||||
const packedNote = await Notes.pack(note);
|
||||
const profile = await UserProfiles.findOneByOrFail({ userId: note.userId });
|
||||
const meta = await fetchMeta();
|
||||
await ctx.render("note", {
|
||||
...metaToPugArgs(meta),
|
||||
note: _note,
|
||||
note: packedNote,
|
||||
profile,
|
||||
avatarUrl: await Users.getAvatarUrl(
|
||||
await Users.findOneByOrFail({ id: note.userId }),
|
||||
),
|
||||
// TODO: Let locale changeable by instance setting
|
||||
summary: getNoteSummary(_note),
|
||||
summary: getNoteSummary(note.fileIds, note.text, note.cw, note.hasPoll),
|
||||
});
|
||||
|
||||
ctx.set("Cache-Control", "public, max-age=15");
|
||||
|
|
Loading…
Reference in a new issue