ErisPulse-MatrixAdapter 4.3.0__tar.gz → 4.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {erispulse_matrixadapter-4.3.0 → erispulse_matrixadapter-4.4.0}/ErisPulse_MatrixAdapter.egg-info/PKG-INFO +1 -1
- {erispulse_matrixadapter-4.3.0 → erispulse_matrixadapter-4.4.0}/MatrixAdapter/Core.py +100 -1
- {erispulse_matrixadapter-4.3.0 → erispulse_matrixadapter-4.4.0}/PKG-INFO +1 -1
- {erispulse_matrixadapter-4.3.0 → erispulse_matrixadapter-4.4.0}/pyproject.toml +1 -1
- {erispulse_matrixadapter-4.3.0 → erispulse_matrixadapter-4.4.0}/ErisPulse_MatrixAdapter.egg-info/SOURCES.txt +0 -0
- {erispulse_matrixadapter-4.3.0 → erispulse_matrixadapter-4.4.0}/ErisPulse_MatrixAdapter.egg-info/dependency_links.txt +0 -0
- {erispulse_matrixadapter-4.3.0 → erispulse_matrixadapter-4.4.0}/ErisPulse_MatrixAdapter.egg-info/entry_points.txt +0 -0
- {erispulse_matrixadapter-4.3.0 → erispulse_matrixadapter-4.4.0}/ErisPulse_MatrixAdapter.egg-info/requires.txt +0 -0
- {erispulse_matrixadapter-4.3.0 → erispulse_matrixadapter-4.4.0}/ErisPulse_MatrixAdapter.egg-info/top_level.txt +0 -0
- {erispulse_matrixadapter-4.3.0 → erispulse_matrixadapter-4.4.0}/LICENSE +0 -0
- {erispulse_matrixadapter-4.3.0 → erispulse_matrixadapter-4.4.0}/MatrixAdapter/Converter.py +0 -0
- {erispulse_matrixadapter-4.3.0 → erispulse_matrixadapter-4.4.0}/MatrixAdapter/NioSession.py +0 -0
- {erispulse_matrixadapter-4.3.0 → erispulse_matrixadapter-4.4.0}/MatrixAdapter/__init__.py +0 -0
- {erispulse_matrixadapter-4.3.0 → erispulse_matrixadapter-4.4.0}/README.md +0 -0
- {erispulse_matrixadapter-4.3.0 → erispulse_matrixadapter-4.4.0}/setup.cfg +0 -0
- {erispulse_matrixadapter-4.3.0 → erispulse_matrixadapter-4.4.0}/test/test.py +0 -0
- {erispulse_matrixadapter-4.3.0 → erispulse_matrixadapter-4.4.0}/test/test_e2ee.py +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
+
import html as _html
|
|
2
3
|
import mimetypes
|
|
3
4
|
import uuid
|
|
4
5
|
from dataclasses import dataclass, field
|
|
@@ -14,12 +15,63 @@ from ErisPulse.Core.i18n import i18n
|
|
|
14
15
|
from .Converter import MatrixConverter
|
|
15
16
|
from .NioSession import NIO_AVAILABLE, NioSession, NioSessionError
|
|
16
17
|
|
|
18
|
+
|
|
19
|
+
def _forward_node_text(node: Dict) -> str:
|
|
20
|
+
"""提取合并转发节点 content 中全部 text 段文本(段间直接连接)"""
|
|
21
|
+
data = node.get("data") or {}
|
|
22
|
+
return "".join(
|
|
23
|
+
str(seg.get("data", {}).get("text") or "")
|
|
24
|
+
for seg in (data.get("content") or [])
|
|
25
|
+
if isinstance(seg, dict) and seg.get("type") == "text"
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _forward_nodes_plain(nodes, separator: str = "\n") -> str:
|
|
30
|
+
"""合并转发节点降级纯文本:每条「昵称: 正文」"""
|
|
31
|
+
lines = []
|
|
32
|
+
for node in nodes if isinstance(nodes, list) else [nodes]:
|
|
33
|
+
if not isinstance(node, dict):
|
|
34
|
+
continue
|
|
35
|
+
data = node.get("data") or {}
|
|
36
|
+
nickname = str(data.get("nickname") or "").strip()
|
|
37
|
+
text = _forward_node_text(node).strip()
|
|
38
|
+
if nickname and text:
|
|
39
|
+
lines.append(f"{nickname}: {text}")
|
|
40
|
+
elif text:
|
|
41
|
+
lines.append(text)
|
|
42
|
+
return separator.join(lines)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _build_forward_matrix_html(nodes, title: str = "合并聊天记录") -> str:
|
|
46
|
+
"""渲染合并转发为 Matrix formatted_body(白名单标签:p/strong/hr/blockquote/br)
|
|
47
|
+
|
|
48
|
+
Matrix HTML 白名单会剥离 details/summary 与内联样式,故用 blockquote 引用块形态。
|
|
49
|
+
"""
|
|
50
|
+
blocks = []
|
|
51
|
+
for node in nodes if isinstance(nodes, list) else [nodes]:
|
|
52
|
+
if not isinstance(node, dict):
|
|
53
|
+
continue
|
|
54
|
+
data = node.get("data") or {}
|
|
55
|
+
nickname = str(data.get("nickname") or "").strip()
|
|
56
|
+
text = _forward_node_text(node).strip()
|
|
57
|
+
if not text:
|
|
58
|
+
continue
|
|
59
|
+
header = f"<strong>{_html.escape(nickname)}</strong><br/>" if nickname else ""
|
|
60
|
+
body = _html.escape(text).replace("\n", "<br/>")
|
|
61
|
+
blocks.append(f"<blockquote>{header}{body}</blockquote>")
|
|
62
|
+
if not blocks:
|
|
63
|
+
return ""
|
|
64
|
+
return (
|
|
65
|
+
f"<p><strong>{_html.escape(title)}</strong></p>"
|
|
66
|
+
+ "<hr/>".join(blocks)
|
|
67
|
+
)
|
|
68
|
+
|
|
17
69
|
try:
|
|
18
70
|
from ErisPulse.runtime.tasks import spawn_background
|
|
19
71
|
except ImportError: # pragma: no cover
|
|
20
72
|
spawn_background = None
|
|
21
73
|
|
|
22
|
-
__version__ = "4.
|
|
74
|
+
__version__ = "4.4.0"
|
|
23
75
|
|
|
24
76
|
# 软依赖的框架最低版本(运行时检测,仅提示不强制)
|
|
25
77
|
MIN_FRAMEWORK_VERSION = (2, 7, 1)
|
|
@@ -183,7 +235,54 @@ class MatrixAdapter(BaseAdapter):
|
|
|
183
235
|
[{"type": "html", "data": {"html": html, "fallback": fallback}}]
|
|
184
236
|
)
|
|
185
237
|
|
|
238
|
+
def MergeForward(self, nodes, title: str = "合并聊天记录"):
|
|
239
|
+
"""发送合并转发消息(Matrix formatted_body:标题 + 每条 blockquote 引用块)
|
|
240
|
+
|
|
241
|
+
:param nodes: go-cqhttp 扩展的 OneBot v11 合并转发节点数组(或单节点 dict)
|
|
242
|
+
:param title: 标题
|
|
243
|
+
:return: asyncio.Task
|
|
244
|
+
"""
|
|
245
|
+
if isinstance(nodes, dict):
|
|
246
|
+
nodes = [nodes]
|
|
247
|
+
return asyncio.create_task(
|
|
248
|
+
self._do_send_merge_forward(
|
|
249
|
+
[n for n in nodes if isinstance(n, dict)], title
|
|
250
|
+
)
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
async def _do_send_merge_forward(self, nodes, title: str = "合并聊天记录"):
|
|
254
|
+
html = _build_forward_matrix_html(nodes, title)
|
|
255
|
+
if not html:
|
|
256
|
+
return self._adapter.make_error(
|
|
257
|
+
retcode=10006, message="MergeForward: 节点无有效文本内容"
|
|
258
|
+
)
|
|
259
|
+
return await self._do_send_raw_ob12(
|
|
260
|
+
[
|
|
261
|
+
{
|
|
262
|
+
"type": "html",
|
|
263
|
+
"data": {
|
|
264
|
+
"html": html,
|
|
265
|
+
"fallback": _forward_nodes_plain(nodes),
|
|
266
|
+
},
|
|
267
|
+
}
|
|
268
|
+
]
|
|
269
|
+
)
|
|
270
|
+
|
|
186
271
|
def Raw_ob12(self, message: List[Dict], **kwargs):
|
|
272
|
+
# node 段解析:纯 node 列表自动路由合并转发;混合列表降级为纯文本
|
|
273
|
+
if message and all(
|
|
274
|
+
isinstance(seg, dict) and seg.get("type") == "node" for seg in message
|
|
275
|
+
):
|
|
276
|
+
return asyncio.create_task(
|
|
277
|
+
self._do_send_merge_forward([seg for seg in message])
|
|
278
|
+
)
|
|
279
|
+
message = [
|
|
280
|
+
{"type": "text", "data": {"text": _forward_nodes_plain(seg)}}
|
|
281
|
+
if isinstance(seg, dict) and seg.get("type") == "node"
|
|
282
|
+
else seg
|
|
283
|
+
for seg in message
|
|
284
|
+
]
|
|
285
|
+
|
|
187
286
|
async def _send():
|
|
188
287
|
return await self._do_send_raw_ob12(message, **kwargs)
|
|
189
288
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|