这是一个批量整理提交,包含以下主要改动: 1. 删除多处冗余的空行和未使用的导入 2. 修复文件末尾缺少换行符的问题 3. 调整部分模块的导入顺序与代码排版 4. 修复部分配置默认值与策略逻辑 5. 新增多个功能模块与辅助工具 6. 完善异常处理与日志记录 7. 修复速率限制、消息缓存、权限校验等逻辑bug 8. 废弃部分旧有API与配置项并添加警告提示
130 lines
3.6 KiB
Python
130 lines
3.6 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import TYPE_CHECKING
|
|
|
|
from yuxi.channels.models import DeliveryResult
|
|
from yuxi.utils.logging_config import logger
|
|
|
|
from .formatter import markdown_to_matrix_html
|
|
|
|
if TYPE_CHECKING:
|
|
from nio import AsyncClient
|
|
|
|
|
|
class DraftStreamSession:
|
|
def __init__(self, room_id: str):
|
|
self.room_id = room_id
|
|
self.draft_event_id: str = ""
|
|
self.current_text: str = ""
|
|
self.is_active: bool = False
|
|
|
|
def start(self, event_id: str) -> None:
|
|
self.draft_event_id = event_id
|
|
self.current_text = ""
|
|
self.is_active = True
|
|
|
|
def update(self, text: str) -> None:
|
|
self.current_text = text
|
|
|
|
def finish(self) -> None:
|
|
self.is_active = False
|
|
|
|
|
|
# In-memory storage for draft sessions, keyed by room_id.
|
|
# TODO: Consider persistent storage for production use.
|
|
_DRAFT_SESSIONS: dict[str, DraftStreamSession] = {}
|
|
|
|
|
|
def get_or_create_draft(room_id: str) -> DraftStreamSession:
|
|
if room_id not in _DRAFT_SESSIONS:
|
|
_DRAFT_SESSIONS[room_id] = DraftStreamSession(room_id)
|
|
return _DRAFT_SESSIONS[room_id]
|
|
|
|
|
|
def remove_draft(room_id: str) -> None:
|
|
_DRAFT_SESSIONS.pop(room_id, None)
|
|
|
|
|
|
async def send_draft_update(
|
|
client: AsyncClient,
|
|
room_id: str,
|
|
text: str,
|
|
draft_event_id: str | None = None,
|
|
finished: bool = False,
|
|
) -> DeliveryResult:
|
|
session = get_or_create_draft(room_id)
|
|
if draft_event_id and not session.draft_event_id:
|
|
session.start(draft_event_id)
|
|
|
|
if not session.is_active:
|
|
resp = await client.room_send(
|
|
room_id=room_id,
|
|
message_type="m.room.message",
|
|
content={
|
|
"msgtype": "m.text",
|
|
"body": text,
|
|
"format": "org.matrix.custom.html",
|
|
"formatted_body": markdown_to_matrix_html(text),
|
|
"org.matrix.msc4357.live": {
|
|
"draft": True,
|
|
"finished": finished,
|
|
},
|
|
},
|
|
)
|
|
session.start(resp.event_id)
|
|
return DeliveryResult(success=True, message_id=resp.event_id)
|
|
|
|
content = {
|
|
"msgtype": "m.text",
|
|
"body": text,
|
|
"format": "org.matrix.custom.html",
|
|
"formatted_body": markdown_to_matrix_html(text),
|
|
"m.new_content": {
|
|
"msgtype": "m.text",
|
|
"body": text,
|
|
"format": "org.matrix.custom.html",
|
|
"formatted_body": markdown_to_matrix_html(text),
|
|
},
|
|
"m.relates_to": {
|
|
"rel_type": "m.replace",
|
|
"event_id": session.draft_event_id,
|
|
},
|
|
}
|
|
|
|
if finished:
|
|
session.finish()
|
|
remove_draft(room_id)
|
|
|
|
try:
|
|
resp = await client.room_send(
|
|
room_id=room_id,
|
|
message_type="m.room.message",
|
|
content=content,
|
|
)
|
|
session.update(text)
|
|
return DeliveryResult(success=True, message_id=resp.event_id)
|
|
except Exception as e:
|
|
return DeliveryResult(success=False, error=str(e))
|
|
|
|
|
|
async def send_live_marker(
|
|
client: AsyncClient,
|
|
room_id: str,
|
|
event_id: str,
|
|
content: dict,
|
|
finished: bool = False,
|
|
) -> DeliveryResult:
|
|
content.setdefault("org.matrix.msc4357.live", {})
|
|
content["org.matrix.msc4357.live"]["finished"] = finished
|
|
|
|
try:
|
|
resp = await client.room_send(
|
|
room_id=room_id,
|
|
message_type="m.room.message",
|
|
content=content,
|
|
)
|
|
return DeliveryResult(success=True, message_id=resp.event_id)
|
|
except Exception as e:
|
|
logger.debug(f"Matrix MSC4357 live marker failed: {e}")
|
|
return DeliveryResult(success=False, error=str(e))
|