From ad3bcc88de170d3cd96dbb92a9d77203d4556676 Mon Sep 17 00:00:00 2001 From: xmppftw Date: Wed, 7 Aug 2024 11:28:24 +0200 Subject: [PATCH] Move Config to config module --- src/config.rs | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 86 +++------------------------------------------- 2 files changed, 99 insertions(+), 82 deletions(-) create mode 100644 src/config.rs diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..99114e5 --- /dev/null +++ b/src/config.rs @@ -0,0 +1,95 @@ +// Copyright (C) 2023-2099 The crate authors. +// +// 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 . + +use std::io::{Error as IoError, ErrorKind as IoErrorKind}; +use std::net::{IpAddr, Ipv6Addr, SocketAddr}; +use std::path::{Path, PathBuf}; + +use jid::BareJid; +use log::debug; +use serde::{Deserialize, Serialize}; + +use crate::error::Error; + +#[derive(Debug, Serialize, Deserialize)] +pub struct Config { + /// Account address + pub jid: BareJid, + + /// Account password + pub password: String, + + /// Rooms to join, e.g., room@chat.example.org + #[serde(default = "Vec::new")] + pub rooms: Vec, + + /// Nickname to use in rooms + #[serde(default = "Config::default_nickname")] + pub nickname: String, + + /// Secret that matches the one provided to the Webhook service + #[serde(rename = "secret")] + pub secret: String, + + /// HTTP Webhook listening address and port, e.g., 127.0.0.1:1234 or [::1]:1234 + #[serde(default = "Config::default_addr")] + pub addr: SocketAddr, +} + +impl Config { + pub fn default_nickname() -> String { + String::from("cusku") + } + + pub fn default_addr() -> SocketAddr { + SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), 3000) + } + + pub fn from_file(file: PathBuf) -> Result { + if file.try_exists().is_err() { + let err = IoError::new(IoErrorKind::NotFound, format!("{:?} not found", file)); + return Err(Error::Io(err)); + } + + // TODO: tokio::fs + let buf = std::fs::read_to_string(file)?; + Ok(toml::from_str(&buf)?) + } + + pub fn from_arg(file: Option<&PathBuf>) -> Result { + let path = if let Some(path) = file { + // Provided by --config flag + if !path.starts_with("/") { + std::env::current_dir()?.join(path) + } else { + path.to_path_buf() + } + } else { + let confdir: PathBuf = match std::env::var("XDG_CONFIG_HOME") { + Ok(ref dir) => Path::new(dir).to_path_buf(), + Err(_) => { + let home = std::env::var("HOME")?; + Path::new(home.as_str()).join(".config") + } + }; + + confdir.join("cusku/config.toml") + }; + + debug!("Using configuration file: {:?}", path); + + Self::from_file(path) + } +} diff --git a/src/main.rs b/src/main.rs index 2156a36..3075efe 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,74 +17,24 @@ #![feature(never_type)] mod bot; +mod config; mod error; mod hook; mod web; use crate::bot::XmppClient; +use crate::config::Config; use crate::error::Error; use crate::hook::Hook; use crate::web::hooks; -use std::fs::File; -use std::io::{Error as IoError, ErrorKind as IoErrorKind, Read}; -use std::net::{IpAddr, Ipv6Addr, SocketAddr}; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use std::sync::{Arc, Mutex}; use clap::{command, value_parser, Arg}; use hyper::{server::conn::http1, service::service_fn}; use hyper_util::rt::tokio::{TokioIo, TokioTimer}; -use log::debug; -use serde::{Deserialize, Serialize}; use tokio::{net::TcpListener, sync::mpsc}; -use xmpp::BareJid; - -#[derive(Debug, Serialize, Deserialize)] -struct Config { - /// Account address - jid: BareJid, - - /// Account password - password: String, - - /// Rooms to join, e.g., room@chat.example.org - #[serde(default = "Vec::new")] - rooms: Vec, - - /// Nickname to use in rooms - #[serde(default = "default_nickname")] - nickname: String, - - /// Secret that matches the one provided to the Webhook service - #[serde(rename = "secret")] - secret: String, - - /// HTTP Webhook listening address and port, e.g., 127.0.0.1:1234 or [::1]:1234 - #[serde(default = "default_addr")] - addr: SocketAddr, -} - -fn default_nickname() -> String { - String::from("cusku") -} - -fn default_addr() -> SocketAddr { - SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), 3000) -} - -fn config_from_file(file: PathBuf) -> Result { - if file.try_exists().is_err() { - let err = IoError::new(IoErrorKind::NotFound, format!("{:?} not found", file)); - return Err(Error::Io(err)); - } - - let mut buf = String::new(); - let mut f = File::open(file)?; - f.read_to_string(&mut buf)?; - - Ok(toml::from_str(&buf)?) -} #[tokio::main] async fn main() -> Result { @@ -100,35 +50,7 @@ async fn main() -> Result { ) .get_matches(); - let config = { - let path = match matches.get_one::("config") { - Some(path) => { - if !path.starts_with("/") { - std::env::current_dir()?.join(path) - } else { - path.to_path_buf() - } - } - None => { - let confdir: PathBuf = match std::env::var("XDG_CONFIG_HOME") { - Ok(ref dir) => Path::new(dir).to_path_buf(), - Err(_) => { - let home = std::env::var("HOME")?; - Path::new(home.as_str()).join(".config") - } - }; - - confdir.join("cusku/config.toml") - } - }; - - debug!("Using configuration file: {:?}", path); - - match config_from_file(path) { - Ok(config) => config, - Err(err) => return Err(err), - } - }; + let config = Config::from_arg(matches.get_one::("config"))?; let (value_tx, mut value_rx) = mpsc::unbounded_channel::();