#!/usr/bin/python
# -*- coding: utf-8 -*-

# --------------------------------------------------------------------------- #
#                                                                             #
#    Plugin for Isida-NG Jabber Bot                                              #
#    Copyright (C) Luciferus <luciferus@ubunix.pro>                                    #
#                                                                             #
#    This program is free software: you can redistribute it and/or modify     #
#    it under the terms of the GNU General Public License as published by     #
#    the Free Software Foundation, either version 3 of the License, or        #
#    (at your option) any later version.                                      #
#                                                                             #
#    This program is distributed in the hope that it will be useful,          #
#    but WITHOUT ANY WARRANTY; without even the implied warranty of           #
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            #
#    GNU General Public License for more details.                             #
#                                                                             #
#    You should have received a copy of the GNU General Public License        #
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.    #
#                                                                             #
# --------------------------------------------------------------------------- #

import urllib.parse
import urllib.request
import re
import xml.etree.ElementTree as ET

# --------------------------------------------------------------------------- #
# NETWORK HELPERS                                                             #
# --------------------------------------------------------------------------- #

def _fetch_url(url, limit=None):
    """Загружает URL и возвращает (content, headers, status)."""
    try:
        req = urllib.request.Request(url, headers={'User-Agent': GT('user_agent')})
        with urllib.request.urlopen(req, timeout=GT('rss_get_timeout')) as resp:
            if limit:
                data = resp.read(limit)
            else:
                data = resp.read(GT('size_overflow'))
            headers = resp.headers
            status = resp.getcode()
            try:
                content = data.decode('utf-8', errors='replace')
            except:
                content = data.decode('latin-1', errors='replace')
            return content, headers, status
    except Exception as e:
        return None, None, None

def _ensure_url(url):
    if not re.findall('^http(s?)://', url[:10]):
        return 'http://%s' % url
    return url

# --------------------------------------------------------------------------- #
# RSS SEARCH                                                                  #
# --------------------------------------------------------------------------- #

def rss_search(type, jid, nick, text):
    if not text:
        send_msg(type, jid, nick, L('What?', '%s/%s' % (jid, nick)))
        return

    url = _ensure_url(text)
    url = enidna(url)

    content, headers, status = _fetch_url(url, 65536)
    if content is None:
        send_msg(type, jid, nick, L('Bad url or rss/atom not found!', '%s/%s' % (jid, nick)))
        return

    # Проверяем, не является ли это прямым фидом
    content_type = headers.get('Content-Type', '').lower()
    is_feed = False

    if 'application/rss+xml' in content_type or 'application/atom+xml' in content_type:
        is_feed = True
    elif content.strip().startswith('<?xml') and ('<rss' in content.lower() or '<feed' in content.lower()):
        is_feed = True

    if is_feed:
        # Парсим XML-фид
        try:
            # Очищаем от мусора
            clean_xml = content.strip()
            if not clean_xml.startswith('<?xml'):
                clean_xml = '<?xml version="1.0" encoding="utf-8"?>' + clean_xml

            root = ET.fromstring(clean_xml)

            # Определяем тип фида
            if root.tag.endswith('rss'):
                # RSS 2.0
                channel = root.find('channel')
                if channel is not None:
                    title = channel.findtext('title', 'RSS Feed')
                    items = channel.findall('item')
                    msg = L('Feed: %s' % title, '%s/%s' % (jid, nick))
                    for item in items[:5]:
                        item_title = item.findtext('title', 'No title')
                        item_link = item.findtext('link', '')
                        if item_link:
                            msg += '\n• %s - %s' % (item_title, item_link)
                        else:
                            msg += '\n• %s' % item_title
                    send_msg(type, jid, nick, msg)
                    return
            elif root.tag.endswith('feed'):
                # Atom
                title = root.findtext('title', 'Atom Feed')
                entries = root.findall('entry')
                msg = L('Feed: %s' % title, '%s/%s' % (jid, nick))
                for entry in entries[:5]:
                    entry_title = entry.findtext('title', 'No title')
                    link_tag = entry.find('link')
                    if link_tag is not None:
                        entry_link = link_tag.get('href', '')
                    else:
                        entry_link = ''
                    if entry_link:
                        msg += '\n• %s - %s' % (entry_title, entry_link)
                    else:
                        msg += '\n• %s' % entry_title
                send_msg(type, jid, nick, msg)
                return
        except Exception as e:
            pprint('*** RSS parse error: %s' % str(e), 'red')
            send_msg(type, jid, nick, L('Bad url or rss/atom not found!', '%s/%s' % (jid, nick)))
            return

    # Если не фид — ищем ссылки на фиды в HTML
    page = content
    page = get_tag(page, 'head')
    links = []

    while '<link' in page:
        lnk = get_tag_full(page, 'link')
        page = page.replace(lnk, '')
        links.append(lnk)

    if not links:
        send_msg(type, jid, nick, L('Bad url or rss/atom not found!', '%s/%s' % (jid, nick)))
        return

    feeds = []
    for t in links:
        rss_type = get_subtag(t, 'type')
        if rss_type in ['application/rss+xml', 'application/atom+xml']:
            if rss_type == 'application/rss+xml':
                rss_type = 'RSS'
            else:
                rss_type = 'ATOM'
            rss_title = get_subtag(t, 'title')
            rss_href = get_subtag(t, 'href')
            if rss_href == '/':
                rss_href = '/'.join(url.split('/', 3)[:3]) + rss_href
            feeds.append('[%s] %s - %s' % (rss_type, rss_href, rss_title))

    if feeds:
        msg = L('Found feed(s):%s%s', '%s/%s' % (jid, nick)) % (' ', '\n'.join(feeds))
        send_msg(type, jid, nick, unescape(msg))
    else:
        send_msg(type, jid, nick, L('Bad url or rss/atom not found!', '%s/%s' % (jid, nick)))

# --------------------------------------------------------------------------- #
# REGISTER COMMANDS                                                           #
# --------------------------------------------------------------------------- #

execute = [
    (4, 'rss_search', rss_search, 2, 'Search RSS/ATOM feeds.\nrss_search <url> - find feeds on page or parse direct feed'),
]
