Add birthdays and bring back task handling

This commit is contained in:
Joey Hines 2025-03-16 15:56:26 -06:00
parent da59ae0bc9
commit 699a02c642
Signed by: joeyahines
GPG Key ID: 38BA6F25C94C9382
3 changed files with 76 additions and 89 deletions

View File

@ -1,33 +1,19 @@
use crate::discord::Context;
use crate::error::Error;
use crate::models::birthday::BirthdayEntry;
use crate::{command, group, GlobalData};
use rand::{thread_rng, Rng};
use serenity::client::Context;
use serenity::framework::standard::{Args, CommandResult};
use serenity::model::channel::Message;
use serenity::model::id::UserId;
use serenity::utils::MessageBuilder;
use poise::serenity_prelude::model::id::UserId;
use poise::serenity_prelude::utils::MessageBuilder;
use rand::{rng, Rng};
#[group]
#[commands(add_birthday, list_birthdays)]
pub struct Birthday;
#[command]
#[description("Add your birthday to the bot. Please use American dates or i will cut u.")]
#[example("add_birthday 04/21/1997")]
pub async fn add_birthday(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
if args.is_empty() {
msg.reply(
&ctx.http,
"Look just give me a day, doesn't matter. I'm not the IRS",
)
.await?;
return Ok(());
}
let date_split: Vec<&str> = args.rest().split('/').collect();
#[poise::command(prefix_command, category = "Birthdays")]
pub async fn add_birthday(
ctx: Context<'_>,
#[description = "date in the form of mm/dd/yyyy"] date: String,
) -> Result<(), Error> {
let date_split: Vec<&str> = date.split('/').collect();
if date_split.len() < 3 {
msg.reply(&ctx.http, "Try again with a real date").await?;
ctx.reply("Try again with a real date, liberal").await?;
return Ok(());
}
@ -36,43 +22,31 @@ pub async fn add_birthday(ctx: &Context, msg: &Message, args: Args) -> CommandRe
let year: i32 = date_split[2].parse().unwrap_or(0);
if month == 0 || day == 0 || year == 0 {
msg.reply(&ctx.http, "Try again with a real date").await?;
ctx.reply("Try again with a real date, commie").await?;
return Ok(());
}
if let Some(date) = chrono::NaiveDate::from_ymd_opt(year, month, day) {
let data = ctx.data.read().await;
let global_data = data.get::<GlobalData>().unwrap();
BirthdayEntry::add_birthday(&ctx.data().db, ctx.author().id.get(), date)?;
BirthdayEntry::add_birthday(&global_data.db, msg.author.id.get(), date)?;
msg.reply(
&ctx.http,
format!(
ctx.reply(format!(
"Thank you subject #{}, I am now {}% closer to making a full AI replica of you.",
msg.author.id.get(),
thread_rng().gen_range(0.0..100.0)
),
)
ctx.author().id.get(),
rng().random_range(0.0..100.0)
))
.await?;
} else {
msg.reply(&ctx.http, "Try again with a real date").await?;
ctx.reply("Try again with a real date, time wizard").await?;
return Ok(());
}
Ok(())
}
#[command]
#[description("Add your birthday to the bot. Please use American dates or i will cut u.")]
pub async fn list_birthdays(ctx: &Context, msg: &Message) -> CommandResult {
let data = ctx.data.read().await;
let global_data = data.get::<GlobalData>().unwrap();
let birthdays: Vec<BirthdayEntry> = global_data
.db
.filter(|_, _: &BirthdayEntry| true)?
.collect();
#[poise::command(prefix_command, category = "Birthdays")]
pub async fn list_birthdays(ctx: Context<'_>) -> Result<(), Error> {
let birthdays: Vec<BirthdayEntry> =
ctx.data().db.filter(|_, _: &BirthdayEntry| true)?.collect();
let mut msg_builder = MessageBuilder::new();
@ -80,7 +54,7 @@ pub async fn list_birthdays(ctx: &Context, msg: &Message) -> CommandResult {
for birthday in birthdays {
let user_id = UserId::from(birthday.discord_id);
let user = user_id.to_user(&ctx.http).await?;
let user = user_id.to_user(ctx).await?;
msg_builder.push_line(format!(
"* {} {}",
@ -89,7 +63,7 @@ pub async fn list_birthdays(ctx: &Context, msg: &Message) -> CommandResult {
));
}
msg.reply(&ctx.http, msg_builder.build()).await?;
ctx.reply(msg_builder.build()).await?;
Ok(())
}

View File

@ -1,26 +1,42 @@
mod admin;
mod album;
mod birthday;
mod celeryman;
use crate::config::GlobalData;
use crate::error::Error;
use log::info;
use magick_rust::bindings::wchar_t;
use std::sync::Arc;
use std::time::Duration;
use crate::models::task::Task;
use poise::serenity_prelude::Message;
use poise::{find_command, serenity_prelude as serenity, FrameworkOptions};
pub type Context<'a> = poise::Context<'a, GlobalData, Error>;
pub type Context<'a> = poise::Context<'a, Arc<GlobalData>, Error>;
async fn event_handler(
ctx: &serenity::Context,
event: &serenity::FullEvent,
framework: poise::FrameworkContext<'_, GlobalData, Error>,
data: &GlobalData,
framework: poise::FrameworkContext<'_, Arc<GlobalData>, Error>,
data: &Arc<GlobalData>,
) -> Result<(), Error> {
match event {
serenity::FullEvent::Ready { data_about_bot, .. } => {
info!("Bot ready, and logged in as {}", data_about_bot.user.name);
{
let data = data.clone();
let ctx = ctx.clone();
tokio::spawn(async move {
let _ = Task::create_reoccurring_tasks(&data).await.is_ok();
loop {
let _ = Task::run_tasks(&ctx, &data).await.is_ok();
tokio::time::sleep(Duration::from_secs(5)).await;
}
});
}
}
serenity::FullEvent::Message { new_message } => {
if new_message.content.starts_with("!") {
@ -79,7 +95,7 @@ async fn pre_command(ctx: Context<'_>) {
}
pub async fn run_bot(global_data: GlobalData) {
let framework_options: FrameworkOptions<GlobalData, Error> = poise::FrameworkOptions {
let framework_options: FrameworkOptions<Arc<GlobalData>, Error> = poise::FrameworkOptions {
prefix_options: poise::PrefixFrameworkOptions {
prefix: Some("!".into()),
ignore_bots: true,
@ -88,9 +104,6 @@ pub async fn run_bot(global_data: GlobalData) {
..Default::default()
},
commands: vec![
celeryman::nudetayne(),
celeryman::celeryman(),
celeryman::tayne(),
admin::dump_db(),
admin::load_db(),
admin::add_key(),
@ -101,6 +114,11 @@ pub async fn run_bot(global_data: GlobalData) {
admin::list_tasks(),
album::add_image(),
album::list_albums(),
birthday::add_birthday(),
birthday::list_birthdays(),
celeryman::nudetayne(),
celeryman::celeryman(),
celeryman::tayne(),
],
event_handler: |ctx, event, framework, data| {
Box::pin(event_handler(ctx, event, framework, data))
@ -116,7 +134,7 @@ pub async fn run_bot(global_data: GlobalData) {
.setup(move |ctx, _ready, framework| {
Box::pin(async move {
poise::builtins::register_globally(ctx, &framework.options().commands).await?;
Ok(global_data)
Ok(Arc::new(global_data))
})
})
.build();

View File

@ -1,4 +1,5 @@
use crate::config::GlobalData;
use std::sync::Arc;
//use crate::discord::shop::restock_shop;
use crate::discord::Context;
use crate::error::Error;
@ -80,11 +81,11 @@ impl Task {
Ok(())
}
pub async fn create_reoccurring_tasks(ctx: Context<'_>) -> Result<(), Error> {
Task::add_task(&ctx.data().db, TaskType::CheckBirthdays, Utc::now())?;
Task::add_task(&ctx.data().db, TaskType::RestockShop, Utc::now())?;
pub async fn create_reoccurring_tasks(data: &Arc<GlobalData>) -> Result<(), Error> {
Task::add_task(&data.db, TaskType::CheckBirthdays, Utc::now())?;
Task::add_task(&data.db, TaskType::RestockShop, Utc::now())?;
Task::add_task(
&ctx.data().db,
&data.db,
TaskType::HandleReload,
Utc::now() + Duration::hours(1),
)?;
@ -92,9 +93,11 @@ impl Task {
Ok(())
}
pub async fn run_tasks(ctx: Context<'_>) -> Result<(), Error> {
let active_tasks: Vec<Task> = ctx
.data()
pub async fn run_tasks(
ctx: &poise::serenity_prelude::Context,
data: &Arc<GlobalData>,
) -> Result<(), Error> {
let active_tasks: Vec<Task> = data
.db
.filter(|_, task: &Task| task.time < Utc::now())?
.collect();
@ -102,43 +105,35 @@ impl Task {
for task in active_tasks {
match task.task_type {
TaskType::RemoveRole { user_id, role_id } => {
let user = ctx.data().cfg.guild_id.member(ctx.http(), user_id).await?;
let user = data.cfg.guild_id.member(&ctx.http, user_id).await?;
info!("Removing role {} from {}", role_id, user.display_name());
user.remove_role(ctx.http(), role_id).await?;
user.remove_role(&ctx.http, role_id).await?;
}
TaskType::CheckBirthdays => {
info!("Checking Birthdays");
let todays_birthdays = BirthdayEntry::todays_birthdays(
&ctx.data().db,
chrono::Utc::now().date_naive(),
)?;
let todays_birthdays =
BirthdayEntry::todays_birthdays(&data.db, chrono::Utc::now().date_naive())?;
for birth in todays_birthdays {
if let Ok(user) = ctx
.data()
.cfg
.guild_id
.member(ctx.http(), birth.discord_id)
.await
if let Ok(user) =
data.cfg.guild_id.member(&ctx.http, birth.discord_id).await
{
ctx.data()
.cfg
data.cfg
.announcement_channel
.say(ctx.http(), format!("Happy birthday {}!", user.mention()))
.say(&ctx.http, format!("Happy birthday {}!", user.mention()))
.await?;
let compliment = RandomResponseTemplate::get_random_response(
&ctx.data().db,
&data.db,
ResponseType::Compliment,
user.display_name(),
)?
.unwrap_or("I couldn't think of anything funny tbh...".to_string());
ctx.data()
.cfg
data.cfg
.announcement_channel
.say(ctx.http(), compliment)
.say(&ctx.http, compliment)
.await?;
}
}
@ -155,7 +150,7 @@ impl Task {
.unwrap();
Task::add_task(
&ctx.data().db,
&data.db,
TaskType::CheckBirthdays,
next_check.with_timezone(&Utc),
)?;
@ -173,14 +168,14 @@ impl Task {
// }
Task::add_task(
&ctx.data().db,
&data.db,
TaskType::RestockShop,
Utc::now() + Duration::hours(1),
)?;
}
}
let _ = ctx.data().db.remove::<Task>(task.id().unwrap()).is_ok();
let _ = data.db.remove::<Task>(task.id().unwrap()).is_ok();
}
Ok(())