aboutsummaryrefslogtreecommitdiff
path: root/src/bin/lambo.rs
blob: 6b5f349338e0614f53b7920d6862c57ae13a64cd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
use anyhow::{Context as _, Result};
use clap::{value_parser, ArgAction, Parser};
use lambo::{config::Config, handlers::*};
use serenity::{all::GatewayIntents, Client};
use sqlx::sqlite::SqlitePoolOptions;
use std::{path::PathBuf, sync::Arc};

#[derive(Debug, Parser)]
struct Args {
    /// The path to the lambo configuration file.
    config_path: PathBuf,

    /// Decreases the log level.
    #[clap(
        short,
        long,
        conflicts_with("verbose"),
        action = ArgAction::Count,
        value_parser = value_parser!(u8).range(..=2)
    )]
    quiet: u8,

    /// Increases the log level.
    #[clap(
        short,
        long,
        conflicts_with("quiet"),
        action = ArgAction::Count,
        value_parser = value_parser!(u8).range(..=3)
    )]
    verbose: u8,
}

#[tokio::main]
async fn main() -> Result<()> {
    // Parse the arguments.
    let args = Args::parse();

    // Set up logging.
    lambo::configure_logger(args.quiet, args.verbose)?;

    // Parse the config file.
    let config = Config::read_from_file(&args.config_path)?;

    // Connect to the database.
    let db = SqlitePoolOptions::new()
        .connect(&config.database_url)
        .await
        .with_context(|| format!("failed to connect to database at {:?}", config.database_url))?;

    // Run any necessary migrations.
    sqlx::migrate!().run(&db).await.with_context(|| {
        format!(
            "failed to run migrations on database at {:?}",
            config.database_url
        )
    })?;

    // Create the handlers.
    let handler = MultiHandler(vec![
        Box::new(Commands {
            config: config.commands,
            db: db.clone(),
        }),
        Box::new(PresenceSetter),
        Box::new(X500Mapper {
            config: Arc::new(config.x500_mapper),
            db,
        }),
    ]);

    // Start up the client.
    let intents = GatewayIntents::default() | GatewayIntents::GUILD_MEMBERS;
    Client::builder(&config.discord_token, intents)
        .event_handler(handler)
        .await
        .context("failed to create Discord client")?
        .start()
        .await
        .context("failed to start Discord client")?;

    Ok(())
}