style: use tabs over spaces

This commit is contained in:
seth 2024-01-08 14:56:37 -05:00
parent f2979d4cde
commit f0550dd429
No known key found for this signature in database
GPG key ID: D31BD0D494BBEE86
41 changed files with 1112 additions and 1109 deletions

View file

@ -7,164 +7,164 @@ use regex::Regex;
pub type Issue = Option<(String, String)>;
pub async fn find_issues(log: &str, data: &Data) -> Result<Vec<(String, String)>> {
let issues = [
fabric_internal,
flatpak_nvidia,
forge_java,
intel_hd,
java_option,
lwjgl_2_java_9,
macos_ns,
oom,
optinotfine,
pre_1_12_native_transport_java_9,
wrong_java,
];
let issues = [
fabric_internal,
flatpak_nvidia,
forge_java,
intel_hd,
java_option,
lwjgl_2_java_9,
macos_ns,
oom,
optinotfine,
pre_1_12_native_transport_java_9,
wrong_java,
];
let mut res: Vec<(String, String)> = issues.iter().filter_map(|issue| issue(log)).collect();
let mut res: Vec<(String, String)> = issues.iter().filter_map(|issue| issue(log)).collect();
if let Some(issues) = outdated_launcher(log, data).await? {
res.push(issues)
}
if let Some(issues) = outdated_launcher(log, data).await? {
res.push(issues)
}
Ok(res)
Ok(res)
}
fn fabric_internal(log: &str) -> Issue {
const CLASS_NOT_FOUND: &str = "Caused by: java.lang.ClassNotFoundException: ";
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 \
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(),
);
.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 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)
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.
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(),
);
.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");
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)
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+.
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(),
);
.to_string(),
);
let found = log.contains("java.lang.NoSuchMethodError: sun.security.util.ManifestEntryVerifier.<init>(Ljava/util/jar/Manifest;)V");
found.then_some(issue)
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 =
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)
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());
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) = 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]),
));
}
if let Some(captures) = OPTION_REGEX.captures(log) {
return Some((
"Wrong Java Arguments".to_string(),
format!("Remove `{}` from your Java arguments", &captures[1]),
));
}
None
None
}
fn lwjgl_2_java_9(log: &str) -> Issue {
let issue = (
"Linux: crash with pre-1.13 and Java 9+".to_string(),
"Using pre-1.13 (which uses LWJGL 2) with Java 9 or later usually causes a crash. \
let issue = (
"Linux: crash with pre-1.13 and Java 9+".to_string(),
"Using pre-1.13 (which uses LWJGL 2) with Java 9 or later usually causes a crash. \
Switching to Java 8 or below will fix your issue.
Alternatively, you can use [Temurin](https://adoptium.net/temurin/releases). \
However, multiplayer will not work in versions from 1.8 to 1.11.
For more information, type `/tag java`."
.to_string(),
);
.to_string(),
);
let found = log.contains("check_match: Assertion `version->filename == NULL || ! _dl_name_match_p (version->filename, map)' failed!");
found.then_some(issue)
let found = log.contains("check_match: Assertion `version->filename == NULL || ! _dl_name_match_p (version->filename, map)' failed!");
found.then_some(issue)
}
fn macos_ns(log: &str) -> Issue {
let 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)
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 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)
let found = log.contains("java.lang.OutOfMemoryError");
found.then_some(issue)
}
fn optinotfine(log: &str) -> Issue {
let 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.
@ -172,50 +172,50 @@ fn optinotfine(log: &str) -> Issue {
.to_string(),
);
let found = log.contains("[✔] OptiFine_") || log.contains("[✔] optifabric-");
found.then_some(issue)
let found = log.contains("[✔] OptiFine_") || log.contains("[✔] optifabric-");
found.then_some(issue)
}
async fn outdated_launcher(log: &str, data: &Data) -> Result<Issue> {
static OUTDATED_LAUNCHER_REGEX: Lazy<Regex> =
Lazy::new(|| Regex::new("Prism Launcher version: [0-9].[0-9].[0-9]").unwrap());
static OUTDATED_LAUNCHER_REGEX: Lazy<Regex> =
Lazy::new(|| Regex::new("Prism Launcher version: [0-9].[0-9].[0-9]").unwrap());
let Some(captures) = OUTDATED_LAUNCHER_REGEX.captures(log) else {
return Ok(None);
};
let Some(captures) = OUTDATED_LAUNCHER_REGEX.captures(log) else {
return Ok(None);
};
let version_from_log = captures[0].replace("Prism Launcher version: ", "");
let version_from_log = captures[0].replace("Prism Launcher version: ", "");
let storage = &data.storage;
let latest_version = if storage.launcher_version_is_cached().await? {
storage.get_launcher_version().await?
} else {
let version = data
.octocrab
.repos("PrismLauncher", "PrismLauncher")
.releases()
.get_latest()
.await?
.tag_name;
let storage = &data.storage;
let latest_version = if storage.launcher_version_is_cached().await? {
storage.get_launcher_version().await?
} else {
let version = data
.octocrab
.repos("PrismLauncher", "PrismLauncher")
.releases()
.get_latest()
.await?
.tag_name;
storage.cache_launcher_version(&version).await?;
version
};
storage.cache_launcher_version(&version).await?;
version
};
if version_from_log < latest_version {
let issue = (
if version_from_log < latest_version {
let issue = (
"Outdated Prism Launcher".to_string(),
format!("Your installed version is {version_from_log}, while the newest version is {latest_version}.\nPlease update, for more info see https://prismlauncher.org/download/")
);
Ok(Some(issue))
} else {
Ok(None)
}
Ok(Some(issue))
} else {
Ok(None)
}
}
fn pre_1_12_native_transport_java_9(log: &str) -> Issue {
let issue = (
let issue = (
"Linux: broken multiplayer with 1.8-1.11 and Java 9+".to_string(),
"These versions of Minecraft use an outdated version of Netty which does not properly support Java 9.
@ -229,33 +229,33 @@ which is why the issue was not present."
.to_string(),
);
let found = log.contains(
let found = log.contains(
"java.lang.RuntimeException: Unable to access address of buffer\n\tat io.netty.channel.epoll"
);
found.then_some(issue)
found.then_some(issue)
}
fn wrong_java(log: &str) -> Issue {
static SWITCH_VERSION_REGEX: Lazy<Regex> = Lazy::new(|| {
Regex::new(
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((
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 = (
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)
log.contains("Java major version is incompatible. Things might break.")
.then_some(issue)
}

View file

@ -12,57 +12,57 @@ use issues::find_issues;
use providers::find_log;
pub async fn handle(ctx: &Context, message: &Message, data: &Data) -> Result<()> {
let channel = message.channel_id;
let channel = message.channel_id;
let log = find_log(message).await;
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?;
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(());
}
return Ok(());
}
let Some(log) = log? else {
debug!("No log found in message! Skipping analysis");
return Ok(());
};
let Some(log) = log? else {
debug!("No log found in message! Skipping analysis");
return Ok(());
};
let issues = find_issues(&log, data).await?;
let issues = find_issues(&log, data).await?;
channel
.send_message(ctx, |m| {
m.reference_message(message)
.allowed_mentions(|am| am.replied_user(true))
.embed(|e| {
e.title("Log analysis");
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"]);
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);
}
}
for (title, description) in issues {
e.field(title, description, false);
}
}
e
})
})
.await?;
e
})
})
.await?;
Ok(())
Ok(())
}

View file

@ -8,17 +8,17 @@ 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 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();
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}",))
}
if let StatusCode::OK = status {
Ok(Some(response.text().await?))
} else {
Err(eyre!("Failed to fetch paste from {url} with {status}",))
}
}

View file

@ -2,17 +2,17 @@ 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)
}
// 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)
}
}

View file

@ -6,21 +6,21 @@ use regex::Regex;
use reqwest::StatusCode;
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>> {
let Some(captures) = REGEX.captures(content) else {
return Ok(None);
};
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();
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}"))
}
if let StatusCode::OK = status {
Ok(Some(response.text().await?))
} else {
Err(eyre!("Failed to fetch paste from {url} with {status}"))
}
}

View file

@ -8,18 +8,18 @@ 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 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();
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}"))
}
if let StatusCode::OK = status {
Ok(Some(response.text().await?))
} else {
Err(eyre!("Failed to fetch log from {url} with {status}"))
}
}

View file

@ -12,22 +12,22 @@ 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);
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));
}
if let Some(content) = attachment::find(message).await? {
return Ok(Some(content));
}
Ok(None)
Ok(None)
}

View file

@ -12,59 +12,59 @@ static REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"https://paste.gg/p/\w+/(\w
#[derive(Clone, Debug, Deserialize, Serialize)]
struct PasteResponse {
status: String,
result: Option<Vec<PasteResult>>,
error: Option<String>,
message: Option<String>,
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>,
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 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 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();
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}!"
));
}
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 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 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();
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}!"
));
}
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?;
let text = resp.text().await?;
Ok(Some(text))
Ok(Some(text))
}

View file

@ -6,21 +6,21 @@ use regex::Regex;
use reqwest::StatusCode;
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>> {
let Some(captures) = REGEX.captures(content) else {
return Ok(None);
};
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();
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}"))
}
if let StatusCode::OK = status {
Ok(Some(response.text().await?))
} else {
Err(eyre!("Failed to fetch paste from {url} with {status}"))
}
}

View file

@ -2,24 +2,24 @@ use color_eyre::eyre::{Context as _, Result};
use poise::serenity_prelude::{Context, InteractionType, Reaction};
pub async fn handle(ctx: &Context, reaction: &Reaction) -> Result<()> {
let user = reaction
.user(ctx)
.await
.wrap_err_with(|| "Couldn't fetch user from reaction!")?;
let user = reaction
.user(ctx)
.await
.wrap_err_with(|| "Couldn't fetch user from reaction!")?;
let message = reaction
.message(ctx)
.await
.wrap_err_with(|| "Couldn't fetch message from reaction!")?;
let message = reaction
.message(ctx)
.await
.wrap_err_with(|| "Couldn't fetch message from reaction!")?;
if let Some(interaction) = &message.interaction {
if interaction.kind == InteractionType::ApplicationCommand
&& interaction.user == user
&& reaction.emoji.unicode_eq("")
{
message.delete(ctx).await?;
}
}
if let Some(interaction) = &message.interaction {
if interaction.kind == InteractionType::ApplicationCommand
&& interaction.user == user
&& reaction.emoji.unicode_eq("")
{
message.delete(ctx).await?;
}
}
Ok(())
Ok(())
}

View file

@ -8,15 +8,15 @@ use regex::Regex;
static ETA_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"\beta\b").unwrap());
pub async fn handle(ctx: &Context, message: &Message) -> Result<()> {
if !ETA_REGEX.is_match(&message.content) {
return Ok(());
}
if !ETA_REGEX.is_match(&message.content) {
return Ok(());
}
let response = format!(
"{} <:pofat:1031701005559144458>",
utils::random_choice(consts::ETA_MESSAGES)?
);
let response = format!(
"{} <:pofat:1031701005559144458>",
utils::random_choice(consts::ETA_MESSAGES)?
);
message.reply(ctx, response).await?;
Ok(())
message.reply(ctx, response).await?;
Ok(())
}

View file

@ -4,25 +4,25 @@ use poise::serenity_prelude::{Context, Message};
use crate::utils;
pub async fn handle(ctx: &Context, message: &Message) -> Result<()> {
let embeds = utils::resolve_message(ctx, message).await?;
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 = message
.channel(ctx)
.await
.wrap_err_with(|| "Couldn't get channel from message!")?
.guild()
.ok_or_else(|| eyre!("Couldn't convert to GuildChannel!"))?;
// TOOD getchoo: actually reply to user
// ...not sure why Message doesn't give me a builder in reply() or equivalents
let our_channel = message
.channel(ctx)
.await
.wrap_err_with(|| "Couldn't get channel from message!")?
.guild()
.ok_or_else(|| eyre!("Couldn't convert to GuildChannel!"))?;
if !embeds.is_empty() {
our_channel
.send_message(ctx, |m| {
m.set_embeds(embeds)
.allowed_mentions(|am| am.replied_user(false))
})
.await?;
}
if !embeds.is_empty() {
our_channel
.send_message(ctx, |m| {
m.set_embeds(embeds)
.allowed_mentions(|am| am.replied_user(false))
})
.await?;
}
Ok(())
Ok(())
}

View file

@ -13,53 +13,53 @@ pub mod pluralkit;
mod support_onboard;
pub async fn handle(
ctx: &Context,
event: &Event<'_>,
_framework: FrameworkContext<'_, Data, Report>,
data: &Data,
ctx: &Context,
event: &Event<'_>,
_framework: FrameworkContext<'_, Data, Report>,
data: &Data,
) -> Result<()> {
match event {
Event::Ready { data_about_bot } => {
info!("Logged in as {}!", data_about_bot.user.name);
match event {
Event::Ready { data_about_bot } => {
info!("Logged in as {}!", data_about_bot.user.name);
let latest_minecraft_version = api::prism_meta::get_latest_minecraft_version().await?;
let activity = Activity::playing(format!("Minecraft {}", latest_minecraft_version));
let latest_minecraft_version = api::prism_meta::get_latest_minecraft_version().await?;
let activity = Activity::playing(format!("Minecraft {}", latest_minecraft_version));
info!("Setting presence to activity {activity:#?}");
ctx.set_presence(Some(activity), OnlineStatus::Online).await;
}
info!("Setting presence to activity {activity:#?}");
ctx.set_presence(Some(activity), OnlineStatus::Online).await;
}
Event::Message { new_message } => {
// ignore new messages from bots
// NOTE: the webhook_id check allows us to still respond to PK users
if new_message.author.bot && new_message.webhook_id.is_none() {
debug!("Ignoring message {} from bot", new_message.id);
return Ok(());
}
Event::Message { new_message } => {
// ignore new messages from bots
// NOTE: the webhook_id check allows us to still respond to PK users
if new_message.author.bot && new_message.webhook_id.is_none() {
debug!("Ignoring message {} from bot", new_message.id);
return Ok(());
}
// detect PK users first to make sure we don't respond to unproxied messages
pluralkit::handle(ctx, new_message, data).await?;
// detect PK users first to make sure we don't respond to unproxied messages
pluralkit::handle(ctx, new_message, data).await?;
if data.storage.is_user_plural(new_message.author.id).await?
&& pluralkit::is_message_proxied(new_message).await?
{
debug!("Not replying to unproxied PluralKit message");
return Ok(());
}
if data.storage.is_user_plural(new_message.author.id).await?
&& pluralkit::is_message_proxied(new_message).await?
{
debug!("Not replying to unproxied PluralKit message");
return Ok(());
}
eta::handle(ctx, new_message).await?;
expand_link::handle(ctx, new_message).await?;
analyze_logs::handle(ctx, new_message, data).await?;
}
eta::handle(ctx, new_message).await?;
expand_link::handle(ctx, new_message).await?;
analyze_logs::handle(ctx, new_message, data).await?;
}
Event::ReactionAdd { add_reaction } => {
delete_on_reaction::handle(ctx, add_reaction).await?
}
Event::ReactionAdd { add_reaction } => {
delete_on_reaction::handle(ctx, add_reaction).await?
}
Event::ThreadCreate { thread } => support_onboard::handle(ctx, thread).await?,
Event::ThreadCreate { thread } => support_onboard::handle(ctx, thread).await?,
_ => {}
}
_ => {}
}
Ok(())
Ok(())
}

View file

@ -9,34 +9,34 @@ use tokio::time::sleep;
const PK_DELAY_SEC: Duration = Duration::from_secs(1000);
pub async fn is_message_proxied(message: &Message) -> Result<bool> {
debug!(
"Waiting on PluralKit API for {} seconds",
PK_DELAY_SEC.as_secs()
);
sleep(PK_DELAY_SEC).await;
debug!(
"Waiting on PluralKit API for {} seconds",
PK_DELAY_SEC.as_secs()
);
sleep(PK_DELAY_SEC).await;
let proxied = api::pluralkit::get_sender(message.id).await.is_ok();
let proxied = api::pluralkit::get_sender(message.id).await.is_ok();
Ok(proxied)
Ok(proxied)
}
pub async fn handle(_ctx: &Context, msg: &Message, data: &Data) -> Result<()> {
if msg.webhook_id.is_some() {
debug!(
"Message {} has a webhook ID. Checking if it was sent through PluralKit",
msg.id
);
if msg.webhook_id.is_some() {
debug!(
"Message {} has a webhook ID. Checking if it was sent through PluralKit",
msg.id
);
debug!(
"Waiting on PluralKit API for {} seconds",
PK_DELAY_SEC.as_secs()
);
sleep(PK_DELAY_SEC).await;
debug!(
"Waiting on PluralKit API for {} seconds",
PK_DELAY_SEC.as_secs()
);
sleep(PK_DELAY_SEC).await;
if let Ok(sender) = api::pluralkit::get_sender(msg.id).await {
data.storage.store_user_plurality(sender).await?;
}
}
if let Ok(sender) = api::pluralkit::get_sender(msg.id).await {
data.storage.store_user_plurality(sender).await?;
}
}
Ok(())
Ok(())
}

View file

@ -3,41 +3,41 @@ use log::*;
use poise::serenity_prelude::{ChannelType, Context, GuildChannel};
pub async fn handle(ctx: &Context, thread: &GuildChannel) -> Result<()> {
if thread.kind != ChannelType::PublicThread {
return Ok(());
}
if thread.kind != ChannelType::PublicThread {
return Ok(());
}
let parent_id = thread
.parent_id
.ok_or_else(|| eyre!("Couldn't get parent ID from thread {}!", thread.name))?;
let parent_id = thread
.parent_id
.ok_or_else(|| eyre!("Couldn't get parent ID from thread {}!", thread.name))?;
let parent_channel = ctx
.cache
.guild_channel(parent_id)
.ok_or_else(|| eyre!("Couldn't get GuildChannel {}!", parent_id))?;
let parent_channel = ctx
.cache
.guild_channel(parent_id)
.ok_or_else(|| eyre!("Couldn't get GuildChannel {}!", parent_id))?;
if parent_channel.name != "support" {
debug!("Not posting onboarding message to threads outside of support");
return Ok(());
}
if parent_channel.name != "support" {
debug!("Not posting onboarding message to threads outside of support");
return Ok(());
}
let owner = thread
.owner_id
.ok_or_else(|| eyre!("Couldn't get owner of thread!"))?;
let owner = thread
.owner_id
.ok_or_else(|| eyre!("Couldn't get owner of thread!"))?;
let msg = format!(
let msg = format!(
"<@{}> We've received your support ticket! {} {}",
owner,
"Please upload your logs and post the link here if possible (run `tag log` to find out how).",
"Please don't ping people for support questions, unless you have their permission."
);
thread
.send_message(ctx, |m| {
m.content(msg)
.allowed_mentions(|am| am.replied_user(true).users(Vec::from([owner])))
})
.await?;
thread
.send_message(ctx, |m| {
m.content(msg)
.allowed_mentions(|am| am.replied_user(true).users(Vec::from([owner])))
})
.await?;
Ok(())
Ok(())
}