use std::sync::Arc;
use std::time::Duration;
use serenity::all::{ChannelId, Http};
use tokio_util::sync::CancellationToken;
use uuid::Uuid;
use crate::brain::agent::service::background_tasks::BackgroundTaskManager;
const TICK: Duration = Duration::from_secs(8);
pub(crate) struct TypingGuard(pub(crate) CancellationToken);
impl Drop for TypingGuard {
fn drop(&mut self) {
self.0.cancel();
}
}
pub(crate) fn spawn_typing(
http: Arc<Http>,
channel: ChannelId,
cancel: CancellationToken,
background: Option<Arc<BackgroundTaskManager>>,
session_id: Uuid,
) {
tokio::spawn(async move {
broadcast(&http, channel, "turn start").await;
loop {
tokio::select! {
_ = cancel.cancelled() => break,
_ = tokio::time::sleep(TICK) => broadcast(&http, channel, "turn tick").await,
}
}
crate::channels::typing_tick::tick_while_detached(background, session_id, TICK, || {
broadcast(&http, channel, "handover")
})
.await;
});
}
async fn broadcast(http: &Arc<Http>, channel: ChannelId, why: &str) {
if let Err(e) = channel.broadcast_typing(http).await {
tracing::warn!("Discord: typing broadcast failed ({why}): {e}");
}
}