97 lines
2.9 KiB
Python
97 lines
2.9 KiB
Python
from __future__ import annotations
|
|
|
|
import logging
|
|
|
|
from yuxi.channel.extensions.googlechat.api import (
|
|
delete_message,
|
|
send_message,
|
|
update_message,
|
|
)
|
|
from yuxi.channel.extensions.googlechat.formatting import (
|
|
build_typing_indicator_text,
|
|
chunk_markdown_text,
|
|
resolve_bot_display_name,
|
|
)
|
|
from yuxi.channel.extensions.googlechat.types import ResolvedGoogleChatAccount
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class TypingPlaceholder:
|
|
def __init__(self, message_name: str, space_name: str, consumed: bool = False):
|
|
self.message_name = message_name
|
|
self.space_name = space_name
|
|
self.consumed = consumed
|
|
|
|
|
|
async def send_typing_placeholder(
|
|
account: ResolvedGoogleChatAccount,
|
|
space_name: str,
|
|
bot_name: str | None = None,
|
|
) -> TypingPlaceholder:
|
|
name = bot_name or resolve_bot_display_name(account.config if hasattr(account, "config") else {})
|
|
text = build_typing_indicator_text(name)
|
|
result = await send_message(account, space_name, text)
|
|
message_name = result.get("name", "")
|
|
return TypingPlaceholder(message_name=message_name, space_name=space_name)
|
|
|
|
|
|
async def deliver_text_chunk(
|
|
account: ResolvedGoogleChatAccount,
|
|
space_name: str,
|
|
text: str,
|
|
placeholder: TypingPlaceholder | None = None,
|
|
thread_name: str | None = None,
|
|
) -> str:
|
|
if placeholder and not placeholder.consumed:
|
|
await update_message(account, placeholder.message_name, text)
|
|
placeholder.consumed = True
|
|
return placeholder.message_name
|
|
|
|
if placeholder and placeholder.consumed:
|
|
result = await send_message(account, space_name, text, thread_name=thread_name)
|
|
return result.get("name", "")
|
|
|
|
result = await send_message(account, space_name, text, thread_name=thread_name)
|
|
return result.get("name", "")
|
|
|
|
|
|
async def deliver_text_with_streaming(
|
|
account: ResolvedGoogleChatAccount,
|
|
space_name: str,
|
|
full_text: str,
|
|
bot_name: str | None = None,
|
|
thread_name: str | None = None,
|
|
text_chunk_limit: int = 4000,
|
|
) -> list[str]:
|
|
chunks = chunk_markdown_text(full_text, text_chunk_limit)
|
|
if not chunks:
|
|
return []
|
|
|
|
placeholder = await send_typing_placeholder(account, space_name, bot_name)
|
|
message_names = []
|
|
|
|
for i, chunk in enumerate(chunks):
|
|
try:
|
|
name = await deliver_text_chunk(
|
|
account, space_name, chunk, placeholder if i == 0 else None, thread_name
|
|
)
|
|
if name:
|
|
message_names.append(name)
|
|
except Exception as e:
|
|
logger.warning("Failed to deliver chunk %d: %s", i, e)
|
|
|
|
return message_names
|
|
|
|
|
|
async def clear_typing_placeholder(
|
|
account: ResolvedGoogleChatAccount,
|
|
placeholder: TypingPlaceholder,
|
|
) -> None:
|
|
try:
|
|
await delete_message(account, placeholder.message_name)
|
|
except Exception:
|
|
try:
|
|
await update_message(account, placeholder.message_name, "")
|
|
except Exception:
|
|
pass |