Files
appks/service/im/util.rs
T
2026-06-07 11:30:56 +08:00

65 lines
1.7 KiB
Rust

pub use crate::service::util::{
clamp_limit_offset, ensure_affected, merge_optional_text, parse_enum, required_text, role_level,
};
/// Maximum length for a channel name.
pub const MAX_CHANNEL_NAME: usize = 100;
/// Maximum length for a channel topic.
pub const MAX_CHANNEL_TOPIC: usize = 1024;
/// Maximum length for a message body.
pub const MAX_MESSAGE_BODY: usize = 4096;
/// Maximum length for an article title.
pub const MAX_ARTICLE_TITLE: usize = 256;
/// Maximum number of poll options.
pub const MAX_POLL_OPTIONS: usize = 10;
/// Maximum length for a poll option text.
pub const MAX_POLL_OPTION_TEXT: usize = 100;
/// Redis key prefix for typing indicators.
pub const TYPING_PREFIX: &str = "im:typing:";
/// Redis key prefix for user presence.
pub const PRESENCE_PREFIX: &str = "im:presence:";
/// Redis TTL for typing indicators (seconds).
pub const TYPING_TTL_SECS: usize = 8;
/// Redis TTL for presence heartbeats (seconds).
pub const PRESENCE_TTL_SECS: usize = 120;
/// Maximum length for generated slugs.
pub const MAX_SLUG_LEN: usize = 128;
/// Generate a slug from a title string.
pub fn slugify(title: &str) -> String {
let slug: String = title
.to_lowercase()
.chars()
.filter_map(|c| {
if c.is_ascii_alphanumeric() {
Some(c)
} else if c.is_whitespace() || !c.is_ascii() {
Some('-')
} else {
None
}
})
.collect::<String>()
.split('-')
.filter(|s| !s.is_empty())
.collect::<Vec<_>>()
.join("-");
let mut result = slug;
result.truncate(MAX_SLUG_LEN);
if result.ends_with('-') {
result.pop();
}
result
}