use chrono::Utc; use chrono_tz::{Tz, TZ_VARIANTS}; use levenshtein::levenshtein; use poise::{ serenity_prelude::{CreateEmbed, CreateEmbedFooter}, CreateReply, }; use serde::{Deserialize, Serialize}; use crate::{ commands::autocomplete::timezone_autocomplete, consts::THEME_COLOR, models::CtxData, utils::{Extract, Recordable}, Context, Error, }; #[derive(Serialize, Deserialize, Extract)] pub struct Options { pub timezone: Option, } impl Recordable for Options { async fn run(self, ctx: Context<'_>) -> Result<(), Error> { let mut user_data = ctx.author_data().await.unwrap(); let footer_text = format!("Current timezone: {}", user_data.timezone); if let Some(timezone) = self.timezone { match timezone.parse::() { Ok(tz) => { user_data.timezone = timezone.clone(); user_data.commit_changes(&ctx.data().database).await; let now = Utc::now().with_timezone(&tz); ctx.send( CreateReply::default().embed( CreateEmbed::new() .title("Timezone Set") .description(format!( "Timezone has been set to **{}**. Your current time should be `{}`", timezone, now.format("%H:%M") )) .color(*THEME_COLOR), ), ) .await?; } Err(_) => { let filtered_tz = TZ_VARIANTS .iter() .filter(|tz| { timezone.contains(&tz.to_string()) || tz.to_string().contains(&timezone) || levenshtein(&tz.to_string(), &timezone) < 4 }) .take(25) .map(|t| t.to_owned()) .collect::>(); let fields = filtered_tz.iter().map(|tz| { ( tz.to_string(), format!("🕗 `{}`", Utc::now().with_timezone(tz).format("%H:%M")), true, ) }); ctx.send( CreateReply::default().embed( CreateEmbed::new() .title("Timezone Not Recognized") .description(concat!( "Possibly you meant one of the following timezones,", " otherwise click [here](https://gist.github.com/JellyWX/", "913dfc8b63d45192ad6cb54c829324ee):" )) .color(*THEME_COLOR) .fields(fields) .footer(CreateEmbedFooter::new(footer_text)) .url( "https://gist.github.com/JellyWX/913dfc8b63d45192ad6cb54c829324ee", ), ), ) .await?; } } } else { let popular_timezones_iter = ctx.data().popular_timezones.iter().map(|t| { ( t.to_string(), format!("🕗 `{}`", Utc::now().with_timezone(t).format("%H:%M")), true, ) }); ctx.send( CreateReply::default().embed( CreateEmbed::new() .title("Timezone Usage") .description( "**Usage:** `/timezone Name` **Example:** `/timezone Europe/London` You may want to use one of the popular timezones below, otherwise click [here](https://gist.github.com/JellyWX/913dfc8b63d45192ad6cb54c829324ee):", ) .color(*THEME_COLOR) .fields(popular_timezones_iter) .footer(CreateEmbedFooter::new(footer_text)) .url("https://gist.github.com/JellyWX/913dfc8b63d45192ad6cb54c829324ee"), ), ) .await?; } Ok(()) } } /// Select your timezone #[poise::command(slash_command, rename = "timezone", identifying_name = "timezone")] pub async fn command( ctx: Context<'_>, #[description = "Timezone to use from this list: https://gist.github.com/JellyWX/913dfc8b63d45192ad6cb54c829324ee"] #[autocomplete = "timezone_autocomplete"] timezone: Option, ) -> Result<(), Error> { (Options { timezone }).run(ctx).await }