import redis import xml.etree.ElementTree as ET from wcferry import Wcf class GroupMemberChange: def __init__(self, wcf: Wcf, redis_pool: redis.ConnectionPool): self.wcf = wcf # 假设 wcf 对象在此类中初始化 self.redis_pool = redis_pool # 初始化本地缓存字典,使用 group_id 作为键 self.local_membercounts = {} self.local_members = {} def _get_redis_connection(self): """从连接池获取 Redis 连接""" return redis.Redis(connection_pool=self.redis_pool) def get_current_members(self, group_id): """ 获取当前群成员信息 """ print(f"Fetching current members for group_id: {group_id}") members = self.wcf.get_chatroom_members(group_id) # 假设返回的数据格式是 {wxid1: 昵称1, wxid2: 昵称2, ...} print(f"Current members: {members}") return members def get_previous_data_from_redis(self, group_id): """ 从 Redis 获取上次的数据 """ membercount_key = f"group:group_member_count:{group_id}" members_key = f"group:group_members:{group_id}" # 读取 Redis 中的数据 print(f"Fetching previous data from Redis for group_id: {group_id}") membercount_previous = self._get_redis_connection().get(membercount_key) members_previous = self._get_redis_connection().hgetall(members_key) # 获取上次的成员信息 print(f"Previous membercount: {membercount_previous}, Previous members: {members_previous}") return membercount_previous, members_previous def process_message(self, group_id, xml_data_current): """ 处理消息并更新 Redis """ root_current = ET.fromstring(xml_data_current) membercount_current = root_current.find('membercount').text result = [] # 初始化文案列表 # 检查是否存在本地缓存数据,如果不存在,则从 Redis 获取 if group_id not in self.local_membercounts or group_id not in self.local_members: print("No local data, fetching from Redis") membercount_previous, members_previous = self.get_previous_data_from_redis(group_id) # 如果没有上次的数据,说明是第一次处理,直接存储本次数据 if membercount_previous is None or not members_previous: print("First time processing, saving current data to Redis") members_current = self.get_current_members(group_id) self._get_redis_connection().set(f"group:group_member_count:{group_id}", membercount_current) self._get_redis_connection().delete(f"group:group_members:{group_id}") self._get_redis_connection().hset(f"group:group_members:{group_id}", mapping=members_current) # 存储当前成员信息 # 更新本地缓存 self.local_membercounts[group_id] = membercount_current self.local_members[group_id] = members_current result.append("$NO_CHANGE$") return "\n".join(result) else: # 如果 Redis 中有数据,就更新本地缓存 self.local_membercounts[group_id] = membercount_previous self.local_members[group_id] = members_previous else: # 使用本地缓存的数据进行比较 membercount_previous = self.local_membercounts[group_id] members_previous = self.local_members[group_id] # 比较 membercount 是否发生变化 if membercount_current != membercount_previous: print(f"Membercount changed: {membercount_previous} -> {membercount_current}") members_current = self.get_current_members(group_id) # TODO 如果用户达到了500人,则删除该群自动添加内容 # 比较成员,仅使用 wxid 进行比较 members_current_set = set(members_current.keys()) members_previous_set = set(members_previous.keys()) added_members = members_current_set - members_previous_set removed_members = members_previous_set - members_current_set # 添加变化成员的文案 for wxid in added_members: nickname = members_current[wxid] result.append(f"检测到\n {nickname}({wxid})\n加入群聊") for wxid in removed_members: nickname = members_previous[wxid] result.append(f"检测到\n {nickname}({wxid})\n退出群聊") # 更新本地缓存 print(f"Updating local cache with current membercount and members") self.local_membercounts[group_id] = membercount_current self.local_members[group_id] = members_current print(f"Current membercount: {membercount_current}, Current members: {members_current}") print( f"Local Current membercount: {self.local_membercounts[group_id]}, Local Current members: {self.local_members[group_id]}") # 更新 Redis 数据 print(f"Updating Redis with current membercount and members") self._get_redis_connection.set(f"group:group_member_count:{group_id}", membercount_current) self._get_redis_connection.delete(f"group:group_members:{group_id}") # 更新 Redis 中的成员信息,确保在成员变化时也更新 self._get_redis_connection.hset(f"group:group_members:{group_id}", mapping=members_current) else: result.append("$NO_CHANGE$") # 返回拼接后的结果 return "\n".join(result)