#!/usr/bin/env python3

#========================================================================
# POPIS SKRIPTU
#========================================================================
#
# Tento skript načíta M3U playlist a pre každý kanál s CID zavolá
# sweet.tv OpenStream API.
#
# Ak API vráti novú stream URL, pôvodná URL sa nahradí novou.
# Ak API zlyhá, pôvodná URL zostane zachovaná.
#
# Vstup:
#   premium.m3u
#
# Výstup:
#   premium1.m3u
#
#========================================================================


#========================================================================
# IMPORT
#========================================================================

import re
import json
import sys
import time
import requests
from urllib.parse import urljoin


#========================================================================
# NASTAVENIE SÚBOROV A API
#========================================================================

INPUT_M3U = "/opt/epg/sk_tvg-id.m3u"

OUTPUT_M3U = "/opt/epg/1.m3u"

OPEN_STREAM_URL = "https://api.sweet.tv/TvService/OpenStream.json"


#========================================================================
# HTTP HLAVIČKY
#========================================================================

HEADERS = {
    "User-Agent": "Mozilla/5.0",
    "Accept": "application/json, text/plain, */*",
    "Content-Type": "application/json",
}


#========================================================================
# PARAMETRE PRE OPENSTREAM API
#========================================================================

# Ak OpenStream vyžaduje iné parametre, upravíme ich neskôr

REQUEST_TEMPLATE = {
    "channel_id": None
}


#========================================================================
# TIMEOUT
#========================================================================

TIMEOUT = 15


#========================================================================
# OPEN STREAM
#========================================================================

def open_stream(cid):

    payload = dict(REQUEST_TEMPLATE)

    payload["channel_id"] = int(cid)

    try:

        r = requests.post(
            OPEN_STREAM_URL,
            headers=HEADERS,
            json=payload,
            timeout=TIMEOUT
        )

        print(f"      HTTP: {r.status_code}")

        #----------------------------------------------------------------
        # NAČÍTANIE JSON ODPOVEDE
        #----------------------------------------------------------------

        try:

            data = r.json()

        except Exception:

            print("      ERROR: odpoveď nie je JSON")
            print("      ", r.text[:500])

            return None

        #----------------------------------------------------------------
        # KONTROLA RESULT
        #----------------------------------------------------------------

        result = data.get("result")

        print(f"      RESULT: {result}")

        if result != "OK":

            print(
                f"      API: {json.dumps(data, ensure_ascii=False)}"
            )

            return None

        #----------------------------------------------------------------
        # NÁJDENIE STREAM URL
        #----------------------------------------------------------------

        url = data.get("url")

        #----------------------------------------------------------------
        # ALTERNATÍVNA HTTP STREAM ŠTRUKTÚRA
        #----------------------------------------------------------------

        if not url:

            http_stream = data.get(
                "http_stream",
                {}
            )

            url = http_stream.get("url")

            if url:

                host = http_stream.get(
                    "host",
                    {}
                ).get("address")

                if host:

                    url = f"https://{host}{url}"

        #----------------------------------------------------------------
        # KONTROLA STREAM URL
        #----------------------------------------------------------------

        if not url:

            print(
                "      ERROR: API nevrátil stream URL"
            )

            return None

        #----------------------------------------------------------------
        # PREVOD HTTP NA HTTPS
        #----------------------------------------------------------------

        # sweet môže vrátiť HTTP URL.
        # Pre HLS použijeme HTTPS.

        if url.startswith("http://"):

            url = "https://" + url[7:]

        #----------------------------------------------------------------
        # VRÁTENIE STREAM INFORMÁCIÍ
        #----------------------------------------------------------------

        return {
            "url": url,
            "stream_id": data.get("stream_id"),
            "update_interval": data.get("update_interval"),
        }

    except requests.RequestException as e:

        print(
            f"      REQUEST ERROR: {e}"
        )

        return None


#========================================================================
# M3U PARSER
#========================================================================

def parse_m3u(filename):

    #--------------------------------------------------------------------
    # NAČÍTANIE M3U
    #--------------------------------------------------------------------

    with open(
        filename,
        "r",
        encoding="utf-8",
        errors="replace"
    ) as f:

        lines = f.readlines()

    channels = []

    i = 0

    #--------------------------------------------------------------------
    # SPRACOVANIE RIADKOV
    #--------------------------------------------------------------------

    while i < len(lines):

        line = lines[i].strip()

        #----------------------------------------------------------------
        # NÁJDENIE #EXTINF
        #----------------------------------------------------------------

        if line.startswith("#EXTINF:"):

            extinf = line

            url = None

            j = i + 1

            #------------------------------------------------------------
            # NÁJDENIE STREAM URL
            #------------------------------------------------------------

            while j < len(lines):

                candidate = lines[j].strip()

                if not candidate:

                    j += 1
                    continue

                if candidate.startswith("#"):

                    j += 1
                    continue

                url = candidate

                break

            #------------------------------------------------------------
            # AK SA NAŠLA URL
            #------------------------------------------------------------

            if url:

                #--------------------------------------------------------
                # NÁJDENIE CID ALEBO TVG-ID
                #--------------------------------------------------------

                cid_match = re.search(
                    r'(?:cid|tvg-id)=["\']?([^"\',\s]+)',
                    extinf,
                    re.IGNORECASE
                )

                cid = (
                    cid_match.group(1)
                    if cid_match
                    else None
                )

                #--------------------------------------------------------
                # ULOŽENIE KANÁLA
                #--------------------------------------------------------

                channels.append({
                    "extinf": extinf,
                    "url": url,
                    "cid": cid,
                })

                i = j

        i += 1

    return channels


#========================================================================
# HLAVNÁ FUNKCIA
#========================================================================

def main():

    #--------------------------------------------------------------------
    # ÚVODNÝ VÝPIS
    #--------------------------------------------------------------------

    print(
        "======================================"
    )

    print(
        "sweet TV PLAYLIST UPDATE"
    )

    print(
        "======================================"
    )

    print(
        f"INPUT : {INPUT_M3U}"
    )

    print(
        f"OUTPUT: {OUTPUT_M3U}"
    )

    print()

    #--------------------------------------------------------------------
    # NAČÍTANIE PLAYLISTU
    #--------------------------------------------------------------------

    try:

        channels = parse_m3u(
            INPUT_M3U
        )

    except FileNotFoundError:

        print(
            f"CHYBA: súbor {INPUT_M3U} neexistuje"
        )

        sys.exit(1)

    print(
        f"Nájdené kanály: {len(channels)}"
    )

    print()

    #--------------------------------------------------------------------
    # POČÍTADLÁ
    #--------------------------------------------------------------------

    updated = 0
    failed = 0
    no_cid = 0

    #--------------------------------------------------------------------
    # HLAVIČKA VÝSTUPNÉHO M3U
    #--------------------------------------------------------------------

    output = [
        "#EXTM3U\n"
    ]

    #--------------------------------------------------------------------
    # SPRACOVANIE VŠETKÝCH KANÁLOV
    #--------------------------------------------------------------------

    for index, ch in enumerate(
        channels,
        1
    ):

        cid = ch["cid"]

        #---------------------------------------------------------------
        # ODSTRÁNENIE PREFIXU CID=
        #---------------------------------------------------------------

        if cid and cid.upper().startswith("CID="):

            cid = cid[4:]

        print(
            "--------------------------------------"
        )

        print(
            f"[{index}/{len(channels)}]"
        )

        #---------------------------------------------------------------
        # VÝPIS CID
        #---------------------------------------------------------------

        if cid:

            print(
                f"CID : {cid}"
            )

        else:

            print(
                "CID : NENÁJDENÉ"
            )

        #---------------------------------------------------------------
        # VÝPIS INFORMÁCIE O KANÁLI
        #---------------------------------------------------------------

        print(
            f"NAME: {ch['extinf']}"
        )

        new_url = None

        #---------------------------------------------------------------
        # AK EXISTUJE CID
        #---------------------------------------------------------------

        if cid:

            stream = open_stream(
                cid
            )

            #-----------------------------------------------------------
            # STREAM ÚSPEŠNE ZÍSKANÝ
            #-----------------------------------------------------------

            if stream:

                new_url = stream["url"]

                print(
                    "      STREAM: OK"
                )

                print(
                    f"      STREAM ID: {stream['stream_id']}"
                )

                print(
                    f"      URL: {new_url}"
                )

                updated += 1

            #-----------------------------------------------------------
            # STREAM SA NEPODARILO ZÍSKAŤ
            #-----------------------------------------------------------

            else:

                print(
                    "      STREAM: FAILED"
                )

                print(
                    "      Ponechávam pôvodnú URL"
                )

                failed += 1

        #---------------------------------------------------------------
        # KANÁL NEMÁ CID
        #---------------------------------------------------------------

        else:

            no_cid += 1

            print(
                "      Bez CID - ponechávam pôvodnú URL"
            )

        #---------------------------------------------------------------
        # ZÁPIS #EXTINF
        #---------------------------------------------------------------

        output.append(
            ch["extinf"] + "\n"
        )

        #---------------------------------------------------------------
        # ZÁPIS STREAM URL
        #---------------------------------------------------------------

        output.append(
            (new_url or ch["url"]) + "\n"
        )

        #---------------------------------------------------------------
        # PAUZA MEDZI API POŽIADAVKAMI
        #---------------------------------------------------------------

        time.sleep(0.2)

    #========================================================================
    # ULOŽENIE VÝSTUPNÉHO PLAYLISTU
    #========================================================================

    with open(
        OUTPUT_M3U,
        "w",
        encoding="utf-8"
    ) as f:

        f.writelines(
            output
        )


    #========================================================================
    # ZÁVEREČNÉ ŠTATISTIKY
    #========================================================================

    print()

    print(
        "======================================"
    )

    print(
        "HOTOVO"
    )

    print(
        "======================================"
    )

    print(
        f"Celkom       : {len(channels)}"
    )

    print(
        f"Aktualizované: {updated}"
    )

    print(
        f"Neúspešné    : {failed}"
    )

    print(
        f"Bez CID      : {no_cid}"
    )

    print(
        f"Výstup       : {OUTPUT_M3U}"
    )

    print(
        "======================================"
    )


#========================================================================
# SPUSTENIE SKRIPTU
#========================================================================

if __name__ == "__main__":

    main()