Skip to content

Commit

Permalink
feat: add GitHub link expansion
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanccn committed Oct 17, 2023
1 parent 1977846 commit 601a966
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 7 deletions.
13 changes: 7 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ num = "0.4.1"
once_cell = "1.18.0"
owo-colors = { version = "3.5.0", features = ["supports-colors"] }
poise = { git = "https://github.com/serenity-rs/poise.git", branch = "serenity-next", version = "0.5.5" }
regex = "1.10.2"
reqwest = { version = "0.11.22", default-features = false, features = [
"rustls-tls",
"json",
Expand Down
105 changes: 105 additions & 0 deletions src/handlers/github_expansion.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
use poise::serenity_prelude as serenity;

use anyhow::{anyhow, Result};
use once_cell::sync::Lazy;
use regex::Regex;

use crate::reqwest_client;

static GITHUB: Lazy<Regex> = Lazy::new(|| {
Regex::new(r"https?://github\.com/(?P<repo>[\w-]+/[\w.-]+)/blob/(?P<ref>.+?)/(?P<file>.*\.(?:(?P<language>\w+))?)#L(?P<start>\d+)(?:[~-]L?(?P<end>\d+)?)?").unwrap()
});

pub async fn handle(message: &serenity::Message, ctx: &serenity::Context) -> Result<()> {
let message = message.clone();
let mut embeds: Vec<serenity::CreateEmbed> = vec![];

for captures in GITHUB.captures_iter(&message.content) {
let repo = captures
.name("repo")
.ok_or_else(|| anyhow!("Could not obtain `repo`"))?
.as_str();
let ref_ = captures
.name("ref")
.ok_or_else(|| anyhow!("Could not obtain `ref`"))?
.as_str();
let file = captures
.name("file")
.ok_or_else(|| anyhow!("Could not obtain `file`"))?
.as_str();

let language = if let Some(m) = captures.name("language") {
m.as_str().to_owned()
} else {
"".to_owned()
};

let start = captures
.name("start")
.ok_or_else(|| anyhow!("Could not obtain `start`"))?
.as_str()
.parse::<usize>()?;
let end = captures
.name("end")
.and_then(|end| end.as_str().parse::<usize>().ok());

let resp = reqwest_client::HTTP
.get(format!(
"https://raw.githubusercontent.com/{repo}/{ref_}/{file}"
))
.send()
.await?;

let lines: Vec<String> = resp
.text()
.await?
.split("\n")
.map(|s| s.to_owned())
.collect();

let idx_start = start - 1;
let idx_end = if let Some(end) = end {
end
} else {
lines.len()
};
let selected_lines = &lines[idx_start..idx_end];

let embed = serenity::CreateEmbed::new()
.title(repo)
.field(
file,
"```".to_owned() + &language + "\n" + &selected_lines.join("\n") + "\n```",
true,
)
.footer(serenity::CreateEmbedFooter::new(ref_));

embeds.push(embed);
}

// {
// let msg_id = message.id;
// let mut message_updates = serenity::collector::collect(&ctx.shard, move |ev| match ev {
// serenity::Event::MessageUpdate(x) if x.id == msg_id => Some(()),
// _ => None,
// });
// let _ = tokio::time::timeout(Duration::from_millis(2000), message_updates.next()).await;
// message
// .edit(&ctx, serenity::EditMessage::new().suppress_embeds(true))
// .await?;
// }

if !embeds.is_empty() {
message
.channel_id
.send_message(
&ctx,
serenity::CreateMessage::new()
.embeds(embeds)
.reference_message(&message),
)
.await?;
};

Ok(())
}
10 changes: 10 additions & 0 deletions src/handlers/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use anyhow::Result;
use poise::serenity_prelude as serenity;

mod github_expansion;

pub async fn handle(message: &serenity::Message, ctx: &serenity::Context) -> Result<()> {
github_expansion::handle(message, ctx).await?;

Ok(())
}
15 changes: 14 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use anyhow::{Error, Result};
use owo_colors::OwoColorize;
use poise::{
serenity_prelude::{Client, GatewayIntents},
serenity_prelude::{Client, FullEvent, GatewayIntents},
Framework, FrameworkOptions,
};

Expand All @@ -11,6 +11,7 @@ pub struct Data {}
pub type Context<'a> = poise::Context<'a, Data, Error>;

mod commands;
mod handlers;
mod reqwest_client;
mod utils;

Expand All @@ -26,6 +27,18 @@ async fn main() -> Result<()> {
.framework(Framework::new(
FrameworkOptions {
commands: commands::vec(),
event_handler: |ev, _, _| {
Box::pin(async move {
match ev {
FullEvent::Message { new_message, ctx } => {
handlers::handle(&new_message, &ctx).await?;
}
&_ => {}
}

Ok(())
})
},
..Default::default()
},
|ctx, ready, framework| {
Expand Down

0 comments on commit 601a966

Please sign in to comment.