refactor(database): add version tracking functions and update notification logic

This commit is contained in:
Félix MARQUET
2025-06-14 13:58:36 +02:00
parent 43275d1fd9
commit 79e48391cb
4 changed files with 103 additions and 63 deletions

View File

@@ -1,5 +1,5 @@
use log::info;
use rusqlite::{Connection, Result as SqliteResult, OpenFlags};
pub(crate) use rusqlite::{Connection, Result as SqliteResult, OpenFlags};
use std::env;
use std::path::Path;
@@ -78,4 +78,26 @@ pub fn get_docker_watched_repos(conn: &Connection) -> SqliteResult<Vec<String>>
repos.push(repo?);
}
Ok(repos)
}
pub fn is_new_version(conn: &Connection, repo: &str, version: &str) -> SqliteResult<bool> {
let mut stmt = conn.prepare("SELECT version FROM versions WHERE repo = ?")?;
let result = stmt.query_map([repo], |row| row.get::<_, String>(0))?;
for stored_version in result {
if let Ok(v) = stored_version {
return Ok(v != version);
}
}
Ok(true)
}
pub fn update_version(conn: &Connection, repo: &str, version: &str, changelog: Option<&str>) -> SqliteResult<()> {
conn.execute(
"REPLACE INTO versions (repo, version, changelog) VALUES (?, ?, ?)",
[repo, version, changelog.unwrap_or("")],
)?;
Ok(())
}

View File

@@ -29,7 +29,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
env_logger::init();
let config = config::Config::from_env();
let (_conn_versions, conn_repos) = database::init_databases()?;
let (conn_versions, conn_repos) = database::init_databases()?;
start_api();
@@ -57,7 +57,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let github_releases = github::get_latest_releases(&github_repos, &client, config.github_headers()).await;
let docker_releases = docker::get_latest_docker_releases(&docker_repos, &client, config.docker_headers()).await;
notifications::send_notifications(github_releases, docker_releases, &config).await;
notifications::send_notifications(github_releases, docker_releases, &config, &conn_versions).await;
tokio::time::sleep(Duration::from_secs_f64(config.timeout)).await;
}

View File

@@ -33,4 +33,10 @@ pub struct DockerReleaseInfo {
pub digest: String,
pub html_url: String,
pub published_at: String,
}
pub struct NotifiedRelease {
pub repo: String,
pub tag_name: String,
pub notified_at: chrono::DateTime<chrono::Utc>,
}

View File

@@ -8,85 +8,95 @@ pub mod docker;
use tokio::task;
use crate::models::{GithubReleaseInfo, DockerReleaseInfo};
use crate::config::Config;
use crate::database::{Connection, is_new_version, update_version};
use rusqlite::Result as SqliteResult;
pub async fn send_notifications(
github_releases: Vec<GithubReleaseInfo>,
docker_releases: Vec<DockerReleaseInfo>,
config: &Config,
) {
db_conn: &Connection,
) -> SqliteResult<()> {
let mut tasks = Vec::new();
// Create tasks for GitHub notifications
for release in &github_releases {
if let Some(url) = &config.ntfy_url {
let release = release.clone();
let auth = config.auth.clone();
let url = url.clone();
tasks.push(task::spawn(async move {
github::send_to_ntfy(release, &auth, &url).await;
}));
}
if is_new_version(db_conn, &release.repo, &release.tag_name)? {
if let Some(url) = &config.ntfy_url {
let release = release.clone();
let auth = config.auth.clone();
let url = url.clone();
tasks.push(task::spawn(async move {
github::send_to_ntfy(release, &auth, &url).await;
}));
}
if let (Some(gotify_url), Some(gotify_token)) = (&config.gotify_url, &config.gotify_token) {
let release = release.clone();
let url = gotify_url.clone();
let token = gotify_token.clone();
tasks.push(task::spawn(async move {
github::send_to_gotify(release, &token, &url).await;
}));
}
if let (Some(gotify_url), Some(gotify_token)) = (&config.gotify_url, &config.gotify_token) {
let release = release.clone();
let url = gotify_url.clone();
let token = gotify_token.clone();
tasks.push(task::spawn(async move {
github::send_to_gotify(release, &token, &url).await;
}));
}
if let Some(discord_url) = &config.discord_webhook_url {
let release = release.clone();
let url = discord_url.clone();
tasks.push(task::spawn(async move {
github::send_to_discord(release, &url).await;
}));
}
if let Some(discord_url) = &config.discord_webhook_url {
let release = release.clone();
let url = discord_url.clone();
tasks.push(task::spawn(async move {
github::send_to_discord(release, &url).await;
}));
}
if let Some(slack_url) = &config.slack_webhook_url {
let release = release.clone();
let url = slack_url.clone();
tasks.push(task::spawn(async move {
github::send_to_slack(release, &url).await;
}));
if let Some(slack_url) = &config.slack_webhook_url {
let release = release.clone();
let url = slack_url.clone();
tasks.push(task::spawn(async move {
github::send_to_slack(release, &url).await;
}));
}
update_version(db_conn, &release.repo, &release.tag_name, Some(release.changelog.as_str()))?;
}
}
// Create tasks for Docker notifications
for release in &docker_releases {
if let Some(url) = &config.ntfy_url {
let release = release.clone();
let auth = config.auth.clone();
let url = url.clone();
tasks.push(task::spawn(async move {
docker::send_to_ntfy(release, &auth, &url).await;
}));
}
if is_new_version(db_conn, &release.repo, &release.digest)? {
if let Some(url) = &config.ntfy_url {
let release = release.clone();
let auth = config.auth.clone();
let url = url.clone();
tasks.push(task::spawn(async move {
docker::send_to_ntfy(release, &auth, &url).await;
}));
}
if let (Some(gotify_url), Some(gotify_token)) = (&config.gotify_url, &config.gotify_token) {
let release = release.clone();
let url = gotify_url.clone();
let token = gotify_token.clone();
tasks.push(task::spawn(async move {
docker::send_to_gotify(release, &token, &url).await;
}));
}
if let (Some(gotify_url), Some(gotify_token)) = (&config.gotify_url, &config.gotify_token) {
let release = release.clone();
let url = gotify_url.clone();
let token = gotify_token.clone();
tasks.push(task::spawn(async move {
docker::send_to_gotify(release, &token, &url).await;
}));
}
if let Some(discord_url) = &config.discord_webhook_url {
let release = release.clone();
let url = discord_url.clone();
tasks.push(task::spawn(async move {
docker::send_to_discord(release, &url).await;
}));
}
if let Some(discord_url) = &config.discord_webhook_url {
let release = release.clone();
let url = discord_url.clone();
tasks.push(task::spawn(async move {
docker::send_to_discord(release, &url).await;
}));
}
if let Some(slack_url) = &config.slack_webhook_url {
let release = release.clone();
let url = slack_url.clone();
tasks.push(task::spawn(async move {
docker::send_to_slack(release, &url).await;
}));
if let Some(slack_url) = &config.slack_webhook_url {
let release = release.clone();
let url = slack_url.clone();
tasks.push(task::spawn(async move {
docker::send_to_slack(release, &url).await;
}));
}
update_version(db_conn, &release.repo, &release.digest, None)?;
}
}
@@ -94,4 +104,6 @@ pub async fn send_notifications(
for task in tasks {
let _ = task.await;
}
Ok(())
}