Redact whole review threads on decision (replies too)
The bot was granted a redact/mod power level in the review room, so it can now clear a resolved thread entirely, not just the card: redact_thread redacts the card root then scans recent history for its m.thread replies (the human's yes/no + any bot messages) and redacts those too, so decided threads drop out of the threads view, not only the main timeline. Drops the in-thread confirmation on a successful decision (the thread clearing is the ack; a confirmation would keep the thread alive). redact_resolved.py extended to also clear replies of already- resolved threads for the one-time backfill. Bot-only; no s9pk change.
This commit is contained in:
@@ -39,7 +39,8 @@ async def main(apply):
|
||||
|
||||
sync = await client.sync(timeout=10000, full_state=False)
|
||||
token = sync.next_batch
|
||||
cards = {} # event_id -> snippet (dedup across pages)
|
||||
cards = {} # root event_id -> snippet (still-identifiable card bodies)
|
||||
replies = {} # reply event_id -> (thread_root, snippet)
|
||||
for _ in range(MAX_PAGES):
|
||||
resp = await client.room_messages(review_room, start=token,
|
||||
direction=MessageDirection.back, limit=100)
|
||||
@@ -47,24 +48,28 @@ async def main(apply):
|
||||
if not chunk:
|
||||
break
|
||||
for ev in chunk:
|
||||
if getattr(ev, "sender", None) != mx["user_id"]:
|
||||
continue
|
||||
body = getattr(ev, "body", "") or ""
|
||||
if CARD_MARKER in body:
|
||||
cards[ev.event_id] = body.replace("\n", " ")[:70]
|
||||
body = (getattr(ev, "body", "") or "").replace("\n", " ")
|
||||
rel = ((getattr(ev, "source", None) or {}).get("content", {}) or {}).get("m.relates_to") or {}
|
||||
if rel.get("rel_type") == "m.thread" and rel.get("event_id"):
|
||||
replies[ev.event_id] = (rel["event_id"], body[:50]) # a threaded reply (card already redacted)
|
||||
elif getattr(ev, "sender", None) == mx["user_id"] and CARD_MARKER in body:
|
||||
cards[ev.event_id] = body[:70] # an un-redacted card root
|
||||
token = getattr(resp, "end", None)
|
||||
if not token:
|
||||
break
|
||||
|
||||
to_redact = [(eid, snip) for eid, snip in cards.items() if eid not in open_ids]
|
||||
print(f"bot cards found: {len(cards)}; resolved (to redact): {len(to_redact)}")
|
||||
for eid, snip in to_redact:
|
||||
print(("APPLY redact " if apply else "WOULD redact ") + eid + " :: " + snip)
|
||||
# Redact card roots that aren't still pending, AND any reply whose thread isn't still pending.
|
||||
targets = [(eid, "card :: " + snip) for eid, snip in cards.items() if eid not in open_ids]
|
||||
targets += [(eid, "reply :: " + snip) for eid, (root, snip) in replies.items() if root not in open_ids]
|
||||
print(f"resolved cards: {sum(1 for e,_ in cards.items() if e not in open_ids)}; "
|
||||
f"thread replies to clear: {sum(1 for _,(r,_) in replies.items() if r not in open_ids)}")
|
||||
for eid, label in targets:
|
||||
print(("APPLY redact " if apply else "WOULD redact ") + eid + " :: " + label)
|
||||
if apply:
|
||||
r = await client.room_redact(review_room, eid, reason="retroactive cleanup of resolved cards")
|
||||
r = await client.room_redact(review_room, eid, reason="retroactive cleanup of resolved review threads")
|
||||
if not hasattr(r, "event_id"):
|
||||
print(f" ! redact failed: {r}")
|
||||
print(("done — redacted " if apply else "dry run — would redact ") + f"{len(to_redact)} card(s).")
|
||||
print(("done — redacted " if apply else "dry run — would redact ") + f"{len(targets)} event(s).")
|
||||
finally:
|
||||
await client.close()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user