mirror of
https://github.com/kuhyx/signal-bot.git
synced 2026-11-10 19:37:03 +01:00
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
57 lines
2.0 KiB
Python
57 lines
2.0 KiB
Python
# Copyright (c) 2026 Krzysztof Rudnicki. MIT licence.
|
|
"""Which messages count toward the daily tally, and which chats we listen to."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import TYPE_CHECKING
|
|
|
|
if TYPE_CHECKING:
|
|
from signal_bot.discovery import GroupDirectory
|
|
from signal_bot.models import IncomingMessage
|
|
|
|
|
|
def watched_group(message: IncomingMessage, directory: GroupDirectory) -> str | None:
|
|
"""Return the canonical id of the watched group a message came from.
|
|
|
|
The bot answers in every group it has been added to, and in nothing
|
|
else. Direct messages are rejected here by an explicit lookup rather
|
|
than a falsy check: a DM carries no group id at all, and one must never
|
|
reach a handler no matter how the surrounding code is later rearranged.
|
|
|
|
It returns the id rather than a bool so that the gate and the reply
|
|
router are the same decision. Answering "may this run?" and "where does
|
|
the answer go?" separately is how a bot ends up replying to the wrong
|
|
group.
|
|
|
|
Args:
|
|
message: The parsed inbound message.
|
|
directory: The live set of groups the bot is a member of.
|
|
|
|
Returns:
|
|
The canonical group id, or None for a direct message or any group
|
|
the bot is not scoped to.
|
|
"""
|
|
if message.group_id is None:
|
|
return None
|
|
return directory.resolve(message.group_id)
|
|
|
|
|
|
def should_count(message: IncomingMessage) -> bool:
|
|
"""True when a message should add to its sender's tally.
|
|
|
|
Reactions and stickers are not messages for tally purposes, and a frame
|
|
with no text body carries nothing to count.
|
|
"""
|
|
if message.is_reaction or message.has_sticker:
|
|
return False
|
|
return bool(message.text)
|
|
|
|
|
|
def format_tally(rows: list[tuple[str, int]]) -> str:
|
|
"""Render the daily report, or a placeholder when nobody spoke."""
|
|
if not rows:
|
|
return "Brak wiadomosci dzisiaj."
|
|
width = max(len(name) for name, _ in rows)
|
|
lines = [f"{name.ljust(width)} {count}" for name, count in rows]
|
|
return "\n".join(lines)
|