diff --git a/Cargo.lock b/Cargo.lock index ba57f24..935c9f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1497,7 +1497,6 @@ dependencies = [ "gray_matter", "log", "octocrab", - "once_cell", "owo-colors 4.0.0", "poise", "rand", diff --git a/Cargo.toml b/Cargo.toml index 6af8378..7678984 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,6 @@ eyre = "0.6.11" log = "0.4.20" poise = "0.6.1" octocrab = "0.37.0" -once_cell = "1.19.0" owo-colors = "4.0.0" rand = "0.8.5" redis = { version = "0.25.2", features = ["tokio-comp", "tokio-rustls-comp"] } diff --git a/src/api/dadjoke.rs b/src/api/dadjoke.rs index 2675da6..642d656 100644 --- a/src/api/dadjoke.rs +++ b/src/api/dadjoke.rs @@ -1,5 +1,3 @@ -use crate::api::REQWEST_CLIENT; - use eyre::Result; use log::debug; @@ -8,7 +6,7 @@ const DADJOKE: &str = "https://icanhazdadjoke.com"; pub async fn get_joke() -> Result { debug!("Making request to {DADJOKE}"); - let resp = REQWEST_CLIENT + let resp = super::client() .get(DADJOKE) .header("Accept", "text/plain") .send() diff --git a/src/api/github.rs b/src/api/github.rs index 18fce69..42f4a8b 100644 --- a/src/api/github.rs +++ b/src/api/github.rs @@ -1,16 +1,18 @@ -use std::sync::Arc; +use std::sync::{Arc, OnceLock}; use eyre::{Context, OptionExt, Result}; use log::debug; use octocrab::Octocrab; -use once_cell::sync::Lazy; -static OCTOCRAB: Lazy> = Lazy::new(octocrab::instance); +fn octocrab() -> &'static Arc { + static OCTOCRAB: OnceLock> = OnceLock::new(); + OCTOCRAB.get_or_init(octocrab::instance) +} pub async fn get_latest_prism_version() -> Result { debug!("Fetching the latest version of Prism Launcher"); - let version = OCTOCRAB + let version = octocrab() .repos("PrismLauncher", "PrismLauncher") .releases() .get_latest() @@ -23,7 +25,7 @@ pub async fn get_latest_prism_version() -> Result { pub async fn get_prism_stargazers_count() -> Result { debug!("Fetching Prism Launcher's stargazer count"); - let stargazers_count = OCTOCRAB + let stargazers_count = octocrab() .repos("PrismLauncher", "PrismLauncher") .get() .await diff --git a/src/api/mod.rs b/src/api/mod.rs index 649be3e..99d51fb 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -1,4 +1,8 @@ -use once_cell::sync::Lazy; +use std::sync::OnceLock; + +use eyre::Result; +use log::debug; +use reqwest::{Client, Response}; pub mod dadjoke; pub mod github; @@ -7,15 +11,36 @@ pub mod pluralkit; pub mod prism_meta; pub mod rory; -pub static USER_AGENT: Lazy = Lazy::new(|| { - let version = option_env!("CARGO_PKG_VERSION").unwrap_or("development"); +pub fn client() -> &'static reqwest::Client { + static CLIENT: OnceLock = OnceLock::new(); + CLIENT.get_or_init(|| { + let version = option_env!("CARGO_PKG_VERSION").unwrap_or("development"); + let user_agent = format!("refraction/{version}"); + Client::builder() + .user_agent(user_agent) + .build() + .unwrap_or_default() + }) +} - format!("refraction/{version}") -}); +pub async fn get_url(url: &str) -> Result { + debug!("Making request to {url}"); + let resp = client().get(url).send().await?; + resp.error_for_status_ref()?; -pub static REQWEST_CLIENT: Lazy = Lazy::new(|| { - reqwest::Client::builder() - .user_agent(USER_AGENT.to_string()) - .build() - .unwrap_or_default() -}); + Ok(resp) +} + +pub async fn text_from_url(url: &str) -> Result { + let resp = get_url(url).await?; + + let text = resp.text().await?; + Ok(text) +} + +pub async fn bytes_from_url(url: &str) -> Result> { + let resp = get_url(url).await?; + + let bytes = resp.bytes().await?; + Ok(bytes.to_vec()) +} diff --git a/src/api/paste_gg.rs b/src/api/paste_gg.rs index c649429..4fdd59d 100644 --- a/src/api/paste_gg.rs +++ b/src/api/paste_gg.rs @@ -1,5 +1,3 @@ -use crate::{api::REQWEST_CLIENT, utils}; - use eyre::{eyre, OptionExt, Result}; use log::debug; use serde::{Deserialize, Serialize}; @@ -32,7 +30,7 @@ pub struct Files { pub async fn get_files(id: &str) -> Result> { let url = format!("{PASTE_GG}{PASTES}/{id}/files"); debug!("Making request to {url}"); - let resp = REQWEST_CLIENT.get(url).send().await?; + let resp = super::client().get(url).send().await?; resp.error_for_status_ref()?; let resp: Response = resp.json().await?; @@ -49,7 +47,7 @@ pub async fn get_files(id: &str) -> Result> { pub async fn get_raw_file(paste_id: &str, file_id: &str) -> eyre::Result { let url = format!("{PASTE_GG}{PASTES}/{paste_id}/files/{file_id}/raw"); - let text = utils::text_from_url(&url).await?; + let text = super::text_from_url(&url).await?; Ok(text) } diff --git a/src/api/pluralkit.rs b/src/api/pluralkit.rs index b711be6..5e28512 100644 --- a/src/api/pluralkit.rs +++ b/src/api/pluralkit.rs @@ -1,5 +1,3 @@ -use crate::api::REQWEST_CLIENT; - use eyre::{Context, Result}; use log::debug; use poise::serenity_prelude::{MessageId, UserId}; @@ -17,7 +15,7 @@ pub async fn get_sender(message_id: MessageId) -> Result { let url = format!("{PLURAL_KIT}{MESSAGES}/{message_id}"); debug!("Making request to {url}"); - let resp = REQWEST_CLIENT.get(url).send().await?; + let resp = super::client().get(url).send().await?; resp.error_for_status_ref()?; let data: Message = resp.json().await?; diff --git a/src/api/prism_meta.rs b/src/api/prism_meta.rs index fbc5878..9b23fd4 100644 --- a/src/api/prism_meta.rs +++ b/src/api/prism_meta.rs @@ -1,5 +1,3 @@ -use crate::api::REQWEST_CLIENT; - use eyre::{OptionExt, Result}; use log::debug; use serde::{Deserialize, Serialize}; @@ -20,7 +18,7 @@ pub async fn get_latest_minecraft_version() -> Result { let url = format!("{META}{MINECRAFT_PACKAGEJSON}"); debug!("Making request to {url}"); - let resp = REQWEST_CLIENT.get(url).send().await?; + let resp = super::client().get(url).send().await?; resp.error_for_status_ref()?; let data: MinecraftPackageJson = resp.json().await?; diff --git a/src/api/rory.rs b/src/api/rory.rs index ccbcada..bb64a0c 100644 --- a/src/api/rory.rs +++ b/src/api/rory.rs @@ -1,5 +1,3 @@ -use crate::api::REQWEST_CLIENT; - use eyre::{Context, Result}; use log::debug; use serde::{Deserialize, Serialize}; @@ -20,10 +18,7 @@ pub async fn get(id: Option) -> Result { debug!("Making request to {url}"); - let resp = REQWEST_CLIENT - .get(format!("{RORY}{PURR}/{target}")) - .send() - .await?; + let resp = super::client().get(url).send().await?; resp.error_for_status_ref()?; let data: Response = resp diff --git a/src/commands/general/members.rs b/src/commands/general/members.rs index 94204cc..48525be 100644 --- a/src/commands/general/members.rs +++ b/src/commands/general/members.rs @@ -29,7 +29,7 @@ pub async fn members(ctx: Context<'_>) -> Result<()> { let embed = CreateEmbed::new() .title(format!("{member_count} total members!",)) .description(format!("{online_count} online members",)) - .color(consts::COLORS["blue"]); + .color(consts::colors()["blue"]); let reply = CreateReply::default().embed(embed); ctx.send(reply).await?; diff --git a/src/commands/general/stars.rs b/src/commands/general/stars.rs index 710fa5d..4858d87 100644 --- a/src/commands/general/stars.rs +++ b/src/commands/general/stars.rs @@ -27,7 +27,7 @@ pub async fn stars(ctx: Context<'_>) -> Result<()> { let embed = CreateEmbed::new() .title(format!("⭐ {count} total stars!")) - .color(consts::COLORS["yellow"]); + .color(consts::colors()["yellow"]); let reply = CreateReply::default().embed(embed); ctx.send(reply).await?; diff --git a/src/commands/general/tag.rs b/src/commands/general/tag.rs index 43fa7a8..b34a250 100644 --- a/src/commands/general/tag.rs +++ b/src/commands/general/tag.rs @@ -1,16 +1,18 @@ #![allow(non_camel_case_types, clippy::upper_case_acronyms)] -use crate::tags::Tag; -use crate::{consts, Context}; +use crate::{consts, tags::Tag, Context}; use std::env; +use std::sync::OnceLock; use eyre::{eyre, Result}; use log::trace; -use once_cell::sync::Lazy; use poise::serenity_prelude::{Color, CreateEmbed, User}; use poise::CreateReply; include!(concat!(env!("OUT_DIR"), "/generated.rs")); -static TAGS: Lazy> = Lazy::new(|| serde_json::from_str(env!("TAGS")).unwrap()); +fn tags() -> &'static Vec { + static TAGS: OnceLock> = OnceLock::new(); + TAGS.get_or_init(|| serde_json::from_str(env!("TAGS")).unwrap()) +} /// Send a tag #[poise::command( @@ -27,7 +29,7 @@ pub async fn tag( trace!("Running tag command"); let tag_id = name.as_str(); - let tag = TAGS + let tag = tags() .iter() .find(|t| t.id == tag_id) .ok_or_else(|| eyre!("Tried to get non-existent tag: {tag_id}"))?; @@ -38,7 +40,7 @@ pub async fn tag( let mut e = CreateEmbed::new(); if let Some(color) = &frontmatter.color { - let color = *consts::COLORS + let color = *consts::colors() .get(color.as_str()) .unwrap_or(&Color::default()); e = e.color(color); @@ -76,7 +78,7 @@ pub async fn tag( } fn help() -> String { - let tag_list = TAGS + let tag_list = tags() .iter() .map(|tag| format!("`{}`", tag.id)) .collect::>() diff --git a/src/commands/moderation/set_welcome.rs b/src/commands/moderation/set_welcome.rs index c5c7f03..a9438d2 100644 --- a/src/commands/moderation/set_welcome.rs +++ b/src/commands/moderation/set_welcome.rs @@ -1,6 +1,6 @@ use std::{fmt::Write, str::FromStr}; -use crate::{utils, Context}; +use crate::{api, utils, Context}; use eyre::{bail, Result}; use log::trace; @@ -144,7 +144,7 @@ pub async fn set_welcome( return Ok(()); } - utils::text_from_url(&url).await? + api::text_from_url(&url).await? } else { ctx.say("A text file or URL must be provided!").await?; return Ok(()); diff --git a/src/consts.rs b/src/consts.rs index 5a0aa29..f823470 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -1,15 +1,17 @@ -use std::collections::HashMap; +use std::{collections::HashMap, sync::OnceLock}; -use once_cell::sync::Lazy; use poise::serenity_prelude::Color; -pub static COLORS: Lazy> = Lazy::new(|| { - HashMap::from([ - ("red", Color::from((239, 68, 68))), - ("green", Color::from((34, 197, 94))), - ("blue", Color::from((96, 165, 250))), - ("yellow", Color::from((253, 224, 71))), - ("orange", Color::from((251, 146, 60))), - // TODO purple & pink :D - ]) -}); +pub fn colors() -> &'static HashMap<&'static str, Color> { + static COLORS: OnceLock> = OnceLock::new(); + COLORS.get_or_init(|| { + HashMap::from([ + ("red", Color::from((239, 68, 68))), + ("green", Color::from((34, 197, 94))), + ("blue", Color::from((96, 165, 250))), + ("yellow", Color::from((253, 224, 71))), + ("orange", Color::from((251, 146, 60))), + // TODO purple & pink :D + ]) + }) +} diff --git a/src/handlers/error.rs b/src/handlers/error.rs index b0e8462..019bb3f 100644 --- a/src/handlers/error.rs +++ b/src/handlers/error.rs @@ -34,7 +34,7 @@ pub async fn handle(error: FrameworkError<'_, Data, Report>) { .title("Something went wrong!") .description("oopsie") .timestamp(Timestamp::now()) - .color(consts::COLORS["red"]); + .color(consts::colors()["red"]); let reply = CreateReply::default().embed(embed); diff --git a/src/handlers/event/analyze_logs/issues.rs b/src/handlers/event/analyze_logs/issues.rs index 50822c1..72ee00a 100644 --- a/src/handlers/event/analyze_logs/issues.rs +++ b/src/handlers/event/analyze_logs/issues.rs @@ -1,8 +1,9 @@ use crate::{api, Data}; +use std::sync::OnceLock; + use eyre::Result; use log::trace; -use once_cell::sync::Lazy; use regex::Regex; pub type Issue = Option<(String, String)>; @@ -103,12 +104,15 @@ fn intel_hd(log: &str) -> Issue { } fn java_option(log: &str) -> Issue { - static VM_OPTION_REGEX: Lazy = - Lazy::new(|| Regex::new(r"Unrecognized VM option '(.+)'[\r\n]").unwrap()); - static OPTION_REGEX: Lazy = - Lazy::new(|| Regex::new(r"Unrecognized option: (.+)[\r\n]").unwrap()); + static VM_OPTION_REGEX: OnceLock = OnceLock::new(); + static UNRECOGNIZED_OPTION_REGEX: OnceLock = OnceLock::new(); - if let Some(captures) = VM_OPTION_REGEX.captures(log) { + let vm_option = + VM_OPTION_REGEX.get_or_init(|| Regex::new(r"Unrecognized VM option '(.+)'[\r\n]").unwrap()); + let unrecognized_option = UNRECOGNIZED_OPTION_REGEX + .get_or_init(|| Regex::new(r"Unrecognized option: (.+)[\r\n]").unwrap()); + + if let Some(captures) = vm_option.captures(log) { let title = if &captures[1] == "UseShenandoahGC" { "Wrong Java Arguments" } else { @@ -120,7 +124,7 @@ fn java_option(log: &str) -> Issue { )); } - if let Some(captures) = OPTION_REGEX.captures(log) { + if let Some(captures) = unrecognized_option.captures(log) { return Some(( "Wrong Java Arguments".to_string(), format!("Remove `{}` from your Java arguments", &captures[1]), @@ -180,10 +184,11 @@ fn optinotfine(log: &str) -> Issue { } async fn outdated_launcher(log: &str, data: &Data) -> Result { - static OUTDATED_LAUNCHER_REGEX: Lazy = - Lazy::new(|| Regex::new("Prism Launcher version: [0-9].[0-9].[0-9]").unwrap()); + static OUTDATED_LAUNCHER_REGEX: OnceLock = OnceLock::new(); + let outdated_launcher = OUTDATED_LAUNCHER_REGEX + .get_or_init(|| Regex::new("Prism Launcher version: [0-9].[0-9].[0-9]").unwrap()); - let Some(captures) = OUTDATED_LAUNCHER_REGEX.captures(log) else { + let Some(captures) = outdated_launcher.captures(log) else { return Ok(None); }; @@ -235,13 +240,12 @@ which is why the issue was not present." } fn wrong_java(log: &str) -> Issue { - static SWITCH_VERSION_REGEX: Lazy = Lazy::new(|| { - Regex::new( - r"(?m)Please switch to one of the following Java versions for this instance:[\r\n]+(Java version [\d.]+)", - ).unwrap() - }); + static SWITCH_VERSION_REGEX: OnceLock = OnceLock::new(); + let switch_version = SWITCH_VERSION_REGEX.get_or_init(|| 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) { + if let Some(captures) = switch_version.captures(log) { let versions = captures[1].split('\n').collect::>().join(", "); return Some(( "Wrong Java Version".to_string(), diff --git a/src/handlers/event/analyze_logs/mod.rs b/src/handlers/event/analyze_logs/mod.rs index 5d55694..58c38cf 100644 --- a/src/handlers/event/analyze_logs/mod.rs +++ b/src/handlers/event/analyze_logs/mod.rs @@ -1,5 +1,4 @@ -use crate::consts::COLORS; -use crate::Data; +use crate::{consts, Data}; use eyre::Result; use log::{debug, trace}; @@ -49,10 +48,10 @@ pub async fn handle(ctx: &Context, message: &Message, data: &Data) -> Result<()> if issues.is_empty() { e = e - .color(COLORS["green"]) + .color(consts::colors()["green"]) .description("No issues found automatically"); } else { - e = e.color(COLORS["red"]); + e = e.color(consts::colors()["red"]); for (title, description) in issues { e = e.field(title, description, false); diff --git a/src/handlers/event/analyze_logs/providers/0x0.rs b/src/handlers/event/analyze_logs/providers/0x0.rs index 39b715c..14f7feb 100644 --- a/src/handlers/event/analyze_logs/providers/0x0.rs +++ b/src/handlers/event/analyze_logs/providers/0x0.rs @@ -1,8 +1,9 @@ -use crate::utils; +use crate::api; + +use std::sync::OnceLock; use eyre::Result; use log::trace; -use once_cell::sync::Lazy; use poise::serenity_prelude::Message; use regex::Regex; @@ -10,17 +11,18 @@ pub struct _0x0; impl super::LogProvider for _0x0 { async fn find_match(&self, message: &Message) -> Option { - static REGEX: Lazy = Lazy::new(|| Regex::new(r"https://0x0\.st/\w*.\w*").unwrap()); + static REGEX: OnceLock = OnceLock::new(); + let regex = REGEX.get_or_init(|| Regex::new(r"https://0x0\.st/\w*.\w*").unwrap()); trace!("Checking if message {} is a 0x0 paste", message.id); - REGEX + regex .find_iter(&message.content) .map(|m| m.as_str().to_string()) .nth(0) } async fn fetch(&self, content: &str) -> Result { - let log = utils::text_from_url(content).await?; + let log = api::text_from_url(content).await?; Ok(log) } diff --git a/src/handlers/event/analyze_logs/providers/attachment.rs b/src/handlers/event/analyze_logs/providers/attachment.rs index 103c4c2..25ce3cc 100644 --- a/src/handlers/event/analyze_logs/providers/attachment.rs +++ b/src/handlers/event/analyze_logs/providers/attachment.rs @@ -2,7 +2,7 @@ use eyre::Result; use log::trace; use poise::serenity_prelude::Message; -use crate::utils; +use crate::api; pub struct Attachment; @@ -22,7 +22,7 @@ impl super::LogProvider for Attachment { } async fn fetch(&self, content: &str) -> Result { - let attachment = utils::bytes_from_url(content).await?; + let attachment = api::bytes_from_url(content).await?; let log = String::from_utf8(attachment)?; Ok(log) } diff --git a/src/handlers/event/analyze_logs/providers/haste.rs b/src/handlers/event/analyze_logs/providers/haste.rs index 9909176..c4113d5 100644 --- a/src/handlers/event/analyze_logs/providers/haste.rs +++ b/src/handlers/event/analyze_logs/providers/haste.rs @@ -1,8 +1,9 @@ -use crate::utils; +use crate::api; + +use std::sync::OnceLock; use eyre::Result; use log::trace; -use once_cell::sync::Lazy; use poise::serenity_prelude::Message; use regex::Regex; @@ -13,16 +14,17 @@ pub struct Haste; impl super::LogProvider for Haste { async fn find_match(&self, message: &Message) -> Option { - static REGEX: Lazy = - Lazy::new(|| Regex::new(r"https://hst\.sh(?:/raw)?/(\w+(?:\.\w*)?)").unwrap()); + static REGEX: OnceLock = OnceLock::new(); + let regex = + REGEX.get_or_init(|| Regex::new(r"https://hst\.sh(?:/raw)?/(\w+(?:\.\w*)?)").unwrap()); trace!("Checking if message {} is a hst.sh paste", message.id); - super::get_first_capture(®EX, &message.content) + super::get_first_capture(regex, &message.content) } async fn fetch(&self, content: &str) -> Result { let url = format!("{HASTE}{RAW}/{content}"); - let log = utils::text_from_url(&url).await?; + let log = api::text_from_url(&url).await?; Ok(log) } diff --git a/src/handlers/event/analyze_logs/providers/mclogs.rs b/src/handlers/event/analyze_logs/providers/mclogs.rs index 7e9265b..b0f0c35 100644 --- a/src/handlers/event/analyze_logs/providers/mclogs.rs +++ b/src/handlers/event/analyze_logs/providers/mclogs.rs @@ -1,8 +1,9 @@ -use crate::utils; +use crate::api; + +use std::sync::OnceLock; use eyre::Result; use log::trace; -use once_cell::sync::Lazy; use poise::serenity_prelude::Message; use regex::Regex; @@ -13,15 +14,16 @@ pub struct MCLogs; impl super::LogProvider for MCLogs { async fn find_match(&self, message: &Message) -> Option { - static REGEX: Lazy = Lazy::new(|| Regex::new(r"https://mclo\.gs/(\w+)").unwrap()); + static REGEX: OnceLock = OnceLock::new(); + let regex = REGEX.get_or_init(|| Regex::new(r"https://mclo\.gs/(\w+)").unwrap()); trace!("Checking if message {} is an mclo.gs paste", message.id); - super::get_first_capture(®EX, &message.content) + super::get_first_capture(regex, &message.content) } async fn fetch(&self, content: &str) -> Result { let url = format!("{MCLOGS}{RAW}/{content}"); - let log = utils::text_from_url(&url).await?; + let log = api::text_from_url(&url).await?; Ok(log) } diff --git a/src/handlers/event/analyze_logs/providers/mod.rs b/src/handlers/event/analyze_logs/providers/mod.rs index 679f944..e20547f 100644 --- a/src/handlers/event/analyze_logs/providers/mod.rs +++ b/src/handlers/event/analyze_logs/providers/mod.rs @@ -2,7 +2,6 @@ use std::slice::Iter; use enum_dispatch::enum_dispatch; use eyre::Result; -use once_cell::sync::Lazy; use poise::serenity_prelude::Message; use regex::Regex; @@ -25,7 +24,7 @@ pub trait LogProvider { async fn fetch(&self, content: &str) -> Result; } -fn get_first_capture(regex: &Lazy, string: &str) -> Option { +fn get_first_capture(regex: &Regex, string: &str) -> Option { regex .captures_iter(string) .find_map(|c| c.get(1).map(|c| c.as_str().to_string())) diff --git a/src/handlers/event/analyze_logs/providers/paste_gg.rs b/src/handlers/event/analyze_logs/providers/paste_gg.rs index 5800a68..7ebead7 100644 --- a/src/handlers/event/analyze_logs/providers/paste_gg.rs +++ b/src/handlers/event/analyze_logs/providers/paste_gg.rs @@ -1,8 +1,9 @@ use crate::api::paste_gg; +use std::sync::OnceLock; + use eyre::{OptionExt, Result}; use log::trace; -use once_cell::sync::Lazy; use poise::serenity_prelude::Message; use regex::Regex; @@ -10,11 +11,11 @@ pub struct PasteGG; impl super::LogProvider for PasteGG { async fn find_match(&self, message: &Message) -> Option { - static REGEX: Lazy = - Lazy::new(|| Regex::new(r"https://paste.gg/p/\w+/(\w+)").unwrap()); + static REGEX: OnceLock = OnceLock::new(); + let regex = REGEX.get_or_init(|| Regex::new(r"https://paste.gg/p/\w+/(\w+)").unwrap()); trace!("Checking if message {} is a paste.gg paste", message.id); - super::get_first_capture(®EX, &message.content) + super::get_first_capture(regex, &message.content) } async fn fetch(&self, content: &str) -> Result { diff --git a/src/handlers/event/analyze_logs/providers/pastebin.rs b/src/handlers/event/analyze_logs/providers/pastebin.rs index f124018..66feecc 100644 --- a/src/handlers/event/analyze_logs/providers/pastebin.rs +++ b/src/handlers/event/analyze_logs/providers/pastebin.rs @@ -1,8 +1,9 @@ -use crate::utils; +use crate::api; + +use std::sync::OnceLock; use eyre::Result; use log::trace; -use once_cell::sync::Lazy; use poise::serenity_prelude::Message; use regex::Regex; @@ -13,16 +14,17 @@ pub struct PasteBin; impl super::LogProvider for PasteBin { async fn find_match(&self, message: &Message) -> Option { - static REGEX: Lazy = - Lazy::new(|| Regex::new(r"https://pastebin\.com(?:/raw)?/(\w+)").unwrap()); + static REGEX: OnceLock = OnceLock::new(); + let regex = + REGEX.get_or_init(|| Regex::new(r"https://pastebin\.com(?:/raw)?/(\w+)").unwrap()); trace!("Checking if message {} is a pastebin paste", message.id); - super::get_first_capture(®EX, &message.content) + super::get_first_capture(regex, &message.content) } async fn fetch(&self, content: &str) -> Result { let url = format!("{PASTEBIN}{RAW}/{content}"); - let log = utils::text_from_url(&url).await?; + let log = api::text_from_url(&url).await?; Ok(log) } diff --git a/src/handlers/event/eta.rs b/src/handlers/event/eta.rs index f818c2e..f4219f1 100644 --- a/src/handlers/event/eta.rs +++ b/src/handlers/event/eta.rs @@ -1,13 +1,17 @@ +use std::sync::OnceLock; + use eyre::Result; use log::trace; -use once_cell::sync::Lazy; use poise::serenity_prelude::{Context, Message}; use rand::seq::SliceRandom; use regex::Regex; -static ETA_REGEX: Lazy = Lazy::new(|| Regex::new(r"\beta\b").unwrap()); +fn regex() -> &'static Regex { + static REGEX: OnceLock = OnceLock::new(); + REGEX.get_or_init(|| Regex::new(r"\beta\b").unwrap()) +} -const ETA_MESSAGES: [&str; 16] = [ +const MESSAGES: [&str; 16] = [ "Sometime", "Some day", "Not far", @@ -27,7 +31,7 @@ const ETA_MESSAGES: [&str; 16] = [ ]; pub async fn handle(ctx: &Context, message: &Message) -> Result<()> { - if !ETA_REGEX.is_match(&message.content) { + if !regex().is_match(&message.content) { trace!( "The message '{}' (probably) doesn't say ETA", message.content @@ -37,7 +41,7 @@ pub async fn handle(ctx: &Context, message: &Message) -> Result<()> { let response = format!( "{} <:pofat:1031701005559144458>", - ETA_MESSAGES + MESSAGES .choose(&mut rand::thread_rng()) .unwrap_or(&"sometime") ); diff --git a/src/main.rs b/src/main.rs index 893250d..118b109 100644 --- a/src/main.rs +++ b/src/main.rs @@ -33,7 +33,7 @@ use storage::Storage; type Context<'a> = poise::Context<'a, Data, Report>; -#[derive(Clone)] +#[derive(Clone, Debug, Default)] pub struct Data { config: Config, storage: Option, diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 62aa051..d12edb2 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -1,34 +1,7 @@ -use crate::api::REQWEST_CLIENT; - -use eyre::Result; -use log::debug; use poise::serenity_prelude::{CreateEmbedAuthor, User}; -use reqwest::Response; pub mod resolve_message; -pub async fn get_url(url: &str) -> Result { - debug!("Making request to {url}"); - let resp = REQWEST_CLIENT.get(url).send().await?; - resp.error_for_status_ref()?; - - Ok(resp) -} - -pub async fn text_from_url(url: &str) -> Result { - let resp = get_url(url).await?; - - let text = resp.text().await?; - Ok(text) -} - -pub async fn bytes_from_url(url: &str) -> Result> { - let resp = get_url(url).await?; - - let bytes = resp.bytes().await?; - Ok(bytes.to_vec()) -} - pub fn embed_author_from_user(user: &User) -> CreateEmbedAuthor { CreateEmbedAuthor::new(user.tag()).icon_url( user.avatar_url() diff --git a/src/utils/resolve_message.rs b/src/utils/resolve_message.rs index 95b01d5..e6bd2dd 100644 --- a/src/utils/resolve_message.rs +++ b/src/utils/resolve_message.rs @@ -1,9 +1,9 @@ use crate::api::pluralkit; -use std::str::FromStr; + +use std::{str::FromStr, sync::OnceLock}; use eyre::{eyre, Context as _, Result}; use log::{debug, trace}; -use once_cell::sync::Lazy; use poise::serenity_prelude::{ Cache, CacheHttp, ChannelId, ChannelType, Colour, Context, CreateEmbed, CreateEmbedAuthor, CreateEmbedFooter, GuildChannel, Member, Message, MessageId, Permissions, UserId, @@ -36,8 +36,9 @@ async fn member_can_view_channel( member: &Member, channel: &GuildChannel, ) -> Result { - static REQUIRED_PERMISSIONS: Lazy = - Lazy::new(|| Permissions::VIEW_CHANNEL | Permissions::READ_MESSAGE_HISTORY); + static REQUIRED_PERMISSIONS: OnceLock = OnceLock::new(); + let required_permissions = REQUIRED_PERMISSIONS + .get_or_init(|| Permissions::VIEW_CHANNEL | Permissions::READ_MESSAGE_HISTORY); let guild = ctx.http().get_guild(channel.guild_id).await?; @@ -60,7 +61,7 @@ async fn member_can_view_channel( let can_view = guild .user_permissions_in(&channel_to_check, member) - .contains(*REQUIRED_PERMISSIONS); + .contains(*required_permissions); Ok(can_view) } @@ -109,9 +110,8 @@ pub async fn to_embed( } pub async fn from_message(ctx: &Context, msg: &Message) -> Result> { - static MESSAGE_PATTERN: Lazy = Lazy::new(|| { - Regex::new(r"(?:https?:\/\/)?(?:canary\.|ptb\.)?discord(?:app)?\.com\/channels\/(?\d+)\/(?\d+)\/(?\d+)").unwrap() - }); + static MESSAGE_PATTERN: OnceLock = OnceLock::new(); + let message_pattern = MESSAGE_PATTERN.get_or_init(|| Regex::new(r"(?:https?:\/\/)?(?:canary\.|ptb\.)?discord(?:app)?\.com\/channels\/(?\d+)\/(?\d+)\/(?\d+)").unwrap()); let Some(guild_id) = msg.guild_id else { debug!("Not resolving message in DM"); @@ -128,7 +128,7 @@ pub async fn from_message(ctx: &Context, msg: &Message) -> Result