diff --git a/.idea/runConfigurations/Clippy.xml b/.idea/runConfigurations/Clippy.xml
index 706202c1..f4af1cd7 100644
--- a/.idea/runConfigurations/Clippy.xml
+++ b/.idea/runConfigurations/Clippy.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/.idea/runConfigurations/Run__debug_.xml b/.idea/runConfigurations/Run__debug_.xml
deleted file mode 100644
index 1d7deb10..00000000
--- a/.idea/runConfigurations/Run__debug_.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Cargo.lock b/Cargo.lock
index 5c3809ea..ed8077ae 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -137,9 +137,9 @@ checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952"
[[package]]
name = "cc"
-version = "1.1.3"
+version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18e2d530f35b40a84124146478cd16f34225306a8441998836466a2e2961c950"
+checksum = "324c74f2155653c90b04f25b2a47a8a631360cb908f92a772695f430c7e31052"
[[package]]
name = "cfg-if"
@@ -1423,7 +1423,7 @@ dependencies = [
[[package]]
name = "royalnet"
-version = "0.3.2"
+version = "0.4.0"
dependencies = [
"anyhow",
"chrono",
@@ -1543,9 +1543,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "security-framework"
-version = "2.11.0"
+version = "2.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0"
+checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
dependencies = [
"bitflags 2.6.0",
"core-foundation",
@@ -1556,9 +1556,9 @@ dependencies = [
[[package]]
name = "security-framework-sys"
-version = "2.11.0"
+version = "2.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7"
+checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf"
dependencies = [
"core-foundation-sys",
"libc",
@@ -1625,15 +1625,6 @@ dependencies = [
"syn 1.0.109",
]
-[[package]]
-name = "signal-hook-registry"
-version = "1.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
-dependencies = [
- "libc",
-]
-
[[package]]
name = "slab"
version = "0.4.9"
@@ -1877,9 +1868,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "tokio"
-version = "1.38.0"
+version = "1.38.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a"
+checksum = "eb2caba9f80616f438e09748d5acda951967e1ea58508ef53d9c6402485a46df"
dependencies = [
"backtrace",
"bytes",
@@ -1887,7 +1878,6 @@ dependencies = [
"mio",
"num_cpus",
"pin-project-lite",
- "signal-hook-registry",
"socket2",
"tokio-macros",
"windows-sys 0.48.0",
diff --git a/Cargo.toml b/Cargo.toml
index cb9d8d0e..f05f28b2 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "royalnet"
description = "Fun software suite for the RYG community"
-version = "0.3.2"
+version = "0.4.0"
edition = "2021"
authors = [
"Stefano Pigozzi "
@@ -26,23 +26,101 @@ exclude = [
"/.env"
]
+#============#
+
[dependencies]
-anyhow = "1.0.86"
-chrono = "0.4.38"
-diesel = { version = "2.2.1", features = ["postgres"] }
-log = { version = "0.4.22", features = ["release_max_level_debug"] }
-micronfig = "0.3.0"
-pretty_env_logger = "0.5.0"
-rand = { version = "0.8.5", features = ["small_rng"] }
-teloxide = { version = "0.12.2", features = ["ctrlc_handler", "native-tls", "macros"], default-features = false }
-tokio = { version = "1.38.0", features = ["macros", "rt-multi-thread", "time"] }
-parse_datetime = "0.6.0"
-regex = "1.10.5"
-once_cell = "1.19.0"
-reqwest = { version = "0.12.5", features = ["json"] }
-serde = { version = "1.0.204", features = ["derive"] }
-graphql_client = "0.14.0"
-thiserror = "1.0.62"
+
+[dependencies.anyhow]
+version = "1.0.86"
+
+[dependencies.thiserror]
+version = "1.0.62"
+
+[dependencies.tokio]
+version = "1.38.0"
+features = ["macros", "rt-multi-thread", "time"]
+
+[dependencies.log]
+version = "0.4.22"
+features = ["release_max_level_debug"]
+
+[dependencies.pretty_env_logger]
+version = "0.5.0"
+
+[dependencies.micronfig]
+version = "0.3.0"
+
+[dependencies.once_cell]
+version = "1.19.0"
+
+[dependencies.regex]
+version = "1.10.5"
+
+[dependencies.reqwest]
+version = "0.12.5"
+features = ["json"]
+
+[dependencies.serde]
+version = "1.0.204"
+features = ["derive"]
+
+[dependencies.diesel]
+version = "2.2.1"
+features = ["postgres"]
+optional = true
+
+[dependencies.teloxide]
+version = "0.12.2"
+default-features = false
+features = ["native-tls", "macros"]
+optional = true
+
+[dependencies.rand]
+version = "0.8.5"
+features = ["small_rng"]
+optional = true
+
+[dependencies.chrono]
+version = "0.4.38"
+optional = true
+
+[dependencies.parse_datetime]
+version = "0.6.0"
+optional = true
+
+[dependencies.graphql_client]
+version = "0.14.0"
+optional = true
+
+#============#
+
+[features]
+default = [
+ "interface_database",
+ "interface_stratz",
+ "service_brooch",
+ "service_telegram",
+]
+interface_database = [
+ "diesel"
+]
+interface_stratz = [
+ "graphql_client"
+]
+service_telegram = [
+ "interface_database",
+ "teloxide",
+ "rand",
+ "chrono",
+ "parse_datetime"
+]
+service_brooch = [
+ "interface_database",
+ "interface_stratz",
+ "graphql_client"
+]
+
+#============#
[[bin]]
name = "royalnet"
diff --git a/src/database/config.rs b/src/database/config.rs
deleted file mode 100644
index abccf732..00000000
--- a/src/database/config.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-use micronfig::config;
-
-config! {
- DATABASE_URL,
-}
diff --git a/src/database/mod.rs b/src/database/mod.rs
deleted file mode 100644
index c82af032..00000000
--- a/src/database/mod.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-use diesel::{Connection, ConnectionResult, PgConnection};
-
-mod config;
-pub mod schema;
-pub mod models;
-
-pub fn connect() -> ConnectionResult {
- PgConnection::establish(config::DATABASE_URL())
-}
diff --git a/src/instance/config.rs b/src/instance/config.rs
new file mode 100644
index 00000000..a41d71eb
--- /dev/null
+++ b/src/instance/config.rs
@@ -0,0 +1,60 @@
+#![allow(unused_attributes, unused_qualifications, clippy::needless_pub_self)]
+
+
+#[cfg(feature = "service_telegram")]
+pub mod service_telegram {
+ use micronfig::config;
+
+ config! {
+ TELEGRAM_DATABASE_URL: String,
+ TELEGRAM_BOT_TOKEN: String,
+ TELEGRAM_NOTIFICATION_CHATID?: String > i64 -> crate::instance::config::ChatIdConversionHack -> teloxide::types::ChatId,
+ }
+}
+
+#[cfg(feature = "service_brooch")]
+pub mod brooch {
+ use micronfig::config;
+
+ #[allow(unused_qualifications)]
+ config! {
+ BROOCH_DATABASE_URL: String,
+ BROOCH_GRAPHQL_URL: String,
+ BROOCH_STRATZ_TOKEN: String,
+ BROOCH_TELEGRAM_BOT_TOKEN: String,
+ BROOCH_WATCHED_GUILD_ID: String > i64,
+ BROOCH_MIN_PLAYERS_TO_PROCESS: String > usize,
+ BROOCH_NOTIFICATION_CHAT_ID: String > i64 -> crate::instance::config::ChatIdConversionHack -> teloxide::types::ChatId,
+ BROOCH_MAX_IMP_WAIT_SECS: String > i64 -> crate::instance::config::TimeDeltaConversionHack => chrono::TimeDelta,
+ }
+}
+
+pub struct ChatIdConversionHack(i64);
+
+impl From for ChatIdConversionHack {
+ fn from(value: i64) -> Self {
+ Self(value)
+ }
+}
+
+impl From for teloxide::types::ChatId {
+ fn from(value: ChatIdConversionHack) -> Self {
+ Self(value.0)
+ }
+}
+
+pub struct TimeDeltaConversionHack(i64);
+
+impl From for TimeDeltaConversionHack {
+ fn from(value: i64) -> Self {
+ Self(value)
+ }
+}
+
+impl TryFrom for chrono::TimeDelta {
+ type Error = ();
+
+ fn try_from(value: TimeDeltaConversionHack) -> Result {
+ Self::new(value.0, 0).ok_or(())
+ }
+}
\ No newline at end of file
diff --git a/src/instance/mod.rs b/src/instance/mod.rs
new file mode 100644
index 00000000..9bd69394
--- /dev/null
+++ b/src/instance/mod.rs
@@ -0,0 +1,102 @@
+use std::future::Future;
+use crate::services::RoyalnetService;
+
+pub(self) mod config;
+
+pub struct RoyalnetInstance {
+ #[cfg(feature = "service_telegram")]
+ service_telegram: crate::services::telegram::TelegramService,
+
+ #[cfg(feature = "service_brooch")]
+ service_brooch: crate::services::brooch::BroochService,
+}
+
+impl RoyalnetInstance {
+ pub async fn new() -> Self {
+ let service_telegram = Self::setup_telegram_service().await;
+ let service_brooch = Self::setup_brooch_service();
+
+ Self {
+ service_telegram,
+ service_brooch,
+ }
+ }
+
+ pub async fn run(mut self) {
+ let future_telegram = async move {
+ Self::get_telegram_future(&mut self.service_telegram).await;
+ };
+ let future_brooch = async move {
+ Self::get_brooch_future(&mut self.service_brooch).await;
+ };
+
+ let task_telegram = tokio::spawn(future_telegram);
+ let task_brooch = tokio::spawn(future_brooch);
+
+ let _ = tokio::join!(
+ task_telegram,
+ task_brooch,
+ );
+ }
+
+ #[cfg(feature = "service_telegram")]
+ async fn setup_telegram_service() -> crate::services::telegram::TelegramService {
+ log::debug!("Setting up Telegram service...");
+
+ crate::services::telegram::TelegramService::new(
+ config::service_telegram::TELEGRAM_DATABASE_URL().clone(),
+ config::service_telegram::TELEGRAM_BOT_TOKEN().clone(),
+ config::service_telegram::TELEGRAM_NOTIFICATION_CHATID().clone(),
+ ).await.expect("Unable to setup Telegram service.")
+ }
+
+ #[cfg(not(feature = "service_telegram"))]
+ async fn setup_telegram_service() -> () {
+ log::warn!("Telegram service is disabled.");
+
+ ()
+ }
+
+ #[cfg(feature = "service_telegram")]
+ fn get_telegram_future(service: &mut crate::services::telegram::TelegramService) -> impl Future