~homeworkprod/orgatalk-discord-orgateams

251a81b928f3a63b11a54d238b047d4746a0ef2e — Jochen Kupperschmidt a month ago c85fe97
Introduce combined data model to generate output from
3 files changed, 34 insertions(+), 22 deletions(-)

M src/main.rs
M src/model.rs
M src/templating.rs
M src/main.rs => src/main.rs +17 -7
@@ 14,6 14,9 @@ mod io;
mod model;
mod templating;

use crate::config::{Config, DiscordConfig};
use crate::model::Data;

fn main() -> Result<()> {
    let args = cli::parse_args();



@@ 25,20 28,18 @@ fn main() -> Result<()> {
        None => fetch_roles_from_discord(&config.discord)?,
    };

    let generated_at = Utc::now();
    let data = assemble_data(config, roles);

    match args.output_format {
        cli::OutputFormat::Html => {
            templating::render_html(config.title, config.subtitle, roles, generated_at, writer)?
        }
        cli::OutputFormat::Json => model::write_roles(roles, writer)?,
        cli::OutputFormat::Text => templating::render_text(roles, writer)?,
        cli::OutputFormat::Html => templating::render_html(data, writer)?,
        cli::OutputFormat::Json => model::write_roles(data.roles, writer)?,
        cli::OutputFormat::Text => templating::render_text(data, writer)?,
    };

    Ok(())
}

fn fetch_roles_from_discord(config: &config::DiscordConfig) -> Result<Vec<model::Role>> {
fn fetch_roles_from_discord(config: &DiscordConfig) -> Result<Vec<model::Role>> {
    let api_client = discord_api::Client::new(&config.bot_token);
    let guild_members = api_client.get_guild_members(&config.guild_id)?;
    let guild_roles = api_client.get_guild_roles(&config.guild_id)?;


@@ 46,3 47,12 @@ fn fetch_roles_from_discord(config: &config::DiscordConfig) -> Result<Vec<model:
    let roles = assembly::assemble_roles(&guild_members, &guild_roles, &config.roles_excluded);
    Ok(roles)
}

fn assemble_data(config: Config, roles: Vec<model::Role>) -> Data {
    Data {
        title: config.title,
        subtitle: config.subtitle,
        roles,
        generated_at: Utc::now(),
    }
}

M src/model.rs => src/model.rs +9 -0
@@ 4,6 4,7 @@
 */

use anyhow::Result;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::io::Write;
use std::path::PathBuf;


@@ 11,6 12,14 @@ use std::path::PathBuf;
use crate::io;

#[derive(Deserialize, Serialize, Debug)]
pub(crate) struct Data {
    pub title: String,
    pub subtitle: Option<String>,
    pub roles: Vec<Role>,
    pub generated_at: DateTime<Utc>,
}

#[derive(Deserialize, Serialize, Debug)]
pub(crate) struct Role {
    pub name: String,
    pub member_names: Vec<String>,

M src/templating.rs => src/templating.rs +8 -15
@@ 4,12 4,11 @@
 */

use anyhow::Result;
use chrono::{DateTime, Utc};
use std::io::Write;
use std::sync::OnceLock;
use tera::{Context, Tera};

use crate::model::Role;
use crate::model::Data;

fn get_tera() -> &'static Tera {
    static TERA: OnceLock<Tera> = OnceLock::new();


@@ 24,18 23,12 @@ fn get_tera() -> &'static Tera {
}

/// Render roles as HTML representation.
pub(crate) fn render_html(
    title: String,
    subtitle: Option<String>,
    roles: Vec<Role>,
    generated_at: DateTime<Utc>,
    writer: impl Write,
) -> Result<()> {
pub(crate) fn render_html(data: Data, writer: impl Write) -> Result<()> {
    let mut context = Context::new();
    context.insert("roles", &roles);
    context.insert("title", &title);
    context.insert("subtitle", &subtitle);
    context.insert("generated_at", &generated_at);
    context.insert("roles", &data.roles);
    context.insert("title", &data.title);
    context.insert("subtitle", &data.subtitle);
    context.insert("generated_at", &data.generated_at);

    render("index.html", &context, writer)?;



@@ 43,9 36,9 @@ pub(crate) fn render_html(
}

/// Render roles as text representation.
pub(crate) fn render_text(roles: Vec<Role>, writer: impl Write) -> Result<()> {
pub(crate) fn render_text(data: Data, writer: impl Write) -> Result<()> {
    let mut context = Context::new();
    context.insert("roles", &roles);
    context.insert("roles", &data.roles);

    render("index.txt", &context, writer)?;