68 lines
1.7 KiB
Python
68 lines
1.7 KiB
Python
|
|
import asyncio
|
||
|
|
import logging
|
||
|
|
import re
|
||
|
|
|
||
|
|
logger = logging.getLogger("yuxi.channel.xmpp.streaming")
|
||
|
|
|
||
|
|
|
||
|
|
def chunk_text(
|
||
|
|
text: str,
|
||
|
|
min_chars: int = 800,
|
||
|
|
max_chars: int = 2000,
|
||
|
|
) -> list[str]:
|
||
|
|
if len(text) <= max_chars:
|
||
|
|
return [text]
|
||
|
|
|
||
|
|
paragraphs = re.split(r"\n\s*\n", text)
|
||
|
|
chunks = []
|
||
|
|
current = ""
|
||
|
|
|
||
|
|
for para in paragraphs:
|
||
|
|
candidate = f"{current}\n\n{para}".strip() if current else para
|
||
|
|
if len(candidate) > max_chars and current:
|
||
|
|
chunks.append(current)
|
||
|
|
current = para
|
||
|
|
else:
|
||
|
|
current = candidate
|
||
|
|
|
||
|
|
if current:
|
||
|
|
chunks.append(current)
|
||
|
|
|
||
|
|
merged = []
|
||
|
|
buf = ""
|
||
|
|
for chunk in chunks:
|
||
|
|
candidate = f"{buf}\n\n{chunk}".strip() if buf else chunk
|
||
|
|
if len(candidate) <= max_chars:
|
||
|
|
buf = candidate
|
||
|
|
else:
|
||
|
|
if buf:
|
||
|
|
merged.append(buf)
|
||
|
|
buf = chunk
|
||
|
|
if buf:
|
||
|
|
merged.append(buf)
|
||
|
|
|
||
|
|
return merged if merged else [text]
|
||
|
|
|
||
|
|
|
||
|
|
async def stream_xmpp_blocks(
|
||
|
|
gateway,
|
||
|
|
target_id: str,
|
||
|
|
chunks: list[str],
|
||
|
|
typing_interval_ms: int = 500,
|
||
|
|
) -> None:
|
||
|
|
from yuxi.channel.extensions.xmpp.outbound import send_xmpp_text, send_xmpp_typing
|
||
|
|
|
||
|
|
for i, chunk in enumerate(chunks):
|
||
|
|
if i == 0:
|
||
|
|
await send_xmpp_typing(gateway, target_id, composing=True)
|
||
|
|
await asyncio.sleep(typing_interval_ms / 1000.0)
|
||
|
|
|
||
|
|
await send_xmpp_text(gateway, target_id, chunk)
|
||
|
|
|
||
|
|
if i < len(chunks) - 1:
|
||
|
|
await asyncio.sleep(typing_interval_ms / 1000.0)
|
||
|
|
await send_xmpp_typing(gateway, target_id, composing=True)
|
||
|
|
await asyncio.sleep(typing_interval_ms / 1000.0)
|
||
|
|
|
||
|
|
await send_xmpp_typing(gateway, target_id, composing=False)
|