make events a module; guild name changes, misc
This commit is contained in:
@@ -1,166 +0,0 @@
|
|||||||
use super::events;
|
|
||||||
use chrono::{Datelike, Duration, Local, TimeZone, Utc};
|
|
||||||
use chrono_tz::Europe::Warsaw;
|
|
||||||
use serenity::all::{Context, CreateAttachment, EditGuild, Guild, GuildId};
|
|
||||||
use std::time::Duration as StdDuration;
|
|
||||||
use tracing::{error, info, warn};
|
|
||||||
|
|
||||||
const MAIN_GUILD_ID: GuildId = GuildId::new(447075692664979466);
|
|
||||||
|
|
||||||
pub enum Event {
|
|
||||||
Normal,
|
|
||||||
PolskaGórą,
|
|
||||||
PrideMonth,
|
|
||||||
ValentineDay,
|
|
||||||
Rogaliki,
|
|
||||||
Halloween,
|
|
||||||
Christmas,
|
|
||||||
NewYears,
|
|
||||||
AnniversaryGractwo,
|
|
||||||
AnniversaryTF2,
|
|
||||||
AnniversaryMinecraft,
|
|
||||||
StarWarsDay,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Event {
|
|
||||||
pub fn icon(&self) -> &str {
|
|
||||||
use Event as E;
|
|
||||||
match self {
|
|
||||||
E::PolskaGórą => "./assets/logo-x512-polish.png",
|
|
||||||
E::PrideMonth => "./assets/logo-x512-lgbtflag.png",
|
|
||||||
E::StarWarsDay => "./assets/logo-x512-starwars.png",
|
|
||||||
_ => "./assets/logo-x512.png",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn guild_name(&self) -> String {
|
|
||||||
use Event as E;
|
|
||||||
match self {
|
|
||||||
E::PolskaGórą => "Gractwo 🇵🇱".into(),
|
|
||||||
E::PrideMonth => "Gractwo 🏳️🌈".into(),
|
|
||||||
E::ValentineDay => "Gractwo 💗".into(),
|
|
||||||
E::Rogaliki => "Rogalictwo 🥐".into(),
|
|
||||||
E::Halloween => "Spooky Gractwo 🎃".into(),
|
|
||||||
E::Christmas => "Jolly Gractwo 🎄🎁☃️".into(),
|
|
||||||
E::NewYears => "New Gractwo, New Me 🎉".into(),
|
|
||||||
E::AnniversaryTF2 => "Polscy Gracze Team Fortress".into(),
|
|
||||||
E::AnniversaryGractwo => {
|
|
||||||
// TODO: this will conjugate badly in 17 years
|
|
||||||
let xlecie = Utc::now().year_ce().1 - 2020;
|
|
||||||
format!("{xlecie} lat Gractwa!")
|
|
||||||
}
|
|
||||||
_ => "Gractwo".into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_current_event() -> Event {
|
|
||||||
let today = Local::now();
|
|
||||||
let (month, day) = (today.month(), today.day());
|
|
||||||
|
|
||||||
match (day, month) {
|
|
||||||
(1, 1) => Event::NewYears,
|
|
||||||
(2..=6, 1) => Event::Christmas,
|
|
||||||
(14, 2) => Event::ValentineDay,
|
|
||||||
(1..=3, 5) => Event::PolskaGórą,
|
|
||||||
(4, 5) => Event::StarWarsDay,
|
|
||||||
(17, 5) => Event::AnniversaryMinecraft,
|
|
||||||
(7, 6) => Event::AnniversaryGractwo,
|
|
||||||
(_, 6) => Event::PrideMonth,
|
|
||||||
(24, 8) => Event::AnniversaryTF2,
|
|
||||||
(10, 10) => Event::AnniversaryTF2,
|
|
||||||
(31, 10) => Event::Halloween,
|
|
||||||
(11, 11) => Event::Rogaliki,
|
|
||||||
(24..=30, 12) => Event::Christmas,
|
|
||||||
(31, 12) => Event::NewYears,
|
|
||||||
_ => Event::Normal,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn init_service(ctx: &Context, guild_id: &GuildId) {
|
|
||||||
let (ctx, guild_id) = (ctx.clone(), guild_id.clone());
|
|
||||||
info!("Initialising event automation service...");
|
|
||||||
|
|
||||||
if guild_id != MAIN_GUILD_ID {
|
|
||||||
info!("Guild event automation service not initialised; Bot not running on main guild.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
tokio::spawn(async move {
|
|
||||||
run_event_service(ctx, guild_id).await;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn run_event_service(ctx: Context, guild_id: GuildId) {
|
|
||||||
loop {
|
|
||||||
update_guild(&ctx, guild_id).await.ok();
|
|
||||||
sleep_until_next_midnight().await;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn update_guild(ctx: &Context, guild_id: GuildId) -> Result<(), String> {
|
|
||||||
let mut guild = match Guild::get(&ctx.http, guild_id).await {
|
|
||||||
Ok(g) => g,
|
|
||||||
Err(e) => {
|
|
||||||
error!("Could not get guild info...");
|
|
||||||
return Err("Could not get guild info: {e}".to_string());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let event = events::get_current_event();
|
|
||||||
|
|
||||||
let icon = match CreateAttachment::path(event.icon()).await {
|
|
||||||
Ok(i) => i,
|
|
||||||
Err(e) => {
|
|
||||||
error!("Could not create icon attachment...");
|
|
||||||
return Err("Could not create icon attachment: {e}".to_string());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
match guild
|
|
||||||
.edit(
|
|
||||||
&ctx.http,
|
|
||||||
EditGuild::new().name(event.guild_name()).icon(Some(&icon)),
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(_) => info!("Guild name/icon updated."),
|
|
||||||
Err(e) => {
|
|
||||||
error!("Could not update guild name/icon...");
|
|
||||||
return Err("Could not update guild name/icon: {e}".to_string());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn sleep_until_next_midnight() {
|
|
||||||
let now = Utc::now().with_timezone(&Warsaw);
|
|
||||||
let tomorrow = now.date_naive() + chrono::Duration::days(1);
|
|
||||||
|
|
||||||
let next_midnight = match Warsaw
|
|
||||||
.with_ymd_and_hms(
|
|
||||||
tomorrow.year_ce().1 as i32,
|
|
||||||
tomorrow.month(),
|
|
||||||
tomorrow.day(),
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
)
|
|
||||||
.earliest()
|
|
||||||
{
|
|
||||||
Some(nm) => nm,
|
|
||||||
None => Utc::now().with_timezone(&Warsaw) + Duration::minutes(61),
|
|
||||||
// e.g. jumps in time occur at 2AM/3AM, Midnight shouldn't be affected
|
|
||||||
// but even if it was, returning None, a gap shouldn't last more than an hour.
|
|
||||||
};
|
|
||||||
|
|
||||||
let sleeptime = match next_midnight.signed_duration_since(now).to_std() {
|
|
||||||
Ok(t) => t,
|
|
||||||
Err(_) => {
|
|
||||||
warn!("The next midnight is, supposedly, not in the future.");
|
|
||||||
warn!("Sleeping an hour instead...");
|
|
||||||
StdDuration::from_secs(1 * 60 * 60)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
tokio::time::sleep(sleeptime).await;
|
|
||||||
}
|
|
||||||
107
src/discordbot/events/mod.rs
Normal file
107
src/discordbot/events/mod.rs
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
use chrono::{Datelike, Utc};
|
||||||
|
use chrono_tz::Europe::Warsaw;
|
||||||
|
use rand::seq::IndexedRandom;
|
||||||
|
use serenity::all::{Context, GuildId};
|
||||||
|
use service::run_event_service;
|
||||||
|
use tracing::info;
|
||||||
|
|
||||||
|
mod service;
|
||||||
|
|
||||||
|
pub fn init_service(ctx: &Context, guild_id: &GuildId) {
|
||||||
|
let (ctx, guild_id) = (ctx.clone(), guild_id.clone());
|
||||||
|
info!("Initialising event automation service...");
|
||||||
|
|
||||||
|
if guild_id != MAIN_GUILD_ID {
|
||||||
|
info!("Guild event automation service not initialised; Bot not running on main guild.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tokio::spawn(async move {
|
||||||
|
run_event_service(ctx, guild_id).await;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const MAIN_GUILD_ID: GuildId = GuildId::new(447075692664979466);
|
||||||
|
|
||||||
|
pub enum Event {
|
||||||
|
Normal,
|
||||||
|
PolskaGórą,
|
||||||
|
PrideMonth,
|
||||||
|
ValentineDay,
|
||||||
|
Rogaliki,
|
||||||
|
Halloween,
|
||||||
|
Christmas,
|
||||||
|
NewYears,
|
||||||
|
AnniversaryGractwo,
|
||||||
|
AnniversaryTF2,
|
||||||
|
AnniversaryMinecraft,
|
||||||
|
StarWarsDay,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Event {
|
||||||
|
pub fn get_current() -> Self {
|
||||||
|
let now = Utc::now().with_timezone(&Warsaw);
|
||||||
|
match (now.day(), now.month()) {
|
||||||
|
(1, 1) => Event::NewYears,
|
||||||
|
(2..=6, 1) => Event::Christmas,
|
||||||
|
(14, 2) => Event::ValentineDay,
|
||||||
|
(1..=3, 5) => Event::PolskaGórą,
|
||||||
|
(4, 5) => Event::StarWarsDay,
|
||||||
|
(17, 5) => Event::AnniversaryMinecraft,
|
||||||
|
(7, 6) => Event::AnniversaryGractwo,
|
||||||
|
(_, 6) => Event::PrideMonth,
|
||||||
|
(24, 8) => Event::AnniversaryTF2,
|
||||||
|
(10, 10) => Event::AnniversaryTF2,
|
||||||
|
(31, 10) => Event::Halloween,
|
||||||
|
(11, 11) => Event::Rogaliki,
|
||||||
|
(24..=30, 12) => Event::Christmas,
|
||||||
|
(31, 12) => Event::NewYears,
|
||||||
|
_ => Event::Normal,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn icon(&self) -> &str {
|
||||||
|
use Event as E;
|
||||||
|
match self {
|
||||||
|
E::PolskaGórą => "./assets/logo-x512-polish.png",
|
||||||
|
E::PrideMonth => "./assets/logo-x512-lgbtflag.png",
|
||||||
|
E::StarWarsDay => "./assets/logo-x512-starwars.png",
|
||||||
|
_ => "./assets/logo-x512.png",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn guild_name(&self) -> String {
|
||||||
|
use Event as E;
|
||||||
|
match self {
|
||||||
|
E::PolskaGórą => {
|
||||||
|
let now = Utc::now().with_timezone(&Warsaw);
|
||||||
|
let suffix = match (now.day(), now.month()) {
|
||||||
|
(1, 5) => ": Święto Pracy",
|
||||||
|
(2, 5) => ": Dzień Flagi",
|
||||||
|
(3, 5) => ": Święto Konstytucji",
|
||||||
|
_ => "",
|
||||||
|
};
|
||||||
|
format!("Gractwo{suffix}")
|
||||||
|
}
|
||||||
|
E::PrideMonth => {
|
||||||
|
let mut rng = rand::rng();
|
||||||
|
const VARIANTS: &[&str] = &["Miesiąc Dumy", "Pride Month", "LGBT Rights!"];
|
||||||
|
format!("Gractwo: {}", VARIANTS.choose(&mut rng).unwrap())
|
||||||
|
}
|
||||||
|
E::ValentineDay => {
|
||||||
|
let mut rng = rand::rng();
|
||||||
|
const VARIANTS: &[&str] = &["Gractwo is in love!", "Gractwo Dating Sim"];
|
||||||
|
VARIANTS.choose(&mut rng).unwrap().to_string()
|
||||||
|
}
|
||||||
|
E::Rogaliki => "Rogalictwo 🥐".to_string(),
|
||||||
|
E::Halloween => "Spooky Gractwo 🎃".to_string(),
|
||||||
|
E::Christmas => "Jolly Gractwo 🎄🎁☃️".to_string(),
|
||||||
|
E::NewYears => "New Gractwo, New Me 🎉".to_string(),
|
||||||
|
E::AnniversaryTF2 => "PGTF: Polscy Gracze Team Fortress".to_string(),
|
||||||
|
E::AnniversaryGractwo => {
|
||||||
|
// TODO: this will conjugate badly in 17 years
|
||||||
|
let xlecie = Utc::now().year_ce().1 - 2020;
|
||||||
|
format!("{xlecie} lat Gractwa!")
|
||||||
|
}
|
||||||
|
_ => "Gractwo".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
81
src/discordbot/events/service.rs
Normal file
81
src/discordbot/events/service.rs
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
use chrono::{Datelike, Duration, TimeZone, Utc};
|
||||||
|
use chrono_tz::Europe::Warsaw;
|
||||||
|
use serenity::all::{Context, CreateAttachment, EditGuild, Guild, GuildId};
|
||||||
|
use tracing::{error, info, warn};
|
||||||
|
|
||||||
|
use super::Event;
|
||||||
|
|
||||||
|
pub async fn run_event_service(ctx: Context, guild_id: GuildId) {
|
||||||
|
loop {
|
||||||
|
update_guild(&ctx, guild_id).await.ok();
|
||||||
|
sleep_until_next_midnight().await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn update_guild(ctx: &Context, guild_id: GuildId) -> Result<(), String> {
|
||||||
|
let mut guild = match Guild::get(&ctx.http, guild_id).await {
|
||||||
|
Ok(g) => g,
|
||||||
|
Err(e) => {
|
||||||
|
error!("Could not get guild info: {e}");
|
||||||
|
return Err("Could not get guild info: {e}".to_string());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let event = Event::get_current();
|
||||||
|
|
||||||
|
let icon = match CreateAttachment::path(event.icon()).await {
|
||||||
|
Ok(i) => i,
|
||||||
|
Err(e) => {
|
||||||
|
error!("Could not create icon attachment: {e}");
|
||||||
|
return Err("Could not create icon attachment: {e}".to_string());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match guild
|
||||||
|
.edit(
|
||||||
|
&ctx.http,
|
||||||
|
EditGuild::new().name(event.guild_name()).icon(Some(&icon)),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(_) => info!("Guild name/icon updated."),
|
||||||
|
Err(e) => {
|
||||||
|
error!("Could not update guild name/icon: {e}");
|
||||||
|
return Err("Could not update guild name/icon: {e}".to_string());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn sleep_until_next_midnight() {
|
||||||
|
let now = Utc::now().with_timezone(&Warsaw);
|
||||||
|
let tomorrow = now.date_naive() + chrono::Duration::days(1);
|
||||||
|
|
||||||
|
let next_midnight = match Warsaw
|
||||||
|
.with_ymd_and_hms(
|
||||||
|
tomorrow.year_ce().1 as i32,
|
||||||
|
tomorrow.month(),
|
||||||
|
tomorrow.day(),
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
.earliest()
|
||||||
|
{
|
||||||
|
Some(nm) => nm,
|
||||||
|
None => Utc::now().with_timezone(&Warsaw) + Duration::minutes(61),
|
||||||
|
// e.g. jumps in time occur at 2AM/3AM, Midnight shouldn't be affected
|
||||||
|
// but even if it was, returning None, a gap shouldn't last more than an hour.
|
||||||
|
};
|
||||||
|
|
||||||
|
let sleeptime = match next_midnight.signed_duration_since(now).to_std() {
|
||||||
|
Ok(t) => t,
|
||||||
|
Err(_) => {
|
||||||
|
warn!("The next midnight is, supposedly, not in the future.");
|
||||||
|
warn!("Sleeping an hour instead...");
|
||||||
|
std::time::Duration::from_secs(1 * 60 * 60)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
tokio::time::sleep(sleeptime).await;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user