Extract trait

This commit is contained in:
jude
2024-02-17 20:24:30 +00:00
parent 4823754955
commit c1305cfb36
14 changed files with 336 additions and 176 deletions

View File

@ -1,17 +1,13 @@
use crate::{consts::MINUTE, models::CtxData, Context, Error};
/// Nudge all future reminders on this channel by a certain amount (don't use for DST! See `/offset`)
#[poise::command(
slash_command,
identifying_name = "nudge",
default_member_permissions = "MANAGE_GUILD"
)]
pub async fn nudge(
ctx: Context<'_>,
#[description = "Number of minutes to nudge new reminders by"] minutes: Option<isize>,
#[description = "Number of seconds to nudge new reminders by"] seconds: Option<isize>,
) -> Result<(), Error> {
let combined_time = minutes.map_or(0, |m| m * MINUTE as isize) + seconds.map_or(0, |s| s);
pub struct Options {
minutes: Option<isize>,
seconds: Option<isize>,
}
pub async fn nudge(ctx: Context<'_>, options: Options) -> Result<(), Error> {
let combined_time =
options.minutes.map_or(0, |m| m * MINUTE as isize) + options.seconds.map_or(0, |s| s);
if combined_time < i16::MIN as isize || combined_time > i16::MAX as isize {
ctx.say("Nudge times must be less than 500 minutes").await?;
@ -26,3 +22,17 @@ pub async fn nudge(
Ok(())
}
/// Nudge all future reminders on this channel by a certain amount (don't use for DST! See `/offset`)
#[poise::command(
slash_command,
identifying_name = "nudge",
default_member_permissions = "MANAGE_GUILD"
)]
pub async fn command(
ctx: Context<'_>,
#[description = "Number of minutes to nudge new reminders by"] minutes: Option<isize>,
#[description = "Number of seconds to nudge new reminders by"] seconds: Option<isize>,
) -> Result<(), Error> {
nudge(ctx, Options { minutes, seconds }).await
}

View File

@ -1,25 +1,23 @@
use serde::{Deserialize, Serialize};
use crate::{
consts::{HOUR, MINUTE},
Context, Error,
};
/// Move all reminders in the current server by a certain amount of time. Times get added together
#[poise::command(
slash_command,
identifying_name = "offset",
default_member_permissions = "MANAGE_GUILD"
)]
pub async fn offset(
ctx: Context<'_>,
#[description = "Number of hours to offset by"] hours: Option<isize>,
#[description = "Number of minutes to offset by"] minutes: Option<isize>,
#[description = "Number of seconds to offset by"] seconds: Option<isize>,
) -> Result<(), Error> {
#[derive(Serialize, Deserialize, Default)]
pub struct Options {
hours: Option<isize>,
minutes: Option<isize>,
seconds: Option<isize>,
}
async fn offset(ctx: Context<'_>, options: Options) -> Result<(), Error> {
ctx.defer().await?;
let combined_time = hours.map_or(0, |h| h * HOUR as isize)
+ minutes.map_or(0, |m| m * MINUTE as isize)
+ seconds.map_or(0, |s| s);
let combined_time = options.hours.map_or(0, |h| h * HOUR as isize)
+ options.minutes.map_or(0, |m| m * MINUTE as isize)
+ options.seconds.map_or(0, |s| s);
if combined_time == 0 {
ctx.say("Please specify one of `hours`, `minutes` or `seconds`").await?;
@ -69,3 +67,18 @@ pub async fn offset(
Ok(())
}
/// Move all reminders in the current server by a certain amount of time. Times get added together
#[poise::command(
slash_command,
identifying_name = "offset",
default_member_permissions = "MANAGE_GUILD"
)]
pub async fn command(
ctx: Context<'_>,
#[description = "Number of hours to offset by"] hours: Option<isize>,
#[description = "Number of minutes to offset by"] minutes: Option<isize>,
#[description = "Number of seconds to offset by"] seconds: Option<isize>,
) -> Result<(), Error> {
offset(ctx, Options { hours, minutes, seconds }).await
}

View File

@ -1,22 +1,28 @@
use chrono::NaiveDateTime;
use serde::{Deserialize, Serialize};
use crate::{models::CtxData, time_parser::natural_parser, Context, Error};
use crate::{
models::CtxData, time_parser::natural_parser, utils::Extract, ApplicationContext, Context,
Error,
};
/// Pause all reminders on the current channel until a certain time or indefinitely
#[poise::command(
slash_command,
identifying_name = "pause",
default_member_permissions = "MANAGE_GUILD"
)]
pub async fn pause(
ctx: Context<'_>,
#[description = "When to pause until"] until: Option<String>,
) -> Result<(), Error> {
#[derive(Serialize, Deserialize, Extract)]
pub struct Options {
until: Option<String>,
}
impl Extract for Options {
fn extract(ctx: ApplicationContext) -> Self {
Self { until: extract_arg!(ctx, "until", Option<String>) }
}
}
pub async fn pause(ctx: Context<'_>, options: Options) -> Result<(), Error> {
let timezone = ctx.timezone().await;
let mut channel = ctx.channel_data().await.unwrap();
match until {
match options.until {
Some(until) => {
let parsed = natural_parser(&until, &timezone.to_string()).await;
@ -65,3 +71,16 @@ pub async fn pause(
Ok(())
}
/// Pause all reminders on the current channel until a certain time or indefinitely
#[poise::command(
slash_command,
identifying_name = "pause",
default_member_permissions = "MANAGE_GUILD"
)]
pub async fn command(
ctx: Context<'_>,
#[description = "When to pause until"] until: Option<String>,
) -> Result<(), Error> {
pause(ctx, Options { until }).await
}

View File

@ -4,18 +4,49 @@ use serde::{Deserialize, Serialize};
use crate::{
commands::autocomplete::{time_hint_autocomplete, timezone_autocomplete},
models::reminder::create_reminder,
utils::{extract_arg, Extract},
ApplicationContext, Context, Error,
};
#[derive(Serialize, Deserialize, Default)]
pub struct RemindOptions {
pub time: String,
pub content: String,
pub channels: Option<String>,
pub interval: Option<String>,
pub expires: Option<String>,
pub tts: Option<bool>,
pub timezone: Option<Tz>,
#[derive(Serialize, Deserialize)]
pub struct Options {
time: String,
content: String,
channels: Option<String>,
interval: Option<String>,
expires: Option<String>,
tts: Option<bool>,
timezone: Option<String>,
}
impl Extract for Options {
fn extract(ctx: ApplicationContext) -> Self {
Self {
time: extract_arg!(ctx, "time", String),
content: extract_arg!(ctx, "content", String),
channels: extract_arg!(ctx, "channels", Option<String>),
interval: extract_arg!(ctx, "interval", Option<String>),
expires: extract_arg!(ctx, "expires", Option<String>),
tts: extract_arg!(ctx, "tts", Option<bool>),
timezone: extract_arg!(ctx, "timezone", Option<String>),
}
}
}
pub async fn remind(ctx: Context<'_>, options: Options) -> Result<(), Error> {
let tz = options.timezone.map(|t| t.parse::<Tz>().ok()).flatten();
create_reminder(
ctx,
options.time,
options.content,
options.channels,
options.interval,
options.expires,
options.tts,
tz,
)
.await
}
/// Create a reminder. Press "+4 more" for other options. Use "/multiline" for multiline content.
@ -24,8 +55,8 @@ pub struct RemindOptions {
identifying_name = "remind",
default_member_permissions = "MANAGE_GUILD"
)]
pub async fn remind(
ctx: ApplicationContext<'_>,
pub async fn command(
ctx: Context<'_>,
#[description = "The time (and optionally date) to set the reminder for"]
#[autocomplete = "time_hint_autocomplete"]
time: String,
@ -41,8 +72,5 @@ pub async fn remind(
#[autocomplete = "timezone_autocomplete"]
timezone: Option<String>,
) -> Result<(), Error> {
let tz = timezone.map(|t| t.parse::<Tz>().ok()).flatten();
create_reminder(Context::Application(ctx), time, content, channels, interval, expires, tts, tz)
.await
remind(ctx, Options { time, content, channels, interval, expires, tts, timezone }).await
}

View File

@ -5,25 +5,24 @@ use poise::{
serenity_prelude::{CreateEmbed, CreateEmbedFooter},
CreateReply,
};
use serde::{Deserialize, Serialize};
use crate::{
commands::autocomplete::timezone_autocomplete, consts::THEME_COLOR, models::CtxData, Context,
Error,
};
/// Select your timezone
#[poise::command(slash_command, identifying_name = "timezone")]
pub async fn timezone(
ctx: Context<'_>,
#[description = "Timezone to use from this list: https://gist.github.com/JellyWX/913dfc8b63d45192ad6cb54c829324ee"]
#[autocomplete = "timezone_autocomplete"]
timezone: Option<String>,
) -> Result<(), Error> {
#[derive(Serialize, Deserialize)]
pub struct Options {
pub timezone: Option<String>,
}
pub async fn timezone_fn(ctx: Context<'_>, options: Options) -> Result<(), Error> {
let mut user_data = ctx.author_data().await.unwrap();
let footer_text = format!("Current timezone: {}", user_data.timezone);
if let Some(timezone) = timezone {
if let Some(timezone) = options.timezone {
match timezone.parse::<Tz>() {
Ok(tz) => {
user_data.timezone = timezone.clone();
@ -115,3 +114,14 @@ You may want to use one of the popular timezones below, otherwise click [here](h
Ok(())
}
/// Select your timezone
#[poise::command(slash_command, 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<String>,
) -> Result<(), Error> {
timezone_fn(ctx, Options { timezone }).await
}

View File

@ -1,15 +1,19 @@
use log::warn;
use poise::CreateReply;
use serde::{Deserialize, Serialize};
use crate::{models::CtxData, Context, Error};
use crate::{models::CtxData, utils::Extract, ApplicationContext, Context, Error};
/// View the webhook being used to send reminders to this channel
#[poise::command(
slash_command,
identifying_name = "webhook_url",
required_permissions = "ADMINISTRATOR"
)]
pub async fn webhook(ctx: Context<'_>) -> Result<(), Error> {
#[derive(Serialize, Deserialize)]
pub struct Options;
impl Extract for Options {
fn extract(_ctx: ApplicationContext) -> Self {
Self {}
}
}
pub async fn webhook(ctx: Context<'_>, _options: Options) -> Result<(), Error> {
match ctx.channel_data().await {
Ok(data) => {
if let (Some(id), Some(token)) = (data.webhook_id, data.webhook_token) {
@ -34,3 +38,13 @@ Do not share it!
Ok(())
}
/// View the webhook being used to send reminders to this channel
#[poise::command(
slash_command,
identifying_name = "webhook_url",
required_permissions = "ADMINISTRATOR"
)]
pub async fn command(ctx: Context<'_>) -> Result<(), Error> {
webhook(ctx, Options {}).await
}