diff --git a/neko/index.js b/neko/index.js index 31eade4ac..b25acfb60 100644 --- a/neko/index.js +++ b/neko/index.js @@ -295,7 +295,7 @@ if (!nativeBinding) { throw new Error(`Failed to load native binding`) } -const { EnvConfig, readEnvironmentConfig, readServerConfig, JsDbConn, connectToDatabase, AntennaSrcEnum, MutedNoteReasonEnum, NoteVisibilityEnum, NotificationTypeEnum, PageVisibilityEnum, PollNotevisibilityEnum, RelayStatusEnum, UserEmojimodpermEnum, UserProfileFfvisibilityEnum, UserProfileMutingnotificationtypesEnum, stringToAcct, acctToString, getFullApAccount, isSelfHost, extractHost, toPuny, toPunyOptional, convertToHiddenPost, sqlLikeEscape, safeForSql, formatMilliseconds, nativeInitIdGenerator, nativeCreateId, nativeGetTimestamp, fetchMeta, metaToPugArgs, hasOtherRenoteOfThisNote, genString, IdConvertType, convertId } = nativeBinding +const { EnvConfig, readEnvironmentConfig, readServerConfig, JsDbConn, connectToDatabase, AntennaSrcEnum, MutedNoteReasonEnum, NoteVisibilityEnum, NotificationTypeEnum, PageVisibilityEnum, PollNotevisibilityEnum, RelayStatusEnum, UserEmojimodpermEnum, UserProfileFfvisibilityEnum, UserProfileMutingnotificationtypesEnum, stringToAcct, acctToString, getFullApAccount, isSelfHost, extractHost, toPuny, toPunyOptional, convertToHiddenPost, sqlLikeEscape, safeForSql, formatMilliseconds, nativeInitIdGenerator, nativeCreateId, nativeGetTimestamp, fetchMeta, metaToPugArgs, hasOtherRenoteOfThisNote, nyaify, genString, IdConvertType, convertId } = nativeBinding module.exports.EnvConfig = EnvConfig module.exports.readEnvironmentConfig = readEnvironmentConfig @@ -329,6 +329,7 @@ module.exports.nativeGetTimestamp = nativeGetTimestamp module.exports.fetchMeta = fetchMeta module.exports.metaToPugArgs = metaToPugArgs module.exports.hasOtherRenoteOfThisNote = hasOtherRenoteOfThisNote +module.exports.nyaify = nyaify module.exports.genString = genString module.exports.IdConvertType = IdConvertType module.exports.convertId = convertId diff --git a/packages/backend-rs/Cargo.lock b/packages/backend-rs/Cargo.lock index 7c939254a..4e6fea190 100644 --- a/packages/backend-rs/Cargo.lock +++ b/packages/backend-rs/Cargo.lock @@ -214,6 +214,7 @@ dependencies = [ "parse-display", "pretty_assertions", "rand", + "regex", "schemars", "sea-orm", "serde", diff --git a/packages/backend-rs/Cargo.toml b/packages/backend-rs/Cargo.toml index 4bab77cdc..1c2b5ef5e 100644 --- a/packages/backend-rs/Cargo.toml +++ b/packages/backend-rs/Cargo.toml @@ -20,6 +20,7 @@ jsonschema = "0.17.1" once_cell = "1.19.0" parse-display = "0.8.2" rand = "0.8.5" +regex = "1.10.3" schemars = { version = "0.8.16", features = ["chrono"] } sea-orm = { version = "0.12.12", features = ["sqlx-postgres", "runtime-tokio-rustls"] } serde = { version = "1.0.195", features = ["derive"] } diff --git a/packages/backend-rs/src/util/mod.rs b/packages/backend-rs/src/util/mod.rs index e4c63fa07..50fab5e07 100644 --- a/packages/backend-rs/src/util/mod.rs +++ b/packages/backend-rs/src/util/mod.rs @@ -6,4 +6,5 @@ pub mod format_milliseconds; pub mod id; pub mod meta; pub mod note; +pub mod nyaify; pub mod random; diff --git a/packages/backend-rs/src/util/nyaify.rs b/packages/backend-rs/src/util/nyaify.rs new file mode 100644 index 000000000..48b0f0cd0 --- /dev/null +++ b/packages/backend-rs/src/util/nyaify.rs @@ -0,0 +1,84 @@ +use once_cell::sync::Lazy; +use regex::{Captures, Regex}; + +#[napi_derive::napi] +pub fn nyaify(text: String, lang: Option, append_miao: bool) -> String { + let mut to_return = text.clone(); + + { + static RE: Lazy = + Lazy::new(|| Regex::new(r"(?i-u)(non)([bcdfghjklmnpqrstvwxyz])").unwrap()); + to_return = RE + .replace_all(&to_return, |caps: &Captures<'_>| { + format!( + "{}{}", + match &caps[1] { + "non" => "nyan", + "Non" => "Nyan", + "NON" => "NYAN", + _ => &caps[1], + }, + &caps[2] + ) + }) + .to_string(); + } + + { + static RE: Lazy = Lazy::new(|| Regex::new(r"다([..。…??!!\s]|$)").unwrap()); + to_return = RE.replace_all(&to_return, r"다냥$1").to_string(); + } + + { + static RE: Lazy = Lazy::new(|| Regex::new(r"야([??\s]|$)").unwrap()); + to_return = RE.replace_all(&to_return, r"냥$1").to_string(); + } + + { + static RE: Lazy = Lazy::new(|| Regex::new(r"([나-낳])").unwrap()); + to_return = RE + .replace_all(&to_return, |caps: &Captures<'_>| { + format!( + "{}", + char::from_u32( + caps[0].chars().next().unwrap() as u32 + 56 /* = '냐' - '나' */ + ) + .unwrap() + ) + }) + .to_string(); + } + + if lang.is_some() && lang.unwrap().starts_with("zh") { + static RE: Lazy = Lazy::new(|| Regex::new(r"[妙庙描渺瞄秒苗藐廟]").unwrap()); + to_return = RE.replace_all(&to_return, "喵").to_string(); + } + + let simple_rules = [ + ("な", "にゃ"), + ("ナ", "ニャ"), + ("ナ", "ニャ"), + ("na", "nya"), + ("NA", "NYA"), + ("Na", "Nya"), + ("morning", "mornyan"), + ("Morning", "Mornyan"), + ("MORNING", "MORNYAN"), + ("everyone", "everynyan"), + ("Everyone", "Everynyan"), + ("EVERYONE", "EVERYNYAN"), + ("να", "νια"), + ("ΝΑ", "ΝΙΑ"), + ("Να", "Νια"), + ]; + + simple_rules.into_iter().for_each(|(from, to)| { + to_return = to_return.replace(from, to); + }); + + if append_miao { + to_return.push('喵'); + } + + to_return +} diff --git a/packages/backend/src/misc/nyaify.ts b/packages/backend/src/misc/nyaify.ts deleted file mode 100644 index 37a0bdecd..000000000 --- a/packages/backend/src/misc/nyaify.ts +++ /dev/null @@ -1,38 +0,0 @@ -export default function ( - text: string, - lang: string | undefined, - appendMiao: boolean, -): string { - text = text - // ja-JP - .replaceAll("な", "にゃ") - .replaceAll("ナ", "ニャ") - .replaceAll("ナ", "ニャ") - // en-US - .replaceAll("na", "nya") - .replaceAll("Na", "Nya") - .replaceAll("NA", "NYA") - .replace(/(?<=morn)ing/gi, (x) => (x === "ING" ? "YAN" : "yan")) - .replace(/(?<=every)one/gi, (x) => (x === "ONE" ? "NYAN" : "nyan")) - .replace(/non(?=[bcdfghjklmnpqrstvwxyz])/gi, (x) => - x === "NON" ? "NYAN" : "nyan", - ) - // ko-KR - .replace(/[나-낳]/g, (match) => - String.fromCharCode( - match.charCodeAt(0)! + "냐".charCodeAt(0) - "나".charCodeAt(0), - ), - ) - .replace(/(다$)|(다(?=\.))|(다(?= ))|(다(?=!))|(다(?=\?))/gm, "다냥") - .replace(/(야(?=\?))|(야$)|(야(?= ))/gm, "냥") - // el-GR - .replaceAll("να", "νια") - .replaceAll("ΝΑ", "ΝΙΑ") - .replaceAll("Να", "Νια"); - - // zh-CN, zh-TW - if (lang === "zh") text = text.replace(/(妙|庙|描|渺|瞄|秒|苗|藐|廟)/g, "喵"); - if (appendMiao) text += "喵"; - - return text; -} diff --git a/packages/backend/src/models/repositories/note.ts b/packages/backend/src/models/repositories/note.ts index ef9871bc2..0fdf7f96e 100644 --- a/packages/backend/src/models/repositories/note.ts +++ b/packages/backend/src/models/repositories/note.ts @@ -12,7 +12,7 @@ import { Channels, } from "../index.js"; import type { Packed } from "@/misc/schema.js"; -import nyaify from "@/misc/nyaify.js"; +import { nyaify } from "backend-rs"; import { awaitAll } from "@/prelude/await-all.js"; import { convertReactions, decodeReaction } from "@/misc/reaction-lib.js"; import type { NoteReaction } from "@/models/entities/note-reaction.js";