Skip to content

Commit e920bf2

Browse files
committed
feat(plugins): Improve cache checking logic
Other notable changes: - Restructured and switched to snake_case in the registry metadata file. - Removed the unnecessary Box of the Config struct. - Started adopting Anyhow in plugin and HTTP registry modules. - Still needs further tweaking (adding/removing context), will happen with a later full anyhow adoption PR. - Added the plugin user ID to their Store - This will allow recognizing plugins during host calls and is the first step towards the new plugin API.
1 parent 5ac68f8 commit e920bf2

10 files changed

Lines changed: 371 additions & 271 deletions

File tree

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,18 @@ edition = "2024"
99
[features]
1010

1111
[dependencies]
12+
anyhow = "1"
1213
bytes = "1"
1314
chrono = "0.4"
1415
clap = { version = "4", features = ["derive"] }
1516
dotenvy = "0.15"
1617
indexmap = "2"
1718
reqwest = { version = "0.13", features = ["hickory-dns"] }
1819
rustls = "0.23"
20+
semver = "1"
1921
serde = "1"
20-
sonic-rs = "0.5"
2122
serde_yaml_ng = "0.10" # Should replace this with a better maintained YAML 1.2 supporting alternative
23+
sonic-rs = "0.5"
2224
tokio = { version = "1", features = ["full"] }
2325
tokio-cron-scheduler = { version = "0.15", features = ["english"] }
2426
tokio-util = "0.7"

src/config.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub struct Config {
1717
}
1818

1919
impl Config {
20-
pub fn new(file_path: &Path) -> Result<Box<Self>, ()> {
20+
pub fn new(file_path: &Path) -> Result<Self, ()> {
2121
info!("Loading and parsing the config file");
2222

2323
let file_bytes = match fs::read(file_path) {
@@ -29,7 +29,7 @@ impl Config {
2929
};
3030

3131
match serde_yaml_ng::from_slice::<Config>(&file_bytes) {
32-
Ok(config) => Ok(Box::new(config)), // TODO: Env var interpolation, maybe via YAML 1.2's' `!val`
32+
Ok(config) => Ok(config), // TODO: Env var interpolation
3333
Err(err) => {
3434
error!(
3535
"An error occurred while trying to deserialize the config file YAML to a struct: {err}"

src/http.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ pub struct HttpClient {
1212
client: Client,
1313
}
1414

15-
const USER_AGENT: &str = "celarye/discord-bot";
15+
static USER_AGENT: &str = "celarye/discord-bot";
1616

1717
impl HttpClient {
1818
pub fn new(http_client_timeout_seconds: u64) -> Result<Self, ()> {

src/http/registry.rs

Lines changed: 19 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,38 @@
11
/* SPDX-License-Identifier: GPL-3.0-or-later */
22
/* Copyright © 2026 Eduard Smet */
33

4-
use std::{
5-
str::FromStr,
6-
sync::{Arc, LazyLock},
7-
};
4+
use std::str::FromStr;
85

6+
use anyhow::{Context, Error, Result};
97
use reqwest::StatusCode;
10-
use tracing::{debug, error};
8+
use tracing::debug;
119
use url::{ParseError, Url};
1210

1311
use crate::http::HttpClient;
1412

15-
static DEFAULT_REGISTRY_URL: LazyLock<Url> = LazyLock::new(|| {
16-
Url::parse("https://raw.githubusercontent.com/celarye/discord-bot-plugins/refs/heads/master/")
17-
.unwrap()
18-
});
19-
2013
impl HttpClient {
21-
pub async fn get_file_from_registry(
22-
&self,
23-
registry: &Arc<Option<String>>,
24-
path: &str,
25-
) -> Result<Vec<u8>, ()> {
26-
let url = match Self::parse_url(registry, path) {
27-
Ok(url) => url,
28-
Err(err) => {
29-
error!(
30-
"An error occurred while trying to construct a valid URL from the provided registry and path: {err}"
31-
);
32-
return Err(());
33-
}
34-
};
14+
pub async fn get_file_from_registry(&self, registry: &str, path: &str) -> Result<Vec<u8>> {
15+
let url = Self::parse_url(registry, path).context("An error occurred while trying to construct a valid URL from the provided registry and path")?;
3516

3617
debug!("Requested registry file: {url}");
3718

38-
match self.client.get(url).send().await {
39-
Ok(raw_response) => {
40-
if raw_response.status() != StatusCode::OK {
41-
error!(
42-
"The response was undesired, status code: {}",
43-
raw_response.status(),
44-
);
45-
return Err(());
46-
}
19+
let response = self.client.get(url).send().await?;
4720

48-
match raw_response.bytes().await {
49-
Ok(response) => Ok(response.to_vec()),
50-
Err(err) => {
51-
error!(
52-
"Something went wrong while getting the raw bytes from the response, error: {err}"
53-
);
54-
Err(())
55-
}
56-
}
57-
}
58-
Err(err) => {
59-
error!("Something went wrong while making the request, error: {err}");
60-
Err(())
61-
}
21+
if response.status() != StatusCode::OK {
22+
return Err(Error::msg(format!(
23+
"The response was undesired, status code: {}",
24+
response.status()
25+
)));
6226
}
63-
}
6427

65-
fn parse_url(registry: &Arc<Option<String>>, path: &str) -> Result<Url, ParseError> {
66-
if let Some(registry) = registry.as_deref() {
67-
return Url::from_str(registry)?.join(path);
68-
}
28+
Ok(response
29+
.bytes()
30+
.await
31+
.context("Something went wrong while getting the raw bytes from the response")?
32+
.to_vec())
33+
}
6934

70-
DEFAULT_REGISTRY_URL.join(path)
35+
fn parse_url(registry: &str, path: &str) -> Result<Url, ParseError> {
36+
Url::from_str(&format!("https://{registry}/"))?.join(path)
7137
}
7238
}

src/main.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
use std::os::unix::process::CommandExt;
66

77
use std::{
8-
collections::VecDeque,
8+
collections::{HashMap, VecDeque},
99
env,
1010
ffi::OsString,
1111
path::{Path, PathBuf},
@@ -139,18 +139,18 @@ fn initialization(
139139

140140
async fn registry_get_plugins(
141141
http_client_timeout_seconds: u64,
142-
config: Box<Config>,
142+
config: Config,
143143
plugin_directory: PathBuf,
144144
cache: bool,
145-
) -> Result<Vec<AvailablePlugin>, ()> {
145+
) -> Result<HashMap<String, AvailablePlugin>, ()> {
146146
let http_client = Arc::new(HttpClient::new(http_client_timeout_seconds)?);
147147

148148
registry::get_plugins(http_client, config, plugin_directory, cache).await
149149
}
150150

151151
async fn plugin_initializations(
152152
runtime: Arc<Runtime>,
153-
available_plugins: Vec<AvailablePlugin>,
153+
available_plugins: HashMap<String, AvailablePlugin>,
154154
plugin_registrations: Arc<RwLock<PluginRegistrations>>,
155155
config_directory: &Path,
156156
) -> Result<(), ()> {

src/plugins.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ pub mod runtime;
77

88
use std::collections::{HashMap, HashSet};
99

10+
use semver::Version;
1011
use serde::{Deserialize, Deserializer};
1112
use serde_yaml_ng::Value;
1213
use twilight_model::id::{Id, marker::CommandMarker};
@@ -15,7 +16,7 @@ use crate::plugins::discord_bot::plugin::plugin_types::SupportedRegistrations;
1516

1617
wasmtime::component::bindgen!({ imports: { default: async }, exports: { default: async } });
1718

18-
#[derive(Deserialize)]
19+
#[derive(Clone, Deserialize)]
1920
pub struct ConfigPlugin {
2021
pub plugin: String,
2122
pub cache: Option<bool>,
@@ -86,8 +87,9 @@ impl<'de> Deserialize<'de> for SupportedRegistrations {
8687
}
8788

8889
pub struct AvailablePlugin {
90+
pub registry_id: String,
8991
pub id: String,
90-
pub version: String,
92+
pub version: Version,
9193
pub permissions: SupportedRegistrations,
9294
pub environment: Option<HashMap<String, String>>,
9395
pub settings: Option<Value>,

0 commit comments

Comments
 (0)