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:
Hermes Skills Manager
2026-07-05 02:31:15 -04:00
commit 6770bc9b9d
908 changed files with 239614 additions and 0 deletions
@@ -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())