#!/usr/bin/python3
import sys
import os
import o11
import base64
import json
import datetime
import pytz
import time
import hmac
import hashlib
import string
import random
import urllib
from urllib.parse import urlencode, quote

user = o11.parse_params(sys.argv, 'user')
password = o11.parse_params(sys.argv, 'password')
device_id = o11.parse_params(
    sys.argv, 'device', 'f26d9ef3-05b7-440f-973b-d7110590124a')

id = o11.parse_params(sys.argv, 'id')
action = o11.parse_params(sys.argv, 'action')

doh = o11.parse_params(sys.argv, 'doh')
bind = o11.parse_params(sys.argv, 'bind')
proxy = o11.parse_params(sys.argv, 'proxy')

cdm = o11.parse_params(sys.argv, 'cdm')
drm = o11.parse_params(sys.argv, 'drm')
challenge = o11.parse_params(sys.argv, 'challenge')
pssh = o11.parse_params(sys.argv, 'pssh')

o11Session = o11.session(bind=bind, proxy=proxy)
req = o11Session.get_session()
if doh != "":
    o11.dns(doh)

if challenge == "cert":
    challenge = "CAQ="

authFile = '/movistar_' + user + '.tokens'


def generate_random_string(length=9):
    characters = string.ascii_letters + string.digits
    random_string = ''.join(random.choice(characters) for i in range(length))
    return random_string


def Hmac(input: str):
    key = 'FhuexVa0VO7ZZcnZYQ7RnaPrQIV4DxAd'
    h = hmac.new(bytes(key, 'UTF-8'), input.encode(), hashlib.sha1)
    return base64.b64encode(h.digest()).decode()


def get_signature(type, url, authType, authValue, post_data):

    ts = int(time.time())
 
    nonce = generate_random_string()

    to_sign = {
        authType: authValue,
        'consumer_key': 'tablet_android_1.0.1',
        'nonce': nonce,
        'signature_method': 'HMAC-SHA1',
        'timestamp': str(ts),
        'version': '1.0'
    }

    if post_data:
        to_sign.update(post_data)
    
    to_sign = dict(sorted(to_sign.items()))
    
    to_sign = type + '&' + quote(url).replace('/',
                                              '%2F') + '&' + quote(urlencode(to_sign))

    signature = "consumer_key=tablet_android_1.0.1,nonce=" + nonce + \
        ",signature_method=HMAC-SHA1,signature=" + \
        Hmac(to_sign) + ",timestamp=" + str(ts) + ",version=1.0"
   # print(to_sign)
    #exit()
    return str(base64.b64encode(signature.encode()), 'ascii')

user='rabiri'
password='Sitolola65'

def login():
    print("logging in...", file=sys.stderr)

    headers = {
        'connection': 'Keep-Alive',
        'host': 'soter-pf.sve.video.telefonicaservices.com',
        'user-agent': 'okhttp/5.0.0-alpha.11; Huawei; BTV-W09',
        'x-signature': 'true'
        
    }

    params = {
        'deviceClass': 'tablet.android',
    }

    data = {
        'password': password,
        'grant_type': 'password',
        'scope': 'api',
        'client_secret': 'secret',
        'client_id': '491aafabb70d4644954d8fb21e0b93b1',
        'username': user,
    }

    url = 'soter-pf.sve.video.telefonicaservices.com/service/oidc/connect/token'
    s = device_id + ":tablet.android"
    a = str(base64.b64encode(s.encode()), 'ascii')
    data_to_sign = dict(data)
    data_to_sign.update(params)
    headers['authorization'] = 'OPPlus Basic=' + a + ', Signature=' + \
        get_signature('POST', url, 'Basic', a, data_to_sign)
    
    response = req.post(
        'https://' + url,
        params=params,
        headers=headers,
        data=data,
    )

    try:
        access_token = response.json()['access_token']
        print("token done", file=sys.stderr)
    except:
        output = {
            "ErrorCode": 401,
            "ErrorMessage": "auth failed"
        }
        print(json.dumps(output))
        sys.exit(0)

    headers = {
        'connection': 'Keep-Alive',
        'content-type': 'application/json;charset=UTF-8',
        'host': 'soter-pf.sve.video.telefonicaservices.com',
        'user-agent': 'okhttp/5.0.0-alpha.3; Huawei; BTV-W09',
        'x-signature': 'true',
    }

    params = {
        'legacy': 'true',
    }

    url = 'soter-pf.sve.video.telefonicaservices.com/service/login/tablet.android/accountInfo'
    headers['authorization'] = 'OPPlus Bearer=' + access_token + \
        ', Signature=' + \
        get_signature('GET', url, 'Bearer', access_token, params)

    response = req.get(
        'https://' + url,
        params=params,
        headers=headers,
    )
    print(response.text)
    print()
    try:
        account = response.json()['ofertas'][0]['accountNumber']
        print("account done", file=sys.stderr)
    except:
        print(response.text)
        print('account error')
        sys.exit(1)

    params = {
        'accountId': account,
        'deviceType': 'tablet.android',
        'legacy': 'true',
    }

    url = 'soter-pf.sve.video.telefonicaservices.com/service/login/devices'
    headers['authorization'] = 'OPPlus Bearer=' + access_token + \
        ', Signature=' + \
        get_signature('POST', url, 'Bearer', access_token, params)
    response = req.post(
        'https://soter-pf.sve.video.telefonicaservices.com/service/login/devices',
        params=params,
        headers=headers,
    )
    if response.status_code >= 300:
        print(response.text)
        print("devices error")
        sys.exit()

    print("device done", file=sys.stderr)

    headers = {
        'cmp_initdata': 'true',
        'connection': 'Keep-Alive',
        'content-type': 'application/json',
        'host': 'soter-pf.sve.video.telefonicaservices.com',
        'user-agent': 'okhttp/5.0.0-alpha.3; Huawei; BTV-W09',
        'x-movistarplus-app': '9.2.1_424',
        'x-movistarplus-deviceid': response.text.replace('"', ''),
        'x-movistarplus-dman': 'Huawei',
        'x-movistarplus-os': 'Android_10',
        'x-movistarplus-servg': 'true',
        'x-movistarplus-ui': 'n',
        'x-signature': 'true',
    }

    params = {
        'legacy': 'true',
        'status': 'login',
    }

    data = {
        'accountNumber': account,
        'sessionUserProfile': 0,
        'deviceType': 'ANT_OTT',
        'isKidProfile': False,
        'streamFormat': 'DASH',
        'streamDRM': 'Widevine',
        'streamMiscellanea': 'HTTPS',
        'deviceManufacturerProduct': 'Android',
        'deviceId': response.text.replace('"', ''),
    }

    url = 'soter-pf.sve.video.telefonicaservices.com/service/login/initData'
    headers['authorization'] = 'OPPlus Bearer=' + access_token + \
        ', Signature=' + \
        get_signature('POST', url, 'Bearer', access_token, params)

    response = req.post(
        'https://' + url,
        params=params,
        headers=headers,
        json=data,
    )
    try:
        response.json()['accessToken']
        json.dump(response.json(), open(os.path.abspath(
            os.path.dirname(__file__)) + authFile, 'w'))
    except:
        print(response.text)
        print('initData error')
        sys.exit(1)

    print("logged in", file=sys.stderr)




def do_action():

    if action != "channels":
        try:
            auth = json.load(open(os.path.abspath(
                os.path.dirname(__file__)) + authFile))
        except:
            return "error"

    if action == "channels" or action == "manifest":
        output = {}
        output['Channels'] = []

        headers = {
            'connection': 'Keep-Alive',
            'header_cache': 'no-cache:',
            'host': 'ottcache.dof6.com',
            'user-agent': 'okhttp/5.0.0-alpha.3; Huawei; BTV-W09',
        }

        params = {
            'sort': 'LC',
            'showNonRated': 'true',
            'tlsstream': 'true',
            'demarcation': '0',
            'version': '8.1',
            'filterQuality': 'UHD',
        }

        response = req.get(
            'http://ottcache.dof6.com/movistarplus/tablet.android/profiles/DTHTITULAR/channels',
            params=params,
            headers=headers,
        )
        mpd_url = ""
        try:
            for chan in response.json():
                if action == "manifest" and chan['CodCadenaTv'] == id:
                    mpd_url = chan['PuntoReproduccion']
                    break
                channel = {}
                channel['Name'] = chan['Nombre']
                channel['SortId'] = chan['Dial']
                channel['EpgId'] = chan['CodCadenaTv']
                channel['Mode'] = "live"
                channel['SessionManifest'] = True
                channel['ManifestScript'] = 'id=' + chan['CodCadenaTv']
                channel['CdmType'] = "widevine"
                channel['UseCdm'] = True
                channel['Cdm'] = 'id=' + chan['CodCadenaTv']
                channel['Video'] = 'best'
                # channel['Audio'] = 'desc:spa'
                channel['OnDemand'] = True
                channel['SpeedUp'] = True
                channel['LogoUrl'] = chan['Logos'][0]['uri']
                output['Channels'].append(channel)

            if action == "channels":
                print(json.dumps(output, indent=2))
        except:
            print(response.text, file=sys.stderr)
            return "error"

        if action == "channels":
            sys.exit()

        if mpd_url == "":
            print("Mpd url not found")
            sys.exit(1)

        headers = {
            "authorization": "Bearer " + auth["legacyAccessToken"],
            "connection": "Keep-Alive",
            "content-type": "application/json",
            "host": "idserver.dof6.com",
            "user-agent": "okhttp/5.0.0-alpha.3; Huawei; BTV-W09",
            "x-signature": "false",
        }

        response = req.post("https://idserver.dof6.com/" +
                            auth["accountNumber"] + "/devices/tablet.android/cdn/token/refresh", headers=headers)
        try:
            output = {
                "ManifestUrl": mpd_url,
                "Headers": {
                    "Manifest": {
                        'X-Tcdn-Token': response.json()['access_token'],
                        'User-Agent': 'Exoplayer-Android-Movilidad',
                    },
                    "Media": {
                        'X-Tcdn-Token': response.json()['access_token'],
                        'User-Agent': 'Exoplayer-Android-Movilidad',
                    }
                },
            }
            print(json.dumps(output))
        except:
            print(response.text, file=sys.stderr)
            print("token/refresh error", file=sys.stderr)
            return "error"

    elif action == "cdm" and cdm == "internal":
        headers = {
            'connection': 'Keep-Alive',
            'host': 'wv-ottlic-f3.imagenio.telefonica.net',
            'nv-authorizations': auth['sspToken'],
            'user-agent': 'Exoplayer-Android-Movilidad',
        }

        response = req.post(
            'https://wv-ottlic-f3.imagenio.telefonica.net/TFAESP/wvls/contentlicenseservice/v1/licenses',
            headers=headers,
            data=base64.b64decode(challenge)
        )
        response_b64 = str(base64.b64encode(response.content), 'ascii')
        if response_b64.startswith('CA'):
            print(response_b64)
        else:
            print(response.text, file=sys.stderr)
            return "error"

    else:
        print("invalid action: " + action)


if do_action() == "error":
    login()
    do_action()
