Files

63 lines
2.3 KiB
Python

"""Единственная ветка голосовых точек: как её открыть и как сменить за ночь."""
from __future__ import annotations
import logging
from typing import TYPE_CHECKING
from beaver_agent.voice.texts import KEY, ROTATED, TITLE
if TYPE_CHECKING:
from beaver_gateway.conversations.service import Conversations
from beaver_gateway.storage.models import Conversation
AGENT = "beaver-voice"
"""Кто сидит в голосовой ветке; ему не видно ни справки, ни vault."""
FRONTEND = "voice"
TELEGRAM = "telegram"
_log = logging.getLogger("beaver_agent.voice")
async def current(conversations: Conversations) -> Conversation | None:
conv = await conversations.find_bound(frontend=FRONTEND, external_id=KEY)
return conv if conv is not None and conv.status == "open" else None
async def open_thread(
conversations: Conversations, *, agent: str, window: str | None = None
) -> Conversation:
"""Завести ветку; без ``window`` окно ей открывает телеграм - новым топиком."""
conv = await conversations.spawn(
kind="branch",
agent=agent,
title=TITLE,
origin=FRONTEND,
binding=(TELEGRAM, window) if window else None,
)
await conversations.bind(conv, frontend=FRONTEND, external_id=KEY)
_log.info("голосовая ветка %s (%s)", conv.external_id, agent)
return conv
async def window_of(conversations: Conversations, conv: Conversation) -> str | None:
for binding in await conversations.bindings(conv):
if binding.frontend == TELEGRAM and binding.visible:
return binding.external_id
return None
async def rotate(conversations: Conversations) -> Conversation | None:
"""Ночью - новая ветка в том же топике; молчавшую за сутки не трогаем."""
old = await current(conversations)
if old is None or old.last_user_activity_at is None:
return None
new = await open_thread(
conversations, agent=old.agent_name, window=await window_of(conversations, old)
)
await conversations.close(old)
await conversations.say(new, ROTATED)
_log.info("голосовая ветка: %s -> %s", old.external_id, new.external_id)
return new