#!/usr/bin/env python3

"""

元宝机器人保活脚本 v3.1 (通道推送版)

通过元宝通道发送自然对话消息，确保消息实际推送到元宝端



原理：

1. 从 sessions.json 自动获取 SESSION_ID 和 USER_ID

2. 通过元宝通道发送自然对话问题

3. 模型生成真实回复后，回复会推送到元宝端

4. 产生真实的收发消息记录，防止 15 天不活跃回收

"""



import subprocess

import json

import random

import os

from datetime import datetime



# ============================================

# 配置区 - 无需手动配置，脚本自动获取

# ============================================



SESSIONS_FILE = os.path.expanduser("~/.openclaw/agents/main/sessions/sessions.json")

LOG_FILE = os.path.expanduser("~/.openclaw/yuanbao_keepalive.log")



# 自然对话消息池 - 确保回复为真实文本（不是 HEARTBEAT_OK）

MESSAGES = [

    "你觉得什么样的生活才算幸福？",

    "最近有什么好看的电影推荐吗？",

    "你会做梦吗？如果会，你会梦到什么？",

    "你最佩服什么样的人？",

    "如果你能拥有一种超能力，你想要什么？",

    "你觉得人工智能会改变世界吗？",

    "你平时喜欢听什么类型的音乐？",

    "你有没有特别想去旅行的地方？",

    "你觉得什么是真正的朋友？",

    "你对未来有什么期待？",

]



# ============================================

# 自动获取配置

# ============================================



def get_session_config():

    """
    从 sessions.json 自动获取 SESSION_ID 和 USER_ID
    """

    with open(SESSIONS_FILE) as f:

        data = json.load(f)



    for key, session in data.items():

        if "yuanbao" in key and "direct" in key:

            session_id = session.get("sessionId")



            # 优先从 deliveryContext.to 获取 USER_ID（格式正确，大小写匹配）

            delivery_context = session.get("deliveryContext", {})

            to_field = delivery_context.get("to", "")

            if "direct:" in to_field:

                user_id = to_field.split("direct:")[1]

            else:

                # 回退：从 key 中提取（可能是小写格式）

                user_id = key.split(":")[-1]



            if session_id and user_id:

                return session_id, user_id



    return None, None



# ============================================

# 发送消息

# ============================================



def send_keepalive_message(session_id, user_id, message):

    """

    通过元宝通道发送消息

    

    命令参数说明：

    - --agent main: 使用主 agent

    - --session-id: 指定元宝会话 ID

    - --deliver: 将回复推送到元宝端

    - --reply-to: 指定接收者 USER_ID（必须是大写格式）

    - --json: 输出 JSON 格式便于解析

    - --timeout 30: 30 秒超时

    """

    cmd = [

        "openclaw", "agent",

        "--agent", "main",

        "--message", message,

        "--session-id", session_id,

        "--deliver",

        "--reply-to", user_id,

        "--json",

        "--timeout", "30"

    ]



    result = subprocess.run(

        cmd,

        capture_output=True,

        text=True,

        timeout=45

    )



    if result.returncode != 0:

        raise Exception(f"命令执行失败: {result.stderr}")



    output = json.loads(result.stdout)

    r = output.get("result", {})



    return {

        "delivery": r.get("deliverySucceeded", False),

        "reply": r.get("meta", {}).get("finalAssistantVisibleText", ""),

        "error": r.get("deliveryError")

    }



# ============================================

# 日志

# ============================================



def log(msg):

    """写入日志"""

    ts = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

    line = f"[{ts}] {msg}"

    print(line)

    with open(LOG_FILE, "a") as f:

        f.write(line + "\n")



# ============================================

# 主逻辑

# ============================================



def main():

    log("=" * 40)

    log("开始元宝机器人保活 (v3.1 - 通道推送，修复USER_ID大小写)...")



    # 自动获取 SESSION_ID 和 USER_ID

    session_id, user_id = get_session_config()

    if not session_id or not user_id:

        log("❌ 无法获取 SESSION_ID 或 USER_ID")

        log("=" * 40)

        return



    # 显示脱敏的 ID

    log(f"SESSION_ID: {session_id[:8]}...{session_id[-8:]}")

    log(f"USER_ID: {user_id[:8]}...{user_id[-8:]}")



    # 随机选择消息

    message = random.choice(MESSAGES)

    log(f"发送消息: {message}")



    try:

        result = send_keepalive_message(session_id, user_id, message)



        if result["delivery"]:

            reply = result["reply"][:50] + "..." if len(result["reply"]) > 50 else result["reply"]

            log(f"保活成功 ✓ 回复: {reply}")

        else:

            log(f"⚠️  消息已处理但未推送到元宝端 (delivery=False)")

            if result["error"]:

                log(f"   错误: {result['error']}")



    except Exception as e:

        log(f"❌ 保活失败: {e}")



    log("=" * 40)



if __name__ == "__main__":

    main()

