fixed safety number logic

This commit is contained in:
2026-03-09 16:25:37 -04:00
parent 7ad321e5e2
commit a6fbbd245f
6 changed files with 291 additions and 6 deletions

View File

@@ -39,7 +39,7 @@ class DeviceRegistry:
device = self._get(phone_number)
return device is not None and device.trust_level == TrustLevel.VERIFIED
def record_contact(self, phone_number: str, safety_number: str) -> SignalDevice:
def record_contact(self, phone_number: str, safety_number: str | None = None) -> SignalDevice:
"""Record seeing a device. Creates entry if new, updates last_seen."""
now = utcnow()
with Session(self.engine) as session:
@@ -67,6 +67,11 @@ class DeviceRegistry:
session.refresh(device)
return device
def has_safety_number(self, phone_number: str) -> bool:
"""Check if a device has a safety number on file."""
device = self._get(phone_number)
return device is not None and device.safety_number is not None
def verify(self, phone_number: str) -> bool:
"""Mark a device as verified. Called by admin over SSH.

View File

@@ -94,17 +94,17 @@ def dispatch(
) -> None:
"""Route an incoming message to the right command handler."""
source = message.source
prefix = config.cmd_prefix
if not registry.is_verified(source):
if not registry.is_verified(source) or not registry.has_safety_number(source):
logger.info(f"Device {source} not verified, ignoring message")
return
text = message.message.strip()
prefix = config.cmd_prefix
if not text.startswith(prefix) and not message.attachments:
return
text.startswith(prefix)
cmd = text.lstrip(prefix).split()[0].lower() if text.startswith(prefix) else ""
commands = {
@@ -134,7 +134,8 @@ def run_loop(
try:
for message in signal.listen():
logger.info(f"Message from {message.source}: {message.message[:80]}")
registry.record_contact(message.source, "")
safety_number = signal.get_safety_number(message.source)
registry.record_contact(message.source, safety_number)
dispatch(message, signal, llm, registry, inventory_path, config)
retries = 0
delay = config.reconnect_delay

View File

@@ -103,6 +103,13 @@ class SignalClient:
response.raise_for_status()
return response.json()
def get_safety_number(self, phone_number: str) -> str | None:
"""Look up the safety number for a contact from signal-cli's local store."""
for identity in self.get_identities():
if identity.get("number") == phone_number:
return identity.get("safety_number", identity.get("fingerprint", ""))
return None
def trust_identity(self, number_to_trust: str, *, trust_all_known_keys: bool = False) -> None:
"""Trust an identity (verify safety number)."""
payload: dict[str, Any] = {}