Improved `start_session` performance and added checklist

main
Joey Hines 2024-09-29 12:45:05 -06:00
parent 4bddb8371c
commit c644874fef
No known key found for this signature in database
GPG Key ID: 995E531F7A569DDB
3 changed files with 99 additions and 36 deletions

View File

@ -2,11 +2,11 @@ use crate::config::BotConfig;
use crate::context::Context;
use crate::model::session::{Session, SessionConfig};
use chrono::Utc;
use log::{debug, info};
use log::{debug, error, info};
use poise::futures_util::{Stream, StreamExt};
use poise::serenity_prelude::{
futures, AutocompleteChoice, CreateAttachment, EditScheduledEvent, MessageBuilder,
ScheduledEventId, ScheduledEventStatus,
futures, AutocompleteChoice, CreateAttachment, CreateEmbed, EditScheduledEvent, GatewayIntents,
MessageBuilder, ScheduledEventId, ScheduledEventStatus,
};
use poise::CreateReply;
use raas_types::raas::bot::roll::{roll_response, Roll, RollCmd};
@ -113,7 +113,7 @@ async fn create_session(
let path = ctx.data().config.session_config_path.clone();
let mut session_config = ctx.data().session_config.lock().await;
session_config.create_session(event.id).await;
session_config.create_session(event.id, &event.name);
session_config.save_config(path).await.unwrap();
@ -131,30 +131,75 @@ async fn start_session(
#[autocomplete = "autocomplete_session"]
session: ScheduledEventId,
) -> Result<(), Error> {
let event = {
let sessions = &mut ctx.data().session_config.lock().await;
let session = sessions
.sessions
.iter()
.find(|s| s.event == session)
.cloned()
.unwrap();
let event = match ctx
.guild_id()
.unwrap()
.scheduled_event(ctx.http(), session.event, false)
.await
{
Ok(e) => e,
Err(err) => {
error!("Event '{}', no longer available", session.event);
sessions.remove_session(session.event);
sessions
.save_config(ctx.data().config.session_config_path.clone())
.await?;
return Err(err.into());
}
};
sessions.active_session = Some(event.id);
sessions
.save_config(ctx.data().config.session_config_path.clone())
.await
.unwrap();
event
};
ctx.reply(format!("Started session '{}'", event.name))
.await?;
ctx.send(
CreateReply::default().reply(true).embed(
CreateEmbed::new()
.title(format!("{} started", event.name))
.field(
"Checklist",
ctx.data().config.checklist.format_as_markdown(),
false,
),
),
)
.await?;
// Note: This needs to be done last to get around timeouts caused by editing the event during event processing
let event = ctx
.guild_id()
.unwrap()
.edit_scheduled_event(
ctx.http(),
session.event,
event.id,
EditScheduledEvent::new().status(ScheduledEventStatus::Active),
)
.await?;
.await
.unwrap();
ctx.reply(format!("Started session '{}'", event.name))
.await?;
sessions.active_session = Some(event.id);
sessions.save_config(ctx.data().config.session_config_path.clone()).await?;
info!("Started event '{}'", event.name);
Ok(())
}
@ -182,36 +227,29 @@ async fn stop_session(ctx: BotContext<'_>) -> Result<(), Error> {
.await?;
}
}
sessions.remove_session(session);
} else {
ctx.reply("No sessions in progress!").await?;
}
sessions.active_session = None;
sessions
.save_config(ctx.data().config.session_config_path.clone())
.await
.unwrap();
Ok(())
}
async fn autocomplete_session<'a>(
ctx: BotContext<'a>,
partial: &'a str,
) -> impl Stream<Item = poise::serenity_prelude::AutocompleteChoice> + 'a {
) -> impl Stream<Item = AutocompleteChoice> + 'a {
let sessions: Vec<Session> = { ctx.data().session_config.lock().await.sessions.clone() };
futures::stream::iter(sessions).filter_map(move |s| async move {
let event = ctx
.guild_id()
.unwrap()
.scheduled_event(ctx.http(), s.event, false)
.await;
if let Ok(event) = event {
if event.status == ScheduledEventStatus::Scheduled
&& event.name.matches(partial).count() > 0
{
Some(AutocompleteChoice::new(event.name, event.id.to_string()))
} else {
None
}
if s.name.matches(partial).count() > 0 {
Some(AutocompleteChoice::new(s.name, s.event.to_string()))
} else {
None
}
@ -221,7 +259,7 @@ async fn autocomplete_session<'a>(
pub async fn start_bot(config: BotConfig) {
info!("Starting bot!");
let intents = poise::serenity_prelude::GatewayIntents::non_privileged();
let intents = GatewayIntents::GUILD_MESSAGES | GatewayIntents::GUILD_SCHEDULED_EVENTS;
let token = config.bot_token.clone();

View File

@ -1,4 +1,5 @@
use config::{Config, File};
use poise::serenity_prelude::MessageBuilder;
use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf};
use structopt::StructOpt;
@ -8,11 +9,29 @@ pub struct Args {
pub config_path: PathBuf,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SessionCheckList {
steps: Vec<String>,
}
impl SessionCheckList {
pub fn format_as_markdown(&self) -> String {
let mut msg = MessageBuilder::new();
for step in &self.steps {
msg.push_line(format!("* {}", step));
}
msg.build()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BotConfig {
pub bot_token: String,
pub raas_url: String,
pub session_config_path: PathBuf,
pub checklist: SessionCheckList,
}
impl BotConfig {

View File

@ -7,6 +7,7 @@ use std::path::PathBuf;
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct Session {
pub name: String,
pub event: ScheduledEventId,
pub scenes: Vec<Scene>,
}
@ -45,10 +46,15 @@ impl SessionConfig {
tokio::fs::write(path, toml::to_string(self).unwrap()).await
}
pub async fn create_session(&mut self, event: ScheduledEventId) {
pub fn create_session(&mut self, event: ScheduledEventId, name: &str) {
self.sessions.push(Session {
name: name.to_string(),
event,
scenes: vec![],
})
});
}
pub fn remove_session(&mut self, event: ScheduledEventId) {
self.sessions.retain(|s| s.event != event);
}
}