2023-07-07 19:47:03 -06:00

271 lines
8.7 KiB
Rust

pub mod admin;
pub mod album;
pub mod birthday;
pub mod celeryman;
pub mod color;
pub mod emoji_race;
pub mod fren_coin;
pub mod joke;
pub mod little_fren;
pub mod motivate;
pub mod shop;
pub mod story;
pub mod voices;
use crate::api::web_server;
use crate::discord::fren_coin::give_coin;
use crate::discord::joke::random;
use crate::discord::shop::restock_shop;
use crate::models::birthday::BirthdayEntry;
use crate::models::insult_compliment::{RandomResponseTemplate, ResponseType};
use crate::models::lil_fren::lil_fren_task;
use crate::{help, hook, GlobalData};
use chrono::{Days, TimeZone, Timelike, Utc};
use rand::prelude::IteratorRandom;
use rand::thread_rng;
use serenity::async_trait;
use serenity::client::Context;
use serenity::framework::standard::{
help_commands, Args, CommandGroup, CommandResult, HelpOptions,
};
use serenity::model::channel::{Message, ReactionType};
use serenity::model::gateway::Activity;
use serenity::model::id::UserId;
use serenity::model::prelude::{GuildId, OnlineStatus, Ready};
use serenity::prelude::{EventHandler, Mentionable};
use std::collections::HashSet;
use std::time::Duration;
pub struct Handler;
static ERROR_MSG: &str =
"OOPSIE WOOPSIE!! Uwu We made a fucky wucky!! A wittle fucko boingo! The admins at our headquarters are working VEWY HAWD to fix this!";
#[async_trait]
impl EventHandler for Handler {
async fn cache_ready(&self, ctx: Context, _guilds: Vec<GuildId>) {
let ctx1 = ctx.clone();
tokio::spawn(async move {
loop {
lil_fren_task(&ctx1).await;
}
});
tokio::spawn(async move {
let mut next_check = chrono_tz::America::Chicago
.from_utc_datetime(&Utc::now().naive_utc())
.checked_sub_days(Days::new(1))
.unwrap();
loop {
{
println!("Restocking shop...");
restock_shop(&ctx).await.unwrap();
}
{
let now =
chrono_tz::America::Chicago.from_utc_datetime(&Utc::now().naive_utc());
if now >= next_check {
let data = ctx.data.read().await;
let global_data = data.get::<GlobalData>().unwrap();
let todays_birthdays =
BirthdayEntry::todays_birthdays(&global_data.db, now.date_naive())
.unwrap();
for birth in todays_birthdays {
if let Ok(user) = global_data
.cfg
.guild_id
.member(&ctx.http, birth.discord_id)
.await
{
global_data
.cfg
.announcement_channel
.say(&ctx.http, format!("Happy birthday {}!", user.mention()))
.await
.unwrap();
let compliment = RandomResponseTemplate::get_random_response(
&global_data.db,
ResponseType::Compliment,
user.display_name().as_str(),
)
.unwrap()
.unwrap();
global_data
.cfg
.announcement_channel
.say(&ctx.http, compliment)
.await
.unwrap();
}
}
next_check = next_check
.with_hour(7)
.unwrap()
.checked_add_days(Days::new(1))
.unwrap();
}
}
tokio::time::sleep(Duration::from_secs(60 * 60)).await;
{
{
println!("Reloading config...");
let mut data = ctx.data.write().await;
let global_data = data.get_mut::<GlobalData>().unwrap();
global_data.reload().await.unwrap();
}
}
}
});
}
async fn message(&self, ctx: Context, new_message: Message) {
if new_message.author.bot {
return;
}
if new_message.guild_id.is_none() {
return;
}
if new_message.content.eq_ignore_ascii_case("yes")
|| new_message.content.eq_ignore_ascii_case("mhmm")
{
let mut data = ctx.data.write().await;
let global_data = data.get_mut::<GlobalData>().unwrap();
if let Some(u) = global_data.bot_state.accepted_nsfw {
if new_message.author.id == u {
new_message.reply(&ctx.http, "||https://cdn.discordapp.com/attachments/614891432079130625/1041545254362423368/unknown.png||").await.unwrap();
global_data.bot_state.accepted_nsfw = None;
}
}
}
if new_message.content.to_lowercase().contains("good bot") {
let recv_coin = give_coin(&ctx, new_message.author.id, 0.50, 25)
.await
.unwrap();
if recv_coin {
let emojis = new_message.guild(&ctx.cache).unwrap().emojis;
let emoji = {
let mut rng = thread_rng();
emojis.iter().choose(&mut rng)
};
if let Some(emoji) = emoji {
new_message
.react(
&ctx.http,
ReactionType::Custom {
animated: emoji.1.animated,
id: emoji.1.id,
name: Some(emoji.1.name.clone()),
},
)
.await
.unwrap();
}
}
}
if new_message.content.to_lowercase().contains("bad bot") {
new_message.react(&ctx.http, '😭').await.unwrap();
}
give_coin(&ctx, new_message.author.id, 0.05, 10)
.await
.unwrap();
}
async fn ready(&self, ctx: Context, ready: Ready) {
println!("Connected as {}", ready.user.name);
ctx.set_presence(
Some(Activity::listening("to your deepest secrets")),
OnlineStatus::Online,
)
.await;
tokio::spawn(async move { web_server(ctx).await });
}
}
#[hook]
pub async fn after(
ctx: &Context,
msg: &Message,
command_name: &str,
command_result: CommandResult,
) {
match command_result {
Ok(()) => {
println!("Processed command '{}'", command_name);
let data = ctx.data.read().await;
let global_data = data.get::<GlobalData>().unwrap();
global_data.db.db.flush_async().await.unwrap();
}
Err(why) => {
println!("Command '{}' returned error {:?}", command_name, why);
msg.reply(
&ctx.http,
format!("{} (Error in command {})", ERROR_MSG, command_name),
)
.await
.unwrap();
}
}
}
#[hook]
pub async fn unrecognised_command_hook(
ctx: &Context,
msg: &Message,
unrecognised_command_name: &str,
) {
let contents_split: Vec<&str> = msg.content.split(' ').collect();
let tags = if contents_split.len() > 1 {
contents_split[1..].to_vec()
} else {
Vec::new()
};
let parsed_album = match album::parse_album(ctx, msg, unrecognised_command_name, tags).await {
Ok(parsed) => parsed,
Err(e) => {
println!("Error processing album command: {}", e);
true
}
};
if !parsed_album {
match random(ctx, msg, unrecognised_command_name).await {
Ok(_) => {}
Err(e) => println!("Error processing random command: {}", e),
}
}
give_coin(ctx, msg.author.id, 0.5, 10).await.unwrap();
}
#[help]
pub async fn my_help(
context: &Context,
msg: &Message,
args: Args,
help_options: &'static HelpOptions,
groups: &[&'static CommandGroup],
owners: HashSet<UserId>,
) -> CommandResult {
let _ = help_commands::with_embeds(context, msg, args, help_options, groups, owners).await;
Ok(())
}