diff --git a/group_auto/group_auto_invite.py b/group_auto/group_auto_invite.py index e69de29..4e47e2b 100644 --- a/group_auto/group_auto_invite.py +++ b/group_auto/group_auto_invite.py @@ -0,0 +1,93 @@ +import redis + +# 创建 Redis 连接 +r = redis.StrictRedis(host='192.168.2.32', port=6379, db=0, decode_responses=True) + +# Redis 中存储群组映射的前缀 +mapping_prefix = "group:group_mapping:" + + +# 添加群组ID到指定key +def add_mapping(key, group_id): + if r.sismember(mapping_prefix + key, group_id): + print(f"Group ID {group_id} already exists for key {key}.") + else: + r.sadd(mapping_prefix + key, group_id) + print(f"Added: {key} -> {group_id}") + + +# 删除指定key下的某个群组ID +def del_mapping(key, group_id): + if r.sismember(mapping_prefix + key, group_id): + r.srem(mapping_prefix + key, group_id) + print(f"Deleted: {key} -> {group_id}") + else: + print(f"Group ID {group_id} not found for key {key}.") + + +# 获取指定key下的所有群组ID +def get_group_ids(key): + group_ids = r.smembers(mapping_prefix + key) + if group_ids: + print(f"Group IDs for {key}: {', '.join(group_ids)}") + else: + print(f"Key '{key}' has no associated group IDs.") + + +# 获取指定key的第一个群组ID +def get_first_group_id(key): + group_ids = r.smembers(mapping_prefix + key) + if group_ids: + first_group_id = next(iter(group_ids)) # 获取集合中的第一个元素 + print(f"First Group ID for {key}: {first_group_id}") + else: + print(f"Key '{key}' has no associated group IDs.") + + +# 处理命令行输入 +def process_command(command): + command_parts = command.split() + if len(command_parts) == 0: + print("Invalid command.") + return + + cmd = command_parts[0] + + if cmd == "add" and len(command_parts) == 3: + key = command_parts[1] + group_id = command_parts[2] + add_mapping(key, group_id) + + elif cmd == "del" and len(command_parts) == 3: + key = command_parts[1] + group_id = command_parts[2] + del_mapping(key, group_id) + + elif cmd == "get" and len(command_parts) == 2: + key = command_parts[1] + get_group_ids(key) + + elif cmd == "get_first" and len(command_parts) == 2: + key = command_parts[1] + get_first_group_id(key) + + else: + print("Unknown command or wrong number of arguments.") + + +# 主函数 +def main(): + print("群自动邀请系统已启动。") + print( + "输入 'add key group_id' 来添加群组ID,'del key group_id' 来删除,'get key' 来查询所有群组ID,'get_first key' 来查询第一个群组ID。") + + while True: + command = input("请输入命令:") + if command.lower() == "exit": + print("退出系统。") + break + process_command(command) + + +if __name__ == "__main__": + main() diff --git a/group_auto/group_member_change.py b/group_auto/group_member_change.py new file mode 100644 index 0000000..d123e6c --- /dev/null +++ b/group_auto/group_member_change.py @@ -0,0 +1,158 @@ +import redis +import xml.etree.ElementTree as ET + +from wcferry import Wcf + + +class GroupMemberChange: + def __init__(self, wcf: Wcf): + self.wcf = wcf # 假设 wcf 对象在此类中初始化 + self.r = redis.Redis(host='192.168.2.32', port=6379, db=0, decode_responses=True) + # 初始化本地缓存 + self.local_membercount = None + self.local_members = {} + + 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.r.get(membercount_key) + members_previous = self.r.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 """ + print(f"Processing message for group_id: {group_id}") + root_current = ET.fromstring(xml_data_current) + membercount_current = root_current.find('membercount').text + print(f"Current membercount: {membercount_current}") + + result = [] # 初始化文案列表 + + # 如果本地没有缓存数据,则从 Redis 获取 + if self.local_membercount is None or not 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.r.set(f"group:group_member_count:{group_id}", membercount_current) + self.r.hmset(f"group:group_members:{group_id}", members_current) # 存储当前成员信息 + + # 更新本地缓存 + self.local_membercount = membercount_current + self.local_members = members_current + + result.append("$NO_CHANGE$") + return "\n".join(result) + + else: + # 使用本地缓存的数据进行比较 + print("Using local data for comparison") + membercount_previous = self.local_membercount + members_previous = self.local_members + + # 比较 membercount 是否发生变化 + if membercount_current != membercount_previous: + print(f"Membercount changed: {membercount_previous} -> {membercount_current}") + result.append(f"membercount has changed: {membercount_previous} -> {membercount_current}") + members_current = self.get_current_members(group_id) + + # 比较成员,仅使用 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] + print(f"Detected member added: {nickname} ({wxid})") + result.append(f"检测到 {nickname}({wxid})加入群聊") + for wxid in removed_members: + nickname = members_previous[wxid] + print(f"Detected member removed: {nickname} ({wxid})") + result.append(f"检测到 {nickname}({wxid})退出群聊") + + # 更新本地缓存 + print(f"Updating local cache with current membercount and members") + self.local_membercount = membercount_current + self.local_members = members_current + + # 更新 Redis 数据 + print(f"Updating Redis with current membercount and members") + self.r.set(f"group:group_member_count:{group_id}", membercount_current) + self.r.hmset(f"group:group_members:{group_id}", members_current) + + else: + print("No change detected in membercount") + result.append("$NO_CHANGE$") + + # 返回拼接后的结果 + return "\n".join(result) + + +def main(): + group_id = "room123" + xml_data_current = """ + + 1 + 1 + 1 + 118 + + + wxid1 + 昵称1 + + + wxid2 + 昵称2 + + + wxid3 + 昵称3 + + + V1_5V25+oDw|v1_5V25+oDw + + + + + + 1 + + + + """ + + # 创建 YourClass 实例 + your_instance = YourClass() + + # 调用 process_message 方法来处理当前数据并获取变化文案 + result = your_instance.process_message(group_id, xml_data_current) + + # 判断是否没有变化 + if "NO_CHANGE" in result: + print("没有变化,跳过处理") + else: + print("检测到变化,进行相关处理") + print(result) # 输出具体的变化文案 + + +if __name__ == "__main__": + main() diff --git a/robot.py b/robot.py index 4894d1f..ec89980 100644 --- a/robot.py +++ b/robot.py @@ -24,6 +24,8 @@ from base.func_xinghuo_web import XinghuoWeb from base.func_claude import Claude from configuration import Config from constants import ChatType +from group_auto.group_auto_invite import get_first_group_id +from group_auto.group_member_change import GroupMemberChange from robot_cmd.robot_command import GroupBotManager from job_mgmt import Job from robot_cmd.robot_command import Feature @@ -51,6 +53,7 @@ class Robot(Job): self.groups = {} # 存储按group_id分组的消息列表,每个group_id最多保留10条消息 GroupBotManager.load_local_cache() self.gbm = GroupBotManager() + self.gmc = GroupMemberChange(wcf) if ChatType.is_in_chat_types(chat_type): if chat_type == ChatType.TIGER_BOT.value and TigerBot.value_check(self.config.TIGERBOT): self.chat = TigerBot(self.config.TIGERBOT) @@ -138,25 +141,32 @@ class Robot(Job): else: # 接了 ChatGPT,智能回复 # 去除@的人和空格等字符 q = re.sub(r"@.*?[\u2005|\s]", "", msg.content).replace(" ", "") + + # 使用正则表达式匹配加群指令 + pattern = r'#加群:\[(.*?)\]' # 匹配 #加群:[<任何内容>] + match = re.match(pattern, q) + # 所有人员都可以要求他撤回刚刚的信息 if q == '撤回': self.revoke_messages(msg.roomid) return True - if q == "今日百度新闻": + if q == "#今日百度新闻": self.newsBaiduReport((msg.roomid if msg.from_group() else msg.sender)) return True elif q in ["nbc", "cnn", "abc", "fox", "bbc"]: self.newsEnReport(q, (msg.roomid if msg.from_group() else msg.sender)) return True - elif q == '/总结': + elif q == '#总结': self.message_summary_robot((msg.roomid if msg.from_group() else msg.sender)) return True - elif q == '4K': + # 如果正则匹配到时加群指令,则从库中提取第一个群ID + elif match: try: - self.LOG.info(f"邀请加入4K群{msg.sender}") - self.wcf.invite_chatroom_members('45317011307@chatroom', msg.sender) + group_id = get_first_group_id(match.group(1)) + self.LOG.info(f"邀请加入{match.group(1)}群{msg.sender}") + self.wcf.invite_chatroom_members(group_id, msg.sender) except Exception as e: - self.LOG.error(f"邀请加入4K群出错:{e}") + self.LOG.error(f"邀请加入群出错:{e}") return True else: # 如果是群消息,并且群没开启AI,则不处理该动作 @@ -214,6 +224,15 @@ class Robot(Job): except Exception as e: self.LOG.error(f"revoke_receive_message error: {e}") + try: + result = self.gmc.process_message(msg.roomid, msg.xml) + # 判断是否没有变化 + if "$NO_CHANGE$" not in result: + self.LOG.info(f"检测到群成员变化,进行相关内容输出:{result}") + self.sendTextMsg(result, msg.roomid) + except Exception as e: + self.LOG.error(f"group_member_change error: {e}") + if msg.is_at(self.wxid): # 被@ self.toAt(msg)