analyze_logs: introduce LogProvider trait
This commit is contained in:
parent
b63ecde6b4
commit
827b5a4bd7
12 changed files with 270 additions and 164 deletions
14
Cargo.lock
generated
14
Cargo.lock
generated
|
@ -465,6 +465,18 @@ dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "enum_dispatch"
|
||||||
|
version = "0.3.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f33313078bb8d4d05a2733a94ac4c2d8a0df9a2b84424ebf4f33bfc224a890e"
|
||||||
|
dependencies = [
|
||||||
|
"once_cell",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.48",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "env_filter"
|
name = "env_filter"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -1390,9 +1402,9 @@ dependencies = [
|
||||||
name = "refraction"
|
name = "refraction"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
|
||||||
"color-eyre",
|
"color-eyre",
|
||||||
"dotenvy",
|
"dotenvy",
|
||||||
|
"enum_dispatch",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"eyre",
|
"eyre",
|
||||||
"gray_matter",
|
"gray_matter",
|
||||||
|
|
|
@ -15,9 +15,9 @@ serde = "1.0.196"
|
||||||
serde_json = "1.0.112"
|
serde_json = "1.0.112"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
async-trait = "0.1.77"
|
|
||||||
color-eyre = "0.6.2"
|
color-eyre = "0.6.2"
|
||||||
dotenvy = "0.15.7"
|
dotenvy = "0.15.7"
|
||||||
|
enum_dispatch = "0.3.12"
|
||||||
env_logger = "0.11.1"
|
env_logger = "0.11.1"
|
||||||
eyre = "0.6.11"
|
eyre = "0.6.11"
|
||||||
log = "0.4.20"
|
log = "0.4.20"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
|
||||||
pub mod dadjoke;
|
pub mod dadjoke;
|
||||||
|
pub mod paste_gg;
|
||||||
pub mod pluralkit;
|
pub mod pluralkit;
|
||||||
pub mod prism_meta;
|
pub mod prism_meta;
|
||||||
pub mod rory;
|
pub mod rory;
|
||||||
|
|
55
src/api/paste_gg.rs
Normal file
55
src/api/paste_gg.rs
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
use crate::{api::REQWEST_CLIENT, utils};
|
||||||
|
|
||||||
|
use eyre::{eyre, OptionExt, Result};
|
||||||
|
use log::debug;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
const PASTE_GG: &str = "https://api.paste.gg/v1";
|
||||||
|
const PASTES: &str = "/pastes";
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Deserialize, Serialize)]
|
||||||
|
enum Status {
|
||||||
|
#[serde(rename = "success")]
|
||||||
|
Success,
|
||||||
|
#[serde(rename = "error")]
|
||||||
|
Error,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
pub struct Response<T> {
|
||||||
|
status: Status,
|
||||||
|
pub result: Option<Vec<T>>,
|
||||||
|
error: Option<String>,
|
||||||
|
message: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
pub struct Files {
|
||||||
|
pub id: String,
|
||||||
|
pub name: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_files(id: &str) -> Result<Response<Files>> {
|
||||||
|
let url = format!("{PASTE_GG}{PASTES}/{id}/files");
|
||||||
|
debug!("Making request to {url}");
|
||||||
|
let resp = REQWEST_CLIENT.get(url).send().await?;
|
||||||
|
resp.error_for_status_ref()?;
|
||||||
|
let resp: Response<Files> = resp.json().await?;
|
||||||
|
|
||||||
|
if resp.status == Status::Error {
|
||||||
|
let message = resp
|
||||||
|
.error
|
||||||
|
.ok_or_eyre("Paste.gg gave us an error but with no message!")?;
|
||||||
|
|
||||||
|
Err(eyre!(message))
|
||||||
|
} else {
|
||||||
|
Ok(resp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_raw_file(paste_id: &str, file_id: &str) -> eyre::Result<String> {
|
||||||
|
let url = format!("{PASTE_GG}{PASTES}/{paste_id}/files/{file_id}/raw");
|
||||||
|
let text = utils::text_from_url(&url).await?;
|
||||||
|
|
||||||
|
Ok(text)
|
||||||
|
}
|
|
@ -1,27 +1,27 @@
|
||||||
use crate::api::REQWEST_CLIENT;
|
use crate::utils;
|
||||||
|
|
||||||
use eyre::{eyre, Result};
|
use eyre::Result;
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
use poise::serenity_prelude::Message;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use reqwest::StatusCode;
|
|
||||||
|
|
||||||
|
pub struct _0x0;
|
||||||
|
|
||||||
|
impl super::LogProvider for _0x0 {
|
||||||
|
async fn find_match(&self, message: &Message) -> Option<String> {
|
||||||
static REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"https://0x0\.st/\w*\.\w*").unwrap());
|
static REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"https://0x0\.st/\w*\.\w*").unwrap());
|
||||||
|
|
||||||
pub async fn find(content: &str) -> Result<Option<String>> {
|
trace!("Checking if message {} is a 0x0 paste", message.id);
|
||||||
trace!("Checking if {content} is a 0x0 paste");
|
REGEX
|
||||||
|
.find_iter(&message.content)
|
||||||
|
.map(|m| m.as_str().to_string())
|
||||||
|
.nth(0)
|
||||||
|
}
|
||||||
|
|
||||||
let Some(url) = REGEX.find(content).map(|m| &content[m.range()]) else {
|
async fn fetch(&self, content: &str) -> Result<String> {
|
||||||
return Ok(None);
|
let log = utils::text_from_url(content).await?;
|
||||||
};
|
|
||||||
|
|
||||||
let request = REQWEST_CLIENT.get(url).build()?;
|
Ok(log)
|
||||||
let response = REQWEST_CLIENT.execute(request).await?;
|
|
||||||
let status = response.status();
|
|
||||||
|
|
||||||
if let StatusCode::OK = status {
|
|
||||||
Ok(Some(response.text().await?))
|
|
||||||
} else {
|
|
||||||
Err(eyre!("Failed to fetch paste from {url} with {status}",))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,20 +2,28 @@ use eyre::Result;
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use poise::serenity_prelude::Message;
|
use poise::serenity_prelude::Message;
|
||||||
|
|
||||||
pub async fn find(message: &Message) -> Result<Option<String>> {
|
use crate::utils;
|
||||||
trace!("Checking for text attachments in message {}", message.id);
|
|
||||||
|
|
||||||
// find first uploaded text file
|
pub struct Attachment;
|
||||||
if let Some(attachment) = message.attachments.iter().find(|a| {
|
|
||||||
|
impl super::LogProvider for Attachment {
|
||||||
|
async fn find_match(&self, message: &Message) -> Option<String> {
|
||||||
|
trace!("Checking if message {} has text attachments", message.id);
|
||||||
|
|
||||||
|
message
|
||||||
|
.attachments
|
||||||
|
.iter()
|
||||||
|
.filter_map(|a| {
|
||||||
a.content_type
|
a.content_type
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|ct| ct.starts_with("text/").then_some(true))
|
.and_then(|ct| ct.starts_with("text/").then_some(a.url.clone()))
|
||||||
.is_some()
|
})
|
||||||
}) {
|
.nth(0)
|
||||||
let bytes = attachment.download().await?;
|
}
|
||||||
let res = String::from_utf8(bytes)?;
|
|
||||||
Ok(Some(res))
|
async fn fetch(&self, content: &str) -> Result<String> {
|
||||||
} else {
|
let attachment = utils::bytes_from_url(content).await?;
|
||||||
Ok(None)
|
let log = String::from_utf8(attachment)?;
|
||||||
|
Ok(log)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,29 +1,29 @@
|
||||||
use crate::api::REQWEST_CLIENT;
|
use crate::utils;
|
||||||
|
|
||||||
use eyre::{eyre, Result};
|
use eyre::Result;
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
use poise::serenity_prelude::Message;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use reqwest::StatusCode;
|
|
||||||
|
|
||||||
|
const HASTE: &str = "https://hst.sh";
|
||||||
|
const RAW: &str = "/raw";
|
||||||
|
|
||||||
|
pub struct Haste;
|
||||||
|
|
||||||
|
impl super::LogProvider for Haste {
|
||||||
|
async fn find_match(&self, message: &Message) -> Option<String> {
|
||||||
static REGEX: Lazy<Regex> =
|
static REGEX: Lazy<Regex> =
|
||||||
Lazy::new(|| Regex::new(r"https://hst\.sh(?:/raw)?/(\w+(?:\.\w*)?)").unwrap());
|
Lazy::new(|| Regex::new(r"https://hst\.sh(?:/raw)?/(\w+(?:\.\w*)?)").unwrap());
|
||||||
|
|
||||||
pub async fn find(content: &str) -> Result<Option<String>> {
|
trace!("Checking if message {} is a hst.sh paste", message.id);
|
||||||
trace!("Checking if {content} is a haste log");
|
super::get_first_capture(®EX, &message.content)
|
||||||
|
}
|
||||||
|
|
||||||
let Some(captures) = REGEX.captures(content) else {
|
async fn fetch(&self, content: &str) -> Result<String> {
|
||||||
return Ok(None);
|
let url = format!("{HASTE}{RAW}/{content}");
|
||||||
};
|
let log = utils::text_from_url(&url).await?;
|
||||||
|
|
||||||
let url = format!("https://hst.sh/raw/{}", &captures[1]);
|
Ok(log)
|
||||||
let request = REQWEST_CLIENT.get(&url).build()?;
|
|
||||||
let response = REQWEST_CLIENT.execute(request).await?;
|
|
||||||
let status = response.status();
|
|
||||||
|
|
||||||
if let StatusCode::OK = status {
|
|
||||||
Ok(Some(response.text().await?))
|
|
||||||
} else {
|
|
||||||
Err(eyre!("Failed to fetch paste from {url} with {status}"))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,28 +1,28 @@
|
||||||
use crate::api::REQWEST_CLIENT;
|
use crate::utils;
|
||||||
|
|
||||||
use eyre::{eyre, Result};
|
use eyre::Result;
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
use poise::serenity_prelude::Message;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use reqwest::StatusCode;
|
|
||||||
|
|
||||||
|
const MCLOGS: &str = "https://api.mclo.gs/1";
|
||||||
|
const RAW: &str = "/raw";
|
||||||
|
|
||||||
|
pub struct MCLogs;
|
||||||
|
|
||||||
|
impl super::LogProvider for MCLogs {
|
||||||
|
async fn find_match(&self, message: &Message) -> Option<String> {
|
||||||
static REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"https://mclo\.gs/(\w+)").unwrap());
|
static REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"https://mclo\.gs/(\w+)").unwrap());
|
||||||
|
|
||||||
pub async fn find(content: &str) -> Result<Option<String>> {
|
trace!("Checking if message {} is an mclo.gs paste", message.id);
|
||||||
trace!("Checking if {content} is an mclo.gs paste");
|
super::get_first_capture(®EX, &message.content)
|
||||||
|
}
|
||||||
|
|
||||||
let Some(captures) = REGEX.captures(content) else {
|
async fn fetch(&self, content: &str) -> Result<String> {
|
||||||
return Ok(None);
|
let url = format!("{MCLOGS}{RAW}/{content}");
|
||||||
};
|
let log = utils::text_from_url(&url).await?;
|
||||||
|
|
||||||
let url = format!("https://api.mclo.gs/1/raw/{}", &captures[1]);
|
Ok(log)
|
||||||
let request = REQWEST_CLIENT.get(&url).build()?;
|
|
||||||
let response = REQWEST_CLIENT.execute(request).await?;
|
|
||||||
let status = response.status();
|
|
||||||
|
|
||||||
if let StatusCode::OK = status {
|
|
||||||
Ok(Some(response.text().await?))
|
|
||||||
} else {
|
|
||||||
Err(eyre!("Failed to fetch log from {url} with {status}"))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,15 @@
|
||||||
|
use std::slice::Iter;
|
||||||
|
|
||||||
|
use enum_dispatch::enum_dispatch;
|
||||||
use eyre::Result;
|
use eyre::Result;
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
use poise::serenity_prelude::Message;
|
use poise::serenity_prelude::Message;
|
||||||
|
use regex::Regex;
|
||||||
|
|
||||||
|
use self::{
|
||||||
|
_0x0::_0x0 as _0x0st, attachment::Attachment, haste::Haste, mclogs::MCLogs, paste_gg::PasteGG,
|
||||||
|
pastebin::PasteBin,
|
||||||
|
};
|
||||||
|
|
||||||
#[path = "0x0.rs"]
|
#[path = "0x0.rs"]
|
||||||
mod _0x0;
|
mod _0x0;
|
||||||
|
@ -9,25 +19,52 @@ mod mclogs;
|
||||||
mod paste_gg;
|
mod paste_gg;
|
||||||
mod pastebin;
|
mod pastebin;
|
||||||
|
|
||||||
pub type LogProvider = Result<Option<String>>;
|
#[enum_dispatch]
|
||||||
|
pub trait LogProvider {
|
||||||
pub async fn find_log(message: &Message) -> LogProvider {
|
async fn find_match(&self, message: &Message) -> Option<String>;
|
||||||
macro_rules! provider_impl {
|
async fn fetch(&self, content: &str) -> Result<String>;
|
||||||
($provider:ident) => {
|
|
||||||
if let Some(content) = $provider::find(&message.content).await? {
|
|
||||||
return Ok(Some(content));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
provider_impl!(_0x0);
|
|
||||||
provider_impl!(mclogs);
|
|
||||||
provider_impl!(haste);
|
|
||||||
provider_impl!(paste_gg);
|
|
||||||
provider_impl!(pastebin);
|
|
||||||
|
|
||||||
if let Some(content) = attachment::find(message).await? {
|
|
||||||
return Ok(Some(content));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(None)
|
fn get_first_capture(regex: &Lazy<Regex>, string: &str) -> Option<String> {
|
||||||
|
regex
|
||||||
|
.captures_iter(string)
|
||||||
|
.filter_map(|c| c.get(1).map(|c| c.as_str().to_string()))
|
||||||
|
.nth(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[enum_dispatch(LogProvider)]
|
||||||
|
enum Provider {
|
||||||
|
_0x0st,
|
||||||
|
Attachment,
|
||||||
|
Haste,
|
||||||
|
MCLogs,
|
||||||
|
PasteGG,
|
||||||
|
PasteBin,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Provider {
|
||||||
|
pub fn interator() -> Iter<'static, Provider> {
|
||||||
|
static PROVIDERS: [Provider; 6] = [
|
||||||
|
Provider::_0x0st(_0x0st),
|
||||||
|
Provider::Attachment(Attachment),
|
||||||
|
Provider::Haste(Haste),
|
||||||
|
Provider::MCLogs(MCLogs),
|
||||||
|
Provider::PasteBin(PasteBin),
|
||||||
|
Provider::PasteGG(PasteGG),
|
||||||
|
];
|
||||||
|
PROVIDERS.iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn find_log(message: &Message) -> Result<Option<String>> {
|
||||||
|
let providers = Provider::interator();
|
||||||
|
|
||||||
|
for provider in providers {
|
||||||
|
if let Some(found) = provider.find_match(message).await {
|
||||||
|
let log = provider.fetch(&found).await?;
|
||||||
|
return Ok(Some(log));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,72 +1,36 @@
|
||||||
use crate::api::REQWEST_CLIENT;
|
use crate::api::paste_gg;
|
||||||
|
|
||||||
use eyre::{eyre, OptionExt, Result};
|
use eyre::{OptionExt, Result};
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
use poise::serenity_prelude::Message;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use reqwest::StatusCode;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
const PASTE_GG: &str = "https://api.paste.gg/v1";
|
pub struct PasteGG;
|
||||||
const PASTES_ENDPOINT: &str = "/pastes";
|
|
||||||
static REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"https://paste.gg/p/\w+/(\w+)").unwrap());
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
impl super::LogProvider for PasteGG {
|
||||||
struct PasteResponse {
|
async fn find_match(&self, message: &Message) -> Option<String> {
|
||||||
status: String,
|
static REGEX: Lazy<Regex> =
|
||||||
result: Option<Vec<PasteResult>>,
|
Lazy::new(|| Regex::new(r"https://paste.gg/p/\w+/(\w+)").unwrap());
|
||||||
error: Option<String>,
|
|
||||||
message: Option<String>,
|
trace!("Checking if message {} is a paste.gg paste", message.id);
|
||||||
|
super::get_first_capture(®EX, &message.content)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
async fn fetch(&self, content: &str) -> Result<String> {
|
||||||
struct PasteResult {
|
let files = paste_gg::get_files(content).await?;
|
||||||
id: String,
|
let result = files
|
||||||
name: Option<String>,
|
|
||||||
description: Option<String>,
|
|
||||||
visibility: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn find(content: &str) -> Result<Option<String>> {
|
|
||||||
trace!("Checking if {content} is a paste.gg log");
|
|
||||||
let Some(captures) = REGEX.captures(content) else {
|
|
||||||
return Ok(None);
|
|
||||||
};
|
|
||||||
|
|
||||||
let paste_id = &captures[1];
|
|
||||||
let files_url = format!("{PASTE_GG}{PASTES_ENDPOINT}/{paste_id}/files");
|
|
||||||
|
|
||||||
let resp = REQWEST_CLIENT
|
|
||||||
.execute(REQWEST_CLIENT.get(&files_url).build()?)
|
|
||||||
.await?;
|
|
||||||
let status = resp.status();
|
|
||||||
|
|
||||||
if resp.status() != StatusCode::OK {
|
|
||||||
return Err(eyre!(
|
|
||||||
"Couldn't get paste {paste_id} from {PASTE_GG} with status {status}!"
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
let paste_files: PasteResponse = resp.json().await?;
|
|
||||||
let file_id = &paste_files
|
|
||||||
.result
|
.result
|
||||||
.ok_or_eyre("Couldn't find any files associated with paste {paste_id}!")?[0]
|
.ok_or_eyre("Got an empty result from paste.gg!")?;
|
||||||
.id;
|
|
||||||
|
|
||||||
let raw_url = format!("{PASTE_GG}{PASTES_ENDPOINT}/{paste_id}/files/{file_id}/raw");
|
let file_id = result
|
||||||
|
.iter()
|
||||||
|
.map(|f| f.id.as_str())
|
||||||
|
.nth(0)
|
||||||
|
.ok_or_eyre("Couldn't get file id from empty paste.gg response!")?;
|
||||||
|
|
||||||
let resp = REQWEST_CLIENT
|
let log = paste_gg::get_raw_file(content, file_id).await?;
|
||||||
.execute(REQWEST_CLIENT.get(&raw_url).build()?)
|
|
||||||
.await?;
|
|
||||||
let status = resp.status();
|
|
||||||
|
|
||||||
if status != StatusCode::OK {
|
Ok(log)
|
||||||
return Err(eyre!(
|
|
||||||
"Couldn't get file {file_id} from paste {paste_id} with status {status}!"
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let text = resp.text().await?;
|
|
||||||
|
|
||||||
Ok(Some(text))
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,28 +1,29 @@
|
||||||
use crate::api::REQWEST_CLIENT;
|
use crate::utils;
|
||||||
|
|
||||||
use eyre::{eyre, Result};
|
use eyre::Result;
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
use poise::serenity_prelude::Message;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use reqwest::StatusCode;
|
|
||||||
|
|
||||||
|
const PASTEBIN: &str = "https://pastebin.com";
|
||||||
|
const RAW: &str = "/raw";
|
||||||
|
|
||||||
|
pub struct PasteBin;
|
||||||
|
|
||||||
|
impl super::LogProvider for PasteBin {
|
||||||
|
async fn find_match(&self, message: &Message) -> Option<String> {
|
||||||
static REGEX: Lazy<Regex> =
|
static REGEX: Lazy<Regex> =
|
||||||
Lazy::new(|| Regex::new(r"https://pastebin\.com(?:/raw)?/(\w+)").unwrap());
|
Lazy::new(|| Regex::new(r"https://pastebin\.com(?:/raw)?/(\w+)").unwrap());
|
||||||
|
|
||||||
pub async fn find(content: &str) -> Result<Option<String>> {
|
trace!("Checking if message {} is a pastebin paste", message.id);
|
||||||
trace!("Checking if {content} is a pastebin log");
|
super::get_first_capture(®EX, &message.content)
|
||||||
let Some(captures) = REGEX.captures(content) else {
|
}
|
||||||
return Ok(None);
|
|
||||||
};
|
|
||||||
|
|
||||||
let url = format!("https://pastebin.com/raw/{}", &captures[1]);
|
async fn fetch(&self, content: &str) -> Result<String> {
|
||||||
let request = REQWEST_CLIENT.get(&url).build()?;
|
let url = format!("{PASTEBIN}{RAW}/{content}");
|
||||||
let response = REQWEST_CLIENT.execute(request).await?;
|
let log = utils::text_from_url(&url).await?;
|
||||||
let status = response.status();
|
|
||||||
|
|
||||||
if let StatusCode::OK = status {
|
Ok(log)
|
||||||
Ok(Some(response.text().await?))
|
|
||||||
} else {
|
|
||||||
Err(eyre!("Failed to fetch paste from {url} with {status}"))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1,29 @@
|
||||||
|
use crate::api::REQWEST_CLIENT;
|
||||||
|
|
||||||
|
use eyre::Result;
|
||||||
|
use log::debug;
|
||||||
|
use reqwest::Response;
|
||||||
|
|
||||||
pub mod resolve_message;
|
pub mod resolve_message;
|
||||||
|
|
||||||
|
pub async fn get_url(url: &str) -> Result<Response> {
|
||||||
|
debug!("Making request to {url}");
|
||||||
|
let resp = REQWEST_CLIENT.get(url).send().await?;
|
||||||
|
resp.error_for_status_ref()?;
|
||||||
|
|
||||||
|
Ok(resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn text_from_url(url: &str) -> Result<String> {
|
||||||
|
let resp = get_url(url).await?;
|
||||||
|
|
||||||
|
let text = resp.text().await?;
|
||||||
|
Ok(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn bytes_from_url(url: &str) -> Result<Vec<u8>> {
|
||||||
|
let resp = get_url(url).await?;
|
||||||
|
|
||||||
|
let bytes = resp.bytes().await?;
|
||||||
|
Ok(bytes.to_vec())
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue