这次实际改的是按钮背后的同步逻辑,不是页面文案本身。现在 /contacts/api/update 触发后会:
个人联系人、公众号:已存在就跳过,不存在才写入。 群:不再删库重建,已有群保留;新群会写入。 群成员:已存在就跳过,不存在就写入。 如果成员这次不在群里了,会把 db/contacts_db.py 里的 status 标成 2,前端会显示“已退群”。 如果整个群查不到了,也不再删除群资料,只把该群历史成员标记为“已退群”。 改动在: robot.py db/contacts_db.py 我还做了语法校验,py_compile 通过。需要的话我也可以继续帮你把“更新通讯录”按钮的成功提示改成更明确,比如“已完成增量同步,未删除历史数据”。
This commit is contained in:
@@ -113,12 +113,13 @@ class ContactsDBOperator(BaseDBOperator):
|
||||
self.LOG.error(f"创建微信联系人表或群成员表失败: {e}")
|
||||
raise
|
||||
|
||||
def save_contacts(self, contacts_data: List[Dict], contact_type: str) -> bool:
|
||||
def save_contacts(self, contacts_data: List[Dict], contact_type: str, only_insert: bool = False) -> bool:
|
||||
"""保存联系人信息到数据库
|
||||
|
||||
Args:
|
||||
contacts_data: 联系人数据列表
|
||||
contact_type: 联系人类型,可选值:'friends', 'chatrooms', 'ghs'
|
||||
only_insert: 为True时仅写入不存在的联系人,已存在则跳过
|
||||
|
||||
Returns:
|
||||
bool: 是否成功保存
|
||||
@@ -165,14 +166,18 @@ class ContactsDBOperator(BaseDBOperator):
|
||||
placeholders = ', '.join(['%s'] * len(data))
|
||||
values = tuple(data.values())
|
||||
|
||||
# 使用INSERT ... ON DUPLICATE KEY UPDATE语法
|
||||
update_clause = ', '.join([f"{k}=VALUES({k})" for k in data.keys() if k != 'user_name'])
|
||||
|
||||
sql = f"""
|
||||
INSERT INTO t_wechat_contacts ({fields})
|
||||
VALUES ({placeholders})
|
||||
ON DUPLICATE KEY UPDATE {update_clause}
|
||||
"""
|
||||
if only_insert:
|
||||
sql = f"""
|
||||
INSERT IGNORE INTO t_wechat_contacts ({fields})
|
||||
VALUES ({placeholders})
|
||||
"""
|
||||
else:
|
||||
update_clause = ', '.join([f"{k}=VALUES({k})" for k in data.keys() if k != 'user_name'])
|
||||
sql = f"""
|
||||
INSERT INTO t_wechat_contacts ({fields})
|
||||
VALUES ({placeholders})
|
||||
ON DUPLICATE KEY UPDATE {update_clause}
|
||||
"""
|
||||
|
||||
self.execute_update(sql, values)
|
||||
|
||||
@@ -315,7 +320,7 @@ class ContactsDBOperator(BaseDBOperator):
|
||||
self.LOG.error(f"获取所有联系人信息失败: {e}")
|
||||
return {}
|
||||
|
||||
def save_chatroom_member_simple(self, chatroom_id: str, member_details: List[Dict]) -> bool:
|
||||
def save_chatroom_member_simple(self, chatroom_id: str, member_details: List[Dict], only_insert: bool = False) -> bool:
|
||||
"""
|
||||
保存群成员简要信息到数据库,兼容不同数据结构
|
||||
Args:
|
||||
@@ -367,13 +372,18 @@ class ContactsDBOperator(BaseDBOperator):
|
||||
placeholders = ', '.join(['%s'] * len(data))
|
||||
values = tuple(data.values())
|
||||
|
||||
update_clause = ', '.join([f"{k}=VALUES({k})" for k in data.keys() if k not in ('chatroom_id', 'wxid')])
|
||||
|
||||
sql = f"""
|
||||
INSERT INTO t_chatroom_member ({fields})
|
||||
VALUES ({placeholders})
|
||||
ON DUPLICATE KEY UPDATE {update_clause}
|
||||
"""
|
||||
if only_insert:
|
||||
sql = f"""
|
||||
INSERT IGNORE INTO t_chatroom_member ({fields})
|
||||
VALUES ({placeholders})
|
||||
"""
|
||||
else:
|
||||
update_clause = ', '.join([f"{k}=VALUES({k})" for k in data.keys() if k not in ('chatroom_id', 'wxid')])
|
||||
sql = f"""
|
||||
INSERT INTO t_chatroom_member ({fields})
|
||||
VALUES ({placeholders})
|
||||
ON DUPLICATE KEY UPDATE {update_clause}
|
||||
"""
|
||||
|
||||
self.execute_update(sql, values)
|
||||
|
||||
@@ -567,6 +577,52 @@ class ContactsDBOperator(BaseDBOperator):
|
||||
self.LOG.error(f"更新群聊{chatroom_id}信息失败: {e}")
|
||||
return False
|
||||
|
||||
def mark_chatroom_members_left(self, chatroom_id: str, active_member_wxids: Optional[List[str]] = None) -> bool:
|
||||
"""将不在当前群成员列表中的用户标记为已退群。"""
|
||||
try:
|
||||
active_member_wxids = [wxid for wxid in (active_member_wxids or []) if wxid]
|
||||
if active_member_wxids:
|
||||
placeholders = ', '.join(['%s'] * len(active_member_wxids))
|
||||
sql = f"""
|
||||
UPDATE t_chatroom_member
|
||||
SET status = 2
|
||||
WHERE chatroom_id = %s AND wxid NOT IN ({placeholders})
|
||||
"""
|
||||
params = (chatroom_id, *active_member_wxids)
|
||||
else:
|
||||
sql = """
|
||||
UPDATE t_chatroom_member
|
||||
SET status = 2
|
||||
WHERE chatroom_id = %s
|
||||
"""
|
||||
params = (chatroom_id,)
|
||||
|
||||
self.execute_update(sql, params)
|
||||
self.LOG.info(f"已将群 {chatroom_id} 中缺失成员标记为已退群")
|
||||
return True
|
||||
except Exception as e:
|
||||
self.LOG.error(f"标记群{chatroom_id}成员退群失败: {e}")
|
||||
return False
|
||||
|
||||
def mark_chatroom_members_active(self, chatroom_id: str, active_member_wxids: List[str]) -> bool:
|
||||
"""将当前仍在群里的成员标记为在群。"""
|
||||
try:
|
||||
active_member_wxids = [wxid for wxid in (active_member_wxids or []) if wxid]
|
||||
if not active_member_wxids:
|
||||
return True
|
||||
|
||||
placeholders = ', '.join(['%s'] * len(active_member_wxids))
|
||||
sql = f"""
|
||||
UPDATE t_chatroom_member
|
||||
SET status = 1
|
||||
WHERE chatroom_id = %s AND wxid IN ({placeholders})
|
||||
"""
|
||||
self.execute_update(sql, (chatroom_id, *active_member_wxids))
|
||||
return True
|
||||
except Exception as e:
|
||||
self.LOG.error(f"恢复群{chatroom_id}成员在群状态失败: {e}")
|
||||
return False
|
||||
|
||||
def delete_chatroom_info(self, chatroom_id: str) -> bool:
|
||||
"""删除群信息"""
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user