gatewayd: approvals answered from Mattermost; typing paused; the notice

Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
This commit is contained in:
2026-09-24 10:19:41 -07:00
parent af7137dafe
commit edf9ba3515
12 changed files with 472 additions and 25 deletions
+37 -7
View File
@@ -4,10 +4,11 @@
use std::sync::Arc;
use std::time::{SystemTime, UNIX_EPOCH};
use crate::deliver::{LOOP_DOWN, deliver};
use crate::approvals::Judged;
use crate::deliver::{LOOP_DOWN, Notice, deliver};
use crate::mm::{Post, typing};
use crate::serve::{Gateway, Stop};
use crate::sessions::{BUSY, Batch, Ignored, M4B_COMMAND, Pushed, Route};
use crate::sessions::{BUSY, Batch, Ignored, Pushed, Route};
use crate::state::InFlight;
use crate::ws::WsError;
use crate::ws::conn::Ws;
@@ -81,8 +82,26 @@ impl Gateway {
}
Route::Ignore(_) => {}
Route::Reply { thread, text } => self.post(&thread.channel, &thread.root, &text),
// Until the approvals module is wired in (task 15), M4a's notice.
Route::Approval { thread, .. } => self.post(&thread.channel, &thread.root, M4B_COMMAND),
Route::Approval {
thread,
command,
user,
post: command_post,
at,
} => {
let approvers = self.config.approvers();
let judged = self.registry.judge(
&command,
&user,
&thread.root,
&command_post,
at,
approvers,
);
if let Judged::Reply(text) = judged {
self.post(&thread.channel, &thread.root, &text);
}
}
Route::Queue(message) => {
if message.joins_thread {
self.state.join_thread(&message.thread.root)?;
@@ -117,6 +136,7 @@ impl Gateway {
channel: batch.thread.channel.clone(),
root: batch.thread.root.clone(),
})?;
let (registry, wait) = (Arc::clone(&self.registry), self.notice);
let (client, socket, log, done) = (
Arc::clone(&self.client),
self.loop_socket.clone(),
@@ -125,7 +145,12 @@ impl Gateway {
);
let (session, thread) = (batch.session.clone(), batch.thread.clone());
let spawned = std::thread::Builder::new().spawn(move || {
deliver(client.as_ref(), &socket, &batch, &|line| log(line));
let posted = |id: u64| registry.was_posted(id);
let notice = Notice {
posted: &posted,
wait,
};
deliver(client.as_ref(), &socket, &batch, &|line| log(line), &notice);
let _ = done.send(batch.session);
});
if let Err(e) = spawned {
@@ -156,9 +181,14 @@ impl Gateway {
/// Show this bot as typing in every thread with a turn running.
pub(super) fn typing(&mut self, ws: &mut Ws) -> Result<(), WsError> {
// `for thread in self.queues.threads() { self.seq += 1;
// ws.send_text(&typing(self.seq, &thread.channel, &thread.root))?; }` then Ok(()).
// `let waiting = self.registry.waiting_sessions();` then for each thread, none that waits
// for its approval: A turn waiting for its approval is not working: no typing in its thread.
// Otherwise `self.seq += 1; ws.send_text(...)`; then Ok(()).
let waiting = self.registry.waiting_sessions();
for thread in self.queues.threads() {
if waiting.contains(&format!("mm-{}", thread.root)) {
continue;
}
self.seq += 1;
ws.send_text(&typing(self.seq, &thread.channel, &thread.root))?;
}