diff --git a/src/autocomplete_helpers/mod.rs b/src/autocomplete_helpers/mod.rs deleted file mode 100644 index e69de29..0000000 diff --git a/src/commands/weather.rs b/src/commands/weather.rs index 8ab54ba..79d7899 100644 --- a/src/commands/weather.rs +++ b/src/commands/weather.rs @@ -1,6 +1,7 @@ use poise::serenity_prelude::utils::Colour; use d20::roll_range; use poise::ReplyHandle; +use poise::serenity_prelude::CreateEmbed; use crate::{ManifoldCommand, ManifoldContext}; use crate::models::weather::{Weather, WeatherForecastRequestResponse}; @@ -15,85 +16,66 @@ async fn weather(ctx: ManifoldContext<'_>, #[rest] #[description="Location to lo let responses = &ctx.data().responses; + let mut pages = Vec::::new(); + + let card_colour = Colour::from_rgb(roll_range(0, 255).unwrap_or(0) as u8, roll_range(0, 255).unwrap_or(0) as u8, roll_range(0, 255).unwrap_or(0) as u8); + pages.push(CreateEmbed::default() + .colour(card_colour) + .title(format!("Current weather at {}, {}, {}", weather_forecast.location.name, weather_forecast.location.region, weather_forecast.location.country)) + .description(format!("Observations recorded at {}.", weather_forecast.current.last_updated)) + .image(format!("https:{}", weather_forecast.current.condition.icon)) + .fields(vec![ + ("Temperature (Dewpoint)", format!("{}°C/{}°F ({:.1}°C/{:.1}°F)", weather_forecast.current.temp_c, weather_forecast.current.temp_f, weather_forecast.current.dewpoint_c.unwrap_or(0.0), weather_forecast.current.dewpoint_f.unwrap_or(0.0)), true), + ("Feels like", format!("{}°C/{}°F", weather_forecast.current.feelslike_c, weather_forecast.current.feelslike_f), true), + ("Condition", format!("{}", weather_forecast.current.condition.text), true), + ("Pressure", format!("{}mb/{}in", weather_forecast.current.pressure_mb, weather_forecast.current.pressure_in), true), + ("Precipitation", format!("{}mm/{}in", weather_forecast.current.precip_mm, weather_forecast.current.precip_in), true), + ("Humidity", format!("{}%", weather_forecast.current.humidity), true), + ("Cloud coverage", format!("{}%", weather_forecast.current.cloud), true), + ("UV index", format!("{}", weather_forecast.current.uv), true), + ("Coordinates", format!("Lat: {} Lon: {}", weather_forecast.location.lat, weather_forecast.location.lon), true), + ]) + .field("Wind", format!("{}mph/{}kph from the {} ({} degrees), gusting to {}mph/{}kph", weather_forecast.current.wind_mph, weather_forecast.current.wind_kph, weather_forecast.current.wind_dir, weather_forecast.current.wind_degree, weather_forecast.current.gust_mph, weather_forecast.current.gust_kph), false) + .footer(|f| { + f.text(format!("{}", responses.get_response(&"weather card footer".to_string()).unwrap_or(&"Weather Powered By Deez Nutz".to_string()))); + f + }).to_owned() + ); + + if let Some(f) = weather_forecast.forecast.forecastday.first() { + f.hour.iter().for_each(|f| { + pages.push(CreateEmbed::default() + .colour(card_colour) + .title(format!("Current weather at {}, {}, {}", weather_forecast.location.name, weather_forecast.location.region, weather_forecast.location.country)) + .description(format!("Forecast for {} made at {}.", f.time, weather_forecast.current.last_updated)) + .image(format!("https:{}", f.condition.icon)) + .fields(vec![ + ("Temperature (Dewpoint)", format!("{}°C/{}°F ({:.1}°C/{:.1}°F)", f.temp_c, f.temp_f, f.dewpoint_c, f.dewpoint_f), true), + ("Feels like", format!("{}°C/{}°F", f.feelslike_c, f.feelslike_f), true), + ("Condition", format!("{}", f.condition.text), true), + ("Pressure", format!("{}mb/{}in", f.pressure_mb, f.pressure_in), true), + ("Precipitation", format!("{}mm/{}in", f.precip_mm, f.precip_in), true), + ("Humidity", format!("{}%", f.humidity), true), + ("Cloud coverage", format!("{}%", f.cloud), true), + ("Coordinates", format!("Lat: {} Lon: {}", weather_forecast.location.lat, weather_forecast.location.lon), true), + ]) + .field("Wind", format!("{}mph/{}kph from the {} ({} degrees), gusting to {}mph/{}kph", f.wind_mph, f.wind_kph, f.wind_dir, f.wind_degree, f.gust_mph, f.gust_kph), false) + .footer(|f| { + f.text(format!("{}", responses.get_response(&"weather card footer".to_string()).unwrap_or(&"Weather Powered By Deez Nutz".to_string()))); + f + }).to_owned()); + }); + } + my_message.edit(ctx, |m| { m.content(""); - m.embed(|e| { - - let card_colour = Colour::from_rgb(roll_range(0, 255).unwrap_or(0) as u8, roll_range(0, 255).unwrap_or(0) as u8, roll_range(0, 255).unwrap_or(0) as u8); - - e.colour(card_colour); - e.title(format!("Current weather at {}, {}, {}", weather_forecast.location.name, weather_forecast.location.region, weather_forecast.location.country)); - e.description(format!("Observations recorded at {}.", weather_forecast.current.last_updated)); - e.image(format!("https:{}", weather_forecast.current.condition.icon)); - e.fields(vec![ - ("Temperature (Dewpoint)", format!("{}°C/{}°F ({:.1}°C/{:.1}°F)", weather_forecast.current.temp_c, weather_forecast.current.temp_f, weather_forecast.current.dewpoint_c.unwrap_or(0.0), weather_forecast.current.dewpoint_f.unwrap_or(0.0)), true), - ("Feels like", format!("{}°C/{}°F", weather_forecast.current.feelslike_c, weather_forecast.current.feelslike_f), true), - ("Condition", format!("{}", weather_forecast.current.condition.text), true), - ("Pressure", format!("{}mb/{}in", weather_forecast.current.pressure_mb, weather_forecast.current.pressure_in), true), - ("Precipitation", format!("{}mm/{}in", weather_forecast.current.precip_mm, weather_forecast.current.precip_in), true), - ("Humidity", format!("{}%", weather_forecast.current.humidity), true), - ("Cloud coverage", format!("{}%", weather_forecast.current.cloud), true), - ("UV index", format!("{}", weather_forecast.current.uv), true), - ("Coordinates", format!("Lat: {} Lon: {}", weather_forecast.location.lat, weather_forecast.location.lon), true), - ]); - e.field("Wind", format!("{}mph/{}kph from the {} ({} degrees), gusting to {}mph/{}kph", weather_forecast.current.wind_mph, weather_forecast.current.wind_kph, weather_forecast.current.wind_dir, weather_forecast.current.wind_degree, weather_forecast.current.gust_mph, weather_forecast.current.gust_kph), false); - e.footer(|f| { - f.text(format!("{}", responses.get_response(&"weather card footer".to_string()).unwrap_or(&"Weather Powered By Deez Nutz".to_string()))); - f - }); - e - }); + m.embeds.extend(pages); m }).await?; Ok(()) } -/* -#[command] -#[aliases("wf")] -pub async fn weather_forecast(ctx: &Context, msg: &Message, args: Args) -> CommandResult { - - let mut my_message = msg.reply_ping(&ctx, "Retrieving weather, be patient").await?; - - let weather_forecast = _get_weather(ctx, msg, args, Some(3)).await?; - - let forecast_index: usize = (chrono::NaiveDateTime::parse_from_str(&*weather_forecast.location.localtime, "%Y-%m-%d %H:%M").unwrap().hour() as usize) + 1; - - debug!("{:?}", weather_forecast); - - my_message.edit(&ctx, |m| { - m.content(""); - - for day in &weather_forecast.forecast.forecastday { - m.add_embed(|e| { - - let this_forecast = &day.hour[forecast_index]; - let card_colour = Colour::from_rgb(roll_range(0, 255).unwrap_or(0) as u8, roll_range(0, 255).unwrap_or(0) as u8, roll_range(0, 255).unwrap_or(0) as u8); - - e.colour(card_colour); - e.title(format!("Weather for {} at {}, {}, {}", this_forecast.time, weather_forecast.location.name, weather_forecast.location.region, weather_forecast.location.country)); - e.description(format!("Observations recorded at {}.", weather_forecast.current.last_updated)); - e.fields(vec![ - ("Temperature (Dewpoint)", format!("{}°C/{}°F ({:.1}°C/{:.1}°F)", this_forecast.temp_c, this_forecast.temp_f, this_forecast.dewpoint_c, this_forecast.dewpoint_f), true), - ("Feels like", format!("{}°C/{}°F", this_forecast.feelslike_c, this_forecast.feelslike_f), true), - ("Condition", format!("{}", this_forecast.condition.text), true), - ("Pressure", format!("{}mb/{}in", this_forecast.pressure_mb, this_forecast.pressure_in), true), - ("Precipitation", format!("{}mm/{}in", this_forecast.precip_mm, this_forecast.precip_in), true), - ("Humidity", format!("{}%", this_forecast.humidity), true), - ]); - e.field("Wind", format!("{}mph/{}kph from the {} ({} degrees), gusting to {}mph/{}kph", this_forecast.wind_mph, this_forecast.wind_kph, this_forecast.wind_dir, this_forecast.wind_degree, this_forecast.gust_mph, this_forecast.gust_kph), false); - e - }); - } - - m - }).await?; - - Ok(()) -} - */ - #[poise::command(slash_command, prefix_command, aliases("wl"))] pub async fn save_weather_location(ctx: ManifoldContext<'_>, #[rest] #[description="Your default weather location"] location: String) -> ManifoldResult<()> { diff --git a/src/helpers/mod.rs b/src/helpers/mod.rs new file mode 100644 index 0000000..5c6c2cd --- /dev/null +++ b/src/helpers/mod.rs @@ -0,0 +1,56 @@ +use crate::error::ManifoldResult; +use crate::ManifoldContext; +use poise::serenity_prelude; + +pub async fn paginate(ctx: ManifoldContext<'_>, pages: &[&str]) -> ManifoldResult<()> { + // Define some unique identifiers for the navigation buttons + let ctx_id = ctx.id(); + let prev_button_id = format!("{}prev", ctx.id()); + let next_button_id = format!("{}next", ctx.id()); + + // Send the embed with the first page as content + let mut current_page = 0; + ctx.send(|b| { + b.embed(|b| b.description(pages[current_page])) + .components(|b| { + b.create_action_row(|b| { + b.create_button(|b| b.custom_id(&prev_button_id).emoji('◀')) + .create_button(|b| b.custom_id(&next_button_id).emoji('▶')) + }) + }) + }) + .await?; + + // Loop through incoming interactions with the navigation buttons + while let Some(press) = serenity_prelude::CollectComponentInteraction::new(ctx) + // We defined our button IDs to start with `ctx_id`. If they don't, some other command's + // button was pressed + .filter(move |press| press.data.custom_id.starts_with(&ctx_id.to_string())) + // Timeout when no navigation button has been pressed for 24 hours + .timeout(std::time::Duration::from_secs(3600 * 24)) + .await + { + // Depending on which button was pressed, go to next or previous page + if press.data.custom_id == next_button_id { + current_page += 1; + if current_page >= pages.len() { + current_page = 0; + } + } else if press.data.custom_id == prev_button_id { + current_page = current_page.checked_sub(1).unwrap_or(pages.len() - 1); + } else { + // This is an unrelated button interaction + continue; + } + + // Update the message with the new page contents + press + .create_interaction_response(ctx, |b| { + b.kind(serenity_prelude::InteractionResponseType::UpdateMessage) + .interaction_response_data(|b| b.embed(|b| b.description(pages[current_page]))) + }) + .await?; + } + + Ok(()) +} diff --git a/src/lib.rs b/src/lib.rs index 7c6e472..267b30a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -21,7 +21,7 @@ use crate::models::user::{ManifoldUserInfo, UserInfo}; use crate::models::fueltank::FuelTank; use crate::responses::Responses; -pub mod autocomplete_helpers; +pub mod helpers; pub mod config; pub mod error; pub mod events;