Skip to content

Commit 429e3f0

Browse files
committed
feat(config): enhance configuration management and add toml support
- Introduced a new configuration structure with Discord and monitoring settings. - Added functionality to load or create a configuration file (`config.toml`). - Updated `CommitTracker` to utilize the new configuration management. - Refactored Discord notification handling to use the new config structure.
1 parent 12e8d7e commit 429e3f0

7 files changed

Lines changed: 172 additions & 25 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
/target
2+
config.toml

Cargo.lock

Lines changed: 60 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: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ scraper = "0.23.1"
1313
serde = { version = "1.0.219", features = ["derive"] }
1414
serde_json = "1.0.140"
1515
tokio = { version = "1.45.1", features = ["full"] }
16+
toml = "0.8.22"

src/core/config.rs

Lines changed: 90 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,105 @@
1-
#[derive(Debug, Clone)]
1+
use serde::{Deserialize, Serialize};
2+
use std::fs;
3+
use std::path::Path;
4+
use std::error::Error;
5+
use std::io::{self, Write};
6+
7+
const CONFIG_FILE: &str = "config.toml";
8+
9+
#[derive(Debug, Clone, Serialize, Deserialize)]
210
pub struct Config {
3-
pub discord_webhook_url: String,
11+
pub discord: DiscordConfig,
12+
pub monitoring: MonitoringConfig,
13+
pub appearance: AppearanceConfig,
14+
}
15+
16+
#[derive(Debug, Clone, Serialize, Deserialize)]
17+
pub struct DiscordConfig {
18+
pub webhook_url: String,
19+
pub bot_name: String,
20+
pub bot_avatar_url: String,
21+
}
22+
23+
#[derive(Debug, Clone, Serialize, Deserialize)]
24+
pub struct MonitoringConfig {
425
pub commits_url: String,
526
pub check_interval_secs: u64,
6-
pub rust_color: u32,
27+
}
28+
29+
#[derive(Debug, Clone, Serialize, Deserialize)]
30+
pub struct AppearanceConfig {
31+
pub embed_color: String,
732
pub footer_icon_url: String,
833
}
934

1035
impl Config {
11-
pub fn new() -> Self {
12-
Self {
13-
discord_webhook_url: "https://discord.com/api/webhooks/1377062435000680469/p8IPNirCl90kWHSpmX-YMEDxeNKdaGOUtofNY_jSX_B-w_3vMSXymIaKuvVVP71Xtlnq".to_string(),
14-
commits_url: "https://commits.facepunch.com/r/rust_reboot".to_string(),
15-
check_interval_secs: 50,
16-
rust_color: 0xCD412B,
17-
footer_icon_url: "https://i.imgur.com/on47Qk9.png".to_string(),
36+
pub fn load_or_create() -> Result<Self, Box<dyn Error>> {
37+
if Path::new(CONFIG_FILE).exists() {
38+
Self::load_from_file()
39+
} else {
40+
Self::create_default_and_prompt()
41+
}
42+
}
43+
44+
fn load_from_file() -> Result<Self, Box<dyn Error>> {
45+
let content = fs::read_to_string(CONFIG_FILE)?;
46+
let config: Config = toml::from_str(&content)?;
47+
Ok(config)
48+
}
49+
50+
fn create_default_and_prompt() -> Result<Self, Box<dyn Error>> {
51+
println!("🔧 First time setup - Creating configuration file...");
52+
53+
let default_config = Self::default();
54+
let toml_content = toml::to_string_pretty(&default_config)?;
55+
56+
fs::write(CONFIG_FILE, &toml_content)?;
57+
58+
println!("✅ Created '{}'", CONFIG_FILE);
59+
println!();
60+
println!("📝 Please edit the configuration file with your settings:");
61+
println!(" - Discord webhook URL");
62+
println!(" - Bot name and avatar");
63+
println!(" - Monitoring settings");
64+
println!();
65+
print!("Press Enter when you've finished editing the config file...");
66+
io::stdout().flush()?;
67+
68+
let mut input = String::new();
69+
io::stdin().read_line(&mut input)?;
70+
71+
// Reload the config after user edits
72+
Self::load_from_file()
73+
}
74+
75+
pub fn rust_color(&self) -> u32 {
76+
// Parse hex color string to u32
77+
if self.appearance.embed_color.starts_with('#') {
78+
u32::from_str_radix(&self.appearance.embed_color[1..], 16)
79+
.unwrap_or(0xCD412B)
80+
} else {
81+
u32::from_str_radix(&self.appearance.embed_color, 16)
82+
.unwrap_or(0xCD412B)
1883
}
1984
}
2085
}
2186

2287
impl Default for Config {
2388
fn default() -> Self {
24-
Self::new()
89+
Self {
90+
discord: DiscordConfig {
91+
webhook_url: "REPLACE_WITH_YOUR_DISCORD_WEBHOOK_URL".to_string(),
92+
bot_name: "Rust Commit Tracker".to_string(),
93+
bot_avatar_url: "https://i.imgur.com/on47Qk9.png".to_string(),
94+
},
95+
monitoring: MonitoringConfig {
96+
commits_url: "https://commits.facepunch.com/r/rust_reboot".to_string(),
97+
check_interval_secs: 50,
98+
},
99+
appearance: AppearanceConfig {
100+
embed_color: "#CD412B".to_string(), // Rust orange
101+
footer_icon_url: "https://i.imgur.com/on47Qk9.png".to_string(),
102+
},
103+
}
25104
}
26105
}

src/core/tracker.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,33 +13,33 @@ pub struct CommitTracker {
1313
}
1414

1515
impl CommitTracker {
16-
pub fn new() -> Self {
17-
let config = Config::new();
16+
pub fn new() -> Result<Self, Box<dyn Error>> {
17+
let config = Config::load_or_create()?;
1818
let scraper = CommitScraper::new();
1919
let notifier = DiscordNotifier::new(config.clone());
2020

21-
Self {
21+
Ok(Self {
2222
config,
2323
scraper,
2424
notifier,
2525
last_commit_id: 0,
26-
}
26+
})
2727
}
2828

2929
pub async fn start(&mut self) -> Result<(), Box<dyn Error>> {
30-
info!("🚀 Rust commit tracker started - monitoring Facepunch commits");
30+
info!("🚀 {} started - monitoring Facepunch commits", self.config.discord.bot_name);
3131

3232
loop {
3333
if let Err(e) = self.check_for_new_commits().await {
3434
error!("❌ {}", e);
3535
}
3636

37-
sleep(Duration::from_secs(self.config.check_interval_secs)).await;
37+
sleep(Duration::from_secs(self.config.monitoring.check_interval_secs)).await;
3838
}
3939
}
4040

4141
async fn check_for_new_commits(&mut self) -> Result<(), Box<dyn Error>> {
42-
let commit = self.scraper.fetch_latest_commit(&self.config.commits_url).await?;
42+
let commit = self.scraper.fetch_latest_commit(&self.config.monitoring.commits_url).await?;
4343

4444
if commit.id > self.last_commit_id {
4545
self.last_commit_id = commit.id;
@@ -57,6 +57,6 @@ impl CommitTracker {
5757

5858
impl Default for CommitTracker {
5959
fn default() -> Self {
60-
Self::new()
60+
Self::new().expect("Failed to create CommitTracker")
6161
}
6262
}

src/main.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,13 @@ async fn main() {
99
.format_timestamp_secs()
1010
.init();
1111

12-
let mut tracker = CommitTracker::new();
12+
let mut tracker = match CommitTracker::new() {
13+
Ok(tracker) => tracker,
14+
Err(e) => {
15+
error!("❌ Failed to initialize tracker: {}", e);
16+
return;
17+
}
18+
};
1319

1420
if let Err(e) = tracker.start().await {
1521
error!("❌ Fatal error: {}", e);

src/services/discord.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ impl DiscordNotifier {
2020
let embed = self.build_embed(commit);
2121

2222
let response = self.client
23-
.post(&self.config.discord_webhook_url)
23+
.post(&self.config.discord.webhook_url)
2424
.header("Content-Type", "application/json")
2525
.json(&embed)
2626
.send()
@@ -38,10 +38,10 @@ impl DiscordNotifier {
3838
embeds: vec![EmbedData {
3939
title: "🔧 New Rust Commit".to_string(),
4040
description: format!("```\n{}\n```", commit.message),
41-
color: self.config.rust_color,
41+
color: self.config.rust_color(),
4242
author: EmbedAuthor {
4343
name: commit.author.clone(),
44-
url: self.config.commits_url.clone(),
44+
url: self.config.monitoring.commits_url.clone(),
4545
icon_url: commit.avatar_url.clone(),
4646
},
4747
fields: vec![
@@ -62,8 +62,8 @@ impl DiscordNotifier {
6262
},
6363
],
6464
footer: EmbedFooter {
65-
text: "Facepunch Rust Commits".to_string(),
66-
icon_url: self.config.footer_icon_url.clone(),
65+
text: self.config.discord.bot_name.clone(),
66+
icon_url: self.config.discord.bot_avatar_url.clone(),
6767
},
6868
timestamp: chrono::Utc::now().to_rfc3339(),
6969
}],

0 commit comments

Comments
 (0)