aboutsummaryrefslogtreecommitdiff
path: root/src/main.rs
blob: 2968f2058e410331f3ad7f7ca52eade92385465f (plain) (blame)
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
use std::{sync::Mutex, time::Duration};

use dotenv::dotenv;
use sqlx::{postgres::PgPoolOptions, PgPool};
use tracing::{info, instrument};

type Error = Box<dyn std::error::Error + Send + Sync>;
type Context<'a> = poise::Context<'a, Data, Error>;

mod commands;
mod handler;
mod models;

pub struct Data {
    pg: Mutex<PgPool>,
}

/// Show help menu
#[poise::command(prefix_command, slash_command)]
async fn help(
    ctx: Context<'_>,
    #[description = "Command to get help for"] command: Option<String>,
) -> Result<(), Error> {
    poise::builtins::help(
        ctx,
        command.as_deref(),
        poise::builtins::HelpConfiguration::default(),
    )
    .await?;
    Ok(())
}

async fn on_error(error: poise::FrameworkError<'_, Data, Error>) {
    match error {
        poise::FrameworkError::Setup { error } => panic!("Failed to start bot: {:?}", error),
        poise::FrameworkError::Command { error, ctx } => {
            println!("Error in command {}: {:?}", ctx.command().name, error);
            ctx.say(format!("Whoops! Something went wrong: {:?}", error))
                .await
                .unwrap();
        }
        error => {
            if let Err(e) = poise::builtins::on_error(error).await {
                println!("Error handling error: {}", e);
            }
        }
    }
}

/// Register application commands in this guild or globally
///
/// Run with no arguments to register in guild, run with argument "global" to register globally.
#[poise::command(prefix_command, hide_in_help)]
async fn register(ctx: Context<'_>, #[flag] global: bool) -> Result<(), Error> {
    poise::builtins::register_application_commands(ctx, global).await?;

    Ok(())
}

#[tokio::main]
#[instrument]
async fn main() {
    dotenv().unwrap();
    tracing_subscriber::fmt::init();
    info!("Initialized logging");
    let options = poise::FrameworkOptions {
        commands: vec![
            help(),
            register(),
            commands::meta::ping(),
            commands::meta::about(),
            commands::meta::userinfo(),
            commands::actions::boop(),
            commands::actions::hug(),
            commands::pony::randpony(),
            commands::pony::tpony(),
            commands::pony::ponybyid(),
            commands::osu::osup(),
            commands::osu::osubm(),
            poise::Command {
                subcommands: vec![
                    commands::reactionroles::init(),
                    commands::reactionroles::add(),
                    commands::reactionroles::del(),
                ],
                ..commands::reactionroles::rroles()
            },
        ],
        on_error: |error| Box::pin(on_error(error)),
        pre_command: |ctx| {
            Box::pin(async move {
                println!("Executing command {}...", ctx.command().name);
            })
        },
        post_command: |ctx| {
            Box::pin(async move {
                println!("Done executing command {}!", ctx.command().name);
            })
        },

        prefix_options: poise::PrefixFrameworkOptions {
            prefix: Some("~".into()),
            edit_tracker: Some(poise::EditTracker::for_timespan(Duration::from_secs(3600))),
            additional_prefixes: vec![
                poise::Prefix::Literal("hey glitch"),
                poise::Prefix::Literal("hey glitch,"),
            ],
            ..Default::default()
        },
        listener: |ctx, event, _, data| Box::pin(handler::event_handler(ctx, event, data)),
        ..Default::default()
    };

    poise::Framework::build()
        .token(std::env::var("DISCORD_TOKEN").unwrap_or("BAD-TOKEN".into()))
        .user_data_setup(move |_ctx, _ready, _framework| {
            Box::pin(async move {
                let pool = PgPoolOptions::new()
                    .max_connections(5)
                    .connect(
                        &std::env::var("DATABASE_URL")
                            .unwrap_or("postgres://postgres@localhost/glitch".to_string()),
                    )
                    .await
                    .expect("Couldn't connect to postgresql");
                Ok(Data {
                    pg: Mutex::new(pool),
                })
            })
        })
        .options(options)
        .run()
        .await
        .unwrap();
}