// bebot -- a Gitlab -> Matrix event publisher // Copyright (C) 2023-2025 Brian Tarricone // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #[macro_use(anyhow)] extern crate anyhow; #[macro_use] extern crate log; #[macro_use] extern crate serde; mod config; mod gitlab_event; mod gitlab_webhook; mod mail_archive; mod matrix; use std::{env, net::IpAddr, process::exit}; use anyhow::Context; use futures::future::join_all; use warp::Filter; async fn run() -> anyhow::Result<()> { info!("{} v{} starting...", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION")); let config_path = env::args() .nth(1) .ok_or_else(|| anyhow!("Config file should be passed as only parameter"))?; let mut config = config::load(config_path).await?; let matrix_client = matrix::connect(&config).await.context("Failed to connect to Matrix")?; let handles = if let Some(mail_archive) = config.mail_archive.take() { mail_archive::start_polling(mail_archive, matrix_client.clone())? } else { vec![] }; if let Some(gitlab_webhook) = config.gitlab_webhook.take() { let gitlab = gitlab_webhook::build_route(gitlab_webhook, matrix_client.clone())?; let routes = gitlab.with(warp::log("bebot")); let addr = config .bind_address .as_ref() .cloned() .unwrap_or_else(|| "127.0.0.1".to_string()) .parse::() .context("Failed to parse bind_address")?; let port = config.bind_port.unwrap_or(3000); warp::serve(routes).run((addr, port)).await; } join_all(handles).await; error!("No functionality is configured; exiting"); exit(1); } #[tokio::main] async fn main() { let lenv = env_logger::Env::new() .filter("BEBOT_LOG") .write_style("BEBOT_LOG_STYLE"); env_logger::init_from_env(lenv); if let Err(err) = run().await { error!("{err:#}"); exit(1); } }