From 65dd1e75cd87ae8d62be5bc998ef4f2a184c45bc Mon Sep 17 00:00:00 2001 From: Esteve Autet Alexe Date: Wed, 24 Jul 2024 20:28:59 +0200 Subject: [PATCH] Leer enlaces de github (#35) * feat: event * fix: imports * Update read_github_links.rs Allow to show entire files without `#L` in url --------- Co-authored-by: Apika Luca --- src/config/setup.rs | 3 + src/events/mod.rs | 1 + src/events/read_github_links.rs | 144 ++++++++++++++++++++++++++++++++ 3 files changed, 148 insertions(+) create mode 100644 src/events/read_github_links.rs diff --git a/src/config/setup.rs b/src/config/setup.rs index 1995561..dd6e1cc 100644 --- a/src/config/setup.rs +++ b/src/config/setup.rs @@ -15,6 +15,8 @@ use crate::config::songbird_config::SoundStore; use super::general_command_loader::GENERAL_GROUP; +use crate::events::read_github_links::ReadGithubLinkHandler; + use super::slash_command_loader::Handler; pub async fn setup(secret_store: SecretStore, _: PathBuf) -> Result { @@ -51,6 +53,7 @@ pub async fn setup(secret_store: SecretStore, _: PathBuf) -> Result Option { + let extension_regex = Regex::new(r"\.([^./?#]+)(#|$)").unwrap(); + + let range_regex + = Regex::new(r"(?:\.(?[^#]+))?(?:#L(?\d+)?(?:-L(?\d+))?)?$") + .unwrap(); + + let language = extension_regex + .captures(url) + .and_then(|caps| caps.get(1)) + .map(|m| m.as_str().to_string()) + .unwrap_or_default(); + + if let Some(caps) = range_regex.captures(url) { + let start = caps.name("start").and_then(|m| m.as_str().parse::().ok()); + let end = caps.name("end").and_then(|m| m.as_str().parse::().ok()); + + if end < start { + return None; + } + + match (start, end) { + (Some(start), Some(end)) => Some(RangeOrIndex::Range( + language, + start - 1, + end + )), + (Some(start), None) => Some(RangeOrIndex::Index( + language, + start - 1 + )), + (None, None) => { + Some(RangeOrIndex::Language(language)) + } + _ => None + } + } else { + None + } +} + + +async fn read_message(link: String) -> Option { + if let Ok(result) = get(&link).await { + if result.status() == 200 { + if let Ok(text) = result.text().await { + let parsed = parse_url(&link)?; + + let subtext: Vec<&str> = text.split('\n').collect(); + + return match parsed { + RangeOrIndex::Language(language) + => Some(format!( + "Mostrando <{link}>\n```{language}\n{text}\n```" + )), + RangeOrIndex::Index(language, index) + => { + if index < subtext.len() as i32 { + Some(format!( + "Mostrando linea {} de <{link}>\n```{language}\n{}\n```", + index + 1, + subtext[index as usize].to_string()) + ) + } else { + None + } + } + RangeOrIndex::Range(language, start, end) + => { + if start < subtext.len() as i32 && end <= subtext.len() as i32 { + Some(format!( + "Mostrando desde la linea {} hasta la linea {end} de <{link}>\n```{language}\n{}\n```", + start + 1, + subtext[start as usize..end as usize].join("\n") + )) + } else { + None + } + } + }; + } + } + } + None +} + +#[async_trait] +impl EventHandler for ReadGithubLinkHandler { + async fn message(&self, ctx: Context, msg: Message) { + let repo_regex + = Regex::new(r"(https://github\.com/(?:[^/]+/){2})blob/(.*)") + .unwrap(); + let hidden_link_regex + = Regex::new(r"[<>]") + .unwrap(); + let split_message_regex + = Regex::new(r"[\n ]") + .unwrap(); + + let replaced = if repo_regex.is_match(&msg.content) { + repo_regex.replace_all(&msg.content, |captures: &Captures| { + captures[1].to_string() + &captures[2] + }) + } else { + return; + }.replace("https://github.com/", "https://raw.githubusercontent.com/"); + + let without_hidden = hidden_link_regex + .replace_all(&replaced, ""); + + let without_spaces = split_message_regex + .split(&without_hidden); + + let links = without_spaces + .filter(|s| s.starts_with("https://raw.githubusercontent.com/")); + + let mut dup: Vec<&str> = Vec::new(); + for link in links { + if dup.contains(&link) { + continue; + } + + if let Some(content) = read_message(link.to_string()).await { + msg.reply(&ctx, content).await.unwrap(); + } + + dup.push(link); + } + } +}