#!/usr/bin/env python3

import requests
import re
import time
from pathlib import Path


# ============================================================
# CONFIG
# ============================================================

INPUT_M3U = Path(
    "/opt/epg/megahit.m3u"
)

OUTPUT_M3U = Path(
    "/opt/epg/cz1.m3u"
)

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

# ============================================================
# ACCESS TOKEN
# ============================================================

# VLOŽ SEM AKTUÁLNY ACCESS TOKEN
# IBA TOKEN, BEZ "Bearer "
#
# Príklad:
# ACCESS_TOKEN = "eyJhbGciOi..."
#
# Token sa NEZAPISUJE do M3U.

ACCESS_TOKEN = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIzNzU0NzcyODgwNjMwOTUyNjUyIiwiaXNzIjoiQW5hbHl0aWNzIiwic3ViIjoiMCIsImV4cCI6MTc5MDE4NjQ2NCwiaWF0IjoxNzkwMTc1NjY0LCJkZXZpY2UiOnsidHlwZSI6MjIsImZpcm13YXJlIjp7InZlcnNpb25Db2RlIjoxLCJ2ZXJzaW9uU3RyaW5nIjoiOS4xLjM0In0sInN1Yl90eXBlIjo0MCwibW9kZWwiOiJNb3ppbGxhLzUuMCAoV2luZG93cyBOVCAxMC4wOyBXaW42NDsgeDY0KSBBcHBsZVdlYktpdC81MzcuMzYgKEtIVE1MLCBsaWtlIEdlY2tvKSBDaHJvbWUvMTU0LjAuMC4wIFNhZmFyaS81MzcuMzYgRWRnLzE1NC4wLjAuMCIsInV1aWQiOiIxYzVjMjljMi0wZjdmLTQ0NDAtOTgzYi0yMDM5NmEzYjAwMTUiLCJzY3JlZW5faW5mbyI6eyJ3aWR0aCI6MTUzNiwiaGVpZ2h0Ijo4NjQsImFzcGVjdFJhdGlvIjo2fSwiYXBwbGljYXRpb24iOnsidHlwZSI6Mn0sInN1cHBvcnRlZF9kcm0iOnsid2lkZXZpbmVfbW9kdWxhciI6dHJ1ZX0sImRybV9pbmZvIjp7IndpZGV2aW5lX2luZm8iOnsic2VjdXJpdHlfbGV2ZWwiOjN9fX0sImlwIjoiMTkzLjEyMy4xODcuMjQ3In0.wBeHxRl5AHt9PrrxRmE2HilNC1W3b9dKarGiP29Kik0"

# ============================================================
# USER AGENT
# ============================================================

USER_AGENT = (
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
    "AppleWebKit/537.36 (KHTML, like Gecko) "
    "Chrome/151.0.0.0 Safari/537.36 Edg/151.0.0.0"
)


# ============================================================
# CATCHUP
# ============================================================

# Sweet TV pri Jednotke napr.:
#
# catchup: true
# catchup_duration: 7
# epg_days_past: 7
#
# Preto zatiaľ nastavíme 7 dní.

CATCHUP_DAYS = 7


# ============================================================
# OTHER
# ============================================================

TIMEOUT = 20
DELAY = 0.15


# ============================================================
# SESSION
# ============================================================

session = requests.Session()

session.headers.update({
    "User-Agent": USER_AGENT,
    "Accept": "application/json, text/plain, */*",
    "Accept-Language": "cs,en-GB;q=0.9,en;q=0.8,en-US;q=0.7",
    "Content-Type": "application/json",
    "Origin": "https://sweet.tv",
    "Referer": "https://sweet.tv/",
})


# ============================================================
# PARSE M3U
# ============================================================

def load_channels(filename):

    channels = []

    try:

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

            lines = [x.strip() for x in f if x.strip()]

        for i, line in enumerate(lines):

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

            # ------------------------------------------------
            # CID
            # ------------------------------------------------

            cid_match = re.search(
                r'cid="(\d+)"',
                line
            )

            if not cid_match:
                continue

            cid = cid_match.group(1)

            # ------------------------------------------------
            # NAME
            # ------------------------------------------------

            name_match = re.search(
                r'tvg-name="([^"]*)"',
                line
            )

            name = (
                name_match.group(1)
                if name_match
                else ""
            )

            # ------------------------------------------------
            # LOGO
            # ------------------------------------------------

            logo_match = re.search(
                r'tvg-logo="([^"]*)"',
                line
            )

            logo = (
                logo_match.group(1)
                if logo_match
                else ""
            )

            # ------------------------------------------------
            # FIND EXISTING URL
            # ------------------------------------------------

            old_url = ""

            for j in range(i + 1, len(lines)):

                if lines[j].startswith("#EXTINF:"):
                    break

                if not lines[j].startswith("#"):

                    old_url = lines[j]
                    break

            channels.append({
                "cid": cid,
                "name": name,
                "logo": logo,
                "extinf": line,
                "old_url": old_url
            })

    except FileNotFoundError:

        print()
        print("CHYBA: Súbor neexistuje:")
        print(filename)
        return []

    except Exception as e:

        print()
        print("CHYBA pri čítaní M3U:")
        print(type(e).__name__, e)
        return []

    return channels


# ============================================================
# ADD CATCHUP TO EXTINF
# ============================================================

def add_catchup(extinf):

    # Rozdelíme EXTINF na:
    # 1. atribúty
    # 2. názov kanála

    if "," in extinf:
        attributes, name = extinf.split(",", 1)
    else:
        attributes = extinf
        name = ""

    # Odstránime prípadné staré hodnoty
    attributes = re.sub(
        r'\s+catchup="[^"]*"',
        "",
        attributes
    )

    attributes = re.sub(
        r'\s+catchup-days="[^"]*"',
        "",
        attributes
    )

    attributes = re.sub(
        r'\s+catchup-duration="[^"]*"',
        "",
        attributes
    )

    # Pridáme catchup
    attributes += (
        f' catchup="default"'
        f' catchup-days="{CATCHUP_DAYS}"'
    )

    # Zložíme EXTINF späť
    return attributes + "," + name

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

def open_stream(cid, use_bearer=False):

    headers = {}

    if use_bearer and ACCESS_TOKEN:

        headers["Authorization"] = (
            f"Bearer {ACCESS_TOKEN}"
        )

    payload = {
        "channel_id": int(cid)
    }

    try:

        response = session.post(
            STREAM_API,
            headers=headers,
            json=payload,
            timeout=TIMEOUT
        )

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

        try:

            data = response.json()

        except Exception:

            print("      API nevrátilo JSON")
            print(response.text[:500])
            return None

        result = data.get("result")
        status = data.get("status")

        print(
            f"      RESULT: {result}  STATUS: {status}"
        )

        # ----------------------------------------------------
        # NO AUTH
        # ----------------------------------------------------

        if result == "NoAuth" or status == "NoAuth":

            print(
                "      API RESPONSE: NoAuth"
            )

            return None

        # ----------------------------------------------------
        # ERROR
        # ----------------------------------------------------

        if result != "OK":

            print(
                "      API RESPONSE:"
            )

            print(data)

            return None

        # ----------------------------------------------------
        # HTTP STREAM
        # ----------------------------------------------------

        stream_url = None

        http_stream = data.get(
            "http_stream"
        )

        if isinstance(http_stream, dict):

            stream_url = http_stream.get("url")

            # ------------------------------------------------
            # RELATIVE URL
            # ------------------------------------------------

            if (
                stream_url
                and stream_url.startswith("/")
            ):

                host = http_stream.get("host")

                if isinstance(host, dict):

                    address = host.get("address")

                    if address:

                        stream_url = (
                            "https://"
                            + address
                            + stream_url
                        )

        # ----------------------------------------------------
        # ALTERNATIVE URL
        # ----------------------------------------------------

        if not stream_url:

            stream_url = data.get("url")

        # ----------------------------------------------------
        # NO URL
        # ----------------------------------------------------

        if not stream_url:

            print(
                "      STREAM URL: NENAJDENÁ"
            )

            return None

        print(
            "      => STREAM OK"
        )

        if data.get("stream_id"):

            print(
                "      STREAM ID:",
                data.get("stream_id")
            )

        print(
            "      URL:",
            stream_url
        )

        return stream_url

    except requests.RequestException as e:

        print(
            "      REQUEST ERROR:",
            e
        )

        return None


# ============================================================
# MAIN
# ============================================================

def main():

    print()
    print("======================================")
    print(" SWEET TV LIVE + CATCHUP UPDATE")
    print("======================================")

    print(
        "INPUT :",
        INPUT_M3U
    )

    print(
        "OUTPUT:",
        OUTPUT_M3U
    )


    print(
        "API   :",
        STREAM_API
    )

    print(
        "Bearer:",
        "ÁNO" if ACCESS_TOKEN else "NIE"
    )

    print(
        "Catchup:",
        CATCHUP_DAYS,
        "dní"
    )

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

    # ========================================================
    # LOAD
    # ========================================================

    channels = load_channels(
        INPUT_M3U
    )

    if not channels:

        print(
            "Nenašli sa žiadne kanály."
        )

        return

    print(
        "Nájdených kanálov:",
        len(channels)
    )

    print()

    # ========================================================
    # OUTPUT
    # ========================================================

    output = [
        "#EXTM3U"
    ]

    updated = 0
    failed = 0

    # ========================================================
    # PROCESS
    # ========================================================

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

        cid = channel["cid"]
        name = channel["name"]
        extinf = channel["extinf"]

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

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

        print(
            "CID :",
            cid
        )

        print(
            "NAME:",
            name
        )

        # ====================================================
        # OPENSTREAM WITHOUT BEARER
        # ====================================================

        print(
            "      OpenStream bez Bearer..."
        )

        stream_url = open_stream(
            cid,
            use_bearer=False
        )

        # ====================================================
        # TRY BEARER
        # ====================================================

        if not stream_url and ACCESS_TOKEN:

            print(
                "      Skúšam Bearer..."
            )

            stream_url = open_stream(
                cid,
                use_bearer=True
            )

            if stream_url:

                print(
                    "      => BEARER FUNGUJE"
                )

        # ====================================================
        # SAVE
        # ====================================================

        if stream_url:

            # ------------------------------------------------
            # CATCHUP
            # ------------------------------------------------

            extinf = add_catchup(
                extinf
            )

            # ------------------------------------------------
            # EXTINF
            # ------------------------------------------------

            output.append(
                extinf
            )

            # ------------------------------------------------
            # VLC USER AGENT
            # ------------------------------------------------

            output.append(
                "#EXTVLCOPT:http-user-agent="
                + USER_AGENT
            )

            # ------------------------------------------------
            # KODI USER AGENT
            # ------------------------------------------------

            output.append(
                "#KODIPROP:http-user-agent="
                + USER_AGENT
            )

            # ------------------------------------------------
            # STREAM
            # ------------------------------------------------

            output.append(
                stream_url
            )

            updated += 1

            print(
                "      => PRIDANÉ DO M3U"
            )

            print(
                "      => CATCHUP:",
                CATCHUP_DAYS,
                "dní"
            )

        else:

            failed += 1

            print(
                "      => STREAM FAILED"
            )

            print(
                "      => NEPRIDANÉ DO M3U"
            )

        print()

        time.sleep(
            DELAY
        )

    # ========================================================
    # WRITE
    # ========================================================

    try:

        OUTPUT_M3U.parent.mkdir(
            parents=True,
            exist_ok=True
        )

        OUTPUT_M3U.write_text(
            "\n".join(output) + "\n",
            encoding="utf-8"
        )

    except Exception as e:

        print()
        print(
            "CHYBA pri zápise M3U:"
        )

        print(
            type(e).__name__,
            e
        )

        return

    # ========================================================
    # SUMMARY
    # ========================================================

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

    print(
        "Zdrojových kanálov:",
        len(channels)
    )

    print(
        "Aktualizované     :",
        updated
    )

    print(
        "Neúspešné         :",
        failed
    )

    print(
        "Catchup           :",
        CATCHUP_DAYS,
        "dní"
    )

    print(
        "Výstup            :",
        OUTPUT_M3U
    )

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


# ============================================================
# START
# ============================================================

if __name__ == "__main__":
    main()