feat: log analysis
Signed-off-by: seth <getchoo@tuta.io>
This commit is contained in:
parent
026d4cb607
commit
c6f4295d6a
18 changed files with 487 additions and 20 deletions
|
@ -9,7 +9,7 @@ const DADJOKE: &str = "https://icanhazdadjoke.com";
|
|||
pub async fn get_joke() -> Result<String> {
|
||||
let req = REQWEST_CLIENT.get(DADJOKE).build()?;
|
||||
|
||||
info!("Making request to {}", req.url());
|
||||
debug!("Making request to {}", req.url());
|
||||
let resp = REQWEST_CLIENT.execute(req).await?;
|
||||
let status = resp.status();
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ pub async fn get_sender(message_id: MessageId) -> Result<UserId> {
|
|||
.get(format!("{PLURAL_KIT}{MESSAGES_ENDPOINT}/{message_id}"))
|
||||
.build()?;
|
||||
|
||||
info!("Making request to {}", req.url());
|
||||
debug!("Making request to {}", req.url());
|
||||
let resp = REQWEST_CLIENT.execute(req).await?;
|
||||
let status = resp.status();
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ pub async fn get_latest_minecraft_version() -> Result<String> {
|
|||
.get(format!("{PRISM_META}{MINECRAFT_PACKAGEJSON_ENDPOINT}"))
|
||||
.build()?;
|
||||
|
||||
info!("Making request to {}", req.url());
|
||||
debug!("Making request to {}", req.url());
|
||||
let resp = REQWEST_CLIENT.execute(req).await?;
|
||||
let status = resp.status();
|
||||
|
||||
|
|
|
@ -16,31 +16,26 @@ const RORY: &str = "https://rory.cat";
|
|||
const ENDPOINT: &str = "/purr";
|
||||
|
||||
pub async fn get_rory(id: Option<u64>) -> Result<RoryResponse> {
|
||||
let target = {
|
||||
if let Some(id) = id {
|
||||
id.to_string()
|
||||
} else {
|
||||
"".to_string()
|
||||
}
|
||||
};
|
||||
let target = id.map(|id| id.to_string()).unwrap_or_default();
|
||||
|
||||
let req = REQWEST_CLIENT
|
||||
.get(format!("{RORY}{ENDPOINT}/{target}"))
|
||||
.build()
|
||||
.wrap_err_with(|| "Couldn't build reqwest client!")?;
|
||||
|
||||
info!("Making request to {}", req.url());
|
||||
debug!("Making request to {}", req.url());
|
||||
let resp = REQWEST_CLIENT
|
||||
.execute(req)
|
||||
.await
|
||||
.wrap_err_with(|| "Couldn't make request for shiggy!")?;
|
||||
.wrap_err_with(|| "Couldn't make request for rory!")?;
|
||||
|
||||
let status = resp.status();
|
||||
|
||||
if let StatusCode::OK = status {
|
||||
let data = resp
|
||||
.json::<RoryResponse>()
|
||||
.await
|
||||
.wrap_err_with(|| "Couldn't parse the shiggy response!")?;
|
||||
.wrap_err_with(|| "Couldn't parse the rory response!")?;
|
||||
|
||||
Ok(data)
|
||||
} else {
|
||||
|
|
|
@ -10,6 +10,7 @@ pub static COLORS: Lazy<HashMap<&str, Color>> = Lazy::new(|| {
|
|||
("blue", Color::from((96, 165, 250))),
|
||||
("yellow", Color::from((253, 224, 71))),
|
||||
("orange", Color::from((251, 146, 60))),
|
||||
// TODO purple & pink :D
|
||||
])
|
||||
});
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ pub async fn handle(error: FrameworkError<'_, Data, Report>) {
|
|||
e.title("Something went wrong!")
|
||||
.description("oopsie")
|
||||
.timestamp(Timestamp::now())
|
||||
.color(COLORS["orange"])
|
||||
.color(COLORS["red"])
|
||||
})
|
||||
})
|
||||
.await
|
||||
|
|
181
src/handlers/event/analyze_logs/issues.rs
Normal file
181
src/handlers/event/analyze_logs/issues.rs
Normal file
|
@ -0,0 +1,181 @@
|
|||
use once_cell::sync::Lazy;
|
||||
use regex::Regex;
|
||||
|
||||
pub type Issue = Option<(String, String)>;
|
||||
|
||||
pub fn find_issues(log: &str) -> Vec<(String, String)> {
|
||||
let issues = [
|
||||
fabric_internal,
|
||||
flatpak_nvidia,
|
||||
forge_java,
|
||||
intel_hd,
|
||||
java_option,
|
||||
macos_ns,
|
||||
oom,
|
||||
optinofine,
|
||||
outdated_launcher,
|
||||
wrong_java,
|
||||
];
|
||||
|
||||
issues.iter().filter_map(|issue| issue(log)).collect()
|
||||
}
|
||||
|
||||
fn fabric_internal(log: &str) -> Issue {
|
||||
const CLASS_NOT_FOUND: &str = "Caused by: java.lang.ClassNotFoundException: ";
|
||||
|
||||
let issue = (
|
||||
"Fabric Internal Access".to_string(),
|
||||
"The mod you are using is using fabric internals that are not meant \
|
||||
to be used by anything but the loader itself.
|
||||
Those mods break both on Quilt and with fabric updates.
|
||||
If you're using fabric, downgrade your fabric loader could work, \
|
||||
on Quilt you can try updating to the latest beta version, \
|
||||
but there's nothing much to do unless the mod author stops using them."
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
let errors = [
|
||||
&format!("{CLASS_NOT_FOUND}net.fabricmc.fabric.impl"),
|
||||
&format!("{CLASS_NOT_FOUND}net.fabricmc.fabric.mixin"),
|
||||
&format!("{CLASS_NOT_FOUND}net.fabricmc.fabric.loader.impl"),
|
||||
&format!("{CLASS_NOT_FOUND}net.fabricmc.fabric.loader.mixin"),
|
||||
"org.quiltmc.loader.impl.FormattedException: java.lang.NoSuchMethodError:",
|
||||
];
|
||||
|
||||
let found = errors.iter().any(|e| log.contains(e));
|
||||
found.then_some(issue)
|
||||
}
|
||||
|
||||
fn flatpak_nvidia(log: &str) -> Issue {
|
||||
let issue = (
|
||||
"Outdated Nvidia Flatpak Driver".to_string(),
|
||||
"The Nvidia driver for flatpak is outdated.
|
||||
Please run `flatpak update` to fix this issue. \
|
||||
If that does not solve it, \
|
||||
please wait until the driver is added to Flathub and run it again."
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
let found = log.contains("org.lwjgl.LWJGLException: Could not choose GLX13 config")
|
||||
|| log.contains("GLFW error 65545: GLX: Failed to find a suitable GLXFBConfig");
|
||||
|
||||
found.then_some(issue)
|
||||
}
|
||||
|
||||
fn forge_java(log: &str) -> Issue {
|
||||
let issue = (
|
||||
"Forge Java Bug".to_string(),
|
||||
"Old versions of Forge crash with Java 8u321+.
|
||||
To fix this, update forge to the latest version via the Versions tab
|
||||
(right click on Forge, click Change Version, and choose the latest one)
|
||||
Alternatively, you can download 8u312 or lower. \
|
||||
See [archive](https://github.com/adoptium/temurin8-binaries/releases/tag/jdk8u312-b07)"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
let found = log.contains("java.lang.NoSuchMethodError: sun.security.util.ManifestEntryVerifier.<init>(Ljava/util/jar/Manifest;)V");
|
||||
found.then_some(issue)
|
||||
}
|
||||
|
||||
fn intel_hd(log: &str) -> Issue {
|
||||
let issue =
|
||||
(
|
||||
"Intel HD Windows 10".to_string(),
|
||||
"Your drivers don't support windows 10 officially
|
||||
See https://prismlauncher.org/wiki/getting-started/installing-java/#a-note-about-intel-hd-20003000-on-windows-10 for more info".to_string()
|
||||
);
|
||||
|
||||
let found = log.contains("java.lang.NoSuchMethodError: sun.security.util.ManifestEntryVerifier.<init>(Ljava/util/jar/Manifest;)V");
|
||||
found.then_some(issue)
|
||||
}
|
||||
|
||||
fn java_option(log: &str) -> Issue {
|
||||
static VM_OPTION_REGEX: Lazy<Regex> =
|
||||
Lazy::new(|| Regex::new(r"Unrecognized VM option '(.+)'[\r\n]").unwrap());
|
||||
static OPTION_REGEX: Lazy<Regex> =
|
||||
Lazy::new(|| Regex::new(r"Unrecognized option: (.+)[\r\n]").unwrap());
|
||||
|
||||
if let Some(captures) = VM_OPTION_REGEX.captures(log) {
|
||||
let title = if &captures[1] == "UseShenandoahGC" {
|
||||
"Wrong Java Arguments"
|
||||
} else {
|
||||
"Java 8 and below don't support ShenandoahGC"
|
||||
};
|
||||
return Some((
|
||||
title.to_string(),
|
||||
format!("Remove `-XX:{}` from your Java arguments", &captures[1]),
|
||||
));
|
||||
}
|
||||
|
||||
if let Some(captures) = OPTION_REGEX.captures(log) {
|
||||
return Some((
|
||||
"Wrong Java Arguments".to_string(),
|
||||
format!("Remove `{}` from your Java arguments", &captures[1]),
|
||||
));
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn macos_ns(log: &str) -> Issue {
|
||||
let issue = (
|
||||
"MacOS NSInternalInconsistencyException".to_string(),
|
||||
"You need to downgrade your Java 8 version. See https://prismlauncher.org/wiki/getting-started/installing-java/#older-minecraft-on-macos".to_string()
|
||||
);
|
||||
|
||||
let found =
|
||||
log.contains("Terminating app due to uncaught exception 'NSInternalInconsistencyException");
|
||||
found.then_some(issue)
|
||||
}
|
||||
|
||||
fn oom(log: &str) -> Issue {
|
||||
let issue = (
|
||||
"Out of Memory".to_string(),
|
||||
"Allocating more RAM to your instance could help prevent this crash.".to_string(),
|
||||
);
|
||||
|
||||
let found = log.contains("java.lang.OutOfMemoryError");
|
||||
found.then_some(issue)
|
||||
}
|
||||
|
||||
fn optinofine(log: &str) -> Issue {
|
||||
let issue = (
|
||||
"Potential OptiFine Incompatibilities".to_string(),
|
||||
"OptiFine is known to cause problems when paired with other mods. \
|
||||
Try to disable OptiFine and see if the issue persists.
|
||||
Check `/tag optifine` for more info & some typically more compatible alternatives you can use."
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
let found = log.contains("[✔] OptiFine_") || log.contains("[✔] optifabric-");
|
||||
found.then_some(issue)
|
||||
}
|
||||
|
||||
// TODO: @TheKodeToad
|
||||
fn outdated_launcher(_log: &str) -> Issue {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn wrong_java(log: &str) -> Issue {
|
||||
static SWITCH_VERSION_REGEX: Lazy<Regex> = Lazy::new(|| {
|
||||
Regex::new(
|
||||
r"(?m)Please switch to one of the following Java versions for this instance:[\r\n]+(Java version [\d.]+)",
|
||||
).unwrap()
|
||||
});
|
||||
|
||||
if let Some(captures) = SWITCH_VERSION_REGEX.captures(log) {
|
||||
let versions = captures[1].split('\n').collect::<Vec<&str>>().join(", ");
|
||||
return Some((
|
||||
"Wrong Java Version".to_string(),
|
||||
format!("Please switch to one of the following: `{versions}`\nFor more information, type `/tag java`"),
|
||||
));
|
||||
}
|
||||
|
||||
let issue = (
|
||||
"Java compatibility check skipped".to_string(),
|
||||
"The Java major version may not work with your Minecraft instance. Please switch to a compatible version".to_string()
|
||||
);
|
||||
|
||||
log.contains("Java major version is incompatible. Things might break.")
|
||||
.then_some(issue)
|
||||
}
|
66
src/handlers/event/analyze_logs/mod.rs
Normal file
66
src/handlers/event/analyze_logs/mod.rs
Normal file
|
@ -0,0 +1,66 @@
|
|||
use crate::consts::COLORS;
|
||||
use color_eyre::eyre::Result;
|
||||
use log::*;
|
||||
use poise::serenity_prelude::{Context, Message};
|
||||
|
||||
mod issues;
|
||||
mod providers;
|
||||
|
||||
use issues::find_issues;
|
||||
use providers::find_log;
|
||||
|
||||
pub async fn handle(ctx: &Context, message: &Message) -> Result<()> {
|
||||
let channel = message.channel_id;
|
||||
|
||||
let log = find_log(message).await;
|
||||
|
||||
if log.is_err() {
|
||||
channel
|
||||
.send_message(ctx, |m| {
|
||||
m.reference_message(message)
|
||||
.allowed_mentions(|am| am.replied_user(true))
|
||||
.embed(|e| {
|
||||
e.title("Analyze failed!")
|
||||
.description("Couldn't download log")
|
||||
})
|
||||
})
|
||||
.await?;
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let Some(log) = log? else {
|
||||
debug!("No log found in message! Skipping analysis");
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
let issues = find_issues(&log);
|
||||
|
||||
channel
|
||||
.send_message(ctx, |m| {
|
||||
m.reference_message(message)
|
||||
.allowed_mentions(|am| am.replied_user(true))
|
||||
.embed(|e| {
|
||||
e.title("Log analysis");
|
||||
|
||||
if issues.is_empty() {
|
||||
e.color(COLORS["green"]).field(
|
||||
"Analyze failed!",
|
||||
"No issues found automatically",
|
||||
false,
|
||||
);
|
||||
} else {
|
||||
e.color(COLORS["red"]);
|
||||
|
||||
for (title, description) in issues {
|
||||
e.field(title, description, false);
|
||||
}
|
||||
}
|
||||
|
||||
e
|
||||
})
|
||||
})
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
24
src/handlers/event/analyze_logs/providers/0x0.rs
Normal file
24
src/handlers/event/analyze_logs/providers/0x0.rs
Normal file
|
@ -0,0 +1,24 @@
|
|||
use crate::api::REQWEST_CLIENT;
|
||||
|
||||
use color_eyre::eyre::{eyre, Result};
|
||||
use once_cell::sync::Lazy;
|
||||
use regex::Regex;
|
||||
use reqwest::StatusCode;
|
||||
|
||||
static REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"https://0x0\.st/\w*\.\w*").unwrap());
|
||||
|
||||
pub async fn find(content: &str) -> Result<Option<String>> {
|
||||
let Some(url) = REGEX.find(content).map(|m| &content[m.range()]) else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
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}",))
|
||||
}
|
||||
}
|
18
src/handlers/event/analyze_logs/providers/attachment.rs
Normal file
18
src/handlers/event/analyze_logs/providers/attachment.rs
Normal file
|
@ -0,0 +1,18 @@
|
|||
use color_eyre::eyre::Result;
|
||||
use poise::serenity_prelude::Message;
|
||||
|
||||
pub async fn find(message: &Message) -> Result<Option<String>> {
|
||||
// find first uploaded text file
|
||||
if let Some(attachment) = message.attachments.iter().find(|a| {
|
||||
a.content_type
|
||||
.as_ref()
|
||||
.and_then(|ct| ct.starts_with("text/").then_some(true))
|
||||
.is_some()
|
||||
}) {
|
||||
let bytes = attachment.download().await?;
|
||||
let res = String::from_utf8(bytes)?;
|
||||
Ok(Some(res))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
26
src/handlers/event/analyze_logs/providers/haste.rs
Normal file
26
src/handlers/event/analyze_logs/providers/haste.rs
Normal file
|
@ -0,0 +1,26 @@
|
|||
use crate::api::REQWEST_CLIENT;
|
||||
|
||||
use color_eyre::eyre::{eyre, Result};
|
||||
use once_cell::sync::Lazy;
|
||||
use regex::Regex;
|
||||
use reqwest::StatusCode;
|
||||
|
||||
static REGEX: Lazy<Regex> =
|
||||
Lazy::new(|| Regex::new(r"https://hst\.sh(?:/raw)?/(\w+(?:\.\w*)?)").unwrap());
|
||||
|
||||
pub async fn find(content: &str) -> Result<Option<String>> {
|
||||
let Some(captures) = REGEX.captures(content) else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
let url = format!("https://hst.sh/raw/{}", &captures[1]);
|
||||
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}"))
|
||||
}
|
||||
}
|
25
src/handlers/event/analyze_logs/providers/mclogs.rs
Normal file
25
src/handlers/event/analyze_logs/providers/mclogs.rs
Normal file
|
@ -0,0 +1,25 @@
|
|||
use crate::api::REQWEST_CLIENT;
|
||||
|
||||
use color_eyre::eyre::{eyre, Result};
|
||||
use once_cell::sync::Lazy;
|
||||
use regex::Regex;
|
||||
use reqwest::StatusCode;
|
||||
|
||||
static REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"https://mclo\.gs/(\w+)").unwrap());
|
||||
|
||||
pub async fn find(content: &str) -> Result<Option<String>> {
|
||||
let Some(captures) = REGEX.captures(content) else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
let url = format!("https://api.mclo.gs/1/raw/{}", &captures[1]);
|
||||
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}"))
|
||||
}
|
||||
}
|
33
src/handlers/event/analyze_logs/providers/mod.rs
Normal file
33
src/handlers/event/analyze_logs/providers/mod.rs
Normal file
|
@ -0,0 +1,33 @@
|
|||
use color_eyre::eyre::Result;
|
||||
use poise::serenity_prelude::Message;
|
||||
|
||||
#[path = "0x0.rs"]
|
||||
mod _0x0;
|
||||
mod attachment;
|
||||
mod haste;
|
||||
mod mclogs;
|
||||
mod paste_gg;
|
||||
mod pastebin;
|
||||
|
||||
pub type LogProvider = Result<Option<String>>;
|
||||
|
||||
pub async fn find_log(message: &Message) -> LogProvider {
|
||||
macro_rules! provider_impl {
|
||||
($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)
|
||||
}
|
70
src/handlers/event/analyze_logs/providers/paste_gg.rs
Normal file
70
src/handlers/event/analyze_logs/providers/paste_gg.rs
Normal file
|
@ -0,0 +1,70 @@
|
|||
use crate::api::REQWEST_CLIENT;
|
||||
|
||||
use color_eyre::eyre::{eyre, Result};
|
||||
use once_cell::sync::Lazy;
|
||||
use regex::Regex;
|
||||
use reqwest::StatusCode;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
const PASTE_GG: &str = "https://api.paste.gg/v1";
|
||||
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)]
|
||||
struct PasteResponse {
|
||||
status: String,
|
||||
result: Option<Vec<PasteResult>>,
|
||||
error: Option<String>,
|
||||
message: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
struct PasteResult {
|
||||
id: String,
|
||||
name: Option<String>,
|
||||
description: Option<String>,
|
||||
visibility: Option<String>,
|
||||
}
|
||||
|
||||
pub async fn find(content: &str) -> Result<Option<String>> {
|
||||
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
|
||||
.ok_or_else(|| eyre!("Couldn't find any files associated with paste {paste_id}!"))?[0]
|
||||
.id;
|
||||
|
||||
let raw_url = format!("{PASTE_GG}{PASTES_ENDPOINT}/{paste_id}/files/{file_id}/raw");
|
||||
|
||||
let resp = REQWEST_CLIENT
|
||||
.execute(REQWEST_CLIENT.get(&raw_url).build()?)
|
||||
.await?;
|
||||
let status = resp.status();
|
||||
|
||||
if status != StatusCode::OK {
|
||||
return Err(eyre!(
|
||||
"Couldn't get file {file_id} from paste {paste_id} with status {status}!"
|
||||
));
|
||||
}
|
||||
|
||||
let text = resp.text().await?;
|
||||
|
||||
Ok(Some(text))
|
||||
}
|
26
src/handlers/event/analyze_logs/providers/pastebin.rs
Normal file
26
src/handlers/event/analyze_logs/providers/pastebin.rs
Normal file
|
@ -0,0 +1,26 @@
|
|||
use crate::api::REQWEST_CLIENT;
|
||||
|
||||
use color_eyre::eyre::{eyre, Result};
|
||||
use once_cell::sync::Lazy;
|
||||
use regex::Regex;
|
||||
use reqwest::StatusCode;
|
||||
|
||||
static REGEX: Lazy<Regex> =
|
||||
Lazy::new(|| Regex::new(r"https://pastebin\.com(?:/raw)?/(\w+)").unwrap());
|
||||
|
||||
pub async fn find(content: &str) -> Result<Option<String>> {
|
||||
let Some(captures) = REGEX.captures(content) else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
let url = format!("https://pastebin.com/raw/{}", &captures[1]);
|
||||
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}"))
|
||||
}
|
||||
}
|
|
@ -7,8 +7,8 @@ use regex::Regex;
|
|||
|
||||
static ETA_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"\beta\b").unwrap());
|
||||
|
||||
pub async fn handle(ctx: &Context, msg: &Message) -> Result<()> {
|
||||
if !ETA_REGEX.is_match(&msg.content) {
|
||||
pub async fn handle(ctx: &Context, message: &Message) -> Result<()> {
|
||||
if !ETA_REGEX.is_match(&message.content) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,6 @@ pub async fn handle(ctx: &Context, msg: &Message) -> Result<()> {
|
|||
utils::random_choice(consts::ETA_MESSAGES)?
|
||||
);
|
||||
|
||||
msg.reply(ctx, response).await?;
|
||||
message.reply(ctx, response).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -3,12 +3,12 @@ use poise::serenity_prelude::{Context, Message};
|
|||
|
||||
use crate::utils;
|
||||
|
||||
pub async fn handle(ctx: &Context, msg: &Message) -> Result<()> {
|
||||
let embeds = utils::resolve_message(ctx, msg).await?;
|
||||
pub async fn handle(ctx: &Context, message: &Message) -> Result<()> {
|
||||
let embeds = utils::resolve_message(ctx, message).await?;
|
||||
|
||||
// TOOD getchoo: actually reply to user
|
||||
// ...not sure why Message doesn't give me a builder in reply() or equivalents
|
||||
let our_channel = msg
|
||||
let our_channel = message
|
||||
.channel(ctx)
|
||||
.await
|
||||
.wrap_err_with(|| "Couldn't get channel from message!")?
|
||||
|
|
|
@ -5,6 +5,7 @@ use log::*;
|
|||
use poise::serenity_prelude::{Activity, Context, OnlineStatus};
|
||||
use poise::{Event, FrameworkContext};
|
||||
|
||||
mod analyze_logs;
|
||||
mod delete_on_reaction;
|
||||
mod eta;
|
||||
mod expand_link;
|
||||
|
@ -52,6 +53,7 @@ pub async fn handle(
|
|||
|
||||
eta::handle(ctx, new_message).await?;
|
||||
expand_link::handle(ctx, new_message).await?;
|
||||
analyze_logs::handle(ctx, new_message).await?;
|
||||
}
|
||||
|
||||
Event::MessageDelete {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue