feature:加入了群成员变化监控功能,提醒群成员,有人退出了群聊
This commit is contained in:
@@ -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()
|
||||
|
||||
158
group_auto/group_member_change.py
Normal file
158
group_auto/group_member_change.py
Normal file
@@ -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 = """
|
||||
<msgsource>
|
||||
<pua>1</pua>
|
||||
<eggIncluded>1</eggIncluded>
|
||||
<silence>1</silence>
|
||||
<membercount>118</membercount>
|
||||
<members>
|
||||
<member>
|
||||
<wxid>wxid1</wxid>
|
||||
<nickname>昵称1</nickname>
|
||||
</member>
|
||||
<member>
|
||||
<wxid>wxid2</wxid>
|
||||
<nickname>昵称2</nickname>
|
||||
</member>
|
||||
<member>
|
||||
<wxid>wxid3</wxid>
|
||||
<nickname>昵称3</nickname>
|
||||
</member>
|
||||
</members>
|
||||
<signature>V1_5V25+oDw|v1_5V25+oDw</signature>
|
||||
<tmp_node>
|
||||
<publisher-id />
|
||||
</tmp_node>
|
||||
<sec_msg_node>
|
||||
<alnode>
|
||||
<fr>1</fr>
|
||||
</alnode>
|
||||
</sec_msg_node>
|
||||
</msgsource>
|
||||
"""
|
||||
|
||||
# 创建 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()
|
||||
31
robot.py
31
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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user