use serenity::model::id::{ChannelId, MessageId};
use super::state::DiscordState;
pub(crate) const OPTIONS_TOOL: &str = "suggest_options";
#[derive(Default)]
pub(crate) struct OptionsHost {
adjacent: Option<String>,
}
impl OptionsHost {
pub(crate) fn on_text(&mut self, text: &str) {
match &mut self.adjacent {
Some(prev) => {
prev.push_str("\n\n");
prev.push_str(text);
}
None => self.adjacent = Some(text.to_string()),
}
}
pub(crate) fn on_tool_started(&mut self, tool_name: &str) {
if tool_name != OPTIONS_TOOL {
self.adjacent = None;
}
}
pub(crate) fn take(&mut self) -> Option<String> {
self.adjacent.take()
}
}
pub(crate) async fn post_options_host(
state: &DiscordState,
channel: ChannelId,
http: &serenity::http::Http,
sent: &tokio::sync::Mutex<Vec<String>>,
group_mid: Option<MessageId>,
host: &str,
) {
let host_head = host
.lines()
.map(str::trim)
.find(|l| !l.is_empty())
.unwrap_or("")
.to_lowercase();
if let Some(mid) = group_mid
&& let Some(group) = state
.drop_note_if(mid.get(), |n| note_belongs_to(n, &host_head))
.await
{
let edit = serenity::builder::EditMessage::new()
.content(super::tool_group::render_content(&group))
.embeds(super::tool_group::render_embeds(&group))
.components(super::tool_group::render_components(&group, mid.get()));
if let Some(Err(e)) =
super::governor::edit_chrome(&state.governor, channel, http, mid, edit).await
{
tracing::debug!("Discord: options host note drop edit failed: {e}");
}
}
sent.lock().await.push(host.to_string());
for chunk in super::resume::resume_delivery_chunks(host) {
if let Err(e) = super::governor::say(
&state.governor,
channel,
http,
super::governor::Surface::Send,
&chunk,
)
.await
{
tracing::warn!(error = %e, "Discord: options host post failed");
}
}
}
pub(crate) fn note_belongs_to(note: &str, host_head: &str) -> bool {
let core = note.trim_end_matches('…').to_lowercase();
!core.is_empty() && host_head.starts_with(&core)
}