diff --git a/.env b/.env new file mode 100644 index 0000000..0ab61a8 --- /dev/null +++ b/.env @@ -0,0 +1 @@ +DISCORD_TOKEN=$(cat token.txt) diff --git a/.github/workflows/deploy-to-vps.yaml b/.github/workflows/deploy-to-vps.yaml new file mode 100644 index 0000000..6ecfe4c --- /dev/null +++ b/.github/workflows/deploy-to-vps.yaml @@ -0,0 +1,35 @@ +name: Deploy main to Huey-Dewey-Louie + +on: + push: + branches: + - main + +jobs: + build-and-deploy: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Setup SSH + uses: webfactory/ssh-agent@v0.5.3 + with: + ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} + + - name: Build and Deploy with Docker Compose + run: | + ssh -o StrictHostKeyChecking=no ${{ secrets.USERNAME }}@${{ secrets.HOST }} << 'EOF' + cd /src/eveningbot + + git reset --hard HEAD + git pull origin main + + touch .env + chmod 644 .env + echo "DISCORD_TOKEN=${{secrets.BOT_TOKEN}}" > .env + + docker compose up -d --build + + docker image prune -f + EOF \ No newline at end of file diff --git a/.gitignore b/.gitignore index 2bc4bc4..178303e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ target/ token.txt +assets/leaderboard.bin diff --git a/Cargo.lock b/Cargo.lock index 4f09250..fc66adc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -415,6 +415,7 @@ dependencies = [ "poise", "rand", "reqwest 0.12.4", + "rmp-serde", "serde", "time", "tokio", @@ -1121,6 +1122,12 @@ dependencies = [ "regex", ] +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + [[package]] name = "percent-encoding" version = "2.3.1" @@ -1442,6 +1449,28 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rmp" +version = "0.8.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "228ed7c16fa39782c3b3468e974aec2795e9089153cd08ee2e9aefb3613334c4" +dependencies = [ + "byteorder", + "num-traits", + "paste", +] + +[[package]] +name = "rmp-serde" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52e599a477cf9840e92f2cde9a7189e67b42c57532749bf90aea6ec10facd4db" +dependencies = [ + "byteorder", + "rmp", + "serde", +] + [[package]] name = "rustc-demangle" version = "0.1.23" diff --git a/Cargo.toml b/Cargo.toml index 232c7b5..0b922f9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ chrono-tz = "0.9.0" poise = "0.6.1" rand = "0.8.5" reqwest = { version = "0.12.4", features = ["json"] } +rmp-serde = "1.3.0" serde = "1.0.200" time = { version = "0.3.36", features = ["serde", "parsing"] } tokio = { version = "1.37.0", features = ["rt-multi-thread"] } diff --git a/Dockerfile b/Dockerfile index 4a8cd3c..0b0e09d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,12 +10,14 @@ copy Cargo.lock Cargo.lock run cargo build --release copy src/ src/ +copy assets/ assets/ run cargo build --release from debian:stable-slim as debug run apt update && apt install -y libssl-dev -copy --from=builder /target/release/eveningbot /eveningbot +copy --from=builder /target/release/eveningbot /eveningbot/eveningbot +copy --from=builder /assets/ /eveningbot/assets/ -cmd ["/eveningbot"] +cmd ["/eveningbot/eveningbot"] diff --git a/assets/fact_check/cat_state_false.gif b/assets/fact_check/cat_state_false.gif new file mode 100644 index 0000000..c0702f7 Binary files /dev/null and b/assets/fact_check/cat_state_false.gif differ diff --git a/assets/fact_check/dark_brandon.jpg b/assets/fact_check/dark_brandon.jpg new file mode 100644 index 0000000..fa83b95 Binary files /dev/null and b/assets/fact_check/dark_brandon.jpg differ diff --git a/assets/fact_check/dark_maga.png b/assets/fact_check/dark_maga.png new file mode 100644 index 0000000..80cfb9c Binary files /dev/null and b/assets/fact_check/dark_maga.png differ diff --git a/assets/fact_check/gabriel.jpg b/assets/fact_check/gabriel.jpg new file mode 100644 index 0000000..e0b45c9 Binary files /dev/null and b/assets/fact_check/gabriel.jpg differ diff --git a/assets/fact_check/gilded_dredgens.jpg b/assets/fact_check/gilded_dredgens.jpg new file mode 100644 index 0000000..e81c6f5 Binary files /dev/null and b/assets/fact_check/gilded_dredgens.jpg differ diff --git a/assets/fact_check/soyjak_party_coal.jpg b/assets/fact_check/soyjak_party_coal.jpg new file mode 100644 index 0000000..a2c3db6 Binary files /dev/null and b/assets/fact_check/soyjak_party_coal.jpg differ diff --git a/assets/fact_check/unsc_false.jpg b/assets/fact_check/unsc_false.jpg new file mode 100644 index 0000000..8ca66fc Binary files /dev/null and b/assets/fact_check/unsc_false.jpg differ diff --git a/assets/fact_check/yakub.jpg b/assets/fact_check/yakub.jpg new file mode 100644 index 0000000..25247aa Binary files /dev/null and b/assets/fact_check/yakub.jpg differ diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..95f0449 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,7 @@ +version: '3.8' +services: + eveningbot: + env_file: + - ./.env + build: . + restart: on-failure:3 \ No newline at end of file diff --git a/src/commands.rs b/src/commands.rs index 0c8efa8..51d39c2 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -1,15 +1,15 @@ +use crate::global::*; use poise::{serenity_prelude::CreateAttachment, reply::CreateReply}; use tokio::fs::File; -type Data = (); type Error = Box; -type Context<'a> = poise::Context<'a, Data, Error>; +type Context<'a> = poise::Context<'a, SharedData, Error>; #[poise::command(prefix_command, slash_command)] pub async fn fact_check(ctx: Context<'_>) -> Result<(), Error> { - let image = get_fact_check_image().await; + let (image, filename) = get_fact_check_image(ctx.data()).await; let attachment = CreateAttachment - ::file(&image, "fact_check.png").await.unwrap(); + ::file(&image, filename).await.unwrap(); let reply = CreateReply { attachments: vec![attachment], @@ -22,15 +22,18 @@ pub async fn fact_check(ctx: Context<'_>) -> Result<(), Error> { } -async fn get_fact_check_image() -> File { - let paths = std::fs::read_dir("assets/fact_check/").unwrap(); +async fn get_fact_check_image(shared_data: &SharedData) -> (File, String) { + let root_folder = &shared_data.root_path; + + let paths = std::fs::read_dir(format!("{}/assets/fact_check/", root_folder)).unwrap(); let mut images: Vec = vec![]; + for path in paths { - images.push(path.unwrap().path().display().to_string()); + images.push(format!("{}", path.unwrap().path().display().to_string())); } let rand_index = rand::random::() % images.len(); let image = &images[rand_index]; - File::open(image).await.unwrap() + (File::open(image).await.unwrap(), image.to_string()) } diff --git a/src/event.rs b/src/event.rs new file mode 100644 index 0000000..3688c90 --- /dev/null +++ b/src/event.rs @@ -0,0 +1,83 @@ +use crate::global::*; +use std::sync::atomic::Ordering; +use poise::serenity_prelude::{self as serenity, CreateMessage, EmojiId, GuildRef, ReactionType}; +use time::*; + +type Error = Box; + +pub async fn event_handler( + ctx: &serenity::Context, + event: &serenity::FullEvent, + _framework: poise::FrameworkContext<'_, SharedData, Error>, + shared_data: &SharedData +) -> std::prelude::v1::Result<(), Error> { + match event { + serenity::FullEvent::GuildMemberRemoval { guild_id, user, .. } => { + const USERS_REMOVED_CHANNEL_ID: u64 = 1240091460217344100; + let channel = serenity::ChannelId::new(USERS_REMOVED_CHANNEL_ID); + + let member_count = { + let guild: GuildRef = ctx.cache.guild(guild_id).unwrap(); + guild.member_count + }; + + let message = CreateMessage::new() + .content( + format!("<@{}> left, now {} server members", + user.id, + member_count) + ); + + let _ = channel.send_message(&ctx.http, message).await; + } + + serenity::FullEvent::Message { new_message } => { + // early returns + const BOT_ID: u64 = 1235086289255137404; + #[allow(dead_code)] + const TESTING_CHANNEL_ID: u64 = 1235087573421133824; + const GENERAL_CHANNEL_ID: u64 = 1215048710074011692; + + let sunset_time = *shared_data.sunset_time.lock().unwrap(); + let current_time = OffsetDateTime::now_utc().to_offset(sunset_time.offset()); + + if !(current_time > sunset_time && current_time.hour() < 24) + || !(new_message.channel_id == GENERAL_CHANNEL_ID || new_message.channel_id == TESTING_CHANNEL_ID) + || new_message.author.id == BOT_ID + || !GOOD_EVENINGS.iter().any(|a| new_message.content.to_lowercase().contains(a)) + { + return Ok(()); + } + + + // react to good evenings + let reaction = ReactionType::Custom { + animated: false, + id: EmojiId::new(1241916769648775238), + name: Some("eepy".to_string()), + }; + + new_message.react(&ctx.http, reaction).await.unwrap(); + + + // handle leaderboard if its the first GE of the day + if shared_data.first_ge_sent.load(Ordering::SeqCst) { + return Ok(()); + } + + shared_data.first_ge_sent.store(true, Ordering::SeqCst); + + let user_id = u64::from(new_message.author.id); + let mut leaderboard = shared_data.evening_leaderboard.lock().await; + + leaderboard.entry(user_id).and_modify(|e| *e += 1).or_insert(1); + + let leaderboard_bytes = rmp_serde::encode::to_vec(&*leaderboard).expect("couldnt serialize leaderboard"); + _ = std::fs::write(format!("{}/assets/leaderboard.bin", shared_data.root_path), leaderboard_bytes); + } + + _ => {} + } + + Ok(()) +} diff --git a/src/global.rs b/src/global.rs new file mode 100644 index 0000000..cef771c --- /dev/null +++ b/src/global.rs @@ -0,0 +1,104 @@ +use crate::web; +use std::collections::HashMap; +use std::sync::atomic::AtomicBool; +use std::sync::{Arc, Mutex}; +use tokio::sync as tsync; + + +pub struct SharedData { + pub sunset_time: Arc>, + pub root_path: String, + pub evening_leaderboard: Arc>>, + pub first_ge_sent: Arc +} + +impl SharedData { + pub async fn new() -> Self { + let mut exec_path = std::env::current_exe().expect("couldnt get current executable path"); + exec_path.pop(); + if cfg!(debug_assertions) { + exec_path.pop(); exec_path.pop(); + } + let assets_path = exec_path.to_string_lossy().to_string(); + + let leaderboard: HashMap = { + let path_string = format!("{}/assets/leaderboard.bin", assets_path); + let path = std::path::Path::new(&path_string); + + if !path.try_exists().expect("file checking error") { + HashMap::new() + } else { + let bytes = std::fs::read(format!("{}/assets/leaderboard.bin", assets_path)).expect("couldnt read leaderboard file"); + rmp_serde::decode::from_slice(&bytes).expect("couldnt deserialize leaderboard") + } + }; + + SharedData { + sunset_time: Arc::new(Mutex::new(web::get_sunset_time().await.unwrap())), + root_path: assets_path, + evening_leaderboard: Arc::new(tsync::Mutex::new(leaderboard)), + first_ge_sent: Arc::new(AtomicBool::new(false)) + } + } +} + +pub static EVENING_MOTD: &[&str] = &[ + "evening good?", + "yawn.", + "boo", + "WHATEVER YOU DO, DO NOT LOOK AT THE MOON", + "the sun will rise once again.", + "DAY AND NIGHT, DAY AND NIGHT", + "jkhgkdfhgskjldahfgkljsdfhgjklsdhfgjk", + "mun pona", + "toki a!", +]; + +pub static NIGHT_MOTD: &[&str] = &[ + "the voices are coming.", + "how many eepers does it change to take a log by bolb? none, their to busy ???? their body pillow", + "who up shlombing rn", + ":goofyskull:", + "why are you up? disgusting.", + "gay sex", + "i hope mom doesnt find me playing on my ds", + "estrogen injection hours", + "you should totally knock on the walls your neighbours will appreciate it", + "meow", + "lets cant sleep together :3", + "comrade, we must go hunt for business students", + "yooyokokkokokoiyoykoyoyitoyitoykoyoykoykoyyoyoyoyokokokoykykyoyoyoyoykyoyyyyy", + "THE LONELY STONER FREES HIS MIND AT NIGHT, MIND AT NIGHT", + "THE MOON LOOKS BEAUTIFUL TONIGHT. YOU SHOULD GO LOOK.", + "tenpo pimeja 🌃", + "where are my programming socks", +]; + +pub static GOOD_EVENINGS: &[&str] = &[ + "good evening", + "dobry wieczor", + "dobry wieczór", + "tenpo pimeja pona", + "pimeja pona", + "buenas noches", + "bonsoir", + "こんばんは", + "こんばん", + "konbanwa", + "konbanha", + "konban", + "晚上好", + "晚安", + "wan3 shang4 hao3", + "wan shang hao", + "wan4 an1", + "wan an", + "guten abend", + "tráthnóna maith", + "tráthnona maith", + "trathnóna maith", + "trathnona maith", + "goejûn", + "goejun", + "gott kveld", +]; diff --git a/src/jobs.rs b/src/jobs.rs index c94f6ca..ee6f109 100644 --- a/src/jobs.rs +++ b/src/jobs.rs @@ -1,67 +1,104 @@ -use crate::motd::*; +use crate::global::*; use crate::web; -use poise::serenity_prelude::Http; -use poise::serenity_prelude::{self as serenity, CreateMessage}; -use std::sync::{Arc, Mutex}; +use std::sync::{Arc, Mutex, atomic::Ordering}; +use poise::serenity_prelude::{self as serenity, Colour, CreateEmbed, CreateMessage, Http, UserId}; use tokio_cron_scheduler::{JobBuilder, JobScheduler, JobSchedulerError}; use uuid::Uuid; pub async fn init_jobs( sched: Arc, client: &serenity::Client, + shared_data: &SharedData ) -> Result<(), JobSchedulerError> { const GENERAL_CHANNEL_ID: u64 = 1215048710074011692; - const TESTING_CHANNEL_ID: u64 = 1235087573421133824; - let http = client.http.clone(); + #[allow(dead_code)] const TESTING_CHANNEL_ID: u64 = 1235087573421133824; + let http = client.http.clone(); + + // arc my beloved let sunset_job_id: Arc> = Default::default(); let evening_bag = Arc::new(Mutex::new(EVENING_MOTD.to_vec())); let night_bag = Arc::new(Mutex::new(NIGHT_MOTD.to_vec())); // evening - sunset time from sunrise-sunset.org { - let job = create_sunset_job(http.clone(), GENERAL_CHANNEL_ID, evening_bag.clone()).await; - *sunset_job_id.lock().unwrap() = sched.add(job).await?; + // braces to ensure lock gets dropped + let sunset_time = { *shared_data.sunset_time.lock().unwrap() }; + + let job = create_sunset_job(http.clone(), GENERAL_CHANNEL_ID, sunset_time, evening_bag.clone()).await; + { *sunset_job_id.lock().unwrap() = sched.add(job).await?; } } - // night - 3am + // show leaderboard - 12am { let http = http.clone(); let channel = serenity::ChannelId::new(GENERAL_CHANNEL_ID); + let leaderboard = shared_data.evening_leaderboard.clone(); + let first_ge_sent = shared_data.first_ge_sent.clone(); let job = JobBuilder::new() .with_timezone(chrono_tz::Europe::Dublin) .with_cron_job_type() - .with_schedule("0 0 3 * * *") + .with_schedule("0 0 0 * * *") .unwrap() .with_run_async(Box::new(move |_uuid, _l| { let http = http.clone(); - let mut bag = night_bag.lock().unwrap(); - - if bag.is_empty() { - *bag = NIGHT_MOTD.to_vec(); - } - - let rand_index = rand::random::() % bag.len(); - let motd = bag[rand_index]; - bag.remove(rand_index); - - let message = CreateMessage::new().content(motd); + let leaderboard = leaderboard.clone(); + + // reset first ge message lock + first_ge_sent.store(false, Ordering::SeqCst); Box::pin(async move { - let _ = channel.send_message(http, message).await; + let leaderboard = { leaderboard.lock().await }; + + let leaderboard_top_10: String = 'top_10: { + if leaderboard.len() == 0 { + break 'top_10 "noone yet :(".to_string(); + } + + let mut sorted: Vec<(&u64, &u16)> = leaderboard.iter().collect(); + sorted.sort_by(|a, b| b.1.cmp(a.1)); + sorted.shrink_to(10); + + let mut top_10 = String::new(); + let mut position = 1; + for (id, count) in sorted { + let user_id = UserId::new(id.clone()); + let user = user_id.to_user(http.clone()).await.expect("couldnt get user from id for leaderboard"); + let username = user.global_name.unwrap(); + + top_10.push_str(&format!("{}. {}: {}\n", position, username, count)); + + position += 1; + } + top_10.remove(top_10.len() - 1); + + top_10 + }; + + let embed = CreateEmbed::new() + .colour(Colour::from_rgb(255, 0, 124)) + .title("good evening leaderboard") + .description(leaderboard_top_10); + let message = CreateMessage::new() + .add_embed(embed); + + _ = channel.send_message(http, message).await; }) })) .build() .unwrap(); - sched.add(job).await?; + sched.clone().add(job).await?; } - // refresh sunset job + // refresh sunset job/time - 12:02am { let http = http.clone(); - let scope_sched = sched.clone(); + let sched_closure = sched.clone(); + let sunset_time = shared_data.sunset_time.clone(); + + let new_sunset_time = web::get_sunset_time().await.unwrap(); let job = JobBuilder::new() .with_timezone(chrono_tz::Europe::Dublin) @@ -70,23 +107,63 @@ pub async fn init_jobs( .unwrap() .with_run_async(Box::new(move |_uuid, _l| { let http = http.clone(); - let sched = sched.clone(); + let sched = sched_closure.clone(); + + let sunset_time = sunset_time.clone(); let sunset_job_id = sunset_job_id.clone(); let evening_bag = evening_bag.clone(); Box::pin(async move { - let _ = sched.remove(&sunset_job_id.lock().unwrap()); + { *sunset_time.lock().unwrap() = new_sunset_time; } + + let id = { *sunset_job_id.lock().unwrap() }; + let job = create_sunset_job(http, GENERAL_CHANNEL_ID, new_sunset_time, evening_bag.clone()).await; + + _ = sched.remove(&id).await; + let new_id = sched.add(job).await.unwrap(); + + { *sunset_job_id.lock().unwrap() = new_id; } + }) + })) + .build() + .unwrap(); + + sched.clone().add(job).await?; + } + + // night - 3am + { + let http = http.clone(); + let channel = serenity::ChannelId::new(GENERAL_CHANNEL_ID); + + let job = JobBuilder::new() + .with_timezone(chrono_tz::Europe::Dublin) + .with_cron_job_type() + .with_schedule("0 0 3 * * *") + .unwrap() + .with_run_async(Box::new(move |_uuid, _l| { + let http = http.clone(); + let mut bag = { night_bag.lock().unwrap() }; - let job = - create_sunset_job(http, GENERAL_CHANNEL_ID, evening_bag.clone()).await; - *sunset_job_id.lock().unwrap() = sched.add(job).await.unwrap(); + if bag.is_empty() { + *bag = NIGHT_MOTD.to_vec(); + } + + let rand_index = rand::random::() % bag.len(); + let motd = bag[rand_index]; + bag.remove(rand_index); + + let message = CreateMessage::new().content(motd); + + Box::pin(async move { + _ = channel.send_message(http, message).await; }) })) .build() .unwrap(); - scope_sched.add(job).await?; + sched.add(job).await?; } Ok(()) @@ -95,9 +172,9 @@ pub async fn init_jobs( async fn create_sunset_job( http: Arc, channel_id: u64, - bag: Arc>>, + time: time::OffsetDateTime, + bag: Arc>> ) -> tokio_cron_scheduler::Job { - let time = web::get_sunset_time().await.unwrap(); let schedule = &format!("{} {} {} * * *", time.second(), time.minute(), time.hour())[..]; println!( "sunset today - {:02}:{:02}:{:02}", @@ -115,7 +192,7 @@ async fn create_sunset_job( .unwrap() .with_run_async(Box::new(move |_uuid, _l| { let http = http.clone(); - let mut bag = bag.lock().unwrap(); + let mut bag = { bag.lock().unwrap() }; if bag.is_empty() { *bag = EVENING_MOTD.to_vec(); @@ -125,10 +202,12 @@ async fn create_sunset_job( let motd = bag[rand_index]; bag.remove(rand_index); - let message = CreateMessage::new().content(motd); + let main_message = CreateMessage::new().content(motd); + let ge_message = CreateMessage::new().content("good evening"); Box::pin(async move { - let _ = channel.send_message(http, message).await; + _ = channel.send_message(&http, main_message).await; + _ = channel.send_message(http, ge_message).await; }) })) .build() diff --git a/src/lib.rs b/src/lib.rs index c4713ce..87e23b8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,5 @@ +pub mod global; pub mod jobs; -pub mod motd; -pub mod web; pub mod commands; +pub mod event; +pub mod web; diff --git a/src/main.rs b/src/main.rs index 28ab183..2e594d2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ -use eveningbot::{commands, jobs}; -use poise::serenity_prelude::{self as serenity}; +use eveningbot::{global::*, jobs, commands, event}; +use poise::serenity_prelude::{self as serenity, GatewayIntents}; use std::sync::Arc; use tokio_cron_scheduler::JobScheduler; @@ -7,36 +7,53 @@ type Error = Box; #[tokio::main] async fn main() -> Result<(), Error> { - let mut client = poise_setup().await; + let shared_data = SharedData::new().await; + + let mut client = poise_setup(&shared_data).await; let sched: Arc = Arc::new(JobScheduler::new().await?); - jobs::init_jobs(sched.clone(), &client).await?; + jobs::init_jobs(sched.clone(), &client, &shared_data).await?; - sched.start().await?; - client.start().await.unwrap(); + sched.start().await.expect("scheduler failed"); + client.start().await.expect("client failed"); Ok(()) } -pub async fn poise_setup() -> serenity::Client { +pub async fn poise_setup(shared_data: &SharedData) -> serenity::Client { let token = std::env::var("DISCORD_TOKEN").expect("envvar the DISCORD_TOKEN"); - let intents = serenity::GatewayIntents::non_privileged(); + let intents = GatewayIntents::GUILDS | GatewayIntents::GUILD_MEMBERS | GatewayIntents::MESSAGE_CONTENT + | GatewayIntents::GUILD_MESSAGES; + + let sunset_time = shared_data.sunset_time.clone(); + let assets_path = shared_data.root_path.clone(); + let evening_leaderboard = shared_data.evening_leaderboard.clone(); + let first_ge_sent = shared_data.first_ge_sent.clone(); - let framework = poise::Framework::<(), Error>::builder() + let framework = poise::Framework::builder() + .setup(|ctx, _ready, framework| { + Box::pin(async move { + poise::builtins::register_globally(ctx, &framework.options().commands).await?; + + Ok(SharedData { + sunset_time, + root_path: assets_path, + evening_leaderboard, + first_ge_sent + }) + }) + }) .options(poise::FrameworkOptions { commands: vec![commands::fact_check()], prefix_options: poise::PrefixFrameworkOptions { prefix: Some("!".into()), ..Default::default() }, + event_handler: move |ctx, event, framework, data| { + Box::pin(event::event_handler(ctx, event, framework, data)) + }, ..Default::default() }) - .setup(|ctx, _ready, framework| { - Box::pin(async move { - poise::builtins::register_globally(ctx, &framework.options().commands).await?; - Ok(()) - }) - }) .build(); serenity::ClientBuilder::new(token, intents) diff --git a/src/motd.rs b/src/motd.rs deleted file mode 100644 index 6d55cf7..0000000 --- a/src/motd.rs +++ /dev/null @@ -1,31 +0,0 @@ -pub static EVENING_MOTD: &[&str] = &[ - "good evening", - "yawn.", - "boo", - "WHATEVER YOU DO, DO NOT LOOK AT THE MOON", - "the sun will rise once again.", - "DAY AND NIGHT, DAY AND NIGHT", - "jkhgkdfhgskjldahfgkljsdfhgjklsdhfgjk", - "mun pona", - "toki a!", -]; - -pub static NIGHT_MOTD: &[&str] = &[ - "the voices are coming.", - "how many eepers does it change to take a log by bolb? none, their to busy ???? their body pillow", - "who up shlombing rn", - ":goofyskull:", - "why are you up? disgusting.", - "gay sex", - "i hope mom doesnt find me playing on my ds", - "estrogen injection hours", - "you should totally knock on the walls your neighbours will appreciate it", - "meow", - "lets cant sleep together :3", - "comrade, we must go hunt for business students", - "yooyokokkokokoiyoykoyoyitoyitoykoyoykoykoyyoyoyoyokokokoykykyoyoyoyoykyoyyyyy", - "THE LONELY STONER FREES HIS MIND AT NIGHT, MIND AT NIGHT", - "THE MOON LOOKS BEAUTIFUL TONIGHT. YOU SHOULD GO LOOK.", - "tenpo pimeja 🌃", - "where are my programming socks" -]; diff --git a/src/web.rs b/src/web.rs index b6c4bb8..7018851 100644 --- a/src/web.rs +++ b/src/web.rs @@ -15,7 +15,7 @@ pub async fn get_sunset_time() -> Result { const DUBLIN_COORDS: (&str, &str) = ("53.345727", "-6.269727"); const TIMEZONE: &str = "&tzid=Europe/Dublin"; let url = format!( - "https://api.sunrise-sunset.org/json?lat={}&lng={}&formatted=0&tzid={}", + "http://api.sunrise-sunset.org/json?lat={}&lng={}&formatted=0&tzid={}", DUBLIN_COORDS.0, DUBLIN_COORDS.1, TIMEZONE );