#!/usr/bin/env python3 """ Telegram Callback Query Handler 监听inline keyboard按钮点击,执行交易确认/取消 """ import os import re import sys import json import time import requests import subprocess def _load_env(): env_path = os.path.expanduser("~/.hermes/.env") with open(env_path) as f: for line in f: m = re.match(r'TELEGRAM_BOT_TOKEN=(.*)', line.strip()) if m: return m.group(1).strip() return '' BOT_TOKEN = _load_env() PROXY = 'http://127.0.0.1:7890' SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) NOTIFIER = os.path.join(SCRIPT_DIR, "trade_notifier.py") LAST_UPDATE_FILE = os.path.expanduser("~/.hermes/trading/last_update_id") os.makedirs(os.path.dirname(LAST_UPDATE_FILE), exist_ok=True) def get_updates(offset=None, timeout=30): """Long-poll for updates""" url = f"https://api.telegram.org/bot{BOT_TOKEN}/getUpdates" params = {"timeout": timeout, "allowed_updates": '["callback_query"]'} if offset: params["offset"] = offset resp = requests.get(url, params=params, proxies={"https": PROXY, "http": PROXY}, timeout=timeout+10) return resp.json() def load_last_update_id(): """Load last processed update ID""" try: with open(LAST_UPDATE_FILE) as f: return int(f.read().strip()) except: return None def save_last_update_id(update_id): """Save last processed update ID""" with open(LAST_UPDATE_FILE, "w") as f: f.write(str(update_id)) def handle_callback_query(update): """Process a callback query""" cb = update.get("callback_query", {}) if not cb: return callback_data = cb.get("data", "") callback_query_id = cb.get("id", "") message = cb.get("message", {}) chat_id = str(message.get("chat", {}).get("id", "")) message_id = message.get("message_id", 0) print(f"[{time.strftime('%H:%M:%S')}] Callback: {callback_data} from chat {chat_id}") # Call trade_notifier.py callback handler result = subprocess.run( ["python3", NOTIFIER, "callback", callback_data, str(chat_id), str(message_id), callback_query_id], capture_output=True, text=True, timeout=60 ) if result.returncode != 0: print(f" Error: {result.stderr[:200]}") else: print(f" Result: {result.stdout[:200]}") def main(): print("🔄 Callback handler started, waiting for button clicks...") last_id = load_last_update_id() while True: try: result = get_updates(offset=(last_id + 1) if last_id else None, timeout=30) if not result.get("ok"): print(f"API error: {result}") time.sleep(5) continue updates = result.get("result", []) for update in updates: update_id = update.get("update_id", 0) if update.get("callback_query"): handle_callback_query(update) last_id = update_id save_last_update_id(last_id) except requests.exceptions.Timeout: continue except KeyboardInterrupt: print("\n🛑 Stopped") break except Exception as e: print(f"Error: {e}") time.sleep(5) if __name__ == "__main__": main()