pub fn parse_permalink(link: &str) -> Option<PermalinkTarget> {
let trimmed = link.trim();
if trimmed.starts_with("https://matrix.to/#/") || trimmed.starts_with("http://matrix.to/#/") {
let fragment = trimmed.split("/#/").nth(1)?;
let decoded = urlencoding::decode(fragment).ok()?;
let parts: Vec<&str> = decoded.splitn(2, '/').collect();
if let Some(first) = parts.first() {
let first = first.split('?').next().unwrap_or(first);
if first.starts_with('!') {
let room_id = first.to_string();
let event_id = parts.get(1).and_then(|e| {
let e = e.split('?').next().unwrap_or(e);
if e.starts_with('$') {
Some(e.to_string())
} else {
None
}
});
return Some(PermalinkTarget::RoomId {
room_id,
event_id,
});
} else if first.starts_with('#') {
return Some(PermalinkTarget::RoomAlias {
alias: first.to_string(),
});
} else if first.starts_with('@') {
return Some(PermalinkTarget::UserId {
user_id: first.to_string(),
});
}
}
}
if trimmed.starts_with('!') {
return Some(PermalinkTarget::RoomId {
room_id: trimmed.to_string(),
event_id: None,
});
}
if trimmed.starts_with('#') {
return Some(PermalinkTarget::RoomAlias {
alias: trimmed.to_string(),
});
}
if trimmed.starts_with('@') {
return Some(PermalinkTarget::UserId {
user_id: trimmed.to_string(),
});
}
None
}
#[derive(Clone, Debug, PartialEq)]
pub enum PermalinkTarget {
RoomId {
room_id: String,
event_id: Option<String>,
},
RoomAlias {
alias: String,
},
UserId {
user_id: String,
},
}
pub fn make_room_permalink(room_id: &str) -> String {
format!("https://matrix.to/#/{}", urlencoding::encode(room_id))
}
pub fn make_event_permalink(room_id: &str, event_id: &str) -> String {
format!(
"https://matrix.to/#/{}/{}",
urlencoding::encode(room_id),
urlencoding::encode(event_id)
)
}
pub fn make_user_permalink(user_id: &str) -> String {
format!("https://matrix.to/#/{}", urlencoding::encode(user_id))
}