#!/usr/bin/env python3
"""Export Discord channel history to markdown files on the server."""
import json, os, sys, time, urllib.request, urllib.error
from datetime import datetime

# Load bot token
with open('/root/.openclaw/openclaw.json') as f:
    config = json.load(f)
token = config['channels']['discord']['accounts']['kitt']['token']

GUILD_ID = '1467974388581273603'
OUTPUT_DIR = '/root/.openclaw/workspace/discord-history'
HEADERS = {'Authorization': f'Bot {token}', 'Content-Type': 'application/json'}

def api_get(url):
    req = urllib.request.Request(url, headers=HEADERS)
    try:
        with urllib.request.urlopen(req) as resp:
            return json.loads(resp.read())
    except urllib.error.HTTPError as e:
        if e.code == 429:
            retry = json.loads(e.read()).get('retry_after', 2)
            print(f"  Rate limited, waiting {retry}s...")
            time.sleep(retry + 0.5)
            return api_get(url)
        print(f"  HTTP {e.code} for {url}")
        return None

def get_all_messages(channel_id, channel_name):
    """Fetch all messages from a channel, oldest first."""
    messages = []
    before = None
    while True:
        url = f'https://discord.com/api/v10/channels/{channel_id}/messages?limit=100'
        if before:
            url += f'&before={before}'
        data = api_get(url)
        if not data:
            break
        messages.extend(data)
        print(f"  {channel_name}: {len(messages)} messages fetched...", end='\r')
        if len(data) < 100:
            break
        before = data[-1]['id']
        time.sleep(0.5)  # Rate limit courtesy
    print(f"  {channel_name}: {len(messages)} messages total      ")
    messages.reverse()  # Chronological order
    return messages

def format_message(msg):
    """Format a single message as markdown."""
    author = msg['author'].get('global_name') or msg['author'].get('username', 'Unknown')
    timestamp = msg['timestamp'][:19].replace('T', ' ')
    content = msg.get('content', '')
    
    # Note attachments
    attachments = []
    for att in msg.get('attachments', []):
        attachments.append(f"[📎 {att.get('filename', 'file')}]({att.get('url', '')})")
    
    # Note embeds
    embeds = []
    for emb in msg.get('embeds', []):
        title = emb.get('title', '')
        desc = emb.get('description', '')[:200] if emb.get('description') else ''
        if title or desc:
            embeds.append(f"[embed: {title} — {desc}]")
    
    lines = [f"**{author}** ({timestamp})"]
    if content:
        lines.append(content)
    if attachments:
        lines.append(' '.join(attachments))
    if embeds:
        lines.append(' '.join(embeds))
    lines.append('')
    return '\n'.join(lines)

def export_channel(channel_id, channel_name, category=''):
    """Export a single channel to markdown."""
    messages = get_all_messages(channel_id, channel_name)
    if not messages:
        return 0
    
    subdir = os.path.join(OUTPUT_DIR, category) if category else OUTPUT_DIR
    os.makedirs(subdir, exist_ok=True)
    
    filepath = os.path.join(subdir, f'{channel_name}.md')
    with open(filepath, 'w') as f:
        f.write(f'# #{channel_name}\n\n')
        for msg in messages:
            f.write(format_message(msg))
    
    return len(messages)

# Get channels
print("Fetching channel list...")
channels_url = f'https://discord.com/api/v10/guilds/{GUILD_ID}/channels'
channels = api_get(channels_url)

# Build category map
categories = {}
for ch in channels:
    if ch['type'] == 4:  # Category
        categories[ch['id']] = ch['name'].replace('📍 ', '').replace('📌 ', '').replace('🏢 ', '').replace('📋 ', '').replace('🛠️ ', '').replace('🗄️ ', '').replace('🧠 ', '').strip()

# Export all text channels
os.makedirs(OUTPUT_DIR, exist_ok=True)
total = 0
for ch in sorted(channels, key=lambda c: c.get('position', 999)):
    if ch['type'] != 0:  # Text channels only
        continue
    if not ch.get('last_message_id'):  # Skip empty channels
        continue
    
    name = ch['name']
    cat = categories.get(ch.get('parent_id', ''), '')
    
    print(f"Exporting #{name}...")
    count = export_channel(ch['id'], name, cat)
    total += count
    time.sleep(0.3)

print(f"\n✅ Done! Exported {total} messages to {OUTPUT_DIR}")
print(f"Channels exported: {len(os.listdir(OUTPUT_DIR))} directories")
