style: use tabs over spaces
This commit is contained in:
parent
f2979d4cde
commit
f0550dd429
41 changed files with 1112 additions and 1109 deletions
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
@ -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}",))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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}"))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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}"))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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}"))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue