163 lines
5.1 KiB
Rust
163 lines
5.1 KiB
Rust
use crate::{Context, Error};
|
|
use affluences_api::HourBlock;
|
|
use chrono::{Duration, NaiveDate};
|
|
use uuid::{uuid, Uuid};
|
|
|
|
const STERRE_BIB_ID: Uuid = uuid!("4737e57a-ee05-4f7b-901a-7bb541eeb297");
|
|
const TIME_FORMAT: &'static str = "%H:%M";
|
|
|
|
/// Show this help menu
|
|
#[poise::command(prefix_command, track_edits, slash_command)]
|
|
pub async fn help(
|
|
ctx: Context<'_>,
|
|
#[description = "Specific command to show help about"]
|
|
#[autocomplete = "poise::builtins::autocomplete_command"]
|
|
command: Option<String>,
|
|
) -> Result<(), Error> {
|
|
poise::builtins::help(
|
|
ctx,
|
|
command.as_deref(),
|
|
poise::builtins::HelpConfiguration {
|
|
extra_text_at_bottom: "This is an example bot made to showcase features of my custom Discord bot framework",
|
|
..Default::default()
|
|
},
|
|
)
|
|
.await?;
|
|
Ok(())
|
|
}
|
|
|
|
/// Vote for something
|
|
///
|
|
/// Enter `~vote pumpkin` to vote for pumpkins
|
|
#[poise::command(prefix_command, slash_command)]
|
|
pub async fn vote(
|
|
ctx: Context<'_>,
|
|
#[description = "What to vote for"] choice: String,
|
|
) -> Result<(), Error> {
|
|
// Lock the Mutex in a block {} so the Mutex isn't locked across an await point
|
|
let num_votes = {
|
|
let mut hash_map = ctx.data().votes.lock().unwrap();
|
|
let num_votes = hash_map.entry(choice.clone()).or_default();
|
|
*num_votes += 1;
|
|
*num_votes
|
|
};
|
|
|
|
let response = format!("Successfully voted for {choice}. {choice} now has {num_votes} votes!");
|
|
ctx.say(response).await?;
|
|
Ok(())
|
|
}
|
|
|
|
/// Retrieve number of votes
|
|
///
|
|
/// Retrieve the number of votes either in general, or for a specific choice:
|
|
/// ```
|
|
/// ~getvotes
|
|
/// ~getvotes pumpkin
|
|
/// ```
|
|
#[poise::command(prefix_command, track_edits, aliases("votes"), slash_command)]
|
|
pub async fn getvotes(
|
|
ctx: Context<'_>,
|
|
#[description = "Choice to retrieve votes for"] choice: Option<String>,
|
|
) -> Result<(), Error> {
|
|
if let Some(choice) = choice {
|
|
let num_votes = *ctx.data().votes.lock().unwrap().get(&choice).unwrap_or(&0);
|
|
let response = match num_votes {
|
|
0 => format!("Nobody has voted for {} yet", choice),
|
|
_ => format!("{} people have voted for {}", num_votes, choice),
|
|
};
|
|
ctx.say(response).await?;
|
|
} else {
|
|
let mut response = String::new();
|
|
for (choice, num_votes) in ctx.data().votes.lock().unwrap().iter() {
|
|
response += &format!("{}: {} votes", choice, num_votes);
|
|
}
|
|
|
|
if response.is_empty() {
|
|
response += "Nobody has voted for anything yet :(";
|
|
}
|
|
|
|
ctx.say(response).await?;
|
|
};
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// List available timeslots for day
|
|
#[poise::command(prefix_command, slash_command)]
|
|
pub async fn available(ctx: Context<'_>, date: NaiveDate) -> Result<(), Error> {
|
|
let client = &ctx.data().client;
|
|
let resources = client.available(STERRE_BIB_ID, date, 1).await?;
|
|
let mut fields: Vec<(String, String, bool)> = Default::default();
|
|
|
|
for resource in &resources {
|
|
if resource.hours.len() == 0 {
|
|
fields.push((
|
|
resource.resource_name.clone(),
|
|
"Nothing available.".to_string(),
|
|
false,
|
|
));
|
|
|
|
continue;
|
|
}
|
|
|
|
let mut lines: Vec<String> = Default::default();
|
|
|
|
let mut start_hour_opt: Option<&HourBlock> = None;
|
|
let mut duration = Duration::seconds(0);
|
|
|
|
for hour in &resource.hours {
|
|
if let Some(start_hour) = start_hour_opt {
|
|
if hour.state == 1 {
|
|
duration = duration + Duration::minutes(hour.granularity.into());
|
|
} else {
|
|
let end_hour = start_hour.hour + duration;
|
|
lines.push(format!(
|
|
"{} - {} ({:02}:{:02})",
|
|
start_hour.hour.format(TIME_FORMAT),
|
|
end_hour.format(TIME_FORMAT),
|
|
duration.num_hours(),
|
|
duration.num_minutes() % 60
|
|
));
|
|
start_hour_opt = None;
|
|
}
|
|
} else if hour.state == 1 {
|
|
start_hour_opt = Some(hour);
|
|
duration = Duration::minutes(hour.granularity.into());
|
|
}
|
|
}
|
|
|
|
// Print final entry if present
|
|
if let Some(start_hour) = start_hour_opt {
|
|
let end_hour = start_hour.hour + duration;
|
|
lines.push(format!(
|
|
"{} - {} ({:02}:{:02})",
|
|
start_hour.hour.format(TIME_FORMAT),
|
|
end_hour.format(TIME_FORMAT),
|
|
duration.num_hours(),
|
|
duration.num_minutes() % 60
|
|
));
|
|
}
|
|
|
|
fields.push((resource.resource_name.clone(), lines.join("\n"), false));
|
|
}
|
|
|
|
ctx.send(|f| {
|
|
f.embed(|e| {
|
|
e.description(format!("Available booking dates for {}.", date))
|
|
.fields(fields)
|
|
})
|
|
})
|
|
.await?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
// Create a reservation
|
|
// #[poise::command(prefix_command, slash_command)]
|
|
// pub async fn reserve(
|
|
// ctx: Context<'_>,
|
|
// date: NaiveDate,
|
|
// ) -> Result<(), Error> {
|
|
|
|
// }
|