#!/usr/bin/env python3
"""
Custom news aggregator for Lenta.ru, Habr (overall, AI, development, space),
AI agents (arXiv cs.AI), development (GitHub Blog), space (NASA).
Outputs markdown digest with image URLs.
"""

import urllib.request
import xml.etree.ElementTree as ET
from html import unescape
import sys
import os
from datetime import datetime

FEEDS = {
    "Lenta.ru": "https://lenta.ru/rss",
    "Habr overall": "https://habr.com/ru/rss/all/",
    "Habr AI": "https://habr.com/ru/rss/hubs/artificial_intelligence/articles/",
    "Habr Development": "https://habr.com/ru/rss/hubs/development/articles/",
    "Habr Space": "https://habr.com/ru/rss/hubs/space/articles/",
    "AI agents (arXiv cs.AI)": "http://export.arxiv.org/rss/cs.AI",
    "Development (GitHub Blog)": "https://githubblog.com/feed/",
    "Space (NASA Breaking News)": "https://www.nasa.gov/rss/dyn/breaking_news.rss",
}

USER_AGENT = "Mozilla/5.0 (compatible; HermesNewsBot/1.0; +https://github.com/valldun1)"

def fetch_feed(url):
    req = urllib.request.Request(url, headers={'User-Agent': USER_AGENT})
    try:
        with urllib.request.urlopen(req, timeout=15) as response:
            return response.read()
    except Exception as e:
        print(f"Warning: Failed to fetch {url}: {e}", file=sys.stderr)
        return None

def parse_rss(data):
    if data is None:
        return []
    try:
        root = ET.fromstring(data)
    except ET.ParseError as e:
        print(f"Warning: Failed to parse XML: {e}", file=sys.stderr)
        return []
    # Find channel/items (handles RSS and Atom-like)
    items = []
    # RSS: channel/item
    for item in root.findall('.//item'):
        title = item.findtext('title', default='').strip()
        link = item.findtext('link', default='').strip()
        desc = item.findtext('description', default='').strip()
        # Clean description: strip HTML tags roughly
        # For simplicity, we take first 200 chars of plain text
        # Remove HTML tags
        import re
        desc = re.sub('<[^<]+?>', '', desc)
        desc = unescape(desc)
        if len(desc) > 200:
            desc = desc[:200] + '...'
        # Try to get image URL
        img_url = None
        enclosure = item.find('enclosure')
        if enclosure is not None:
            url = enclosure.get('url')
            type_ = enclosure.get('type', '')
            if url and type_.startswith('image/'):
                img_url = url
        # Also check for media:content or media:thumbnail (requires namespace handling)
        # Simple approach: look for any tag with 'media' in it and url attribute
        for elem in item.iter():
            if 'media' in elem.tag:
                url = elem.get('url')
                if url:
                    img_url = url
                    break
        items.append((title, link, desc, img_url))
    # Atom: entry
    for entry in root.findall('.//{http://www.w3.org/2005/Atom}entry'):
        title = entry.findtext('{http://www.w3.org/2005/Atom}title', default='').strip()
        link_tag = entry.find('{http://www.w3.org/2005/Atom}link')
        link = link_tag.get('href', '') if link_tag is not None else ''
        desc = entry.findtext('{http://www.w3.org/2005/Atom}summary', default='').strip()
        import re
        desc = re.sub('<[^<]+?>', '', desc)
        desc = unescape(desc)
        if len(desc) > 200:
            desc = desc[:200] + '...'
        img_url = None
        # Look for enclosure or media in Atom entries
        for elem in entry.iter():
            if elem.tag.endswith('enclosure'):
                url = elem.get('url')
                type_ = elem.get('type', '')
                if url and type_.startswith('image/'):
                    img_url = url
                    break
            if 'media' in elem.tag:
                url = elem.get('url')
                if url:
                    img_url = url
                    break
        items.append((title, link, desc, img_url))
    return items

def main():
    output_lines = []
    output_lines.append(f"*Сгенерировано: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}*\n")
    for name, url in FEEDS.items():
        print(f"Fetching {name}...")
        data = fetch_feed(url)
        items = parse_rss(data)
        output_lines.append(f"## {name}")
        if not items:
            output_lines.append("_No items found._")
        else:
            for title, link, desc, img_url in items[:20]:  # limit to 20 per feed
                if title and link:
                    if img_url:
                        output_lines.append(f"- [{title}]({link}) — {desc} || {img_url}")
                    else:
                        output_lines.append(f"- [{title}]({link}) — {desc}")
                else:
                    # fallback if missing
                    output_lines.append(f"- [Untitled]({link}) — {desc}")
        output_lines.append("")  # blank line
    output_path = os.path.expanduser('~/custom-news-digest.md')
    with open(output_path, 'w', encoding='utf-8') as f:
        f.write('\n'.join(output_lines))
    print(f"Digest written to {output_path}")

if __name__ == '__main__':
    main()