feat(reaction): 将文字反馈调整为表情反馈

This commit is contained in:
SXP-Simon
2026-03-19 15:12:44 +08:00
parent a71a0a34db
commit 3ec4de1c99
5 changed files with 132 additions and 4 deletions
+8 -4
View File
@@ -459,6 +459,7 @@ class GroupDailyAnalysis(Star):
分析群聊日常活动(跨平台支持)
用法: /群分析 [天数]
"""
event.should_call_llm(True) # 阻止默认 LLM 解析
group_id = self._get_group_id_from_event(event)
platform_id = self._get_platform_id_from_event(event)
@@ -499,7 +500,11 @@ class GroupDailyAnalysis(Star):
)
TraceContext.set(trace_id)
yield event.plain_result("🔍 正在启动跨平台分析引擎,正在拉取最近消息...")
# 使用表情回应代替文本回复
adapter = self.bot_manager.get_adapter(platform_id)
orig_msg_id = getattr(event.message_obj, "message_id", None)
if adapter and orig_msg_id:
await adapter.set_reaction(event.get_group_id(), orig_msg_id, "🔍") # 🔍
try:
# 调用 DDD 应用级服务
@@ -515,9 +520,8 @@ class GroupDailyAnalysis(Star):
yield event.plain_result("❌ 分析失败,原因未知")
return
yield event.plain_result(
f"📊 已获取{result['messages_count']}条消息,正在生成渲染报告..."
)
if adapter and orig_msg_id:
await adapter.set_reaction(event.get_group_id(), orig_msg_id, "📊") # 📊
async for res in self._send_analysis_report(event, result):
yield res
@@ -749,3 +749,39 @@ class DiscordAdapter(PlatformAdapter):
) -> dict[str, str | None]:
"""批量获取头像的最佳实践。"""
return {uid: await self.get_user_avatar_url(uid, size) for uid in user_ids}
async def set_reaction(
self, group_id: str, message_id: str, emoji: str | int, is_add: bool = True
) -> bool:
"""
Discord 实现消息回应。
"""
if not discord:
return False
try:
# 映射常见的表情 ID 为文字表情,使分析状态在跨平台保持一致
mapping = {289: "🔍", 424: "📊", 124: ""}
emoji_to_use = emoji
if isinstance(emoji, int) or (isinstance(emoji, str) and emoji.isdigit()):
emoji_to_use = mapping.get(int(emoji), emoji)
channel_id = int(group_id)
channel = self._discord_client.get_channel(channel_id)
if not channel:
channel = await self._discord_client.fetch_channel(channel_id)
if not hasattr(channel, "get_partial_message"):
# 如果较低版本的 SDK 没这个方法,则直接 fetch
msg = await channel.fetch_message(int(message_id))
else:
msg = channel.get_partial_message(int(message_id))
if is_add:
await msg.add_reaction(emoji_to_use)
else:
await msg.remove_reaction(emoji_to_use, self._discord_client.user)
return True
except Exception as e:
logger.debug(f"Discord set_reaction 失败: {e}")
return False
@@ -1346,3 +1346,30 @@ class OneBotAdapter(PlatformAdapter):
logger.info(f"[群分析相册] 未能找到名为 '{album_name}' 的相册 (群 {group_id})")
return None
async def set_reaction(
self, group_id: str, message_id: str, emoji: str | int, is_add: bool = True
) -> bool:
"""
OneBot 实现消息回应 (set_msg_emoji_like)。
支持 Go-CQHTTP, NapCat, Lagrange 等 OneBot 实现。
"""
try:
# 语义化映射:根据用户喜好精细化 OneBot 端的降级
emoji_id = str(emoji)
if str(emoji) == "🔍":
emoji_id = "289" # 🫣 表情 (表示任务已接收)
elif str(emoji) == "📊":
emoji_id = "124" # 👌 表情 (表示任务处理完成)
await self.bot.call_action(
"set_msg_emoji_like",
message_id=int(message_id),
emoji_id=emoji_id,
emoji_type="1", # 还原为最稳定的系统表情类型
set=is_add,
)
return True
except Exception as e:
logger.debug(f"OneBot set_reaction 失败 (API 可能不支持): {e}")
return False
@@ -890,6 +890,50 @@ class TelegramAdapter(PlatformAdapter):
pairs = await asyncio.gather(*(_fetch_avatar(uid) for uid in user_ids))
return dict(pairs)
async def set_reaction(
self, group_id: str, message_id: str, emoji: str | int, is_add: bool = True
) -> bool:
"""
Telegram 实现消息回应。
"""
client = self._telegram_client
if not client:
return False
try:
# 映射常见的表情 ID 为文字表情
mapping = {289: "🔍", 424: "📊", 124: ""}
emoji_to_use = emoji
if isinstance(emoji, int) or (isinstance(emoji, str) and emoji.isdigit()):
emoji_to_use = mapping.get(int(emoji), emoji)
chat_id, _ = self._parse_group_id(group_id)
# 只有开启了库支持且版本符合时才尝试。set_message_reaction 是 Bot API 7.0 (PTB 20.8+) 特性。
if hasattr(client, "set_message_reaction"):
try:
from telegram import ReactionTypeEmoji
reaction = [ReactionTypeEmoji(emoji=emoji_to_use)] if is_add else []
await client.set_message_reaction(
chat_id=chat_id,
message_id=int(message_id),
reaction=reaction,
)
return True
except ImportError:
# 如果版本太低没有 ReactionTypeEmoji,尝试直接传字符串 (有些实现支持)
await client.set_message_reaction(
chat_id=chat_id,
message_id=int(message_id),
reaction=emoji_to_use if is_add else None,
)
return True
return False
except Exception as e:
logger.debug(f"[Telegram] set_reaction 失败: {e}")
return False
# ==================== 辅助方法 ====================
def _parse_group_id(self, group_id: str) -> tuple[str, str | None]:
+17
View File
@@ -89,3 +89,20 @@ class PlatformAdapter(
list[dict]: 转换后的平台原生消息字典列表
"""
raise NotImplementedError
async def set_reaction(
self, group_id: str, message_id: str, emoji: str | int, is_add: bool = True
) -> bool:
"""
对消息添加/移除表情回应。
Args:
group_id (str): 群组/频道 ID
message_id (str): 消息 ID
emoji (str | int): 表情代码或字符
is_add (bool): True 为添加,False 为移除
Returns:
bool: 平台是否支持并成功执行
"""
return False