Initial commit: Hermes Agent skills collection
- Trading skills (OKX, dividend, lottery, quantitative) - Creative skills (ASCII art, diagrams, video) - Development skills (GitHub, debugging, TDD) - Research skills (arXiv, blog monitoring) - Productivity skills (email, documents, notes) - MCP integration skills - Custom user skills
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
#!/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()
|
||||
Reference in New Issue
Block a user