优化联系人信息,解决总结时使用了其他群的备注信息
This commit is contained in:
@@ -3,7 +3,6 @@
|
||||
|
||||
import logging.config
|
||||
import os
|
||||
import shutil
|
||||
|
||||
import yaml
|
||||
|
||||
@@ -14,26 +13,14 @@ class Config(object):
|
||||
|
||||
def _load_config(self) -> dict:
|
||||
pwd = os.path.dirname(os.path.abspath(__file__))
|
||||
try:
|
||||
with open(f"{pwd}/config.yaml", "rb") as fp:
|
||||
yconfig = yaml.safe_load(fp)
|
||||
except FileNotFoundError:
|
||||
shutil.copyfile(f"{pwd}/config.yaml.template", f"{pwd}/config.yaml")
|
||||
with open(f"{pwd}/config.yaml", "rb") as fp:
|
||||
yconfig = yaml.safe_load(fp)
|
||||
|
||||
with open(f"{pwd}/config.yaml", "rb") as fp:
|
||||
yconfig = yaml.safe_load(fp)
|
||||
return yconfig
|
||||
|
||||
def reload(self) -> None:
|
||||
yconfig = self._load_config()
|
||||
logging.config.dictConfig(yconfig["logging"])
|
||||
|
||||
self.CHATGPT = yconfig.get("chatgpt", {})
|
||||
self.TIGERBOT = yconfig.get("tigerbot", {})
|
||||
self.XINGHUO_WEB = yconfig.get("xinghuo_web", {})
|
||||
self.CHATGLM = yconfig.get("chatglm", {})
|
||||
self.BardAssistant = yconfig.get("bard", {})
|
||||
self.ZhiPu = yconfig.get("zhipu", {})
|
||||
self.CLAUDE = yconfig.get("claude", {})
|
||||
self.DEEPSEEK = yconfig.get("deepseek", {})
|
||||
self.DOUBAO = yconfig.get("doubao", {})
|
||||
|
||||
27
constants.py
27
constants.py
@@ -1,27 +0,0 @@
|
||||
from enum import IntEnum, unique
|
||||
|
||||
|
||||
@unique
|
||||
class ChatType(IntEnum):
|
||||
# UnKnown = 0 # 未知, 即未设置
|
||||
TIGER_BOT = 1 # TigerBot
|
||||
CHATGPT = 2 # ChatGPT
|
||||
XINGHUO_WEB = 3 # 讯飞星火
|
||||
CHATGLM = 4 # ChatGLM
|
||||
BardAssistant = 5 # Google Bard
|
||||
ZhiPu = 6 # ZhiPu
|
||||
CLAUDE = 7 # CLAUDE
|
||||
DOUBAO = 8 # doubao
|
||||
|
||||
@staticmethod
|
||||
def is_in_chat_types(chat_type: int) -> bool:
|
||||
if chat_type in [ChatType.TIGER_BOT.value, ChatType.CHATGPT.value,
|
||||
ChatType.XINGHUO_WEB.value, ChatType.CHATGLM.value,
|
||||
ChatType.BardAssistant.value, ChatType.ZhiPu.value, ChatType.CLAUDE.value,
|
||||
ChatType.DOUBAO.value]:
|
||||
return True
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def help_hint() -> str:
|
||||
return str({member.value: member.name for member in ChatType}).replace('{', '').replace('}', '')
|
||||
@@ -12,7 +12,6 @@ from db.base import BaseDBOperator
|
||||
from db.connection import DBConnectionManager
|
||||
|
||||
|
||||
|
||||
class ContactsDBOperator(BaseDBOperator):
|
||||
"""微信联系人数据库操作类"""
|
||||
|
||||
@@ -153,8 +152,8 @@ class ContactsDBOperator(BaseDBOperator):
|
||||
'small_head_img_url': contact.get('SmallHeadImgUrl', ''),
|
||||
'description': '', # 可根据需要补充
|
||||
'card_img_url': '', # 可根据需要补充
|
||||
'label_list': '', # 可根据需要补充
|
||||
'phone_num_list': '',# 可根据需要补充
|
||||
'label_list': '', # 可根据需要补充
|
||||
'phone_num_list': '', # 可根据需要补充
|
||||
'type': contact_type
|
||||
}
|
||||
|
||||
@@ -289,9 +288,9 @@ class ContactsDBOperator(BaseDBOperator):
|
||||
SELECT chatroom_id as user_name, nick_name, remark as remark
|
||||
FROM t_chatrooms
|
||||
"""
|
||||
|
||||
|
||||
results = self.execute_query(sql)
|
||||
|
||||
|
||||
contacts_dict = {}
|
||||
for result in results:
|
||||
user_name = result.get('user_name')
|
||||
@@ -338,6 +337,7 @@ class ContactsDBOperator(BaseDBOperator):
|
||||
except Exception as e:
|
||||
self.LOG.error(f"获取所有联系人名称映射失败: {e}")
|
||||
return {}
|
||||
|
||||
def save_chatroom_member_simple(self, chatroom_id: str, member_details: List[Dict]) -> bool:
|
||||
"""
|
||||
保存群成员简要信息到数据库,兼容不同数据结构
|
||||
@@ -405,6 +405,7 @@ class ContactsDBOperator(BaseDBOperator):
|
||||
except Exception as e:
|
||||
self.LOG.error(f"保存群 {chatroom_id} 成员信息失败: {e}")
|
||||
return False
|
||||
|
||||
def save_chatroom_member_detail(self, chatroom_id: str, member_details: List[Dict]) -> bool:
|
||||
"""保存群成员详细信息到数据库
|
||||
|
||||
@@ -540,7 +541,8 @@ class ContactsDBOperator(BaseDBOperator):
|
||||
'chat_room_owner': chatroom_data.get('ChatRoomOwner', ''),
|
||||
'small_head_img_url': chatroom_data.get('SmallHeadImgUrl', ''),
|
||||
# 成员列表可选存储为JSON字符串
|
||||
'member_list': json.dumps(chatroom_data.get('NewChatroomData', {}).get('ChatRoomMember', []), ensure_ascii=False)
|
||||
'member_list': json.dumps(chatroom_data.get('NewChatroomData', {}).get('ChatRoomMember', []),
|
||||
ensure_ascii=False)
|
||||
}
|
||||
|
||||
fields = ', '.join(data.keys())
|
||||
@@ -598,7 +600,7 @@ class ContactsDBOperator(BaseDBOperator):
|
||||
self.LOG.error(f"删除群聊{chatroom_id}信息失败: {e}")
|
||||
return False
|
||||
|
||||
#新增获取群列表接口
|
||||
# 新增获取群列表接口
|
||||
def get_chatroom_list(self) -> List[dict]:
|
||||
"""获取群列表"""
|
||||
try:
|
||||
@@ -612,7 +614,7 @@ class ContactsDBOperator(BaseDBOperator):
|
||||
self.LOG.error(f"获取群列表失败: {e}")
|
||||
return []
|
||||
|
||||
#新增获取群成员列表接口
|
||||
# 新增获取群成员列表接口
|
||||
def get_chatroom_member_list(self, chatroom_id: str) -> List[dict]:
|
||||
"""获取群成员列表"""
|
||||
try:
|
||||
@@ -623,7 +625,18 @@ class ContactsDBOperator(BaseDBOperator):
|
||||
self.LOG.error(f"获取群{chatroom_id}成员列表失败: {e}")
|
||||
return []
|
||||
|
||||
#新增获取群成员信息接口
|
||||
# 获取群成员的昵称信息
|
||||
def get_chatroom_member_list_name_all(self) -> List[dict]:
|
||||
"""获取群成员列表"""
|
||||
try:
|
||||
sql = "SELECT chatroom_id,wxid, COALESCE(NULLIF(display_name,''), nick_name, wxid) as nick_name FROM t_chatroom_member"
|
||||
results = self.execute_query(sql)
|
||||
return results
|
||||
except Exception as e:
|
||||
self.LOG.error(f"获取群成员列表失败: {e}")
|
||||
return []
|
||||
|
||||
# 新增获取群成员信息接口
|
||||
def get_chatroom_member_info(self, chatroom_id: str, wxid: str) -> Optional[dict]:
|
||||
"""获取群成员信息"""
|
||||
try:
|
||||
@@ -634,7 +647,7 @@ class ContactsDBOperator(BaseDBOperator):
|
||||
self.LOG.error(f"获取群{chatroom_id}成员{wxid}信息失败: {e}")
|
||||
return None
|
||||
|
||||
#新增群信息删除功能
|
||||
# 新增群信息删除功能
|
||||
def delete_chatroom_all_info(self, chatroom_id: str) -> bool:
|
||||
"""删除群成员信息"""
|
||||
try:
|
||||
@@ -649,7 +662,7 @@ class ContactsDBOperator(BaseDBOperator):
|
||||
self.LOG.error(f"删除群{chatroom_id}信息失败: {e}")
|
||||
return False
|
||||
|
||||
#新增删除所有联系人功能
|
||||
# 新增删除所有联系人功能
|
||||
def delete_all_contacts(self) -> bool:
|
||||
"""删除所有联系人信息"""
|
||||
try:
|
||||
@@ -660,8 +673,8 @@ class ContactsDBOperator(BaseDBOperator):
|
||||
except Exception as e:
|
||||
self.LOG.error(f"删除所有联系人信息失败: {e}")
|
||||
return False
|
||||
|
||||
#新增获取所有联系人头像信息接口
|
||||
|
||||
# 新增获取所有联系人头像信息接口
|
||||
def get_all_contacts_avatar(self) -> Dict[str, str]:
|
||||
"""获取所有联系人头像信息"""
|
||||
try:
|
||||
@@ -676,9 +689,9 @@ class ContactsDBOperator(BaseDBOperator):
|
||||
FROM t_chatrooms
|
||||
"""
|
||||
results = self.execute_query(sql)
|
||||
#返回DICT
|
||||
# 返回DICT
|
||||
results = {result['user_name']: result['small_head_img_url'] for result in results}
|
||||
return results
|
||||
except Exception as e:
|
||||
self.LOG.error(f"获取所有联系人头像信息失败: {e}")
|
||||
return []
|
||||
return []
|
||||
|
||||
@@ -6,6 +6,7 @@ import xml.etree.ElementTree as ET
|
||||
from base.plugin_common.message_plugin_interface import MessagePluginInterface
|
||||
from base.plugin_common.plugin_interface import PluginStatus
|
||||
from utils.robot_cmd.robot_command import Feature, PermissionStatus, GroupBotManager
|
||||
from utils.wechat.contact_manager import ContactManager
|
||||
from wechat_ipad import WechatAPIClient
|
||||
|
||||
|
||||
@@ -118,10 +119,12 @@ class GroupMemberChangePlugin(MessagePluginInterface):
|
||||
|
||||
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
member_wxids = [wxid]
|
||||
|
||||
await bot.send_at_message(roomid, f"👏欢迎 {nickname} 加入群聊!🎉", member_wxids)
|
||||
members = await bot.get_chatroom_member_detail(wxid, roomid)
|
||||
head_url = members.get("SmallHeadImgUrl") or members.get("BigHeadImgUrl") or ""
|
||||
# 更新联系人信息
|
||||
ContactManager.get_instance().update_head_image(wxid, head_url)
|
||||
ContactManager.get_instance().update_group_members(roomid, wxid, nickname)
|
||||
|
||||
xml_content = f"""
|
||||
<appmsg appid="" sdkver="1">
|
||||
|
||||
@@ -9,6 +9,7 @@ import requests
|
||||
|
||||
from utils.revoke.message_auto_revoke import MessageAutoRevoke
|
||||
from utils.string_utils import remove_trailing_content
|
||||
from utils.wechat.contact_manager import ContactManager
|
||||
from utils.wechat.message_to_db import MessageStorage
|
||||
from utils.compress_chat_data import compress_chat_data
|
||||
from base.plugin_common.message_plugin_interface import MessagePluginInterface
|
||||
@@ -109,8 +110,9 @@ class MessageSummaryPlugin(MessagePluginInterface):
|
||||
return False, None
|
||||
# 从消息历史中获取群聊记录
|
||||
all_contacts: dict = message.get("all_contacts")
|
||||
group_members: dict = ContactManager.get_instance().get_group_members()
|
||||
|
||||
chat_content = self.message_storage.get_messages(group_id, all_contacts)
|
||||
chat_content = self.message_storage.get_messages(group_id, group_members)
|
||||
if len(chat_content) < 100:
|
||||
return False, None
|
||||
|
||||
@@ -141,11 +143,13 @@ class MessageSummaryPlugin(MessagePluginInterface):
|
||||
await self.bot.send_image_message(group_id, Path(image_path))
|
||||
else:
|
||||
|
||||
client_msg_id, create_time, new_msg_id = await self.bot.send_text_message(group_id, "❌ 生成总结图片失败")
|
||||
client_msg_id, create_time, new_msg_id = await self.bot.send_text_message(group_id,
|
||||
"❌ 生成总结图片失败")
|
||||
self.revoke.add_message_to_revoke(group_id, client_msg_id, create_time, new_msg_id, 5)
|
||||
except Exception as e:
|
||||
self.LOG.error(f"异步生成总结失败: {e}")
|
||||
client_msg_id, create_time, new_msg_id = await self.bot.send_text_message(group_id, f"❌ 生成总结失败: {str(e)}")
|
||||
client_msg_id, create_time, new_msg_id = await self.bot.send_text_message(group_id,
|
||||
f"❌ 生成总结失败: {str(e)}")
|
||||
self.revoke.add_message_to_revoke(group_id, client_msg_id, create_time, new_msg_id, 5)
|
||||
|
||||
def _sanitize_group_name(self, group_name: str) -> str:
|
||||
|
||||
20
robot.py
20
robot.py
@@ -185,7 +185,8 @@ class Robot:
|
||||
self.allContacts = self.get_all_contacts()
|
||||
friends = await self.ipad_bot.get_contract_list()
|
||||
self.head_images = self.get_all_head_images()
|
||||
self.contact_manager.set_contacts(self.allContacts, friends, self.head_images)
|
||||
self.all_chatroom_members = self.contacts_db.get_chatroom_member_list_name_all()
|
||||
self.contact_manager.set_contacts(self.allContacts, friends, self.head_images, self.all_chatroom_members)
|
||||
|
||||
self.message_storage = MessageStorage(self.ipad_bot)
|
||||
|
||||
@@ -361,10 +362,6 @@ class Robot:
|
||||
try:
|
||||
# self.LOG.debug(f"message: {message}")
|
||||
# 消息已经是WxMessage对象,直接使用其属性和方法
|
||||
from_user = message.sender
|
||||
to_user = message.to_user
|
||||
content = message.content
|
||||
msg_type = message.msg_type
|
||||
|
||||
# 判断是否为群消息
|
||||
is_group = message.from_group()
|
||||
@@ -409,7 +406,9 @@ class Robot:
|
||||
self.head_images[wxid] = small_head_img_url
|
||||
|
||||
friends = await self.ipad_bot.get_contract_list()
|
||||
self.contact_manager.set_contacts(self.allContacts, friends, self.head_images)
|
||||
self.all_chatroom_members = self.contacts_db.get_chatroom_member_list_name_all()
|
||||
self.contact_manager.set_contacts(self.allContacts, friends, self.head_images,
|
||||
self.all_chatroom_members)
|
||||
self.LOG.info(f"已更新群 {group_id} 的成员信息")
|
||||
except Exception as e:
|
||||
self.LOG.error(f"获取群成员信息失败: {e}")
|
||||
@@ -459,7 +458,7 @@ class Robot:
|
||||
"""刷新联系人信息"""
|
||||
self.allContacts = self.get_all_contacts()
|
||||
friends = await self.ipad_bot.get_contract_list()
|
||||
self.contact_manager.refresh_contacts(self.allContacts,friends)
|
||||
self.contact_manager.refresh_contacts(self.allContacts, friends)
|
||||
self.LOG.info("联系人信息已刷新")
|
||||
|
||||
async def send_group_txt_message(self, msg: str, feature: Feature):
|
||||
@@ -609,8 +608,11 @@ class Robot:
|
||||
self.allContacts[wxid] = nick_name
|
||||
|
||||
self.head_images[wxid] = small_head_img_url
|
||||
friends = await self.ipad_bot.get_contract_list()
|
||||
self.contact_manager.set_contacts(self.allContacts, friends, self.head_images)
|
||||
friends = await self.ipad_bot.get_contractlist()
|
||||
|
||||
self.all_chatroom_members = self.contacts_db.get_chatroom_member_list_name_all()
|
||||
self.contact_manager.set_contacts(self.allContacts, friends, self.head_images,
|
||||
self.all_chatroom_members)
|
||||
self.LOG.info(f"已更新群 {group_id} 的成员信息")
|
||||
else:
|
||||
self.LOG.error(f"获取群 {group_id} 信息失败,证明用户无该群信息,删除群的相关资料。")
|
||||
|
||||
@@ -21,6 +21,7 @@ class ContactManager:
|
||||
_initialized = False
|
||||
_logger = logger
|
||||
_friends: List[str] = []
|
||||
_group_members: List[Dict] = []
|
||||
_group_contacts_friends: Dict[str, Dict[str, str]] = {}
|
||||
# 定义公共好友列表
|
||||
_PUBLIC_FRIENDS = {
|
||||
@@ -51,7 +52,8 @@ class ContactManager:
|
||||
cls._instance = ContactManager()
|
||||
return cls._instance
|
||||
|
||||
def set_contacts(self, contacts: Dict[str, str], friends: List[str], head_imgs: Dict[str, str]) -> None:
|
||||
def set_contacts(self, contacts: Dict[str, str], friends: List[str], head_imgs: Dict[str, str],
|
||||
chatroom_members: List[dict]) -> None:
|
||||
"""设置联系人字典
|
||||
|
||||
Args:
|
||||
@@ -66,10 +68,12 @@ class ContactManager:
|
||||
"province": cnt.get("province", ""),
|
||||
"city": cnt.get("city", ""),
|
||||
"gender": gender}
|
||||
chatroom_members: 所有的群成员昵称信息
|
||||
"""
|
||||
self._contacts = contacts
|
||||
self._friends = friends
|
||||
self._head_images = head_imgs
|
||||
self._group_members = chatroom_members
|
||||
self._logger.info(f"联系人信息已更新,共 {len(contacts)} 个联系人")
|
||||
# 分类联系人
|
||||
self._classify_contacts()
|
||||
@@ -91,6 +95,12 @@ class ContactManager:
|
||||
# 判断是否为群组(wxid以@chatroom结尾)
|
||||
elif wxid.endswith('@chatroom'):
|
||||
self._group_contacts[wxid] = nickname
|
||||
# 获取群成员信息:
|
||||
for friend in self._group_members:
|
||||
if friend.get('chatroom_id') == wxid:
|
||||
self._group_contacts_friends[wxid].update(
|
||||
{friend.get('wxid'): friend.get('nick_name', friend.get('wxid'))})
|
||||
|
||||
else:
|
||||
# 判断 frinds 在contacts 里面,将在里面的用户分在
|
||||
if wxid in self._friends:
|
||||
@@ -170,6 +180,18 @@ class ContactManager:
|
||||
"""
|
||||
return self._head_images.get(wxid, "")
|
||||
|
||||
def update_head_image(self, wxid: str, head_image: str) -> bool:
|
||||
"""根据微信ID更新头像
|
||||
|
||||
Args:
|
||||
wxid: 微信ID
|
||||
head_image:头像地址
|
||||
Returns:
|
||||
对应的头像,如果不存在这返回""
|
||||
"""
|
||||
self._head_images.update({wxid: head_image})
|
||||
return True
|
||||
|
||||
def get_group_name(self, roomid: str, wxid: str) -> str:
|
||||
"""
|
||||
Args:
|
||||
@@ -192,6 +214,18 @@ class ContactManager:
|
||||
"""
|
||||
return self._group_contacts_friends.get(roomid, {})
|
||||
|
||||
def update_group_members(self, roomid: str, wxid: str, nick_name: str) -> bool:
|
||||
"""更新指定群的成员列表
|
||||
|
||||
Args:
|
||||
roomid: 群ID
|
||||
|
||||
Returns:
|
||||
群成员字典,格式为 {"wxid": "NickName"}
|
||||
"""
|
||||
self._group_contacts_friends[roomid].update({wxid: nick_name})
|
||||
return True
|
||||
|
||||
def update_contact(self, wxid: str, nickname: str) -> None:
|
||||
"""更新单个联系人信息
|
||||
|
||||
@@ -208,7 +242,10 @@ class ContactManager:
|
||||
elif wxid.endswith('@chatroom'):
|
||||
self._group_contacts[wxid] = nickname
|
||||
# 需要获取群成员昵称信息; 从数据库里面提取。
|
||||
# self._group_contacts_friends[wxid] = {}
|
||||
for friend in self._group_members:
|
||||
if friend.get('chatroom_id') == wxid:
|
||||
self._group_contacts_friends[wxid].update(
|
||||
{friend.get('wxid'): friend.get('nick_name', friend.get('wxid'))})
|
||||
else:
|
||||
if wxid in self._friends:
|
||||
self._personal_contacts[wxid] = nickname
|
||||
|
||||
Reference in New Issue
Block a user