Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- try: # Python 3
- from http.server import BaseHTTPRequestHandler
- except ImportError: # Python 2
- from BaseHTTPServer import BaseHTTPRequestHandler
- try: # Python 3
- from socketserver import TCPServer
- except ImportError: # Python 2
- from SocketServer import TCPServer
- try: # Python 3
- from urllib.parse import parse_qs, urlparse, urlencode, quote, unquote
- except ImportError: # Python 2
- from urlparse import urlparse, parse_qs
- from urllib import urlencode, quote, unquote
- import re
- import xbmcaddon
- import socket
- from contextlib import closing
- addon = xbmcaddon.Addon(id='plugin.video.canalplusvod')
- import requests
- import urllib3
- import xbmc, time
- import json
- requests.packages.urllib3.disable_warnings()
- requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS += ':HIGH:!DH:!aNULL'
- import ssl
- try:
- _create_unverified_https_context = ssl._create_unverified_context
- except AttributeError:
- pass
- else:
- ssl._create_default_https_context = _create_unverified_https_context
- import sys
- PY3 = sys.version_info >= (3, 0, 0)
- __addon__ = xbmcaddon.Addon()
- __scriptname__ = __addon__.getAddonInfo('name')
- sess = requests.Session()
- proxyport = addon.getSetting('proxyport')
- def log(msg=None, ex=None):
- if ex:
- level = xbmc.LOGERROR
- else:
- level = xbmc.LOGINFO
- xbmc.log((u"### [%s] - %s" % (__scriptname__, msg)), level=level)
- def czas():
- import datetime
- now = datetime.datetime.now()
- czas = now.strftime('%Y-%m-%dT%H:%M:%SZ')
- from datetime import datetime
- import time
- try:
- format_date = datetime.strptime(czas, '%Y-%m-%dT%H:%M:%SZ')
- except TypeError:
- format_date = datetime(*(time.strptime(czas, '%Y-%m-%dT%H:%M:%SZ')[0:6]))
- def to_timestamp(a_date):
- from datetime import datetime
- try:
- import pytz
- except:
- pass
- if a_date.tzinfo:
- epoch = datetime(1970, 1, 1, tzinfo=pytz.UTC)
- diff = a_date.astimezone(pytz.UTC) - epoch
- else:
- epoch = datetime(1970, 1, 1)
- diff = a_date - epoch
- return int(diff.total_seconds()) * 1000
- tst4 = to_timestamp(format_date)
- return int(tst4)
- def get_addon():
- return addon
- def set_setting(key, value):
- return get_addon().setSetting(key, value)
- def get_setting(key):
- return get_addon().getSetting(key)
- def dialog_progress():
- return xbmcgui.DialogProgress()
- def xbmc_sleep(time):
- return xbmc.sleep(time)
- def getRequests(url, data="", headers={}, params={}, allo=None):
- if data:
- if allo:
- content = sess.get(url, headers=headers, data=data, params=params, verify=False).url
- else:
- content = sess.post(url, headers=headers, data=data, params=params, verify=False) # .json()
- try:
- content = content.json()
- except:
- content = content.text
- else:
- if allo:
- content = sess.get(url, headers=headers, params=params, verify=False).url
- else:
- content = sess.get(url, headers=headers, params=params, verify=False)
- try:
- content = content.json()
- except:
- content = content.text
- return content
- def PLchar(char):
- if type(char) is not str:
- char = char.encode('utf-8')
- char = char.replace('\\u0105', '\xc4\x85').replace('\\u0104', '\xc4\x84')
- char = char.replace('\\u0107', '\xc4\x87').replace('\\u0106', '\xc4\x86')
- char = char.replace('\\u0119', '\xc4\x99').replace('\\u0118', '\xc4\x98')
- char = char.replace('\\u0142', '\xc5\x82').replace('\\u0141', '\xc5\x81')
- char = char.replace('\\u0144', '\xc5\x84').replace('\\u0144', '\xc5\x83')
- char = char.replace('\\u00f3', '\xc3\xb3').replace('\\u00d3', '\xc3\x93')
- char = char.replace('\\u015b', '\xc5\x9b').replace('\\u015a', '\xc5\x9a')
- char = char.replace('\\u017a', '\xc5\xba').replace('\\u0179', '\xc5\xb9')
- char = char.replace('\\u017c', '\xc5\xbc').replace('\\u017b', '\xc5\xbb')
- char = char.replace('’', "'")
- char = char.replace('–', "-")
- char = char.replace('…', "...")
- char = char.replace('„', '"').replace('”', '"')
- char = char.replace('[…]', "...")
- char = char.replace('&', "&")
- char = char.replace(''', "'")
- char = char.replace('"', '"')
- char = char.replace(' ', ".").replace('&', '&')
- return char
- class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
- PASStoken = get_setting('PASStoken')
- PASSid = get_setting('PASSid')
- clientid = get_setting('clientid')
- portailId = get_setting('portailId')
- OAUTH = 'https://logowanie.pl.canalplus.com/login' # 'https://dev.canalplus.com/pl/oauth'
- CREATE_TOKEN = 'https://pass-api-v2.canal-plus.com/provider/services/PL/public/createToken'
- DEVID = addon.getSetting('devid')
- MACROel = get_setting('MACROel')
- MICROel = get_setting('MICROel')
- EPGid = get_setting('EPGid')
- DEVICE_ID = addon.getSetting('device_id')
- HODORheaders = {
- 'Host': 'hodor.canalplus.pro',
- 'user-agent': 'myCANAL/ 4.6.6 (440010924) - Android/9 - android - SM-J330F',
- }
- CMStoken = get_setting('CMStoken')
- def gen_hex_code(self, myrange=6):
- import random
- return ''.join([random.choice('0123456789abcdef') for x in range(myrange)])
- def TVinit(self):
- self.RefreshPassToken()
- headers = {
- 'User-Agent': 'myCANAL/4.6.6(440010924) - Android/9 - android - SM-J330F',
- 'Content-Type': 'application/json; charset=utf-8',
- 'Host': 'secure-mobiletv.canal-plus.com',
- }
- headers = {
- 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0',
- 'Accept': 'application/json, text/plain, */*',
- 'Accept-Language': 'pl,en-US;q=0.7,en;q=0.3',
- 'Content-Type': 'application/json;charset=utf-8',
- 'Origin': 'https://www.canalplus.com',
- 'DNT': '1',
- 'Connection': 'keep-alive',
- 'Referer': 'https://www.canalplus.com/', }
- import time
- ts = int(time.time()) * 100
- a = str(ts)
- b = str(czas())
- if not self.DEVID:
- self.DEVID = '%s-%s' % (b, self.gen_hex_code(12))
- set_setting('devid', self.DEVID)
- zzzDEVID = '%s-%s' % (b, self.gen_hex_code(12))
- ptok = get_setting('PASStoken') # split('PL=')[-1]
- data = {"ServiceRequest": {
- "InData": {"PassData": {"Id": 0, "Token": ptok}, "UserKeyId": self.DEVICE_ID, "DeviceKeyId": self.DEVID,
- "PDSData": {"GroupTypes": "1;4"}}}}
- data = json.dumps(data)
- # epgs = self.epgLive()
- urlk = 'https://secure-webtv.canal-plus.com/WebPortal/ottlivetv/api/V4/zones/cppol/devices/3/apps/1/jobs/InitLiveTV'
- response = sess.post(urlk, headers=headers, data=data, verify=False).json()
- outdata = response["ServiceResponse"]["OutData"]
- self.LIVEtoken = outdata["LiveToken"]
- set_setting('livetoken', self.LIVEtoken)
- grupy = outdata["PDS"]["ChannelsGroups"]["ChannelsGroup"]
- out = []
- for grupa in grupy:
- channels = grupa["Channels"]
- for channel in channels:
- epgid_ = channel["EpgId"]
- # try:
- # plot = epgs[str(epgid_)]['title']
- # except:
- # plot = ''
- tytul_ = channel["Name"]
- urllogo_ = channel["LogoUrl"]
- urlpage_ = channel["WSXUrl"]
- urlpage_ = urlpage_ + '|' + epgid_
- out.append({"title": PLchar(tytul_), "url": urlpage_, 'image': urllogo_, "code": '', "plot": '',
- 'typ': 'live'})
- return out
- def RefreshPassToken(self):
- headers = {
- 'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 9; SM-J330F Build/PPR1.180610.011)',
- 'Host': 'pass-api-v2.canal-plus.com',
- }
- data = {
- 'analytics': 'true',
- 'noCache': 'false',
- 'passId': self.PASSid,
- 'vect': 'Internet',
- 'media': 'Android Phone',
- 'trackingPub': 'true',
- 'portailId': self.portailId
- }
- data = {
- 'noCache': 'false',
- 'passId': self.PASSid,
- 'deviceId': self.DEVID,
- 'vect': 'Internet',
- 'media': 'PC',
- 'portailId': 'vbdTj7eb6aM.',
- 'zone': 'cppol'
- }
- headers = {
- 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0',
- 'Accept': '*/*',
- 'Accept-Language': 'pl,en-US;q=0.7,en;q=0.3',
- 'Content-Type': 'application/x-www-form-urlencoded',
- 'Origin': 'https://www.canalplus.com',
- 'Connection': 'keep-alive',
- }
- response = sess.post(self.CREATE_TOKEN, headers=headers, data=data, verify=False).json()
- self.PASSid = response["response"]["passId"]
- self.PASStoken = response["response"]["passToken"]
- a11 = self.PASSid
- a22 = self.PASStoken
- set_setting('PASSid', a11)
- set_setting('PASStoken', a22)
- params = (
- ('appLocation', 'PL'),
- ('offerZone', 'cppol'),
- ('isActivated', '1'),
- ('collectUserData', '1'),
- ('pdsNormal', '[' + self.EPGid + ']'),
- ('macros', self.MACROel),
- ('micros', self.MICROel),
- ('isAuthenticated', '1'),
- ('paired', '0'),
- )
- response = getRequests('https://hodor.canalplus.pro/api/v2/mycanalint/authenticate.json/android/4.1',
- headers=self.HODORheaders, params=params)
- self.CMStoken = response['token']
- set_setting('CMStoken', self.CMStoken)
- return
- def do_GET(self):
- """Handle http get requests, used for manifest"""
- path = self.path # Path with parameters received from request e.g. "/manifest?id=234324"
- print('HTTP GET Request received to {}'.format(path))
- if '/manifest' not in path:
- self.send_response(404)
- self.end_headers()
- return
- try:
- # Call your method to do the magic to generate DASH manifest data
- manifest_data = b'my manifest data'
- self.send_response(200)
- self.send_header('Content-type', 'application/xml')
- self.end_headers()
- self.wfile.write(manifest_data)
- except Exception:
- self.send_response(500)
- self.end_headers()
- def do_POST(self):
- """Handle http post requests, used for license"""
- path = self.path # Path with parameters received from request e.g. "/license?id=234324"
- print('HTTP POST Request received to {}'.format(path))
- if '/license' not in path:
- self.send_response(404)
- self.end_headers()
- return
- length = int(self.headers.get('content-length', 0))
- isa_data = self.rfile.read(length).decode('utf-8').split('!')
- challenge = isa_data[0]
- log(path)
- if 'cense=' in path:
- path2 = path.split('cense=')[-1]
- licurl = (addon.getSetting('licurl'))
- ab = eval(addon.getSetting('hea'))
- result = requests.post(url=licurl, headers=ab, data=challenge, verify=False).content
- if PY3:
- result = result.decode(encoding='utf-8', errors='strict')
- licens = re.findall('ontentid=".+?">(.+?)<', result)[0]
- if PY3:
- licens = licens.encode(encoding='utf-8', errors='strict')
- elif 'censetv=' in path:
- path2 = path.split('censetv=')[-1]
- licurl = (addon.getSetting('lictvurl'))
- ab = eval(addon.getSetting('heatv'))
- result = requests.post(url=licurl, headers=ab, data=challenge, verify=False).json()
- log(result)
- if int(result['ServiceResponse']['Status']) < 0:
- self.TVinit()
- result = requests.post(url=licurl, headers=ab, data=challenge, verify=False).json()
- licens = result['ServiceResponse']['OutData']['LicenseInfo']
- if PY3:
- licens = licens.encode(encoding='utf-8', errors='strict')
- self.send_response(200)
- self.end_headers()
- self.wfile.write(licens)
- def find_free_port():
- with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as s:
- s.bind(('', 0))
- s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- addon.setSetting('proxyport', str(s.getsockname()[1]))
- return s.getsockname()[1]
- address = '127.0.0.1' # Localhost
- port = find_free_port()
- server_inst = TCPServer((address, port), SimpleHTTPRequestHandler)
- # The follow line is only for test purpose, you have to implement a way to stop the http service!
- server_inst.serve_forever()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement