Added birthday reminders
+ clippy + fmt
This commit is contained in:
@@ -6,6 +6,7 @@ use config::{Config, File};
|
||||
use j_db::database::Database;
|
||||
use rand::prelude::SliceRandom;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serenity::model::id::ChannelId;
|
||||
use serenity::model::prelude::{GuildId, UserId};
|
||||
use serenity::prelude::TypeMapKey;
|
||||
use std::collections::HashMap;
|
||||
@@ -33,6 +34,7 @@ pub struct BotConfig {
|
||||
pub admins: Vec<UserId>,
|
||||
pub guild_id: GuildId,
|
||||
pub api_addr: SocketAddr,
|
||||
pub announcement_channel: ChannelId,
|
||||
}
|
||||
|
||||
impl BotConfig {
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
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;
|
||||
|
||||
#[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();
|
||||
|
||||
if date_split.len() < 3 {
|
||||
msg.reply(&ctx.http, "Try again with a real date").await?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let month: u32 = date_split[0].parse().unwrap_or(0);
|
||||
let day: u32 = date_split[1].parse().unwrap_or(0);
|
||||
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?;
|
||||
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(&global_data.db, msg.author.id.0, date)?;
|
||||
|
||||
msg.reply(
|
||||
&ctx.http,
|
||||
format!(
|
||||
"Thank you subject #{}, I am now {}% closer to making a full AI replica of you.",
|
||||
msg.author.id.0,
|
||||
thread_rng().gen_range(0.0..100.0)
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
} else {
|
||||
msg.reply(&ctx.http, "Try again with a real date").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();
|
||||
|
||||
let mut msg_builder = MessageBuilder::new();
|
||||
|
||||
msg_builder.push_bold_line("All the birthdays I know:");
|
||||
for birthday in birthdays {
|
||||
let user = msg
|
||||
.guild(&ctx.cache)
|
||||
.unwrap()
|
||||
.member(&ctx.http, UserId::from(birthday.discord_id))
|
||||
.await?;
|
||||
msg_builder.push_line(format!(
|
||||
"* {} {}",
|
||||
user.display_name(),
|
||||
birthday.birthday.format("%m-%d-%Y")
|
||||
));
|
||||
}
|
||||
|
||||
msg.reply(&ctx.http, msg_builder.build()).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
+56
-1
@@ -1,5 +1,6 @@
|
||||
pub mod admin;
|
||||
pub mod album;
|
||||
pub mod birthday;
|
||||
pub mod celeryman;
|
||||
pub mod color;
|
||||
pub mod emoji_race;
|
||||
@@ -14,7 +15,10 @@ 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::{help, hook, GlobalData};
|
||||
use chrono::{Days, TimeZone, Timelike, Utc};
|
||||
use rand::prelude::IteratorRandom;
|
||||
use rand::thread_rng;
|
||||
use serenity::async_trait;
|
||||
@@ -26,7 +30,7 @@ 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;
|
||||
use serenity::prelude::{EventHandler, Mentionable};
|
||||
use std::collections::HashSet;
|
||||
use std::time::Duration;
|
||||
|
||||
@@ -39,12 +43,63 @@ static ERROR_MSG: &str =
|
||||
impl EventHandler for Handler {
|
||||
async fn cache_ready(&self, ctx: Context, _guilds: Vec<GuildId>) {
|
||||
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;
|
||||
{
|
||||
{
|
||||
|
||||
@@ -59,6 +59,7 @@ async fn main() {
|
||||
.group(&discord::motivate::MOTIVATE_GROUP)
|
||||
.group(&discord::voices::VOICES_GROUP)
|
||||
.group(&discord::shop::SHOP_GROUP)
|
||||
.group(&discord::birthday::BIRTHDAY_GROUP)
|
||||
.unrecognised_command(unrecognised_command_hook)
|
||||
.bucket("bad_apple", |b| b.delay(60 * 10))
|
||||
.await
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
use crate::error::Error;
|
||||
use chrono::Datelike;
|
||||
use j_db::database::Database;
|
||||
use j_db::model::JdbModel;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||
pub struct BirthdayEntry {
|
||||
id: Option<u64>,
|
||||
pub discord_id: u64,
|
||||
pub birthday: chrono::NaiveDate,
|
||||
}
|
||||
|
||||
impl BirthdayEntry {
|
||||
pub fn add_birthday(
|
||||
db: &Database,
|
||||
discord_id: u64,
|
||||
birthday: chrono::NaiveDate,
|
||||
) -> Result<(), Error> {
|
||||
let mut entry = db
|
||||
.filter(|_, entry: &BirthdayEntry| entry.discord_id == discord_id)?
|
||||
.next()
|
||||
.unwrap_or(BirthdayEntry {
|
||||
id: None,
|
||||
discord_id,
|
||||
birthday,
|
||||
});
|
||||
|
||||
entry.birthday = birthday;
|
||||
|
||||
db.insert(entry)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn todays_birthdays(
|
||||
db: &Database,
|
||||
date: chrono::NaiveDate,
|
||||
) -> Result<Vec<BirthdayEntry>, Error> {
|
||||
let birthdays: Vec<BirthdayEntry> = db
|
||||
.filter(|_, entry: &BirthdayEntry| {
|
||||
entry.birthday.month() == date.month() && entry.birthday.day() == date.day()
|
||||
})?
|
||||
.collect();
|
||||
|
||||
Ok(birthdays)
|
||||
}
|
||||
}
|
||||
|
||||
impl JdbModel for BirthdayEntry {
|
||||
fn id(&self) -> Option<u64> {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn set_id(&mut self, id: u64) {
|
||||
self.id = Some(id)
|
||||
}
|
||||
|
||||
fn tree() -> String {
|
||||
"Birthday".to_string()
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
pub mod album;
|
||||
pub mod api_key;
|
||||
pub mod birthday;
|
||||
pub mod insult_compliment;
|
||||
pub mod motivation;
|
||||
pub mod random;
|
||||
|
||||
Reference in New Issue
Block a user