rust_commit_tracker/core/
tracker.rs

1use crate::core::Config;
2use crate::services::{CommitScraper, Database, DiscordNotifier};
3use log::{debug, error, info};
4use std::error::Error;
5use std::time::Duration;
6use tokio::time::sleep;
7
8pub struct CommitTracker {
9    config: Config,
10    scraper: CommitScraper,
11    notifier: DiscordNotifier,
12    database: Database,
13}
14
15impl CommitTracker {
16    pub async fn new() -> Result<Self, Box<dyn Error>> {
17        let config = Config::load_or_create()?;
18        let scraper = CommitScraper::new();
19        let notifier = DiscordNotifier::new(config.clone());
20        let database = Database::new(&config.database.url).await?;
21
22        Ok(Self {
23            config,
24            scraper,
25            notifier,
26            database,
27        })
28    }
29
30    pub async fn start(&mut self) -> Result<(), Box<dyn Error>> {
31        info!(
32            "🚀 {} started - monitoring Facepunch commits",
33            self.config.discord.bot_name
34        );
35
36        // Get the last sent commit info from database
37        if let Some((last_id, changeset)) = self.database.get_last_sent_commit_info().await? {
38            info!(
39                "📊 Resuming from last sent commit ID: {} ({})",
40                last_id, changeset
41            );
42        } else {
43            info!("📊 No previous commits found in database - starting fresh");
44        }
45
46        loop {
47            if let Err(e) = self.check_for_new_commits().await {
48                error!("❌ {}", e);
49            }
50
51            sleep(Duration::from_secs(
52                self.config.monitoring.check_interval_secs,
53            ))
54            .await;
55        }
56    }
57
58    async fn check_for_new_commits(&mut self) -> Result<(), Box<dyn Error>> {
59        let result = self
60            .scraper
61            .fetch_latest_commit(&self.config.monitoring.commits_url)
62            .await?;
63        let commit = &result.commit;
64
65        // Check if we've already sent this commit
66        if self.database.is_commit_sent(commit.id).await? {
67            debug!("Commit #{} already sent, skipping", commit.id);
68            return Ok(());
69        }
70
71        info!(
72            "🆕 New commit #{} by {} - {}",
73            commit.id,
74            commit.author(),
75            commit.message
76        );
77
78        // Send notification
79        self.notifier.send_commit_notification(&result).await?;
80
81        // Mark as sent in database
82        self.database
83            .mark_commit_sent(
84                commit.id,
85                &commit.author(),
86                &commit.message,
87                &commit.branch,
88                &commit.changeset,
89            )
90            .await?;
91
92        info!("✅ Sent to Discord and marked as sent");
93
94        // Periodic cleanup to prevent database from growing too large
95        let sent_count = self.database.get_sent_commits_count().await?;
96        if sent_count > self.config.database.cleanup_keep_last + 100 {
97            self.database
98                .cleanup_old_commits(self.config.database.cleanup_keep_last)
99                .await?;
100        }
101
102        Ok(())
103    }
104}