Merge pull request #4 from ZyLacx/notices
Created cron job for events and birthdays announcements
This commit is contained in:
commit
961a7fd951
7 changed files with 102 additions and 62 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -10,4 +10,4 @@
|
||||||
# IDE config
|
# IDE config
|
||||||
.vscode
|
.vscode
|
||||||
|
|
||||||
mooverdb.db
|
mooverdb.db*
|
|
@ -8,8 +8,7 @@ edition = "2021"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
anyhow = "1.0.71"
|
anyhow = "1.0.71"
|
||||||
# tokio-cron-scheduler = "0.9.4"
|
tokio-cron-scheduler = "0.10.0"
|
||||||
tokio_schedule = "0.3.1"
|
|
||||||
dotenv = "0.15.0"
|
dotenv = "0.15.0"
|
||||||
# poise = "0.5.5"
|
# poise = "0.5.5"
|
||||||
serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model", "http", "cache"] }
|
serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model", "http", "cache"] }
|
||||||
|
|
49
src/main.rs
49
src/main.rs
|
@ -1,24 +1,23 @@
|
||||||
use std::sync::atomic::AtomicUsize;
|
|
||||||
|
|
||||||
use chrono::Utc;
|
|
||||||
use serenity::async_trait;
|
use serenity::async_trait;
|
||||||
use serenity::model::channel::Message;
|
use serenity::prelude::GatewayIntents;
|
||||||
use serenity::model::gateway::Ready;
|
|
||||||
use serenity::prelude::*;
|
|
||||||
use serenity::client::Context;
|
use serenity::client::Context;
|
||||||
|
use serenity::model::gateway::Ready;
|
||||||
|
use serenity::all::{Message, EventHandler};
|
||||||
|
use serenity::Client;
|
||||||
|
|
||||||
// use tokio_cron_scheduler::{JobScheduler, JobToRun, Job};
|
use tokio_cron_scheduler::{JobScheduler, Job};
|
||||||
use tokio_schedule::{every, EveryDay, Job};
|
|
||||||
use util::security::dotenv_var;
|
use util::security::dotenv_var;
|
||||||
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
mod message_handler;
|
mod message_handler;
|
||||||
use message_handler::handle;
|
use message_handler::handle;
|
||||||
|
|
||||||
|
use std::future::Future;
|
||||||
|
use std::pin::Pin;
|
||||||
|
|
||||||
|
// use chrono::Utc;
|
||||||
|
|
||||||
mod commands;
|
mod commands;
|
||||||
mod util;
|
mod util;
|
||||||
use util::debug::send_error;
|
|
||||||
|
|
||||||
mod other;
|
mod other;
|
||||||
use other::notice;
|
use other::notice;
|
||||||
|
@ -39,27 +38,17 @@ impl EventHandler for Handler {
|
||||||
hello(ctx.http.clone()).await;
|
hello(ctx.http.clone()).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
// notice::notice_wrapper(ctx).await;
|
let sched = JobScheduler::new().await.unwrap();
|
||||||
|
|
||||||
// let scheduler = every(1).day().at(13, 30, 0)
|
let job_closure = move |_, _| -> Pin<Box<dyn Future<Output = ()> + Send>> {
|
||||||
// .perform(|| async {
|
let ctx_clone = ctx.clone();
|
||||||
// notice::notice_wrapper(ctx.clone()).await
|
Box::pin( async move {
|
||||||
// }).await;
|
notice::notice_wrapper(ctx_clone).await;
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
// let mut scheduler = JobScheduler::new().await;
|
sched.add(Job::new_async("0 0 13 * * *", job_closure).expect("Cron job not set up correctly")).await.unwrap();
|
||||||
// scheduler.
|
sched.start().await.unwrap();
|
||||||
// scheduler.add(match Job::new_async("5 * * * * * *", |uuid, mut l| Box::pin( async {
|
|
||||||
// notice::notice(ctx.clone()).await;
|
|
||||||
// })) {
|
|
||||||
// Ok(_) => {}
|
|
||||||
// Err(e) => {
|
|
||||||
// send_error(ctx.http.clone(), e.to_string());
|
|
||||||
// panic!()
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// scheduler.add(Job::new(daily("22"), move || {
|
|
||||||
// notice::notice(ctx.clone())
|
|
||||||
// }));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,18 +1,20 @@
|
||||||
use chrono::{Datelike, Local};
|
use chrono::{Datelike, Local};
|
||||||
use serenity::{all::{GuildId, UserId}, http::Http, prelude::*};
|
|
||||||
|
|
||||||
use crate::util::debug::send_error;
|
use serenity::{all::{GuildId, UserId}, builder::{CreateEmbed, CreateMessage}, client::Context, http::Http, model::Colour};
|
||||||
|
|
||||||
use anyhow::Ok;
|
use anyhow::Ok;
|
||||||
|
|
||||||
use std::sync::Arc;
|
use sqlx::{Connection, FromRow, SqliteConnection};
|
||||||
|
|
||||||
use crate::util::security::dotenv_var;
|
use crate::util::security::dotenv_var;
|
||||||
|
use crate::util::debug::send_error;
|
||||||
|
use crate::util::utilities;
|
||||||
|
|
||||||
use sqlx::{FromRow, Connection, SqliteConnection};
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
// pub async fn notice_wrapper(http: Arc<Http>) {
|
||||||
pub async fn notice_wrapper(ctx: Context) {
|
pub async fn notice_wrapper(ctx: Context) {
|
||||||
match notice(ctx.clone()).await {
|
match notice(ctx.http.clone()).await {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
send_error(ctx.http.clone(), e.to_string()).await;
|
send_error(ctx.http.clone(), e.to_string()).await;
|
||||||
return;
|
return;
|
||||||
|
@ -21,44 +23,71 @@ pub async fn notice_wrapper(ctx: Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn announce_event(guild_id: GuildId, name: &str, special_message: &str, http: Arc<Http>) {
|
async fn announce_event(guild_id: GuildId, name: &str, special_message: &str, http: Arc<Http>) -> anyhow::Result<()> {
|
||||||
|
let mut event_embed = CreateEmbed::new()
|
||||||
|
.color(Colour::new(rand::random::<u32>() % 0xFFFFFF))
|
||||||
|
.title("Today's event is:");
|
||||||
|
|
||||||
|
let system_channel = utilities::get_system_channel(guild_id, http.clone()).await?;
|
||||||
|
|
||||||
|
if special_message.contains("http") {
|
||||||
|
event_embed = event_embed.description(name);
|
||||||
|
system_channel.send_message(http.clone(),
|
||||||
|
CreateMessage::new().add_embed(event_embed.clone()).content(special_message)).await?;
|
||||||
|
// Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn celebrate_birthday(guild_id: GuildId, user_id: UserId, nick: &str, http: Arc<Http>) {
|
event_embed = event_embed.field(name, special_message, true);
|
||||||
|
system_channel.send_message(http.clone(),
|
||||||
|
CreateMessage::new().add_embed(event_embed)).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn celebrate_birthday(guild_id: GuildId, user_id: UserId, nick: &str, http: Arc<Http>) -> anyhow::Result<()> {
|
||||||
|
let system_channel = utilities::get_system_channel(guild_id, http.clone()).await?;
|
||||||
|
|
||||||
|
let embed = CreateEmbed::new()
|
||||||
|
.color(Colour::new(rand::random::<u32>() % 0xFFFFFF))
|
||||||
|
.title(format!("HAPPY BIRTHDAY {}!", nick))
|
||||||
|
.description(format!("<@{}>'s birthday is today!!! Yay!", user_id.get()));
|
||||||
|
|
||||||
|
system_channel.send_message(http.clone(), CreateMessage::new().add_embed(embed.clone())).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, FromRow, Debug)]
|
#[derive(Clone, FromRow, Debug)]
|
||||||
struct BirthdayRow {
|
struct BirthdayRow {
|
||||||
#[sqlx(try_from="i64")]
|
#[sqlx(try_from="i64")]
|
||||||
id: u64,
|
id: u64,
|
||||||
day: u8,
|
|
||||||
month: u8,
|
|
||||||
nick: String,
|
nick: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, FromRow, Debug)]
|
#[derive(Clone, FromRow, Debug)]
|
||||||
struct EventRow {
|
struct EventRow {
|
||||||
|
id: u32,
|
||||||
#[sqlx(try_from="i64")]
|
#[sqlx(try_from="i64")]
|
||||||
guild: u64,
|
guild: u64,
|
||||||
name: String,
|
name: String,
|
||||||
day: u8,
|
year: i32,
|
||||||
month: u8,
|
|
||||||
special_message: String,
|
special_message: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn notice(ctx: serenity::client::Context) -> anyhow::Result<()> {
|
async fn notice(http: Arc<Http>) -> anyhow::Result<()> {
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
|
|
||||||
let local = Local::now();
|
let local = Local::now();
|
||||||
let day = local.day();
|
let day = local.day();
|
||||||
let month = local.month();
|
let month = local.month();
|
||||||
|
let year = local.year();
|
||||||
|
|
||||||
let db_path = dotenv_var("DATABASE_URL").context("DATABASE_URL not found in env")?;
|
let db_path = dotenv_var("DATABASE_URL").context("DATABASE_URL not found in env")?;
|
||||||
|
|
||||||
let mut db = SqliteConnection::connect(db_path.as_str()).await?;
|
let mut db = SqliteConnection::connect(db_path.as_str()).await?;
|
||||||
|
|
||||||
let birtdays = sqlx::query_as::<_, BirthdayRow>(
|
let birtdays = sqlx::query_as::<_, BirthdayRow>(
|
||||||
"SELECT * FROM birthdays
|
"SELECT id, nick FROM birthdays
|
||||||
WHERE day=? AND month=?;"
|
WHERE day=? AND month=?;"
|
||||||
)
|
)
|
||||||
.bind(day)
|
.bind(day)
|
||||||
|
@ -67,7 +96,7 @@ async fn notice(ctx: serenity::client::Context) -> anyhow::Result<()> {
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let global_events = sqlx::query_as::<_, EventRow>(
|
let global_events = sqlx::query_as::<_, EventRow>(
|
||||||
"SELECT guild, name, day, month, specialMessage from events
|
"SELECT id, guild, name, year, special_message from events
|
||||||
WHERE day=? AND month=? AND guild=0;"
|
WHERE day=? AND month=? AND guild=0;"
|
||||||
)
|
)
|
||||||
.bind(day)
|
.bind(day)
|
||||||
|
@ -75,25 +104,31 @@ async fn notice(ctx: serenity::client::Context) -> anyhow::Result<()> {
|
||||||
.fetch_all(&mut db)
|
.fetch_all(&mut db)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let guilds = ctx.http.get_guilds(None, None).await?;
|
let guilds = http.get_guilds(None, None).await?;
|
||||||
|
|
||||||
for guild in guilds {
|
for guild in guilds {
|
||||||
let guild_id = guild.id;
|
let guild_id = guild.id;
|
||||||
|
|
||||||
for bd in &birtdays {
|
for bd in &birtdays {
|
||||||
let user_id = UserId::new(bd.id);
|
let user_id = UserId::new(bd.id);
|
||||||
guild_id.member(ctx.http(), user_id).await?;
|
guild_id.member(http.clone(), user_id).await?;
|
||||||
|
|
||||||
celebrate_birthday(guild_id, user_id, bd.nick.as_str(), ctx.http.clone()).await;
|
celebrate_birthday(guild_id, user_id, bd.nick.as_str(), http.clone()).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO if has year delete it from announce and delete
|
||||||
|
|
||||||
for e in &global_events {
|
for e in &global_events {
|
||||||
announce_event(guild_id, e.name.as_str(), e.special_message.as_str(), ctx.http.clone()).await;
|
if e.year != 0 && e.year != year {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
announce_event(guild_id, e.name.as_str(), e.special_message.as_str(), http.clone()).await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let global_events = sqlx::query_as::<_, EventRow>(
|
let global_events = sqlx::query_as::<_, EventRow>(
|
||||||
"SELECT guild, name, day, month, specialMessage from events
|
"SELECT id, guild, name, year, special_message from events
|
||||||
WHERE day=? AND month=? AND guild!=0;"
|
WHERE day=? AND month=? AND guild!=0;"
|
||||||
)
|
)
|
||||||
.bind(day)
|
.bind(day)
|
||||||
|
@ -101,8 +136,10 @@ async fn notice(ctx: serenity::client::Context) -> anyhow::Result<()> {
|
||||||
.fetch_all(&mut db)
|
.fetch_all(&mut db)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
// TODO if has year delete it from announce and delete
|
||||||
|
|
||||||
for e in &global_events {
|
for e in &global_events {
|
||||||
announce_event(GuildId::new(e.guild), e.name.as_str(), e.special_message.as_str(), ctx.http.clone()).await;
|
announce_event(GuildId::new(e.guild), e.name.as_str(), e.special_message.as_str(), http.clone()).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -1,18 +1,22 @@
|
||||||
use serenity::{all::ChannelId, builder::CreateMessage, http::Http};
|
use std::sync::Arc;
|
||||||
use std::{process::exit, sync::Arc};
|
|
||||||
|
|
||||||
pub async fn send_error(http: Arc<Http>, msg: String) {
|
use serenity::http::Http;
|
||||||
|
|
||||||
|
pub async fn send_error(_http: Arc<Http>, msg: String) {
|
||||||
println!("ERROR: {msg}");
|
println!("ERROR: {msg}");
|
||||||
|
|
||||||
#[cfg(feature="RELEASE")]
|
#[cfg(feature="RELEASE")]
|
||||||
match ChannelId::new(1199495008416440491)
|
match ChannelId::new(1199495008416440491)
|
||||||
.send_message(http, CreateMessage::new().content(msg)).await {
|
.send_message(_http, CreateMessage::new().content(msg)).await {
|
||||||
Ok(_) => { return; }
|
Ok(_) => { return; }
|
||||||
Err(_) => { exit(-1) }
|
Err(_) => { exit(-1) }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature="RELEASE")]
|
||||||
pub async fn hello(http: Arc<Http>) {
|
pub async fn hello(http: Arc<Http>) {
|
||||||
|
use serenity::http::Http;
|
||||||
|
|
||||||
let messages = [
|
let messages = [
|
||||||
"AAAAAAAAAAAAAAAAAAAA",
|
"AAAAAAAAAAAAAAAAAAAA",
|
||||||
"Henlooo",
|
"Henlooo",
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
pub mod security;
|
pub mod security;
|
||||||
pub mod debug;
|
pub mod debug;
|
||||||
|
pub mod utilities;
|
|
@ -0,0 +1,10 @@
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use serenity::{all::{GuildId, ChannelId}, http::Http};
|
||||||
|
|
||||||
|
use anyhow::Context;
|
||||||
|
|
||||||
|
pub async fn get_system_channel(guild_id: GuildId, http: Arc<Http>) -> anyhow::Result<ChannelId> {
|
||||||
|
return http.get_guild(guild_id).await?.system_channel_id
|
||||||
|
.context(format!("System channel of guild: {} not found", guild_id.get()));
|
||||||
|
}
|
Loading…
Reference in a new issue