..
This commit is contained in:
		
							
								
								
									
										363
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										363
									
								
								src/main.rs
									
									
									
									
									
								
							@@ -29,7 +29,6 @@ use std::{
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
use chrono_tz::Tz;
 | 
			
		||||
use clap::Subcommand;
 | 
			
		||||
use log::warn;
 | 
			
		||||
use poise::serenity_prelude::{
 | 
			
		||||
    model::{
 | 
			
		||||
@@ -121,174 +120,224 @@ async fn _main(tx: Sender<()>) -> Result<(), Box<dyn StdError + Send + Sync>> {
 | 
			
		||||
        let _ = dotenv::dotenv();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let discord_token = env::var("DISCORD_TOKEN").expect("Missing DISCORD_TOKEN from environment");
 | 
			
		||||
 | 
			
		||||
    let options = poise::FrameworkOptions {
 | 
			
		||||
        commands: vec![
 | 
			
		||||
            help::command(),
 | 
			
		||||
            info::command(),
 | 
			
		||||
            clock::command(),
 | 
			
		||||
            donate::command(),
 | 
			
		||||
            clock_context_menu(),
 | 
			
		||||
            dashboard::command(),
 | 
			
		||||
            timezone::command(),
 | 
			
		||||
            poise::Command {
 | 
			
		||||
                subcommands: vec![allowed_dm::set::set(), allowed_dm::unset::unset()],
 | 
			
		||||
                ..allowed_dm::allowed_dm()
 | 
			
		||||
            },
 | 
			
		||||
            poise::Command {
 | 
			
		||||
                subcommands: vec![poise::Command {
 | 
			
		||||
                    subcommands: vec![
 | 
			
		||||
                        settings::ephemeral_confirmations::set::set(),
 | 
			
		||||
                        settings::ephemeral_confirmations::unset::unset(),
 | 
			
		||||
                    ],
 | 
			
		||||
                    ..settings::ephemeral_confirmations::ephemeral_confirmations()
 | 
			
		||||
                }],
 | 
			
		||||
                ..settings::settings()
 | 
			
		||||
            },
 | 
			
		||||
            webhook::command(),
 | 
			
		||||
            poise::Command {
 | 
			
		||||
                subcommands: vec![
 | 
			
		||||
                    command_macro::delete_macro::delete_macro(),
 | 
			
		||||
                    command_macro::finish_macro::finish_macro(),
 | 
			
		||||
                    command_macro::list_macro::list_macro(),
 | 
			
		||||
                    command_macro::record_macro::record_macro(),
 | 
			
		||||
                    command_macro::run_macro::run_macro(),
 | 
			
		||||
                ],
 | 
			
		||||
                ..command_macro::command_macro()
 | 
			
		||||
            },
 | 
			
		||||
            pause::command(),
 | 
			
		||||
            offset::command(),
 | 
			
		||||
            nudge::command(),
 | 
			
		||||
            look::command(),
 | 
			
		||||
            delete::command(),
 | 
			
		||||
            poise::Command {
 | 
			
		||||
                subcommands: vec![
 | 
			
		||||
                    timer::list::list(),
 | 
			
		||||
                    timer::start::start(),
 | 
			
		||||
                    timer::delete::delete(),
 | 
			
		||||
                ],
 | 
			
		||||
                ..timer::timer()
 | 
			
		||||
            },
 | 
			
		||||
            multiline::command(),
 | 
			
		||||
            remind::command(),
 | 
			
		||||
            poise::Command {
 | 
			
		||||
                subcommands: vec![
 | 
			
		||||
                    poise::Command {
 | 
			
		||||
                        subcommands: vec![todo::guild::add::add(), todo::guild::view::view()],
 | 
			
		||||
                        ..todo::guild::guild()
 | 
			
		||||
                    },
 | 
			
		||||
                    poise::Command {
 | 
			
		||||
                        subcommands: vec![todo::channel::add::add(), todo::channel::view::view()],
 | 
			
		||||
                        ..todo::channel::channel()
 | 
			
		||||
                    },
 | 
			
		||||
                    poise::Command {
 | 
			
		||||
                        subcommands: vec![todo::user::add::add(), todo::user::view::view()],
 | 
			
		||||
                        ..todo::user::user()
 | 
			
		||||
                    },
 | 
			
		||||
                ],
 | 
			
		||||
                ..todo::todo()
 | 
			
		||||
            },
 | 
			
		||||
        ],
 | 
			
		||||
        allowed_mentions: None,
 | 
			
		||||
        command_check: Some(|ctx| Box::pin(all_checks(ctx))),
 | 
			
		||||
        event_handler: |ctx, event, _framework, data| Box::pin(listener(ctx, event, data)),
 | 
			
		||||
        on_error: |error| {
 | 
			
		||||
            Box::pin(async move {
 | 
			
		||||
                match error {
 | 
			
		||||
                    poise::FrameworkError::CommandCheckFailed { .. } => {
 | 
			
		||||
                        // suppress error
 | 
			
		||||
                    }
 | 
			
		||||
                    error => {
 | 
			
		||||
                        if let Err(e) = poise::builtins::on_error(error).await {
 | 
			
		||||
                            log::error!("Error while handling error: {}", e);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            })
 | 
			
		||||
        },
 | 
			
		||||
        ..Default::default()
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // Start metrics
 | 
			
		||||
    init_metrics();
 | 
			
		||||
    let args = env::args().collect::<Vec<_>>();
 | 
			
		||||
    let cmd_word = args.last().map(|w| w.as_str());
 | 
			
		||||
 | 
			
		||||
    let database =
 | 
			
		||||
        Pool::connect(&env::var("DATABASE_URL").expect("No database URL provided")).await.unwrap();
 | 
			
		||||
 | 
			
		||||
    sqlx::migrate!().run(&database).await?;
 | 
			
		||||
    match cmd_word {
 | 
			
		||||
        Some("clean") => {
 | 
			
		||||
            let sent_clean_age = env::var("SENT_CLEAN_AGE")?;
 | 
			
		||||
            if sent_clean_age.is_empty() {
 | 
			
		||||
                panic!("No SENT_CLEAN_AGE")
 | 
			
		||||
            }
 | 
			
		||||
            sqlx::query!(
 | 
			
		||||
                "
 | 
			
		||||
                DELETE FROM reminders
 | 
			
		||||
                WHERE `utc_time` < NOW() - INTERVAL ? DAY
 | 
			
		||||
                    AND status != 'pending'
 | 
			
		||||
                ORDER BY `utc_time`
 | 
			
		||||
                LIMIT 1000
 | 
			
		||||
                ",
 | 
			
		||||
                sent_clean_age
 | 
			
		||||
            )
 | 
			
		||||
            .execute(&database)
 | 
			
		||||
            .await?;
 | 
			
		||||
 | 
			
		||||
    let popular_timezones = sqlx::query!(
 | 
			
		||||
        "
 | 
			
		||||
        SELECT IFNULL(timezone, 'UTC') AS timezone
 | 
			
		||||
        FROM users
 | 
			
		||||
        WHERE timezone IS NOT NULL
 | 
			
		||||
        GROUP BY timezone
 | 
			
		||||
        ORDER BY COUNT(timezone) DESC
 | 
			
		||||
        LIMIT 21
 | 
			
		||||
        "
 | 
			
		||||
    )
 | 
			
		||||
    .fetch_all(&database)
 | 
			
		||||
    .await
 | 
			
		||||
    .unwrap()
 | 
			
		||||
    .iter()
 | 
			
		||||
    .map(|t| t.timezone.parse::<Tz>().unwrap())
 | 
			
		||||
    .collect::<Vec<Tz>>();
 | 
			
		||||
            let total_clean_age = env::var("TOTAL_CLEAN_AGE");
 | 
			
		||||
            if let Ok(total_clean_age) = total_clean_age {
 | 
			
		||||
                sqlx::query!(
 | 
			
		||||
                    "
 | 
			
		||||
                    DELETE FROM reminders
 | 
			
		||||
                    WHERE `utc_time` < NOW() - INTERVAL ? DAY
 | 
			
		||||
                    ORDER BY `utc_time`
 | 
			
		||||
                    LIMIT 1000
 | 
			
		||||
                    ",
 | 
			
		||||
                    total_clean_age
 | 
			
		||||
                )
 | 
			
		||||
                .execute(&database)
 | 
			
		||||
                .await?;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
    let framework = poise::Framework::builder()
 | 
			
		||||
        .setup(move |ctx, _bot, framework| {
 | 
			
		||||
            Box::pin(async move {
 | 
			
		||||
                poise::builtins::register_globally(ctx, &framework.options().commands).await?;
 | 
			
		||||
            Ok(())
 | 
			
		||||
        }
 | 
			
		||||
        _ => {
 | 
			
		||||
            let discord_token =
 | 
			
		||||
                env::var("DISCORD_TOKEN").expect("Missing DISCORD_TOKEN from environment");
 | 
			
		||||
 | 
			
		||||
                let kill_tx = tx.clone();
 | 
			
		||||
                let kill_recv = tx.subscribe();
 | 
			
		||||
 | 
			
		||||
                let ctx1 = ctx.clone();
 | 
			
		||||
                let ctx2 = ctx.clone();
 | 
			
		||||
 | 
			
		||||
                let pool1 = database.clone();
 | 
			
		||||
                let pool2 = database.clone();
 | 
			
		||||
 | 
			
		||||
                let run_settings = env::var("DONTRUN").unwrap_or_else(|_| "".to_string());
 | 
			
		||||
 | 
			
		||||
                if !run_settings.contains("postman") {
 | 
			
		||||
                    tokio::spawn(async move {
 | 
			
		||||
                        match postman::initialize(kill_recv, ctx1, &pool1).await {
 | 
			
		||||
                            Ok(_) => {}
 | 
			
		||||
                            Err(e) => {
 | 
			
		||||
                                panic!("postman exiting: {}", e);
 | 
			
		||||
            let options = poise::FrameworkOptions {
 | 
			
		||||
                commands: vec![
 | 
			
		||||
                    help::command(),
 | 
			
		||||
                    info::command(),
 | 
			
		||||
                    clock::command(),
 | 
			
		||||
                    donate::command(),
 | 
			
		||||
                    clock_context_menu(),
 | 
			
		||||
                    dashboard::command(),
 | 
			
		||||
                    timezone::command(),
 | 
			
		||||
                    poise::Command {
 | 
			
		||||
                        subcommands: vec![allowed_dm::set::set(), allowed_dm::unset::unset()],
 | 
			
		||||
                        ..allowed_dm::allowed_dm()
 | 
			
		||||
                    },
 | 
			
		||||
                    poise::Command {
 | 
			
		||||
                        subcommands: vec![poise::Command {
 | 
			
		||||
                            subcommands: vec![
 | 
			
		||||
                                settings::ephemeral_confirmations::set::set(),
 | 
			
		||||
                                settings::ephemeral_confirmations::unset::unset(),
 | 
			
		||||
                            ],
 | 
			
		||||
                            ..settings::ephemeral_confirmations::ephemeral_confirmations()
 | 
			
		||||
                        }],
 | 
			
		||||
                        ..settings::settings()
 | 
			
		||||
                    },
 | 
			
		||||
                    webhook::command(),
 | 
			
		||||
                    poise::Command {
 | 
			
		||||
                        subcommands: vec![
 | 
			
		||||
                            command_macro::delete_macro::delete_macro(),
 | 
			
		||||
                            command_macro::finish_macro::finish_macro(),
 | 
			
		||||
                            command_macro::list_macro::list_macro(),
 | 
			
		||||
                            command_macro::record_macro::record_macro(),
 | 
			
		||||
                            command_macro::run_macro::run_macro(),
 | 
			
		||||
                        ],
 | 
			
		||||
                        ..command_macro::command_macro()
 | 
			
		||||
                    },
 | 
			
		||||
                    pause::command(),
 | 
			
		||||
                    offset::command(),
 | 
			
		||||
                    nudge::command(),
 | 
			
		||||
                    look::command(),
 | 
			
		||||
                    delete::command(),
 | 
			
		||||
                    poise::Command {
 | 
			
		||||
                        subcommands: vec![
 | 
			
		||||
                            timer::list::list(),
 | 
			
		||||
                            timer::start::start(),
 | 
			
		||||
                            timer::delete::delete(),
 | 
			
		||||
                        ],
 | 
			
		||||
                        ..timer::timer()
 | 
			
		||||
                    },
 | 
			
		||||
                    multiline::command(),
 | 
			
		||||
                    remind::command(),
 | 
			
		||||
                    poise::Command {
 | 
			
		||||
                        subcommands: vec![
 | 
			
		||||
                            poise::Command {
 | 
			
		||||
                                subcommands: vec![
 | 
			
		||||
                                    todo::guild::add::add(),
 | 
			
		||||
                                    todo::guild::view::view(),
 | 
			
		||||
                                ],
 | 
			
		||||
                                ..todo::guild::guild()
 | 
			
		||||
                            },
 | 
			
		||||
                            poise::Command {
 | 
			
		||||
                                subcommands: vec![
 | 
			
		||||
                                    todo::channel::add::add(),
 | 
			
		||||
                                    todo::channel::view::view(),
 | 
			
		||||
                                ],
 | 
			
		||||
                                ..todo::channel::channel()
 | 
			
		||||
                            },
 | 
			
		||||
                            poise::Command {
 | 
			
		||||
                                subcommands: vec![todo::user::add::add(), todo::user::view::view()],
 | 
			
		||||
                                ..todo::user::user()
 | 
			
		||||
                            },
 | 
			
		||||
                        ],
 | 
			
		||||
                        ..todo::todo()
 | 
			
		||||
                    },
 | 
			
		||||
                ],
 | 
			
		||||
                allowed_mentions: None,
 | 
			
		||||
                command_check: Some(|ctx| Box::pin(all_checks(ctx))),
 | 
			
		||||
                event_handler: |ctx, event, _framework, data| Box::pin(listener(ctx, event, data)),
 | 
			
		||||
                on_error: |error| {
 | 
			
		||||
                    Box::pin(async move {
 | 
			
		||||
                        match error {
 | 
			
		||||
                            poise::FrameworkError::CommandCheckFailed { .. } => {
 | 
			
		||||
                                // suppress error
 | 
			
		||||
                            }
 | 
			
		||||
                        };
 | 
			
		||||
                    });
 | 
			
		||||
                } else {
 | 
			
		||||
                    warn!("Not running postman");
 | 
			
		||||
                }
 | 
			
		||||
                            error => {
 | 
			
		||||
                                if let Err(e) = poise::builtins::on_error(error).await {
 | 
			
		||||
                                    log::error!("Error while handling error: {}", e);
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    })
 | 
			
		||||
                },
 | 
			
		||||
                ..Default::default()
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
                if !run_settings.contains("web") {
 | 
			
		||||
                    tokio::spawn(async move {
 | 
			
		||||
                        web::initialize(kill_tx, ctx2, pool2).await.unwrap();
 | 
			
		||||
                    });
 | 
			
		||||
                } else {
 | 
			
		||||
                    warn!("Not running web");
 | 
			
		||||
                }
 | 
			
		||||
            // Start metrics
 | 
			
		||||
            init_metrics();
 | 
			
		||||
 | 
			
		||||
                Ok(Data {
 | 
			
		||||
                    database,
 | 
			
		||||
                    popular_timezones,
 | 
			
		||||
                    recording_macros: Default::default(),
 | 
			
		||||
                    _broadcast: tx,
 | 
			
		||||
            sqlx::migrate!().run(&database).await?;
 | 
			
		||||
 | 
			
		||||
            let popular_timezones = sqlx::query!(
 | 
			
		||||
                "
 | 
			
		||||
                SELECT IFNULL(timezone, 'UTC') AS timezone
 | 
			
		||||
                FROM users
 | 
			
		||||
                WHERE timezone IS NOT NULL
 | 
			
		||||
                GROUP BY timezone
 | 
			
		||||
                ORDER BY COUNT(timezone) DESC
 | 
			
		||||
                LIMIT 21
 | 
			
		||||
                "
 | 
			
		||||
            )
 | 
			
		||||
            .fetch_all(&database)
 | 
			
		||||
            .await
 | 
			
		||||
            .unwrap()
 | 
			
		||||
            .iter()
 | 
			
		||||
            .map(|t| t.timezone.parse::<Tz>().unwrap())
 | 
			
		||||
            .collect::<Vec<Tz>>();
 | 
			
		||||
 | 
			
		||||
            let framework = poise::Framework::builder()
 | 
			
		||||
                .setup(move |ctx, _bot, framework| {
 | 
			
		||||
                    Box::pin(async move {
 | 
			
		||||
                        poise::builtins::register_globally(ctx, &framework.options().commands)
 | 
			
		||||
                            .await?;
 | 
			
		||||
 | 
			
		||||
                        let kill_tx = tx.clone();
 | 
			
		||||
                        let kill_recv = tx.subscribe();
 | 
			
		||||
 | 
			
		||||
                        let ctx1 = ctx.clone();
 | 
			
		||||
                        let ctx2 = ctx.clone();
 | 
			
		||||
 | 
			
		||||
                        let pool1 = database.clone();
 | 
			
		||||
                        let pool2 = database.clone();
 | 
			
		||||
 | 
			
		||||
                        let run_settings = env::var("DONTRUN").unwrap_or_else(|_| "".to_string());
 | 
			
		||||
 | 
			
		||||
                        if !run_settings.contains("postman") {
 | 
			
		||||
                            tokio::spawn(async move {
 | 
			
		||||
                                match postman::initialize(kill_recv, ctx1, &pool1).await {
 | 
			
		||||
                                    Ok(_) => {}
 | 
			
		||||
                                    Err(e) => {
 | 
			
		||||
                                        panic!("postman exiting: {}", e);
 | 
			
		||||
                                    }
 | 
			
		||||
                                };
 | 
			
		||||
                            });
 | 
			
		||||
                        } else {
 | 
			
		||||
                            warn!("Not running postman");
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        if !run_settings.contains("web") {
 | 
			
		||||
                            tokio::spawn(async move {
 | 
			
		||||
                                web::initialize(kill_tx, ctx2, pool2).await.unwrap();
 | 
			
		||||
                            });
 | 
			
		||||
                        } else {
 | 
			
		||||
                            warn!("Not running web");
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        Ok(Data {
 | 
			
		||||
                            database,
 | 
			
		||||
                            popular_timezones,
 | 
			
		||||
                            recording_macros: Default::default(),
 | 
			
		||||
                            _broadcast: tx,
 | 
			
		||||
                        })
 | 
			
		||||
                    })
 | 
			
		||||
                })
 | 
			
		||||
            })
 | 
			
		||||
        })
 | 
			
		||||
        .options(options)
 | 
			
		||||
        .build();
 | 
			
		||||
                .options(options)
 | 
			
		||||
                .build();
 | 
			
		||||
 | 
			
		||||
    let mut client = ClientBuilder::new(&discord_token, GatewayIntents::GUILDS)
 | 
			
		||||
        .framework(framework)
 | 
			
		||||
        .activity(ActivityData::watching("for /remind"))
 | 
			
		||||
        .await?;
 | 
			
		||||
            let mut client = ClientBuilder::new(&discord_token, GatewayIntents::GUILDS)
 | 
			
		||||
                .framework(framework)
 | 
			
		||||
                .activity(ActivityData::watching("for /remind"))
 | 
			
		||||
                .await?;
 | 
			
		||||
 | 
			
		||||
    client.start_autosharded().await?;
 | 
			
		||||
            client.start_autosharded().await?;
 | 
			
		||||
 | 
			
		||||
    Ok(())
 | 
			
		||||
            Ok(())
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user