Enigma2 plugin to to play various online streams (mostly Latvian).

urlparserhelper.py 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  1. # -*- coding: utf-8 -*-
  2. ###################################################
  3. # LOCAL import
  4. ###################################################
  5. from Plugins.Extensions.IPTVPlayer.tools.iptvtools import printDBG, printExc
  6. from Plugins.Extensions.IPTVPlayer.tools.iptvtypes import strwithmeta
  7. from Plugins.Extensions.IPTVPlayer.libs.pCommon import CParsingHelper, common
  8. from Plugins.Extensions.IPTVPlayer.libs import m3u8
  9. ###################################################
  10. # FOREIGN import
  11. ###################################################
  12. from binascii import hexlify
  13. import re
  14. import time
  15. import string
  16. import codecs
  17. import urllib
  18. ###################################################
  19. try:
  20. from hashlib import md5
  21. def hex_md5(e):
  22. return md5(e).hexdigest()
  23. except:
  24. from Plugins.Extensions.IPTVPlayer.libs.crypto.hash.md5Hash import MD5 as md5
  25. def hex_md5(e):
  26. hashAlg = MD5()
  27. return hexlify(hashAlg(e))
  28. def int2base(x, base):
  29. digs = string.digits + string.lowercase
  30. if x < 0: sign = -1
  31. elif x==0: return '0'
  32. else: sign = 1
  33. x *= sign
  34. digits = []
  35. while x:
  36. digits.append(digs[x % base])
  37. x /= base
  38. if sign < 0:
  39. digits.append('-')
  40. digits.reverse()
  41. return ''.join(digits)
  42. def JS_toString(x, base):
  43. return int2base(x, base)
  44. # returns timestamp in milliseconds
  45. def JS_DateValueOf():
  46. return time.time()*1000
  47. def JS_FromCharCode(*args):
  48. return ''.join(map(unichr, args))
  49. def unicode_escape(s):
  50. decoder = codecs.getdecoder('unicode_escape')
  51. return re.sub(r'\\u[0-9a-fA-F]{4,}', lambda m: decoder(m.group(0))[0], s).encode('utf-8')
  52. def drdX_fx(e):
  53. t = {}
  54. n = 0
  55. r = 0
  56. i = []
  57. s = ""
  58. o = JS_FromCharCode
  59. u = [[65, 91], [97, 123], [48, 58], [43, 44], [47, 48]]
  60. for z in range(len(u)):
  61. n = u[z][0]
  62. while n < u[z][1]:
  63. i.append(o(n))
  64. n += 1
  65. n = 0
  66. while n < 64:
  67. t[i[n]] = n
  68. n += 1
  69. n = 0
  70. while n < len(e):
  71. a = 0
  72. f = 0
  73. l = 0
  74. c = 0
  75. h = e[n:n+72]
  76. while l < len(h):
  77. f = t[h[l]]
  78. a = (a << 6) + f
  79. c += 6
  80. while c >= 8:
  81. c -= 8
  82. s += o((a >> c) % 256)
  83. l += 1
  84. n += 72
  85. return s
  86. ####################################################
  87. # myobfuscate.com
  88. ####################################################
  89. def MYOBFUSCATECOM_OIO(data, _0lllOI="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", enc=''):
  90. i = 0;
  91. while i < len(data):
  92. h1 = _0lllOI.find(data[i]);
  93. h2 = _0lllOI.find(data[i+1]);
  94. h3 = _0lllOI.find(data[i+2]);
  95. h4 = _0lllOI.find(data[i+3]);
  96. i += 4;
  97. bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
  98. o1 = bits >> 16 & 0xff;
  99. o2 = bits >> 8 & 0xff;
  100. o3 = bits & 0xff;
  101. if h3 == 64:
  102. enc += chr(o1);
  103. else:
  104. if h4 == 64:
  105. enc += chr(o1) + chr(o2);
  106. else:
  107. enc += chr(o1) + chr(o2) + chr(o3);
  108. return enc
  109. def MYOBFUSCATECOM_0ll(string, baseRet=''):
  110. ret = baseRet
  111. i = len(string) - 1
  112. while i >= 0:
  113. ret += string[i]
  114. i -= 1
  115. return ret
  116. def VIDEOMEGA_decryptPlayerParams(p, a, c, k, e, d):
  117. def e1(c):
  118. return JS_toString(c, 36)
  119. return ret
  120. def k1(matchobj):
  121. return d[matchobj.group(0)]
  122. def e2(t=None):
  123. return '\\w+'
  124. e = e1
  125. if True:
  126. while c != 0:
  127. c -= 1
  128. tmp1 = e(c)
  129. d[tmp1] = k[c]
  130. if '' == d[tmp1]:
  131. d[tmp1] = e(c)
  132. c = 1
  133. k = [k1]
  134. e = e2
  135. while c != 0:
  136. c -= 1
  137. if k[c]:
  138. reg = '\\b' + e(c) + '\\b'
  139. p = re.sub(reg, k[c], p)
  140. return p
  141. def SAWLIVETV_decryptPlayerParams(p, a, c, k, e, d):
  142. def e1(c):
  143. if c < a:
  144. ret = ''
  145. else:
  146. ret = e(c / a)
  147. c = c % a
  148. if c > 35:
  149. ret += chr(c+29)
  150. else:
  151. ret += JS_toString(c, 36)
  152. return ret
  153. def k1(matchobj):
  154. return d[matchobj.group(0)]
  155. def e2(t=None):
  156. return '\\w+'
  157. e = e1
  158. if True:
  159. while c != 0:
  160. c -= 1
  161. tmp1 = e(c)
  162. d[tmp1] = k[c]
  163. if '' == d[tmp1]:
  164. d[tmp1] = e(c)
  165. c = 1
  166. k = [k1]
  167. e = e2
  168. while c != 0:
  169. c -= 1
  170. if k[c]:
  171. reg = '\\b' + e(c) + '\\b'
  172. p = re.sub(reg, k[c], p)
  173. return p
  174. def OPENLOADIO_decryptPlayerParams(p, a, c, k, e, d):
  175. def e1(c):
  176. return c
  177. def e2(t=None):
  178. return '\\w+'
  179. def k1(matchobj):
  180. return d[int(matchobj.group(0))]
  181. e = e1
  182. if True:
  183. while c != 0:
  184. c -= 1
  185. d[c] = k[c]
  186. if c < len(k):
  187. d[c] = k[c]
  188. else:
  189. d[c] = c
  190. c = 1
  191. k = [k1]
  192. e = e2
  193. while c != 0:
  194. c -= 1
  195. if k[c]:
  196. reg = '\\b' + e(c) + '\\b'
  197. p = re.sub(reg, k[c], p)
  198. return p
  199. def TEAMCASTPL_decryptPlayerParams(p, a, c, k, e=None, d=None):
  200. def e1(c):
  201. if c < a:
  202. ret = ''
  203. else:
  204. ret = e(c / a)
  205. c = c % a
  206. if c > 35:
  207. ret += chr(c+29)
  208. else:
  209. ret += JS_toString(c, 36)
  210. return ret
  211. e = e1
  212. while c != 0:
  213. c -= 1
  214. if k[c]:
  215. reg = '\\b' + e(c) + '\\b'
  216. p = re.sub(reg, k[c], p)
  217. return p
  218. ###############################################################################
  219. # VIDUP.ME HELPER FUNCTIONS
  220. ###############################################################################
  221. # there is problem in exec when this functions are class methods
  222. # sub (even static) or functions
  223. # Code example:
  224. #<div id="player_code" style="height:100% ; width:100%; visibility:none;"><span id='flvplayer'></span>
  225. #<script type='text/javascript' src='http://vidup.me/player/jwplayer.js'></script>
  226. #<script type='text/javascript'>eval(function(p,a,c,k,e,d){while(c--)if(k[c])p=p.replace(new RegExp('\\b'+c.toString(a)+'\\b','g'),k[c]);return p}('1l(\'1k\').1j({\'1i\':\'/7/7.1h\',a:"0://g.f.e.c:1g/d/1f/1e.1d",1c:"0",\'1b\':\'9\',\'1a\':\'19\',\'18\':\'h%\',\'17\':\'h%\',\'16\':\'15\',\'14\':\'13\',\'12\':\'11\',\'10\':\'0://g.f.e.c/i/z/6.y\',\'b\':\'0://5.4/7/b.x\',\'w\':\'v\',\'2.a\':\'0://5.4/u/t.s\',\'2.8\':\'0://5.4/6\',\'2.r\':\'q\',\'2.p\':\'o\',\'2.n\':\'9-m\',\'l\':{\'k-1\':{\'8\':\'0://5.4/6\'},\'j-3\':{}}});',36,58,'http||logo||me|vidup|yx616ubt7l82|player|link|bottom|file|skin|187||116|39|84|100||timeslidertooltipplugin|fbit|plugins|right|position|false|hide|_blank|linktarget|png|logoheader|images|000000|screencolor|zip|jpg|00049|image|always|allowscriptaccess|true|allowfullscreen|7022|duration|height|width|transparent|wmode|controlbar|provider|flv|video|zesaswuvnsv27kymojykzci5bbll4pqkmqipzoez4eakqgfaacm7fbqf|182|swf|flashplayer|setup|flvplayer|jwplayer'.split('|')))
  227. #</script>
  228. #<br></div>
  229. #
  230. #
  231. def getParamsTouple(code, type=1, r1=False, r2=False ):
  232. mark1Tab = ["}(", "}\r\n(", "}\n(", "}\r("]
  233. mark2 = "))"
  234. for mark1 in mark1Tab:
  235. if r1:
  236. idx1 = code.rfind(mark1)
  237. else:
  238. idx1 = code.find(mark1)
  239. if idx1 > -1: break
  240. if -1 == idx1: return ''
  241. idx1 += len(mark1)
  242. if r2:
  243. idx2 = code.rfind(mark2, idx1)
  244. else:
  245. idx2 = code.find(mark2, idx1)
  246. if -1 == idx2: return ''
  247. idx2 += type
  248. return code[idx1:idx2]
  249. def unpackJSPlayerParams(code, decryptionFun, type=1, r1=False, r2=False):
  250. printDBG('unpackJSPlayerParams')
  251. code = getParamsTouple(code, type, r1, r2)
  252. return unpackJS(code, decryptionFun)
  253. def unpackJS(data, decryptionFun, addCode=''):
  254. paramsCode = addCode
  255. paramsCode += 'paramsTouple = (' + data + ')'
  256. try:
  257. paramsAlgoObj = compile(paramsCode, '', 'exec')
  258. except:
  259. printExc('unpackJS compile algo code EXCEPTION')
  260. return ''
  261. vGlobals = {"__builtins__": None, 'string': string, 'decodeURIComponent':urllib.unquote, 'unescape':urllib.unquote}
  262. vLocals = { 'paramsTouple': None }
  263. try:
  264. exec( paramsAlgoObj, vGlobals, vLocals )
  265. except:
  266. printExc('unpackJS exec code EXCEPTION')
  267. return ''
  268. # decrypt JS Player params
  269. try:
  270. return decryptionFun(*vLocals['paramsTouple'])
  271. except:
  272. printExc('decryptPlayerParams EXCEPTION')
  273. return ''
  274. def VIDUPME_decryptPlayerParams(p=None, a=None, c=None, k=None, e=None, d=None):
  275. while c > 0:
  276. c -= 1
  277. if k[c]:
  278. p = re.sub('\\b'+ int2base(c, a) +'\\b', k[c], p)
  279. return p
  280. ###############################################################################
  281. ###############################################################################
  282. # VIDEOWEED HELPER FUNCTIONS
  283. ###############################################################################
  284. def VIDEOWEED_decryptPlayerParams(w, i, s, e):
  285. lIll = 0
  286. ll1I = 0
  287. Il1l = 0
  288. ll1l = []
  289. l1lI = []
  290. while True:
  291. if lIll < 5: l1lI.append(w[lIll])
  292. elif lIll < len(w): ll1l.append(w[lIll])
  293. lIll += 1
  294. if ll1I < 5: l1lI.append(i[ll1I])
  295. elif ll1I < len(i): ll1l.append(i[ll1I])
  296. ll1I += 1
  297. if Il1l < 5: l1lI.append(s[Il1l])
  298. elif Il1l < len(s): ll1l.append(s[Il1l])
  299. Il1l += 1
  300. if len(w) + len(i) + len(s) + len(e) == len(ll1l) + len(l1lI) + len(e): break
  301. lI1l = ''.join(ll1l)
  302. I1lI = ''.join(l1lI)
  303. ll1I = 0
  304. l1ll = []
  305. lIll = 0
  306. while lIll < len(ll1l):
  307. ll11 = -1;
  308. if ord(I1lI[ll1I]) % 2: ll11 = 1
  309. l1ll.append( JS_FromCharCode( int( lI1l[lIll:lIll+2], 36 ) - ll11 ) )
  310. ll1I += 1;
  311. if ll1I >= len(l1lI): ll1I = 0
  312. lIll += 2
  313. return ''.join(l1ll)
  314. def VIDEOWEED_decryptPlayerParams2(w, i, s=None, e=None):
  315. s = 0
  316. while s < len(w):
  317. i += JS_FromCharCode(int(w[s:s+2], 36))
  318. s += 2
  319. return i
  320. def VIDEOWEED_unpackJSPlayerParams(code):
  321. sts, code = CParsingHelper.rgetDataBeetwenMarkers(code, 'eval(function', '</script>')
  322. if not sts: return ''
  323. while True:
  324. mark1 = "}("
  325. mark2 = "));"
  326. idx1 = code.rfind(mark1)
  327. if -1 == idx1: return ''
  328. idx1 += len(mark1)
  329. idx2 = code.rfind(mark2, idx1)
  330. if -1 == idx2: return ''
  331. #idx2 += 1
  332. paramsCode = 'paramsTouple = (' + code[idx1:idx2] + ')'
  333. paramsAlgoObj = compile(paramsCode, '', 'exec')
  334. try:
  335. paramsAlgoObj = compile(paramsCode, '', 'exec')
  336. except:
  337. printDBG('unpackJSPlayerParams compile algo code EXCEPTION')
  338. return ''
  339. vGlobals = {"__builtins__": None, 'string': string}
  340. vLocals = { 'paramsTouple': None }
  341. try:
  342. exec( paramsAlgoObj, vGlobals, vLocals )
  343. except:
  344. printDBG('unpackJSPlayerParams exec code EXCEPTION')
  345. return ''
  346. # decrypt JS Player params
  347. code = VIDEOWEED_decryptPlayerParams(*vLocals['paramsTouple'])
  348. try:
  349. code = VIDEOWEED_decryptPlayerParams(*vLocals['paramsTouple'])
  350. if -1 == code.find('eval'):
  351. return code
  352. except:
  353. printDBG('decryptPlayerParams EXCEPTION')
  354. return ''
  355. return ''
  356. def pythonUnescape(data):
  357. sourceCode = "retData = '''%s'''" % data
  358. try:
  359. code = compile(sourceCode, '', 'exec')
  360. except:
  361. printExc('pythonUnescape compile algo code EXCEPTION')
  362. return ''
  363. vGlobals = {"__builtins__": None, 'string': string}
  364. vLocals = { 'paramsTouple': None }
  365. try:
  366. exec( code, vGlobals, vLocals )
  367. except:
  368. printExc('pythonUnescape exec code EXCEPTION')
  369. return ''
  370. return vLocals['retData']
  371. ###############################################################################
  372. class captchaParser:
  373. def __init__(self):
  374. pass
  375. def textCaptcha(self, data):
  376. strTab = []
  377. valTab = []
  378. match = re.compile("padding-(.+?):(.+?)px;padding-top:.+?px;'>(.+?)<").findall(data)
  379. if len(match) > 0:
  380. for i in range(len(match)):
  381. value = match[i]
  382. strTab.append(value[2])
  383. strTab.append(int(value[1]))
  384. valTab.append(strTab)
  385. strTab = []
  386. if match[i][0] == 'left':
  387. valTab.sort(key=lambda x: x[1], reverse=False)
  388. else:
  389. valTab.sort(key=lambda x: x[1], reverse=True)
  390. return valTab
  391. def reCaptcha(self, data):
  392. pass
  393. ################################################################################
  394. def decorateUrl(url, metaParams={}):
  395. retUrl = strwithmeta( url )
  396. retUrl.meta.update(metaParams)
  397. urlLower = url.lower()
  398. if 'iptv_proto' not in retUrl.meta:
  399. if urlLower.startswith('merge://'):
  400. retUrl.meta['iptv_proto'] = 'merge'
  401. elif urlLower.split('?')[0].endswith('.m3u8'):
  402. retUrl.meta['iptv_proto'] = 'm3u8'
  403. elif urlLower.split('?')[0].endswith('.f4m'):
  404. retUrl.meta['iptv_proto'] = 'f4m'
  405. elif urlLower.startswith('rtmp'):
  406. retUrl.meta['iptv_proto'] = 'rtmp'
  407. elif urlLower.startswith('https'):
  408. retUrl.meta['iptv_proto'] = 'https'
  409. elif urlLower.startswith('http'):
  410. retUrl.meta['iptv_proto'] = 'http'
  411. elif urlLower.startswith('file'):
  412. retUrl.meta['iptv_proto'] = 'file'
  413. elif urlLower.startswith('rtsp'):
  414. retUrl.meta['iptv_proto'] = 'rtsp'
  415. elif urlLower.startswith('mms'):
  416. retUrl.meta['iptv_proto'] = 'mms'
  417. elif urlLower.startswith('mmsh'):
  418. retUrl.meta['iptv_proto'] = 'mmsh'
  419. elif 'protocol=hls' in url.lower():
  420. retUrl.meta['iptv_proto'] = 'm3u8'
  421. return retUrl
  422. def getDirectM3U8Playlist(M3U8Url, checkExt=True, variantCheck=True, cookieParams={}):
  423. if checkExt and not M3U8Url.split('?')[0].endswith('.m3u8'):
  424. return []
  425. cm = common()
  426. meta = strwithmeta(M3U8Url).meta
  427. params, postData = cm.getParamsFromUrlWithMeta(M3U8Url)
  428. params.update(cookieParams)
  429. retPlaylists = []
  430. try:
  431. finallM3U8Url = meta.get('iptv_m3u8_custom_base_link', '')
  432. if '' == finallM3U8Url:
  433. params['return_data'] = False
  434. sts, response = cm.getPage(M3U8Url, params, postData)
  435. finallM3U8Url = response.geturl()
  436. data = response.read().strip()
  437. response.close()
  438. else:
  439. sts, data = cm.getPage(M3U8Url, params, postData)
  440. data = data.strip()
  441. m3u8Obj = m3u8.inits(data, finallM3U8Url)
  442. if m3u8Obj.is_variant:
  443. for playlist in m3u8Obj.playlists:
  444. item = {}
  445. if not variantCheck or playlist.absolute_uri.split('?')[-1].endswith('.m3u8'):
  446. meta.update({'iptv_proto':'m3u8', 'iptv_bitrate':playlist.stream_info.bandwidth})
  447. item['url'] = strwithmeta(playlist.absolute_uri, meta)
  448. else:
  449. meta.pop('iptv_proto', None)
  450. item['url'] = decorateUrl(playlist.absolute_uri, meta)
  451. item['bitrate'] = playlist.stream_info.bandwidth
  452. if None != playlist.stream_info.resolution:
  453. item['with'] = playlist.stream_info.resolution[0]
  454. item['heigth'] = playlist.stream_info.resolution[1]
  455. else:
  456. item['with'] = 0
  457. item['heigth'] = 0
  458. item['codec'] = playlist.stream_info.codecs
  459. item['name'] = "bitrate: %s res: %dx%d kodek: %s" % ( item['bitrate'], \
  460. item['with'], \
  461. item['heigth'], \
  462. item['codec'] )
  463. retPlaylists.append(item)
  464. else:
  465. item = {'name':'m3u8', 'url':M3U8Url, 'codec':'unknown', 'with':0, 'heigth':0, 'bitrate':'unknown'}
  466. retPlaylists.append(item)
  467. except:
  468. printExc()
  469. return retPlaylists
  470. def getF4MLinksWithMeta(manifestUrl, checkExt=True):
  471. if checkExt and not manifestUrl.split('?')[0].endswith('.f4m'):
  472. return []
  473. cm = common()
  474. headerParams, postData = cm.getParamsFromUrlWithMeta(manifestUrl)
  475. retPlaylists = []
  476. sts, data = cm.getPage(manifestUrl, headerParams, postData)
  477. if sts:
  478. liveStreamDetected = False
  479. if 'live' == CParsingHelper.getDataBeetwenMarkers('<streamType>', '</streamType>', False):
  480. liveStreamDetected = True
  481. bitrates = re.compile('bitrate="([0-9]+?)"').findall(data)
  482. for item in bitrates:
  483. link = strwithmeta(manifestUrl, {'iptv_proto':'f4m', 'iptv_bitrate':item})
  484. if liveStreamDetected:
  485. link.meta['iptv_livestream'] = True
  486. retPlaylists.append({'name':'[f4m/hds] bitrate[%s]' % item, 'url':link})
  487. if 0 == len(retPlaylists):
  488. link = strwithmeta(manifestUrl, {'iptv_proto':'f4m'})
  489. if liveStreamDetected:
  490. link.meta['iptv_livestream'] = True
  491. retPlaylists.append({'name':'[f4m/hds]', 'url':link})
  492. return retPlaylists