#!/usr/bin/env python3 """XMPP Bot mohe@yoin.fun - 通过 ejabberd REST API 实现""" import asyncio, logging, ssl, json, urllib.request, os, time import subprocess, threading logging.basicConfig(level=logging.INFO, format='%(asctime)s %(message)s') GATEWAY = "http://localhost:8642/v1/chat/completions" API_KEY = "hermes123" EJB_ADMIN = "admin@localhost" EJB_PASS = "hermes123" _opener = urllib.request.build_opener(urllib.request.ProxyHandler({})) LAST_SEQ = 0 def call_api(content, sender, seq): """同步调 Hermes API 并回复""" try: payload = json.dumps({ "model": "hermes-agent", "messages": [{"role": "user", "content": content}] }).encode() req = urllib.request.Request(GATEWAY, data=payload, method="POST") req.add_header("Content-Type", "application/json") req.add_header("Authorization", f"Bearer {API_KEY}") req.add_header("X-Hermes-Session-Id", "xmpp-mohe") result = _opener.open(req, timeout=600) data = json.loads(result.read()) reply = data.get("choices", [{}])[0].get("message", {}).get("content", "") finish = data.get("choices", [{}])[0].get("finish_reason", "") global LAST_SEQ if seq < LAST_SEQ: logging.info(f"⏭️ 跳过过期 seq={seq}") return if reply.strip() and finish != "silent": # 通过 ejabberdctl 发送回复 subprocess.run([ "docker", "exec", "ejabberd", "ejabberdctl", "send_stanza", "mohe@yoin.fun", sender, f"{reply}" ], capture_output=True, timeout=30) logging.info(f"✅ 回复: {reply[:80]}") except Exception as e: logging.error(f"❌ 错误: {e}") def poll_messages(): """轮询 ejabberd 离线消息""" global LAST_SEQ while True: try: # 用 ejabberdctl 获取 mohe 的离线消息 result = subprocess.run([ "docker", "exec", "ejabberd", "ejabberdctl", "get_offline_count", "mohe", "yoin.fun" ], capture_output=True, text=True, timeout=10) count = int(result.stdout.strip()) if count > 0: # 获取消息内容并处理 result2 = subprocess.run([ "docker", "exec", "ejabberd", "ejabberdctl", "get_offline_messages", "mohe", "yoin.fun" ], capture_output=True, text=True, timeout=10) # 解析消息并处理(简化处理) except: pass time.sleep(5) if __name__ == '__main__': # 实际上需要通过 XMPP 连接或 BOSH/WS # 这个方案太复杂,直接换个思路:让 ejabberd → webhook → 处理 → reponse print("需要更简单的方法")