pub fn build_session_title(
is_dm: bool,
user_name: &str,
user_id: i64,
chat_title: &str,
chat_id: i64,
topic_id: Option<i32>,
topic_name: Option<&str>,
) -> String {
let suffix = chat_id_suffix(chat_id, topic_id);
if is_dm {
format!("Telegram: DM {user_name} ({user_id}) {suffix}")
} else {
match topic_name.map(str::trim).filter(|n| !n.is_empty()) {
Some(name) if topic_id.is_some() => {
format!("Telegram: {chat_title} / {name} {suffix}")
}
_ => format!("Telegram: {chat_title} {suffix}"),
}
}
}
pub fn build_legacy_session_title(
is_dm: bool,
user_name: &str,
user_id: i64,
chat_title: &str,
) -> String {
if is_dm {
format!("Telegram: DM {user_name} ({user_id})")
} else {
format!("Telegram: {chat_title}")
}
}
pub fn chat_id_suffix(chat_id: i64, topic_id: Option<i32>) -> String {
match topic_id {
Some(tid) => format!("[chat:{chat_id}:topic:{tid}]"),
None => format!("[chat:{chat_id}]"),
}
}
pub fn topic_session_id(is_topic_message: bool, thread_id: Option<i32>) -> Option<i32> {
if is_topic_message { thread_id } else { None }
}
pub fn session_idle_expired(
updated_at: chrono::DateTime<chrono::Utc>,
idle_hours: Option<f64>,
) -> bool {
idle_hours.is_some_and(|h| {
let elapsed = (chrono::Utc::now() - updated_at).num_seconds();
elapsed > (h * 3600.0) as i64
})
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ResolveSource {
ChatBound,
Suffix,
Create,
}
pub fn choose_resolve_source(
chat_bound: Option<uuid::Uuid>,
bound_archived: bool,
suffix_match: Option<uuid::Uuid>,
) -> ResolveSource {
if chat_bound.is_some() && !bound_archived {
ResolveSource::ChatBound
} else if suffix_match.is_some() {
ResolveSource::Suffix
} else {
ResolveSource::Create
}
}
pub fn should_refresh_label(stored: &str, template: &str) -> bool {
if stored == template {
return false;
}
if crate::brain::agent::service::AgentService::is_default_channel_title(stored) {
return crate::brain::agent::service::AgentService::is_default_channel_title(template)
&& stored != template;
}
if is_telegram_group_session_title(stored) && is_telegram_group_session_title(template) {
return telegram_middle_label(stored) != telegram_middle_label(template);
}
false
}
fn is_telegram_group_session_title(title: &str) -> bool {
let Some(rest) = title.strip_prefix("Telegram: ") else {
return false;
};
!rest.starts_with("DM ") && title.contains("[chat:")
}
fn telegram_middle_label(title: &str) -> String {
let body = title.strip_prefix("Telegram: ").unwrap_or(title).trim();
let suffix = crate::brain::agent::service::AgentService::extract_chat_id_suffix(title);
if suffix.is_empty() {
return body.to_string();
}
body.strip_suffix(suffix).unwrap_or(body).trim().to_string()
}