Expand image and edit support across messaging channels

This commit is contained in:
jxxghp
2026-04-11 22:10:54 +08:00
parent bf2d2cbd03
commit 2f53fd3108
12 changed files with 952 additions and 45 deletions

View File

@@ -18,6 +18,17 @@ from app.schemas.types import ModuleType
class QQBotModule(_ModuleBase, _MessageBase[QQBot]):
"""QQ Bot 通知模块"""
_IMAGE_SUFFIXES = (
".png",
".jpg",
".jpeg",
".gif",
".webp",
".bmp",
".tiff",
".svg",
)
def init_module(self) -> None:
self.stop()
super().init_service(service_name=QQBot.__name__.lower(), service_type=QQBot)
@@ -78,7 +89,8 @@ class QQBotModule(_ModuleBase, _MessageBase[QQBot]):
msg_type = msg_body.get("type")
content = (msg_body.get("content") or "").strip()
if not content:
images = self._extract_images(msg_body)
if not content and not images:
return None
if msg_type == "C2C_MESSAGE_CREATE":
@@ -86,13 +98,17 @@ class QQBotModule(_ModuleBase, _MessageBase[QQBot]):
user_openid = author.get("user_openid", "")
if not user_openid:
return None
logger.info(f"收到 QQ 私聊消息: userid={user_openid}, text={content[:50]}...")
logger.info(
f"收到 QQ 私聊消息: userid={user_openid}, "
f"text={(content or '')[:50]}..., images={len(images) if images else 0}"
)
return CommingMessage(
channel=MessageChannel.QQ,
source=client_config.name,
userid=user_openid,
username=user_openid,
text=content,
images=images,
)
elif msg_type == "GROUP_AT_MESSAGE_CREATE":
author = msg_body.get("author", {})
@@ -100,16 +116,65 @@ class QQBotModule(_ModuleBase, _MessageBase[QQBot]):
group_openid = msg_body.get("group_openid", "")
# 群聊用 group:group_openid 作为 userid便于回复时识别
userid = f"group:{group_openid}" if group_openid else member_openid
logger.info(f"收到 QQ 群消息: group={group_openid}, userid={member_openid}, text={content[:50]}...")
logger.info(
f"收到 QQ 群消息: group={group_openid}, userid={member_openid}, "
f"text={(content or '')[:50]}..., images={len(images) if images else 0}"
)
return CommingMessage(
channel=MessageChannel.QQ,
source=client_config.name,
userid=userid,
username=member_openid or group_openid,
text=content,
images=images,
)
return None
@classmethod
def _extract_images(cls, msg_body: dict) -> Optional[List[str]]:
images: List[str] = []
attachments = msg_body.get("attachments") or []
if isinstance(attachments, list):
for attachment in attachments:
if not isinstance(attachment, dict):
continue
url = attachment.get("url") or attachment.get("proxy_url")
if not url:
continue
content_type = (
attachment.get("content_type")
or attachment.get("mime_type")
or ""
).lower()
filename = (
attachment.get("filename")
or attachment.get("name")
or ""
).lower()
if content_type.startswith("image/") or filename.endswith(cls._IMAGE_SUFFIXES):
images.append(url)
for key in ("image", "image_url", "pic_url"):
value = msg_body.get(key)
if isinstance(value, str) and value.startswith("http"):
images.append(value)
extra_images = msg_body.get("images")
if isinstance(extra_images, list):
for item in extra_images:
if isinstance(item, str) and item.startswith("http"):
images.append(item)
elif isinstance(item, dict):
url = item.get("url") or item.get("image_url")
if isinstance(url, str) and url.startswith("http"):
images.append(url)
deduped = []
for image in images:
if image not in deduped:
deduped.append(image)
return deduped or None
def post_message(self, message: Notification, **kwargs) -> None:
for conf in self.get_configs().values():
if not self.check_message(message, conf.name):