Clone-Voice / bot_runner.py
hoainamgo's picture
Upload folder using huggingface_hub
97a4ad8 verified
Raw History Blame Contribute Delete
8.52 kB
"""
bot_runner.py - Dedicated Lightweight Telegram Bot Runner for Hermes Agent (Nous Portal Free Model)
"""
import os
import sys
import subprocess
import threading
import time
import psutil
import requests
from dotenv import load_dotenv
CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))
load_dotenv(os.path.join(CURRENT_DIR, ".env"))
BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN", "").strip()
ALLOWED_USER_ID_RAW = os.getenv("ALLOWED_USER_ID", "0").strip()
try:
ALLOWED_USER_ID = int(ALLOWED_USER_ID_RAW)
except ValueError:
ALLOWED_USER_ID = 0
PROVIDER = os.getenv("HERMES_PROVIDER", "nous").strip()
MODEL_NAME = os.getenv("HERMES_MODEL", "stepfun/step-3.7-flash:free").strip()
print(f"[STARTUP] Bot Token: {BOT_TOKEN[:10]}... | Allowed ID: {ALLOWED_USER_ID} | Provider: {PROVIDER} | Model: {MODEL_NAME}", flush=True)
# Hermes Agent Loader
AIAgent = None
try:
from run_agent import AIAgent
print("[STARTUP] run_agent.AIAgent loaded successfully!", flush=True)
except Exception as e:
print(f"[STARTUP WARN] Could not import AIAgent: {e}", flush=True)
agent_instance = None
def init_hermes_agent(model_name=MODEL_NAME):
global agent_instance
if not AIAgent:
return None
try:
agent_instance = AIAgent(
model=model_name,
provider="nous",
quiet_mode=True
)
print(f"[STARTUP] Hermes Agent ({model_name}) via Nous Portal initialized successfully!", flush=True)
return agent_instance
except Exception as e:
print(f"[STARTUP WARN] AIAgent Nous init ({model_name}): {e}", flush=True)
return None
init_hermes_agent(MODEL_NAME)
START_TIME = time.time()
session = requests.Session()
def send_tg_message(chat_id: int, text: str, parse_mode: str = "Markdown"):
if not BOT_TOKEN:
return
url = f"https://api.telegram.org/bot{BOT_TOKEN}/sendMessage"
payload = {"chat_id": chat_id, "text": text}
if parse_mode:
payload["parse_mode"] = parse_mode
try:
r = session.post(url, json=payload, timeout=20)
res_json = r.json()
if not res_json.get("ok"):
payload.pop("parse_mode", None)
session.post(url, json=payload, timeout=20)
except Exception as e:
print(f"[ERROR] Send TG message failed: {e}", flush=True)
def send_typing(chat_id: int):
if not BOT_TOKEN:
return
try:
session.post(f"https://api.telegram.org/bot{BOT_TOKEN}/sendChatAction", json={"chat_id": chat_id, "action": "typing"}, timeout=5)
except Exception:
pass
def handle_update(update: dict):
global MODEL_NAME, agent_instance
msg = update.get("message")
if not msg:
return
sender = msg.get("from", {})
sender_id = sender.get("id")
chat_id = msg.get("chat", {}).get("id")
text = (msg.get("text") or "").strip()
if sender_id != ALLOWED_USER_ID:
print(f"[BLOCKED] Unauthorized message from User ID {sender_id} (@{sender.get('username')})", flush=True)
return
print(f"[RECV] From {sender_id}: {text}", flush=True)
send_typing(chat_id)
# Command: /start or /help
if text in ["/start", "/help"]:
welcome = (
"🛡️ *HERMES AGENT NOUS PORTAL CONTROLLER* 🛡️\n\n"
"Chào bạn! Bot đã kết nối trực tiếp tài khoản **Nous Portal** qua OAuth.\n\n"
"📌 *Danh sách lệnh:*\n"
f"• Model mặc định: `{MODEL_NAME}` (Free 100%)\n"
"• `/model` : Xem hoặc đổi sang các model Free khác của Nous.\n"
"• `/status` : Xem Uptime, CPU, RAM và trạng thái hệ thống.\n"
"• `/sh <lệnh>` : Chạy lệnh shell/CLI trên máy chủ.\n"
"• Nhắn tin bất kỳ để chat và nhờ Hermes Agent giải quyết task."
)
send_tg_message(chat_id, welcome)
return
# Command: /status
if text == "/status":
uptime_sec = int(time.time() - START_TIME)
uptime_str = f"{uptime_sec // 3600}h {(uptime_sec % 3600) // 60}m {uptime_sec % 60}s"
mem = psutil.virtual_memory()
stat_msg = (
f"📊 *HỆ THỐNG TELEMETRY*\n"
f"━━━━━━━━━━━━━━━━━━━\n"
f"⏱ *Uptime:* `{uptime_str}`\n"
f"💻 *CPU Load:* `{psutil.cpu_percent()}%`\n"
f"🧠 *RAM:* `{round(mem.used / 1024**2, 1)}MB / {round(mem.total / 1024**2, 1)}MB`\n"
f"🌐 *Provider:* `Nous Portal (OAuth Active)`\n"
f"🤖 *Active Model:* `{MODEL_NAME}`\n"
f"🔑 *Authorized User ID:* `{ALLOWED_USER_ID}`\n"
)
send_tg_message(chat_id, stat_msg)
return
# Command: /model
if text == "/model":
model_msg = (
f"🤖 *MODEL NOUS HIỆN TẠI:* `{MODEL_NAME}`\n\n"
f"🎁 *Các model FREE trên Nous Portal:*\n"
f"• `/model stepfun/step-3.7-flash:free` (Khuyên dùng - Cực nhanh & thông minh)\n"
f"• `/model meituan/longcat-2.0:free` (Context dài)\n"
f"• `/model upstage/solar-mini4:free` (Nhẹ & chuẩn xác)\n"
f"• `/model inclusionai/ling-3.0-flash-fin:free`\n\n"
f"💡 *Cách đổi:* Gõ `/model <tên_model>`"
)
send_tg_message(chat_id, model_msg)
return
if text.startswith("/model "):
new_model = text.split(" ", 1)[1].strip()
new_agent = init_hermes_agent(new_model)
if new_agent:
MODEL_NAME = new_model
send_tg_message(chat_id, f"✅ Đã chuyển sang Model Nous: `{MODEL_NAME}` thành công!")
else:
send_tg_message(chat_id, f"⚠️ Không thể khởi tạo model `{new_model}`. Vui lòng kiểm tra lại tên model.")
return
# Command: /sh or /cmd
if text.startswith("/sh ") or text.startswith("/cmd "):
cmd = text.split(" ", 1)[1].strip()
try:
proc = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=45)
out = proc.stdout.strip() if proc.stdout else ""
err = proc.stderr.strip() if proc.stderr else ""
res = out if out else err
if not res:
res = "✅ (Exit code 0, no output)"
if len(res) > 3800:
res = res[:3800] + "\n... [Cắt bớt do quá dài]"
send_tg_message(chat_id, f"```\n{res}\n```")
except subprocess.TimeoutExpired:
send_tg_message(chat_id, "⏱ Lệnh bị quá thời gian cho phép (Timeout 45s).")
except Exception as e:
send_tg_message(chat_id, f"❌ Lỗi CLI: {str(e)}")
return
# Chat with Hermes Agent via Nous Portal
if not agent_instance:
init_hermes_agent(MODEL_NAME)
if not agent_instance:
send_tg_message(chat_id, "⚠️ Chưa khởi tạo được Hermes Agent qua Nous Portal.")
return
try:
reply = agent_instance.chat(text)
send_tg_message(chat_id, reply)
except Exception as e:
send_tg_message(chat_id, f"❌ Lỗi Hermes Agent: {str(e)}")
def main():
if not BOT_TOKEN:
print("[ERROR] No TELEGRAM_BOT_TOKEN found in .env!", flush=True)
return
print(f"🚀 Telegram Long Polling Bot active for User ID: {ALLOWED_USER_ID} on Nous Portal Free Model", flush=True)
last_update_id = 0
if ALLOWED_USER_ID != 0:
send_tg_message(ALLOWED_USER_ID, f"🟢 *Hermes Agent* đã chuyển sang **Model Free của Nous Portal** (`{MODEL_NAME}`) hoàn toàn miễn phí!")
while True:
try:
url = f"https://api.telegram.org/bot{BOT_TOKEN}/getUpdates"
params = {"timeout": 20, "offset": last_update_id + 1}
resp = session.get(url, params=params, timeout=30)
data = resp.json()
if data.get("ok"):
updates = data.get("result", [])
for u in updates:
last_update_id = u["update_id"]
try:
handle_update(u)
except Exception as e:
print(f"[ERROR] handle_update: {e}", flush=True)
else:
time.sleep(2)
except requests.exceptions.Timeout:
continue
except Exception as e:
print(f"[NETWORK NOTE] {e}", flush=True)
time.sleep(3)
if __name__ == "__main__":
main()