65 lines
1.7 KiB
Rust
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
|
|
}
|