import json
import asyncio
import websockets
import sys
import os
import time
from datetime import datetime

# ===================== 配置区（必填！）=====================
WS_SERVER_PORT = 8082  # 和NapCat反向WS端口一致
GROUP_FILE = "qqqun.txt"  # 读取群号的文件
NEW_NICKNAME = "测试昵称123"  # 要设置的群昵称（先填简单纯文本！）
SELF_QQ = 123456789  # 你的QQ号（必填！用于精准修改）
# ===========================================================

def write_log(content):
    """打印带时间戳的日志"""
    now = datetime.now().strftime("[%Y-%m-%d %H:%M:%S]")
    log_msg = f"{now} [改昵称] {content}"
    print(log_msg)
    with open("main_bat_log.txt", "a", encoding="utf-8") as f:
        f.write(log_msg + "\n")
    return log_msg

def check_nickname_valid(nickname):
    """检查昵称合法性"""
    if not nickname.strip():
        return False, "昵称不能为空"
    if len(nickname) > 64:
        return False, f"昵称过长（当前{len(nickname)}字符，上限64）"
    # 过滤敏感字符（可根据实际调整）
    sensitive_chars = ["@", "#", "$", "%", "*", "【", "】"]
    for char in sensitive_chars:
        if char in nickname:
            return False, f"昵称包含敏感字符：{char}"
    return True, "昵称合法"

def load_groups_from_file():
    """从qqqun.txt读取群号列表"""
    try:
        if not os.path.exists(GROUP_FILE):
            write_log(f"❌ 未找到{GROUP_FILE}，无法获取群号")
            return []
        with open(GROUP_FILE, "r", encoding="utf-8") as f:
            groups = [int(line.strip()) for line in f if line.strip().isdigit()]
        write_log(f"✅ 从{GROUP_FILE}加载到{len(groups)}个群号")
        return groups
    except Exception as e:
        write_log(f"❌ 读取群号失败：{str(e)}")
        return []

async def change_group_nickname(websocket, group_id, new_nickname):
    """修改指定群的自身昵称（增强版：解析详细返回）"""
    try:
        # 核心修改：用自己的QQ号（而非0），提高成功率
        req_data = {
            "action": "set_group_card",
            "params": {
                "group_id": group_id,
                "user_id": SELF_QQ,  # 替换为你的真实QQ号
                "card": new_nickname
            },
            "echo": f"change_nick_{group_id}_{int(datetime.now().timestamp())}"
        }
        write_log(f"【群{group_id}】发送修改请求：{new_nickname}")
        await websocket.send(json.dumps(req_data))
        
        # 等待返回并解析详细信息
        response = await asyncio.wait_for(websocket.recv(), timeout=10)
        resp_json = json.loads(response)
        write_log(f"【群{group_id}】NapCat返回：{json.dumps(resp_json, ensure_ascii=False)}")
        
        # 精准判断是否真的成功
        if resp_json.get("status") == "ok":
            # 额外检查retcode（0=真成功，非0=假成功）
            retcode = resp_json.get("retcode", -1)
            if retcode == 0:
                write_log(f"✅ 群{group_id}昵称修改成功：{new_nickname}")
                return True
            else:
                write_log(f"❌ 群{group_id}接口返回成功，但retcode={retcode}（假成功）")
                return False
        else:
            error_msg = resp_json.get("msg", "未知错误")
            error_data = resp_json.get("data", {})
            write_log(f"❌ 群{group_id}昵称修改失败：{error_msg} | 详细信息：{error_data}")
            return False
    except asyncio.TimeoutError:
        write_log(f"❌ 群{group_id}昵称修改超时（10秒）")
        return False
    except Exception as e:
        write_log(f"❌ 群{group_id}昵称修改异常：{str(e)}")
        return False

async def run_ws_server():
    """修复事件循环冲突的核心函数"""
    success_flag = False
    conn_closed = False
    group_ids = load_groups_from_file()
    
    # 1. 检查前置条件
    valid, msg = check_nickname_valid(NEW_NICKNAME)
    if not valid:
        write_log(f"❌ 昵称检查失败：{msg}")
        return False
    if not group_ids:
        write_log("❌ 无有效群号，终止脚本")
        return False
    if SELF_QQ == 123456789:
        write_log("❌ 请修改SELF_QQ为你的真实QQ号！")
        return False

    async def handle_connection(websocket):
        nonlocal success_flag, conn_closed
        write_log("✅ NapCat反向WS连接成功！")
        success_count = 0
        fail_count = 0
        try:
            # 逐个修改群昵称（间隔2秒，避免请求过快）
            for gid in group_ids:
                result = await change_group_nickname(websocket, gid, NEW_NICKNAME)
                if result:
                    success_count += 1
                else:
                    fail_count += 1
                await asyncio.sleep(2)
            # 汇总结果
            write_log(f"📊 批量修改完成：成功{success_count}个，失败{fail_count}个")
            success_flag = success_count > 0
        finally:
            write_log("📌 关闭NapCat连接")
            await websocket.close()
            conn_closed = True

    # 统一事件循环调用（兼容Python 3.7+）
    loop = asyncio.get_running_loop()
    server = await websockets.serve(handle_connection, "127.0.0.1", WS_SERVER_PORT)
    
    # 等待连接完成或超时（3分钟）
    timeout = 180
    start_time = time.time()
    while not conn_closed and (time.time() - start_time) < timeout:
        await asyncio.sleep(1)
    
    server.close()
    await server.wait_closed()
    
    if not conn_closed:
        write_log(f"❌ 超时{timeout}秒，未收到NapCat连接")
        success_flag = False
    return success_flag

def main():
    write_log("🚀 启动群昵称批量修改脚本（增强版）")
    write_log(f"等待NapCat连接到 ws://127.0.0.1:{WS_SERVER_PORT}...")
    
    try:
        success = asyncio.run(run_ws_server())
        sys.exit(0 if success else 1)
    except KeyboardInterrupt:
        write_log("🛑 脚本被手动终止")
        sys.exit(1)
    except Exception as e:
        write_log(f"💥 脚本异常：{str(e)}")
        sys.exit(1)

if __name__ == "__main__":
    main()