#!/usr/bin/env php
<?php
error_reporting(0);
ini_set('memory_limit', '-1');
$base = 'http://';
$mac  = '00:1A:79:30:6F:DD';
$out_file = 'epg.xml';
function curl_req($url, $headers = [], $cookies = '', $timeout = 15) {
    $ch = curl_init($url);
    if ($headers) curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    if ($cookies) curl_setopt($ch, CURLOPT_COOKIE, $cookies);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_TIMEOUT => $timeout,
        CURLOPT_CONNECTTIMEOUT => 6,
        CURLOPT_SSL_VERIFYHOST => 0,
        CURLOPT_SSL_VERIFYPEER => 0
    ]);
    $res  = curl_exec($ch);
    $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    return [$res, $code];
}
function extract_token($body) {
    $j = json_decode($body, true);
    if (isset($j['js']['token'])) return $j['js']['token'];
    if (preg_match('/"token"\s*:\s*"([^"]+)"/', $body, $m)) return $m[1];
    return null;
}
function mag_headers($token = null) {
    $h = [
        "User-Agent: Mozilla/5.0 (QtEmbedded; U; Linux; C) AppleWebKit/533.3 (KHTML, like Gecko) MAG254 stbapp ver: 2 rev: 250 Safari/533.3",
        "X-User-Agent: Model: MAG254; Link: Ethernet",
        "Accept: application/json, text/javascript, */*; q=0.01",
        "X-Requested-With: XMLHttpRequest",
        "Connection: Keep-Alive",
        "Cache-Control: no-store, no-cache, must-revalidate"
    ];
    if ($token) $h[] = "Authorization: Bearer $token";
    return $h;
}
echo "Portal: $base\n";
echo "MAC:    $mac\n";
$cookies = "mac=$mac; stb_lang=en; timezone=Europe/Berlin";
$handshake_urls = [
    "$base/portal.php?action=handshake&type=stb&token=&JsHttpRequest=1-xml",
    "$base/portal.php?type=stb&action=handshake&token=&JsHttpRequest=1-xml",
    "$base/stalker_portal/c/portal.php?action=handshake&type=stb&token=&JsHttpRequest=1-xml"
];
$token = null;
foreach ($handshake_urls as $url) {
    list($body, $code) = curl_req($url, array_merge(mag_headers(), ["Authorization: MAC $mac"]), $cookies);
    if ($code == 200 && $body) {
        $token = extract_token($body);
        if ($token) break;
    }
}
if (!$token) {
    echo "Handshake failed\n";
    exit;
}
$hdr = mag_headers($token);
$epg_data = [];
$epg_urls = [
    "$base/load.php?type=epg&action=get_simple_data_table&JsHttpRequest=1-xml",
    "$base/portal.php?type=epg&action=get_simple_data_table&JsHttpRequest=1-xml",
    "$base/portal.php?type=itv&action=get_epg_info&period=72&JsHttpRequest=1-xml"
];
foreach ($epg_urls as $url) {
    list($body, $code) = curl_req($url, $hdr, $cookies, 25);
    if ($code == 200 && $body) {
        $j = json_decode($body, true);
        if (isset($j['js']['data'])) {
            $epg_data = $j['js']['data'];
            break;
        }
    }
}
if (empty($epg_data)) {
    $chan_url = "$base/portal.php?type=itv&action=get_all_channels&JsHttpRequest=1-xml";
    list($chan_body, $chan_code) = curl_req($chan_url, $hdr, $cookies, 25);
    if ($chan_code == 200 && $chan_body) {
        $c = json_decode($chan_body, true);
        if (isset($c['js']['data'])) {
            $channels = $c['js']['data'];
            foreach ($channels as $ch) {
                if (!isset($ch['id'])) continue;
                $cid = $ch['id'];
                $url = "$base/portal.php?type=itv&action=get_short_epg&ch_id=$cid&JsHttpRequest=1-xml";
                list($b, $cc) = curl_req($url, $hdr, $cookies, 10);
                if ($cc == 200 && $b) {
                    $d = json_decode($b, true);
                    if (isset($d['js']['data'])) $epg_data[$cid] = $d['js']['data'];
                }
            }
        }
    }
}
if (empty($epg_data)) {
    echo "No EPG data found\n";
    exit;
}
$xml = new DOMDocument('1.0', 'UTF-8');
$xml->formatOutput = true;
$tv = $xml->createElement('tv');
$tv->setAttribute('generator-info-name', 'MAG-EPG');
$xml->appendChild($tv);
foreach (array_keys($epg_data) as $cid) {
    $c = $xml->createElement('channel');
    $c->setAttribute('id', $cid);
    $dn = $xml->createElement('display-name', $cid);
    $c->appendChild($dn);
    $tv->appendChild($c);
}
foreach ($epg_data as $cid => $programs) {
    if (!is_array($programs)) continue;
    foreach ($programs as $p) {
        $start = gmdate('YmdHis O', intval($p['start_timestamp']));
        $stop  = gmdate('YmdHis O', intval($p['stop_timestamp']));
        $prog = $xml->createElement('programme');
        $prog->setAttribute('start', $start);
        $prog->setAttribute('stop',  $stop);
        $prog->setAttribute('channel', $cid);
        $t = $xml->createElement('title', $p['name'] ?? '');
        $prog->appendChild($t);
        if (!empty($p['descr'])) {
            $d = $xml->createElement('desc', $p['descr']);
            $prog->appendChild($d);
        }
        $tv->appendChild($prog);
    }
}
$xml->save($out_file);
echo "EPG saved to $out_file\n";