add discord guild icon updating by event schedule
This commit is contained in:
120
Cargo.lock
generated
120
Cargo.lock
generated
@@ -17,6 +17,15 @@ version = "2.0.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
|
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aho-corasick"
|
||||||
|
version = "1.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "android-tzdata"
|
name = "android-tzdata"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
@@ -37,6 +46,8 @@ name = "arche"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"axum",
|
"axum",
|
||||||
|
"chrono",
|
||||||
|
"chrono-tz",
|
||||||
"dotenvy",
|
"dotenvy",
|
||||||
"rand 0.9.1",
|
"rand 0.9.1",
|
||||||
"serenity",
|
"serenity",
|
||||||
@@ -245,17 +256,40 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chrono"
|
name = "chrono"
|
||||||
version = "0.4.40"
|
version = "0.4.41"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c"
|
checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"android-tzdata",
|
"android-tzdata",
|
||||||
"iana-time-zone",
|
"iana-time-zone",
|
||||||
|
"js-sys",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"serde",
|
"serde",
|
||||||
|
"wasm-bindgen",
|
||||||
"windows-link",
|
"windows-link",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "chrono-tz"
|
||||||
|
version = "0.10.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "efdce149c370f133a071ca8ef6ea340b7b88748ab0810097a9e2976eaa34b4f3"
|
||||||
|
dependencies = [
|
||||||
|
"chrono",
|
||||||
|
"chrono-tz-build",
|
||||||
|
"phf",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "chrono-tz-build"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f10f8c9340e31fc120ff885fcdb54a0b48e474bbd77cab557f0c30a3e569402"
|
||||||
|
dependencies = [
|
||||||
|
"parse-zoneinfo",
|
||||||
|
"phf_codegen",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "command_attr"
|
name = "command_attr"
|
||||||
version = "0.5.3"
|
version = "0.5.3"
|
||||||
@@ -1124,12 +1158,59 @@ dependencies = [
|
|||||||
"windows-targets 0.52.6",
|
"windows-targets 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parse-zoneinfo"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1f2a05b18d44e2957b88f96ba460715e295bc1d7510468a2f3d3b44535d26c24"
|
||||||
|
dependencies = [
|
||||||
|
"regex",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "percent-encoding"
|
name = "percent-encoding"
|
||||||
version = "2.3.1"
|
version = "2.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
|
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "phf"
|
||||||
|
version = "0.11.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078"
|
||||||
|
dependencies = [
|
||||||
|
"phf_shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "phf_codegen"
|
||||||
|
version = "0.11.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a"
|
||||||
|
dependencies = [
|
||||||
|
"phf_generator",
|
||||||
|
"phf_shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "phf_generator"
|
||||||
|
version = "0.11.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d"
|
||||||
|
dependencies = [
|
||||||
|
"phf_shared",
|
||||||
|
"rand 0.8.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "phf_shared"
|
||||||
|
version = "0.11.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5"
|
||||||
|
dependencies = [
|
||||||
|
"siphasher",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project-lite"
|
name = "pin-project-lite"
|
||||||
version = "0.2.16"
|
version = "0.2.16"
|
||||||
@@ -1260,6 +1341,35 @@ dependencies = [
|
|||||||
"bitflags 2.9.0",
|
"bitflags 2.9.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex"
|
||||||
|
version = "1.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-automata",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-automata"
|
||||||
|
version = "0.4.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "reqwest"
|
name = "reqwest"
|
||||||
version = "0.11.27"
|
version = "0.11.27"
|
||||||
@@ -1590,6 +1700,12 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "siphasher"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "skeptic"
|
name = "skeptic"
|
||||||
version = "0.13.7"
|
version = "0.13.7"
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ edition = "2024"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
axum = "0.8.3"
|
axum = "0.8.3"
|
||||||
|
chrono = "0.4.41"
|
||||||
|
chrono-tz = "0.10.3"
|
||||||
dotenvy = "0.15.7"
|
dotenvy = "0.15.7"
|
||||||
rand = "0.9.1"
|
rand = "0.9.1"
|
||||||
serenity = "0.12.4"
|
serenity = "0.12.4"
|
||||||
|
|||||||
BIN
assets/logo-x512-lgbtflag.png
Normal file
BIN
assets/logo-x512-lgbtflag.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 48 KiB |
BIN
assets/logo-x512-polish.png
Normal file
BIN
assets/logo-x512-polish.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.1 KiB |
BIN
assets/logo-x512-starwars.png
Normal file
BIN
assets/logo-x512-starwars.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
BIN
assets/logo-x512.png
Normal file
BIN
assets/logo-x512.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
142
src/discordbot/guild_icon.rs
Normal file
142
src/discordbot/guild_icon.rs
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
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);
|
||||||
|
|
||||||
|
enum Event {
|
||||||
|
Normal,
|
||||||
|
PolskaGórą,
|
||||||
|
PrideMonth,
|
||||||
|
ValentineDay,
|
||||||
|
Rogaliki,
|
||||||
|
Halloween,
|
||||||
|
Christmas,
|
||||||
|
NewYears,
|
||||||
|
AnniversaryGractwo,
|
||||||
|
AnniversaryTF2,
|
||||||
|
AnniversaryMinecraft,
|
||||||
|
StarWarsDay,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Event {
|
||||||
|
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",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 guild name/icon automation service...");
|
||||||
|
|
||||||
|
if guild_id != MAIN_GUILD_ID {
|
||||||
|
info!("Guild name/icon automation service not initialised; Bot not running on main guild.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tokio::spawn(async move {
|
||||||
|
run_icon_service(ctx, guild_id).await;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn run_icon_service(ctx: Context, guild_id: GuildId) {
|
||||||
|
loop {
|
||||||
|
update_icon(&ctx, guild_id).await.ok();
|
||||||
|
sleep_until_next_midnight().await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn update_icon(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 = 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().icon(Some(&icon)))
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(_) => info!("Guild icon updated."),
|
||||||
|
Err(e) => {
|
||||||
|
error!("Could not update guild icon...");
|
||||||
|
return Err("Could not update guild 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;
|
||||||
|
}
|
||||||
@@ -11,6 +11,7 @@ const GUILD_ID: &str = "DISCORD_SERVER_ID";
|
|||||||
struct Handler;
|
struct Handler;
|
||||||
|
|
||||||
mod commands;
|
mod commands;
|
||||||
|
mod guild_icon;
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl EventHandler for Handler {
|
impl EventHandler for Handler {
|
||||||
@@ -31,6 +32,8 @@ impl EventHandler for Handler {
|
|||||||
Ok(_) => info!("Successfully registered commands on the guild.",),
|
Ok(_) => info!("Successfully registered commands on the guild.",),
|
||||||
Err(why) => info!("Failed to register commands on the guild: {why:?}"),
|
Err(why) => info!("Failed to register commands on the guild: {why:?}"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
guild_icon::init_service(&ctx, &guild_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn interaction_create(&self, ctx: Context, interaction: Interaction) {
|
async fn interaction_create(&self, ctx: Context, interaction: Interaction) {
|
||||||
|
|||||||
Reference in New Issue
Block a user