fn find_platform_substring(session_id: &str) -> Option<(&'static str, &str)> {
for marker in ["slack:", "discord:", "telegram:"].into_iter() {
if let Some(idx) = session_id.rfind(marker) {
return Some((marker, &session_id[idx..]));
}
}
None
}
fn telegram_session_namespace_and_chat_id(session_id: &str) -> Option<(Option<&str>, i64)> {
if let Some((marker, rest)) = find_platform_substring(session_id) {
if marker != "telegram:" {
return None;
}
let marker_idx = session_id.rfind(marker)?;
let prefix = session_id[..marker_idx].trim_end_matches(':').trim();
let chat_id = rest
.strip_prefix("telegram:")
.and_then(|s| s.trim().parse::<i64>().ok())?;
let namespace = if prefix.is_empty() {
None
} else {
Some(prefix)
};
return Some((namespace, chat_id));
}
let stripped = session_id.strip_prefix("bot:").unwrap_or(session_id);
if let Ok(chat_id) = stripped.trim().parse::<i64>() {
return Some((None, chat_id));
}
if stripped.contains("slack:") || stripped.contains("discord:") {
return None;
}
let (prefix, suffix) = stripped.rsplit_once(':')?;
let prefix = prefix.trim();
if prefix.is_empty() {
return None;
}
let chat_id = suffix.trim().parse::<i64>().ok()?;
Some((Some(prefix), chat_id))
}
pub fn telegram_chat_id_from_session(session_id: &str) -> Option<i64> {
telegram_session_namespace_and_chat_id(session_id).map(|(_, chat_id)| chat_id)
}
fn telegram_channel_namespace_and_chat_id(channel_id: &str) -> Option<(Option<&str>, i64)> {
let stripped = channel_id.strip_prefix("telegram:")?;
if let Ok(chat_id) = stripped.trim().parse::<i64>() {
return Some((None, chat_id));
}
let (namespace, suffix) = stripped.rsplit_once(':')?;
let namespace = namespace.trim();
if namespace.is_empty() {
return None;
}
let chat_id = suffix.trim().parse::<i64>().ok()?;
Some((Some(namespace), chat_id))
}
pub fn stored_channel_matches_current(stored_channel_id: &str, current_channel_id: &str) -> bool {
if stored_channel_id == current_channel_id {
return true;
}
let Some((stored_namespace, stored_chat_id)) =
telegram_channel_namespace_and_chat_id(stored_channel_id)
else {
return false;
};
let Some((current_namespace, current_chat_id)) =
telegram_channel_namespace_and_chat_id(current_channel_id)
else {
return false;
};
stored_chat_id == current_chat_id && stored_namespace.is_none() && current_namespace.is_some()
}
pub fn telegram_channel_id_from_session(session_id: &str) -> Option<String> {
let (namespace, chat_id) = telegram_session_namespace_and_chat_id(session_id)?;
match namespace {
Some(prefix) => Some(format!("telegram:{}:{}", prefix, chat_id)),
None => Some(format!("telegram:{}", chat_id)),
}
}
pub fn derive_channel_id_from_session(session_id: &str) -> Option<String> {
if let Some((marker, rest)) = find_platform_substring(session_id) {
match marker {
"slack:" => {
let mut it = rest.splitn(3, ':');
let _slack = it.next()?;
let channel = it.next()?;
if channel.is_empty() {
return None;
}
return Some(format!("slack:{}", channel));
}
"discord:" => {
return Some(rest.to_string());
}
"telegram:" => {
return telegram_channel_id_from_session(session_id);
}
_ => {}
}
}
telegram_channel_id_from_session(session_id)
}
pub fn is_group_session(session_id: &str) -> bool {
if let Some((marker, rest)) = find_platform_substring(session_id) {
match marker {
"discord:" => {
return rest.contains("discord:ch:");
}
"slack:" => {
if let Some(after) = rest.strip_prefix("slack:") {
return after.starts_with('C') || after.starts_with('G');
}
}
"telegram:" => {
if let Some(chat_id) = telegram_chat_id_from_session(rest) {
return chat_id < 0;
}
}
_ => {}
}
}
if let Some(chat_id) = telegram_chat_id_from_session(session_id) {
return chat_id < 0;
}
false
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn telegram_chat_id_parses_default_numeric() {
assert_eq!(telegram_chat_id_from_session("12345"), Some(12345));
assert_eq!(telegram_chat_id_from_session("-10012345"), Some(-10012345));
}
#[test]
fn telegram_chat_id_parses_multi_bot() {
assert_eq!(telegram_chat_id_from_session("mybot:12345"), Some(12345));
assert_eq!(
telegram_chat_id_from_session("mybot:-10012345"),
Some(-10012345)
);
}
#[test]
fn telegram_chat_id_parses_explicit_marker() {
assert_eq!(telegram_chat_id_from_session("telegram:12345"), Some(12345));
assert_eq!(
telegram_chat_id_from_session("bot:telegram:12345"),
Some(12345)
);
}
#[test]
fn derive_channel_id_handles_slack_and_discord_prefixes() {
assert_eq!(
derive_channel_id_from_session("mybot:slack:C123:123.45").as_deref(),
Some("slack:C123")
);
assert_eq!(
derive_channel_id_from_session("mybot:discord:dm:42").as_deref(),
Some("discord:dm:42")
);
}
#[test]
fn derive_channel_id_handles_telegram_forms() {
assert_eq!(
derive_channel_id_from_session("12345").as_deref(),
Some("telegram:12345")
);
assert_eq!(
derive_channel_id_from_session("mybot:12345").as_deref(),
Some("telegram:mybot:12345")
);
assert_eq!(
derive_channel_id_from_session("mybot:telegram:12345").as_deref(),
Some("telegram:mybot:12345")
);
}
#[test]
fn stored_channel_match_restores_legacy_telegram_reads() {
assert!(stored_channel_matches_current(
"telegram:12345",
"telegram:mybot:12345"
));
assert!(!stored_channel_matches_current(
"telegram:otherbot:12345",
"telegram:mybot:12345"
));
assert!(!stored_channel_matches_current(
"telegram:mybot:12345",
"telegram:12345"
));
}
#[test]
fn group_session_detects_telegram_groups() {
assert!(is_group_session("-10012345"));
assert!(is_group_session("mybot:-10012345"));
assert!(!is_group_session("12345"));
assert!(!is_group_session("mybot:12345"));
}
}