Initial draft

This commit is contained in:
Candifloss 2026-05-25 16:34:08 +05:30
parent 8d90777f82
commit c318ccbeb4
5 changed files with 117 additions and 0 deletions

5
.gitignore vendored
View File

@ -20,3 +20,8 @@ Cargo.lock
# and can be added to the global gitignore or merged into this file. For a more nuclear # and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder. # option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/ #.idea/
# Added by cargo
/target

14
Cargo.toml Normal file
View File

@ -0,0 +1,14 @@
[package]
name = "motdgen"
version = "0.1.0"
edition = "2024"
[dependencies]
rand = "0.10.1"
serde = { version = "1.0.228", features = ["derive"] }
toml = "1.1.2"
[profile.release]
lto = true
codegen-units = 1
strip = true

9
src/ansi.rs Normal file
View File

@ -0,0 +1,9 @@
pub const RESET: &str = "\x1b[0m";
pub fn fg([r, g, b]: [u8; 3]) -> String {
format!("\x1b[38;2;{r};{g};{b}m")
}
pub fn bg([r, g, b]: [u8; 3]) -> String {
format!("\x1b[48;2;{r};{g};{b}m")
}

25
src/config.rs Normal file
View File

@ -0,0 +1,25 @@
use serde::Deserialize;
use std::path::PathBuf;
#[derive(Debug, Deserialize)]
pub struct Config {
pub description: String,
pub ascii_art: String,
pub output: PathBuf,
pub colors: Colors,
}
#[derive(Debug, Deserialize)]
pub struct Colors {
pub background: [u8; 3],
pub description: [u8; 3],
pub random_art: RandomColor,
}
#[derive(Debug, Deserialize)]
pub struct RandomColor {
pub enabled: bool,
pub r: [u8; 2],
pub g: [u8; 2],
pub b: [u8; 2],
}

64
src/main.rs Normal file
View File

@ -0,0 +1,64 @@
mod ansi;
mod config;
use ansi::{RESET, bg, fg};
use config::{Config, RandomColor};
use rand::RngExt;
use std::{fmt::Write, fs, process};
const CONFIG: &str = "/etc/motdgen/config.toml";
fn random_rgb(cfg: &RandomColor) -> [u8; 3] {
let mut rng = rand::rng();
[
rng.random_range(cfg.r[0]..=cfg.r[1]),
rng.random_range(cfg.g[0]..=cfg.g[1]),
rng.random_range(cfg.b[0]..=cfg.b[1]),
]
}
fn load_config() -> Result<Config, Box<dyn std::error::Error>> {
let raw = fs::read_to_string(CONFIG)?;
Ok(toml::from_str(&raw)?)
}
fn build_motd(cfg: &Config) -> String {
let art_fg = if cfg.colors.random_art.enabled {
fg(random_rgb(&cfg.colors.random_art))
} else {
fg(cfg.colors.description)
};
let art_bg = bg(cfg.colors.background);
let desc_fg = fg(cfg.colors.description);
let mut out = String::new();
for line in cfg.ascii_art.lines() {
let _ = writeln!(out, "{art_fg}{art_bg} {line} {RESET}");
}
out.push_str(&desc_fg);
out.push_str(&cfg.description);
out.push_str(RESET);
out.push('\n');
out
}
fn main() {
let cfg = match load_config() {
Ok(c) => c,
Err(e) => {
eprintln!("config error: {e}");
process::exit(1);
}
};
if let Err(e) = fs::write(&cfg.output, build_motd(&cfg)) {
eprintln!("write failed: {e}");
process::exit(1);
}
}