完整 AgentSkill:词库外部化 + 全部脚本/Skill 脱敏上传
- 高危词库从 process.py 抽到 config.toml [security] section - process.py 改为 _get_high_risk_words() 动态加载(配置优先) - 新增 15 个 QQ 操作脚本(已脱敏:QQ号/IP/Token → 占位符) - 新增 8 个 SKILL.md(qq-messenger/management/resolver/napcat-extras 等) - 新增 SKILL.md 入口(完整部署方案文档) - 保留 SDK 框架(plugin_modules.py, file_store_api.py, package.py 等)
This commit is contained in:
205
scripts/qq_group_action.py
Normal file
205
scripts/qq_group_action.py
Normal file
@ -0,0 +1,205 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
QQ 群管理动作 — 通过 NapCat (OneBot) HTTP API
|
||||
|
||||
支持操作:
|
||||
- 退群(leave group)
|
||||
- 按群号加群(join group)
|
||||
- 接受进群邀请(approve invite)
|
||||
- 拒绝进群邀请(reject invite)
|
||||
- 处理加群请求(approve/reject group request)
|
||||
|
||||
注意:
|
||||
- 进群/退群操作 **必须** 先问老板,老板同意才能执行
|
||||
- 紧急情况(如检测到攻击性信息)除外
|
||||
- 退群操作不可逆,执行前二次确认
|
||||
- 加群需要有人邀请或群主通过群链接/名片形式邀请,无法通过纯 API 直接加入
|
||||
|
||||
用法:
|
||||
python3 qq_group_action.py --leave YOUR_BOT_QQ # 退出群
|
||||
python3 qq_group_action.py --join YOUR_BOT_QQ # 按群号尝试加群(需有邀请)
|
||||
python3 qq_group_action.py --approve-invite <flag> # 接受进群邀请
|
||||
python3 qq_group_action.py --reject-invite <flag> # 拒绝进群邀请
|
||||
python3 qq_group_action.py --list-groups # 列出当前群列表
|
||||
"""
|
||||
|
||||
import json
|
||||
import sys
|
||||
import argparse
|
||||
import requests
|
||||
|
||||
CQHTTP_URL = "http://YOUR_NAP CAT_HOST:25570"
|
||||
|
||||
|
||||
def get_group_list():
|
||||
"""获取当前已加入的群列表"""
|
||||
resp = requests.post(f"{CQHTTP_URL}/get_group_list", json={}, timeout=10)
|
||||
data = resp.json()
|
||||
if data.get("status") == "ok":
|
||||
return data.get("data", [])
|
||||
raise Exception(f"API 异常: {json.dumps(data, ensure_ascii=False)}")
|
||||
|
||||
|
||||
def get_group_system_msgs():
|
||||
"""获取系统消息,包括待处理的进群邀请"""
|
||||
resp = requests.post(f"{CQHTTP_URL}/get_group_system_msg", json={}, timeout=10)
|
||||
data = resp.json()
|
||||
if data.get("status") == "ok":
|
||||
return data.get("data", {})
|
||||
return {}
|
||||
|
||||
|
||||
def leave_group(group_id: int) -> dict:
|
||||
"""退出指定群聊。不可逆!"""
|
||||
resp = requests.post(f"{CQHTTP_URL}/set_group_leave",
|
||||
json={"group_id": group_id}, timeout=10)
|
||||
return resp.json()
|
||||
|
||||
|
||||
def join_group_via_invite(group_id: int) -> str:
|
||||
"""
|
||||
尝试通过群号加群。
|
||||
|
||||
策略:
|
||||
1. 检查是否已在群里 → 直接返回
|
||||
2. 检查是否有该群的待处理邀请 → 接受邀请
|
||||
3. 没有邀请 → 告知需要通过邀请方式加群
|
||||
"""
|
||||
# 1. 检查是否已在群
|
||||
groups = get_group_list()
|
||||
for g in groups:
|
||||
if g.get("group_id") == group_id:
|
||||
return f"✅ 已经在群里: {g.get('group_name', '未知')} ({group_id})"
|
||||
|
||||
# 2. 检查待处理邀请
|
||||
sys_msgs = get_group_system_msgs()
|
||||
invites = sys_msgs.get("invited_requests", [])
|
||||
for inv in invites:
|
||||
if inv.get("group_id") == group_id:
|
||||
# 接受邀请
|
||||
flag = str(inv.get("request_id", ""))
|
||||
resp = requests.post(f"{CQHTTP_URL}/set_group_add_request", json={
|
||||
"flag": flag,
|
||||
"sub_type": "invite",
|
||||
"approve": True,
|
||||
}, timeout=10)
|
||||
data = resp.json()
|
||||
if data.get("status") == "ok":
|
||||
return f"✅ 已接受群邀请,成功加入: {inv.get('group_name', '?')} ({group_id})"
|
||||
else:
|
||||
return f"❌ 接受邀请失败: {data.get('message', '未知错误')}"
|
||||
|
||||
# 3. 没有待处理的邀请
|
||||
group_name = "(未知)"
|
||||
try:
|
||||
resp = requests.post(f"{CQHTTP_URL}/get_group_info", json={"group_id": group_id}, timeout=5)
|
||||
d = resp.json()
|
||||
if d.get("status") == "ok" and d.get("data"):
|
||||
group_name = d["data"].get("group_name", group_name)
|
||||
except:
|
||||
pass
|
||||
|
||||
return (
|
||||
f"⚠️ 无法自动加入群 {group_name} ({group_id})\n"
|
||||
f" QQ 协议不提供通过 API 直接加群的能力。\n"
|
||||
f" 需要有人邀请 bot 进群,bot 收到邀请后自动处理。\n"
|
||||
f" 请让群管理用 QQ 客户端邀请 bot(QQ号: YOUR_ADMIN_QQ),\n"
|
||||
f" 或发送群邀请链接/二维码给 bot,bot 会自动接受。"
|
||||
)
|
||||
|
||||
|
||||
def handle_group_request(flag: str, approve: bool, reason: str = "") -> dict:
|
||||
"""处理加群请求 / 群邀请"""
|
||||
params = {
|
||||
"flag": flag,
|
||||
"sub_type": "invite" if "invite" in flag else "add",
|
||||
"approve": approve,
|
||||
}
|
||||
if not approve and reason:
|
||||
params["reason"] = reason
|
||||
resp = requests.post(f"{CQHTTP_URL}/set_group_add_request",
|
||||
json=params, timeout=10)
|
||||
return resp.json()
|
||||
|
||||
|
||||
def format_group_info(groups: list) -> str:
|
||||
"""格式化群列表为可读文本"""
|
||||
if not groups:
|
||||
return "当前没有加入任何群"
|
||||
lines = [f"共 {len(groups)} 个群\n"]
|
||||
for g in groups:
|
||||
gid = g.get("group_id", "?")
|
||||
name = g.get("group_name", "?")
|
||||
mc = g.get("member_count", "?")
|
||||
mm = g.get("max_member_count", "?")
|
||||
lines.append(f"• {name} ({gid}) — {mc}/{mm} 人")
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="QQ 群管理操作")
|
||||
parser.add_argument("--leave", type=int, help="退出指定群(输入群号)")
|
||||
parser.add_argument("--join", type=int, help="尝试加入指定群(输入群号)")
|
||||
parser.add_argument("--approve-invite", type=str, help="接受进群邀请(输入 flag)")
|
||||
parser.add_argument("--reject-invite", type=str, help="拒绝进群邀请(输入 flag)")
|
||||
parser.add_argument("--reason", type=str, default="", help="拒绝理由(可选)")
|
||||
parser.add_argument("--list-groups", action="store_true", help="列出当前加入的群")
|
||||
parser.add_argument("--json", action="store_true", help="JSON 格式输出")
|
||||
args = parser.parse_args()
|
||||
|
||||
try:
|
||||
if args.list_groups:
|
||||
groups = get_group_list()
|
||||
if args.json:
|
||||
print(json.dumps(groups, ensure_ascii=False, indent=2))
|
||||
else:
|
||||
print(format_group_info(groups))
|
||||
return
|
||||
|
||||
if args.leave:
|
||||
result = leave_group(args.leave)
|
||||
if result.get("status") == "ok":
|
||||
print(f"✅ 已退出群 {args.leave}")
|
||||
else:
|
||||
print(f"❌ 退群失败: {result.get('message', '未知错误')}")
|
||||
sys.exit(1)
|
||||
return
|
||||
|
||||
if args.join:
|
||||
result = join_group_via_invite(args.join)
|
||||
success = result.startswith("✅")
|
||||
print(result)
|
||||
sys.exit(0 if success else 1)
|
||||
return
|
||||
|
||||
if args.approve_invite:
|
||||
result = handle_group_request(args.approve_invite, approve=True)
|
||||
if result.get("status") == "ok":
|
||||
print(f"✅ 已接受群邀请 {args.approve_invite}")
|
||||
else:
|
||||
print(f"❌ 接受邀请失败: {result.get('message', '未知错误')}")
|
||||
sys.exit(1)
|
||||
return
|
||||
|
||||
if args.reject_invite:
|
||||
result = handle_group_request(args.reject_invite, approve=False,
|
||||
reason=args.reason)
|
||||
if result.get("status") == "ok":
|
||||
print(f"✅ 已拒绝群邀请 {args.reject_invite}")
|
||||
else:
|
||||
print(f"❌ 拒绝邀请失败: {result.get('message', '未知错误')}")
|
||||
sys.exit(1)
|
||||
return
|
||||
|
||||
parser.print_help()
|
||||
|
||||
except requests.exceptions.ConnectionError:
|
||||
print(f"❌ 连接失败: 无法连接到 NapCat ({CQHTTP_URL})")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"❌ 操作失败: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user