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,200 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Diagnose TelegramForwarder → Hermes forwarding chain.
|
||||
|
||||
Run inside the container:
|
||||
docker exec telegram-forwarder python3 /app/scripts/diagnose_chain.py
|
||||
|
||||
Or from host (container must be stopped):
|
||||
cd ~/TelegramForwarder && docker run --rm -v $(pwd)/sessions:/app/sessions \
|
||||
-v $(pwd)/db:/app/db --network host \
|
||||
-e HTTP_PROXY=http://127.0.0.1:7890 \
|
||||
telegramforwarder-telegram-forwarder python3 /app/scripts/diagnose_chain.py
|
||||
"""
|
||||
|
||||
import sqlite3
|
||||
import asyncio
|
||||
import socks
|
||||
|
||||
DB_PATH = '/app/db/forward.db'
|
||||
|
||||
def check_db():
|
||||
"""Check forwarder database configuration."""
|
||||
print("=" * 50)
|
||||
print("1. DATABASE CONFIG")
|
||||
print("=" * 50)
|
||||
conn = sqlite3.connect(DB_PATH)
|
||||
c = conn.cursor()
|
||||
|
||||
print("\n--- Chats ---")
|
||||
for row in c.execute('SELECT id, telegram_chat_id, name FROM chats'):
|
||||
print(f" {row}")
|
||||
|
||||
print("\n--- Forward Rules ---")
|
||||
for row in c.execute('SELECT id, source_chat_id, target_chat_id, forward_mode, enable_rule FROM forward_rules'):
|
||||
print(f" Rule {row[0]}: source={row[1]} → target={row[2]} | mode={row[3]} | enabled={row[4]}")
|
||||
|
||||
print("\n--- Keywords ---")
|
||||
for row in c.execute('SELECT * FROM keywords'):
|
||||
print(f" {row}")
|
||||
|
||||
conn.close()
|
||||
|
||||
async def check_entity_resolution():
|
||||
"""Test if bot can resolve the target group entity."""
|
||||
print("\n" + "=" * 50)
|
||||
print("2. ENTITY RESOLUTION TEST")
|
||||
print("=" * 50)
|
||||
|
||||
try:
|
||||
from telethon import TelegramClient
|
||||
except ImportError:
|
||||
print(" SKIP: telethon not available")
|
||||
return
|
||||
|
||||
import os
|
||||
api_id = os.getenv('API_ID')
|
||||
api_hash = os.getenv('API_HASH')
|
||||
if not api_id or not api_hash:
|
||||
print(" SKIP: API_ID/API_HASH not set")
|
||||
return
|
||||
|
||||
proxy = (socks.SOCKS5, '127.0.0.1', 7890)
|
||||
bot = TelegramClient('./sessions/bot', int(api_id), api_hash, proxy=proxy)
|
||||
await bot.start()
|
||||
|
||||
conn = sqlite3.connect(DB_PATH)
|
||||
c = conn.cursor()
|
||||
targets = c.execute('SELECT id, telegram_chat_id, name FROM chats').fetchall()
|
||||
conn.close()
|
||||
|
||||
for chat_id, tg_id, name in targets:
|
||||
try:
|
||||
entity = await bot.get_entity(int(tg_id) if not tg_id.startswith('-') else tg_id)
|
||||
deactivated = getattr(entity, 'deactivated', False)
|
||||
migrated = getattr(entity, 'migrated_to', None)
|
||||
if deactivated and migrated:
|
||||
new_id = f"-100{migrated.channel_id}"
|
||||
print(f" ❌ {name} ({tg_id}): DEACTIVATED → migrated to {new_id}")
|
||||
else:
|
||||
print(f" ✅ {name} ({tg_id}): OK - {type(entity).__name__}")
|
||||
except Exception as e:
|
||||
print(f" ❌ {name} ({tg_id}): {e}")
|
||||
|
||||
await bot.disconnect()
|
||||
|
||||
async def check_send_permission():
|
||||
"""Test if bot can send to the target group."""
|
||||
print("\n" + "=" * 50)
|
||||
print("3. SEND PERMISSION TEST")
|
||||
print("=" * 50)
|
||||
|
||||
try:
|
||||
from telethon import TelegramClient
|
||||
except ImportError:
|
||||
print(" SKIP: telethon not available")
|
||||
return
|
||||
|
||||
import os
|
||||
api_id = os.getenv('API_ID')
|
||||
api_hash = os.getenv('API_HASH')
|
||||
if not api_id or not api_hash:
|
||||
print(" SKIP: API_ID/API_HASH not set")
|
||||
return
|
||||
|
||||
proxy = (socks.SOCKS5, '127.0.0.1', 7890)
|
||||
bot = TelegramClient('./sessions/bot', int(api_id), api_hash, proxy=proxy)
|
||||
await bot.start()
|
||||
|
||||
conn = sqlite3.connect(DB_PATH)
|
||||
c = conn.cursor()
|
||||
rules = c.execute('SELECT id, target_chat_id FROM forward_rules WHERE enable_rule=1').fetchall()
|
||||
conn.close()
|
||||
|
||||
for rule_id, target_id in rules:
|
||||
conn = sqlite3.connect(DB_PATH)
|
||||
c = conn.cursor()
|
||||
tg_id = c.execute('SELECT telegram_chat_id FROM chats WHERE id=?', (target_id,)).fetchone()
|
||||
conn.close()
|
||||
if not tg_id:
|
||||
print(f" ❌ Rule {rule_id}: target chat {target_id} not found in chats table")
|
||||
continue
|
||||
|
||||
tg_id = tg_id[0]
|
||||
try:
|
||||
await bot.send_message(int(tg_id) if not tg_id.startswith('-') else tg_id, '🤖 Forward chain diagnostic test')
|
||||
print(f" ✅ Rule {rule_id}: can send to {tg_id}")
|
||||
except Exception as e:
|
||||
print(f" ❌ Rule {rule_id}: cannot send to {tg_id}: {e}")
|
||||
|
||||
await bot.disconnect()
|
||||
|
||||
def check_hermes_config():
|
||||
"""Check if Hermes free_response_chats matches."""
|
||||
print("\n" + "=" * 50)
|
||||
print("4. HERMES CONFIG CHECK")
|
||||
print("=" * 50)
|
||||
|
||||
import os
|
||||
config_path = os.path.expanduser('~/.hermes/config.yaml')
|
||||
if not os.path.exists(config_path):
|
||||
print(" SKIP: ~/.hermes/config.yaml not found")
|
||||
return
|
||||
|
||||
with open(config_path) as f:
|
||||
content = f.read()
|
||||
|
||||
# Extract telegram section
|
||||
in_telegram = False
|
||||
in_extra = False
|
||||
found_correct_key = False
|
||||
found_wrong_key = False
|
||||
|
||||
for line in content.split('\n'):
|
||||
stripped = line.strip()
|
||||
if stripped == 'telegram:':
|
||||
in_telegram = True
|
||||
continue
|
||||
if in_telegram and line and not line.startswith(' ') and not line.startswith('\t'):
|
||||
in_telegram = False
|
||||
in_extra = False
|
||||
if in_telegram:
|
||||
if stripped == 'extra:':
|
||||
in_extra = True
|
||||
continue
|
||||
if in_extra and not line.startswith(' ') and not line.startswith('\t') and stripped:
|
||||
in_extra = False
|
||||
|
||||
# CORRECT key: telegram.extra.free_response_chats
|
||||
if in_extra and 'free_response_chats' in line:
|
||||
val = line.split(':')[-1].strip().strip("'\"")
|
||||
found_correct_key = True
|
||||
if val:
|
||||
print(f" ✅ free_response_chats = {val}")
|
||||
else:
|
||||
print(f" ❌ free_response_chats is EMPTY — Hermes will ignore group messages")
|
||||
|
||||
# WRONG key: telegram.free_response_channels (legacy, ignored by code)
|
||||
if not in_extra and 'free_response_channels' in line:
|
||||
val = line.split(':')[-1].strip().strip("'\"")
|
||||
found_wrong_key = True
|
||||
if val:
|
||||
print(f" ⚠️ free_response_channels = {val} (WRONG KEY — ignored by Hermes code!)")
|
||||
else:
|
||||
print(f" ⚠️ free_response_channels is empty (also wrong key)")
|
||||
|
||||
if not found_correct_key:
|
||||
print(f" ❌ free_response_chats NOT FOUND in telegram.extra — add it!")
|
||||
if found_wrong_key and not found_correct_key:
|
||||
print(f" 💡 Move free_response_channels value to telegram.extra.free_response_chats")
|
||||
|
||||
async def main():
|
||||
check_db()
|
||||
await check_entity_resolution()
|
||||
await check_send_permission()
|
||||
check_hermes_config()
|
||||
print("\n" + "=" * 50)
|
||||
print("DIAGNOSIS COMPLETE")
|
||||
print("=" * 50)
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
Reference in New Issue
Block a user