fork(68) download
  1. import sys
  2. import urllib
  3. import json
  4. import os
  5. import urlparse
  6. import re, uuid
  7. from time import time
  8. from datetime import datetime
  9. import math
  10. import urllib2
  11. import hashlib
  12.  
  13. from xml.dom import minidom
  14.  
  15. key = None;
  16. mac = ':'.join(re.findall('..', '%012x' % uuid.getnode()));
  17. sn = None;
  18. device_id = None;
  19. device_id2 = None;
  20. signature = None;
  21.  
  22. cache_version = '3'
  23.  
  24. def is_json(myjson):
  25. try:
  26. json_object = json.loads(myjson)
  27. except ValueError, e:
  28. return False
  29. return True
  30.  
  31. def setMac(nmac):
  32. global mac;
  33.  
  34. if re.match("[0-9a-f]{2}([-:])[0-9a-f]{2}(\\1[0-9a-f]{2}){4}$", nmac.lower()):
  35. mac = nmac;
  36.  
  37. def getMac():
  38. global mac;
  39. return mac;
  40.  
  41.  
  42. def setSerialNumber(serial):
  43. global sn, device_id, device_id2, signature;
  44.  
  45. if serial == None:
  46. return;
  47.  
  48. elif serial['custom'] == False:
  49. sn = hashlib.md5(mac).hexdigest().upper()[13:];
  50. device_id = hashlib.sha256(sn).hexdigest().upper();
  51. device_id2 = hashlib.sha256(mac).hexdigest().upper();
  52. signature = hashlib.sha256(sn + mac).hexdigest().upper();
  53.  
  54. elif serial['custom'] == True:
  55. sn = serial['sn'];
  56. device_id = serial['device_id'];
  57. device_id2 = serial['device_id2'];
  58. signature = serial['signature'];
  59.  
  60. def handshake(url):
  61. global key;
  62.  
  63. if key != None:
  64. return;
  65.  
  66. info = retrieveData(url, values = {
  67. 'type' : 'stb',
  68. 'action' : 'handshake',
  69. 'JsHttpRequest' : '1-xml'})
  70.  
  71. key = info['js']['token']
  72.  
  73. getProfile(url);
  74.  
  75.  
  76. def getProfile(url):
  77. global sn, device_id, device_id2, signature;
  78.  
  79. values = {
  80. 'type' : 'stb',
  81. 'action' : 'get_profile',
  82. 'hd' : '1',
  83. 'ver' : 'ImageDescription:%200.2.18-r11-pub-254;%20ImageDate:%20Wed%20Mar%2018%2018:09:40%20EET%202015;%20PORTAL%20version:%204.9.14;%20API%20Version:%20JS%20API%20version:%20331;%20STB%20API%20version:%20141;%20Player%20Engine%20version:%200x572',
  84. 'num_banks' : '1',
  85. 'stb_type' : 'MAG254',
  86. 'image_version' : '218',
  87. 'auth_second_step' : '0',
  88. 'hw_version' : '2.6-IB-00',
  89. 'not_valid_token' : '0',
  90. 'JsHttpRequest' : '1-xml'}
  91.  
  92. if sn != None:
  93. values['sn'] = sn;
  94. values['device_id'] = device_id;
  95. values['device_id2'] = device_id2;
  96. values['signature'] = signature;
  97.  
  98.  
  99. info = retrieveData(url, values);
  100.  
  101.  
  102. def retrieveData(url, values ):
  103. global key, mac;
  104.  
  105. url += '/stalker_portal'
  106. load = '/server/load.php'
  107. refer = '/c/'
  108. timezone = 'America%2FChicago';
  109.  
  110. user_agent = 'Mozilla/5.0 (QtEmbedded; U; Linux; C) AppleWebKit/533.3 (KHTML, like Gecko) MAG200 stbapp ver: 4 rev: 1812 Mobile Safari/533.3';
  111.  
  112. if key != None:
  113. headers = {
  114. 'User-Agent' : user_agent,
  115. 'Cookie' : 'mac=' + mac + '; stb_lang=en; timezone=' + timezone,
  116. 'Referer' : url + refer,
  117. 'Accept' : '*/*',
  118. 'Connection' : 'Keep-Alive',
  119. 'X-User-Agent' : 'Model: MAG254; Link: Ethernet',
  120. 'Authorization' : 'Bearer ' + key };
  121.  
  122. else:
  123. headers = {
  124. 'User-Agent' : user_agent,
  125. 'Cookie' : 'mac=' + mac+ '; stb_lang=en; timezone=' + timezone,
  126. 'Referer' : url + refer,
  127. 'Accept' : '*/*',
  128. 'Connection' : 'Keep-Alive',
  129. 'X-User-Agent' : 'Model: MAG254; Link: Ethernet' };
  130.  
  131.  
  132. data = urllib.urlencode(values);
  133.  
  134.  
  135. req = urllib2.Request(url + load, data, headers);
  136. resp = urllib2.urlopen(req).read().decode("utf-8");
  137.  
  138. if not is_json(resp):
  139. req = urllib2.Request(url + load + '?' + data, headers=headers);
  140. resp = urllib2.urlopen(req).read().decode("utf-8");
  141.  
  142. if not is_json(resp):
  143. raise Exception(resp)
  144.  
  145. info = json.loads(resp)
  146.  
  147. return info;
  148.  
  149.  
  150. def getGenres(portal_mac, url, serial, path):
  151. global key, cache_version;
  152.  
  153. now = time();
  154. portalurl = "_".join(re.findall("[a-zA-Z0-9]+", url));
  155. portalurl = path + '/' + portalurl + '-genres';
  156.  
  157. setMac(portal_mac);
  158. setSerialNumber(serial);
  159.  
  160. if not os.path.exists(path):
  161. os.makedirs(path);
  162.  
  163. if os.path.exists(portalurl):
  164. #check last time
  165. with open(portalurl) as data_file: data = json.load(data_file);
  166.  
  167. if 'version' not in data or data['version'] != cache_version:
  168. clearCache(url, path);
  169.  
  170. else:
  171. time_init = float(data['time']);
  172. # update 12h
  173. if ((now - time_init) / 3600) < 12:
  174. return data;
  175.  
  176. handshake(url);
  177.  
  178. info = retrieveData(url, values = {
  179. 'type' : 'itv',
  180. 'action' : 'get_genres',
  181. 'JsHttpRequest' : '1-xml'})
  182.  
  183.  
  184. results = info['js']
  185.  
  186. data = '{ "version" : "' + cache_version + '", "time" : "' + str(now) + '", "genres" : { \n'
  187.  
  188. for i in results:
  189. alias = i["alias"]
  190. id = i["id"]
  191. title = i['title']
  192.  
  193. data += '"'+ id +'" : {"alias":"'+ alias +'", "title":"'+ title +'"}, \n'
  194.  
  195.  
  196. data = data[:-3] + '\n}}'
  197.  
  198. with open(portalurl, 'w') as f: f.write(data.encode('utf-8'));
  199.  
  200. return json.loads(data.encode('utf-8'));
  201.  
  202. def getVoD(portal_mac, url, serial, path):
  203. now = time();
  204. portalurl = "_".join(re.findall("[a-zA-Z0-9]+", url));
  205. portalurl = path + '/' + portalurl + '-vod';
  206.  
  207. setMac(portal_mac);
  208. setSerialNumber(serial);
  209.  
  210. if not os.path.exists(path):
  211. os.makedirs(path)
  212.  
  213. if os.path.exists(portalurl):
  214. #check last time
  215. with open(portalurl) as data_file: data = json.load(data_file);
  216.  
  217. if 'version' not in data or data['version'] != cache_version:
  218. clearCache(url, path);
  219.  
  220. else:
  221. time_init = float(data['time']);
  222. # update 12h
  223. if ((now - time_init) / 3600) < 12:
  224. return data;
  225.  
  226. handshake(url);
  227.  
  228. data = '{ "version" : "' + cache_version + '", "time" : "' + str(now) + '", "vod" : [ \n'
  229.  
  230. page = 1;
  231. pages = 0;
  232. total_items = 1.0;
  233. max_page_items = 1.0;
  234.  
  235. while True:
  236. info = retrieveData(url, values = {
  237. 'type' : 'vod',
  238. 'action' : 'get_ordered_list',
  239. 'sortby' : 'added',
  240. 'not_ended' : '0',
  241. 'p' : page,
  242. 'fav' : '0',
  243. 'JsHttpRequest' : '1-xml'})
  244.  
  245. total_items = float(info['js']['total_items']);
  246. max_page_items = float(info['js']['max_page_items']);
  247. pages = math.ceil(total_items/max_page_items);
  248.  
  249. results = info['js']['data']
  250.  
  251.  
  252. for i in results:
  253. name = i["name"]
  254. cmd = i['cmd']
  255. logo = i["screenshot_uri"]
  256.  
  257. data += '{"name":"'+ name +'", "cmd":"'+ cmd +'", "logo":"'+ logo +'"}, \n'
  258.  
  259. page += 1;
  260. if page > pages or page == 10:
  261. break;
  262.  
  263. data = data[:-3] + '\n]}'
  264.  
  265. with open(portalurl, 'w') as f: f.write(data.encode('utf-8'));
  266.  
  267. return json.loads(data.encode('utf-8'));
  268.  
  269.  
  270. def orderChannels(channels):
  271. n_data = {};
  272. for i in channels:
  273. number = i["number"];
  274. n_data[int(number)] = i;
  275.  
  276. ordered = sorted(n_data);
  277. data = {};
  278. for i in ordered:
  279. data[i] = n_data[i];
  280.  
  281. return data.values();
  282.  
  283.  
  284. def getAllChannels(portal_mac, url, serial, path):
  285.  
  286. added = False;
  287.  
  288. now = time();
  289.  
  290. portalurl = "_".join(re.findall("[a-zA-Z0-9]+", url));
  291. portalurl = path + '/' + portalurl
  292.  
  293. setMac(portal_mac);
  294. setSerialNumber(serial);
  295.  
  296. if not os.path.exists(path):
  297. os.makedirs(path)
  298.  
  299. if os.path.exists(portalurl):
  300. #check last time
  301. with open(portalurl) as data_file: data = json.load(data_file);
  302.  
  303. if 'version' not in data or data['version'] != cache_version:
  304. clearCache(url, path);
  305.  
  306. else:
  307. time_init = float(data['time']);
  308. # update 12h
  309. if ((now - time_init) / 3600) < 12:
  310. return data;
  311.  
  312. handshake(url);
  313.  
  314. genres = getGenres(portal_mac, url, serial, path);
  315. genres = genres["genres"];
  316.  
  317. info = retrieveData(url, values = {
  318. 'type' : 'itv',
  319. 'action' : 'get_all_channels',
  320. 'JsHttpRequest' : '1-xml'})
  321.  
  322.  
  323. results = info['js']['data'];
  324.  
  325. data = '{ "version" : "' + cache_version + '", "time" : "' + str(now) + '", "channels" : { \n'
  326.  
  327. for i in results:
  328. id = i["id"]
  329. number = i["number"]
  330. name = i["name"]
  331. cmd = i['cmd']
  332. logo = i["logo"]
  333. tmp = i["use_http_tmp_link"]
  334. genre_id = i["tv_genre_id"];
  335.  
  336. genre_title = genres[genre_id]['title'];
  337.  
  338. _s1 = cmd.split(' ');
  339. _s2 = _s1[0];
  340. if len(_s1)>1:
  341. _s2 = _s1[1];
  342.  
  343. added = True;
  344. data += '"' + id + '": {"number":"'+ number +'", "name":"'+ name +'", "cmd":"'+ cmd +'", "logo":"'+ logo +'", "tmp":"'+ str(tmp) +'", "genre_id":"'+ str(genre_id) +'", "genre_title":"'+ genre_title +'"}, \n'
  345.  
  346.  
  347. page = 1;
  348. pages = 0;
  349. total_items = 0;
  350. max_page_items = 0;
  351.  
  352. while True:
  353. # retrieve adults
  354. info = retrieveData(url, values = {
  355. 'type' : 'itv',
  356. 'action' : 'get_ordered_list',
  357. 'genre' : '10',
  358. 'p' : page,
  359. 'fav' : '0',
  360. 'JsHttpRequest' : '1-xml'})
  361.  
  362. total_items = float(info['js']['total_items']);
  363. max_page_items = float(info['js']['max_page_items']);
  364. pages = math.ceil(total_items/max_page_items);
  365.  
  366. results = info['js']['data']
  367.  
  368. for i in results:
  369. id = i["id"]
  370. number = i["number"]
  371. name = i["name"]
  372. cmd = i['cmd']
  373. logo = i["logo"]
  374. tmp = i["use_http_tmp_link"]
  375. genre_id = i["tv_genre_id"];
  376. genre_title = genres[genre_id]['title'];
  377.  
  378. data += '"' + id + '": {"number":"'+ number +'", "name":"'+ name +'", "cmd":"'+ cmd +'", "logo":"'+ logo +'", "tmp":"'+ str(tmp) +'", "genre_id":"'+ str(genre_id) +'", "genre_title":"'+ genre_title +'"}, \n'
  379.  
  380. added = True;
  381.  
  382. page += 1;
  383. if page > pages:
  384. break;
  385.  
  386.  
  387. if not added:
  388. data = data + '\n}}';
  389. else:
  390. data = data[:-3] + '\n}}';
  391.  
  392.  
  393. with open(portalurl, 'w') as f: f.write(data.encode('utf-8'));
  394.  
  395. return json.loads(data.encode('utf-8'));
  396.  
  397. def getEPG(portal_mac, url, serial, path):
  398. global key, cache_version;
  399.  
  400. now = time();
  401. portalurl = "_".join(re.findall("[a-zA-Z0-9]+", url));
  402. portalurl = path + '/' + portalurl + '-epg';
  403.  
  404. setMac(portal_mac);
  405. setSerialNumber(serial);
  406.  
  407. if not os.path.exists(path):
  408. os.makedirs(path);
  409.  
  410. if os.path.exists(portalurl):
  411. #check last time
  412. xmldoc = minidom.parse(portalurl);
  413.  
  414. itemlist = xmldoc.getElementsByTagName('tv');
  415.  
  416. version = itemlist[0].attributes['cache-version'].value;
  417.  
  418. if version != cache_version:
  419. clearCache(url, path);
  420.  
  421. else:
  422. time_init = float(itemlist[0].attributes['cache-time'].value);
  423. # update 2h
  424. if ((now - time_init) / 3600) < 2:
  425. return xmldoc.toxml(encoding='utf-8');
  426.  
  427.  
  428. channels = getAllChannels(portal_mac, url, serial, path);
  429. channels = channels['channels'];
  430.  
  431. handshake(url);
  432.  
  433. info = retrieveData(url, values = {
  434. 'type' : 'itv',
  435. 'action' : 'get_epg_info',
  436. 'period' : '6',
  437. 'JsHttpRequest' : '1-xml'})
  438.  
  439.  
  440. results = info['js']['data'];
  441.  
  442. doc = minidom.Document();
  443. base = doc.createElement('tv');
  444. base.setAttribute("cache-version", cache_version);
  445. base.setAttribute("cache-time", str(now));
  446. base.setAttribute("generator-info-name", "IPTV Plugin");
  447. base.setAttribute("generator-info-url", "http://w...content-available-to-author-only...v.org/");
  448. doc.appendChild(base)
  449.  
  450.  
  451. for c in results:
  452.  
  453. if not str(c) in channels:
  454. continue;
  455.  
  456. channel = channels[str(c)];
  457. name = channel['name'];
  458.  
  459. c_entry = doc.createElement('channel');
  460. c_entry.setAttribute("id", str(c));
  461. base.appendChild(c_entry)
  462.  
  463.  
  464. dn_entry = doc.createElement('display-name');
  465. dn_entry_content = doc.createTextNode(name);
  466. dn_entry.appendChild(dn_entry_content);
  467. c_entry.appendChild(dn_entry);
  468.  
  469.  
  470. for k,v in results.iteritems():
  471.  
  472. channel = None;
  473.  
  474. if str(k) in channels:
  475. channel = channels[str(k)];
  476.  
  477. for epg in v:
  478.  
  479. start_time = datetime.fromtimestamp(float(epg['start_timestamp']));
  480. stop_time = datetime.fromtimestamp(float(epg['stop_timestamp']));
  481.  
  482. pg_entry = doc.createElement('programme');
  483. pg_entry.setAttribute("start", start_time.strftime('%Y%m%d%H%M%S -0000'));
  484. pg_entry.setAttribute("stop", stop_time.strftime('%Y%m%d%H%M%S -0000'));
  485. pg_entry.setAttribute("channel", str(k));
  486. base.appendChild(pg_entry);
  487.  
  488. t_entry = doc.createElement('title');
  489. t_entry.setAttribute("lang", "en");
  490. t_entry_content = doc.createTextNode(epg['name']);
  491. t_entry.appendChild(t_entry_content);
  492. pg_entry.appendChild(t_entry);
  493.  
  494. d_entry = doc.createElement('desc');
  495. d_entry.setAttribute("lang", "en");
  496. d_entry_content = doc.createTextNode(epg['descr']);
  497. d_entry.appendChild(d_entry_content);
  498. pg_entry.appendChild(d_entry);
  499.  
  500. dt_entry = doc.createElement('date');
  501. dt_entry_content = doc.createTextNode(epg['on_date']);
  502. dt_entry.appendChild(dt_entry_content);
  503. pg_entry.appendChild(dt_entry);
  504.  
  505. c_entry = doc.createElement('category');
  506. c_entry_content = doc.createTextNode(epg['category']);
  507. c_entry.appendChild(c_entry_content);
  508. pg_entry.appendChild(c_entry);
  509.  
  510.  
  511. if channel != None and channel['logo'] != '':
  512. i_entry = doc.createElement('icon');
  513. i_entry.setAttribute("src", url + '/stalker_portal/misc/logos/320/' + channel['logo']);
  514. i_entry.appendChild(i_entry_content);
  515. pg_entry.appendChild(i_entry);
  516.  
  517.  
  518. with open(portalurl, 'w') as f: f.write(doc.toxml(encoding='utf-8'));
  519.  
  520. return doc.toxml(encoding='utf-8');
  521.  
  522.  
  523.  
  524.  
  525. def retriveUrl(portal_mac, url, serial, channel, tmp):
  526.  
  527. setMac(portal_mac);
  528. setSerialNumber(serial);
  529.  
  530. if 'matrix' in channel:
  531. return retrieve_matrixUrl(url, channel);
  532.  
  533. else:
  534. return retrive_defaultUrl(url, channel, tmp);
  535.  
  536.  
  537.  
  538. def retrive_defaultUrl(url, channel, tmp):
  539.  
  540. if tmp == '0':
  541. s = channel.split(' ');
  542. url = s[0];
  543. if len(s)>1:
  544. url = s[1];
  545. return url;
  546.  
  547.  
  548. handshake(url);
  549.  
  550. cmd = channel;
  551.  
  552.  
  553. info = retrieveData(url, values = {
  554. 'type' : 'itv',
  555. 'action' : 'create_link',
  556. 'cmd' : channel,
  557. 'forced_storage' : 'undefined',
  558. 'disable_ad' : '0',
  559. 'JsHttpRequest' : '1-xml'});
  560. cmd = info['js']['cmd'];
  561.  
  562. s = cmd.split(' ');
  563.  
  564. url = s[0];
  565.  
  566. if len(s)>1:
  567. url = s[1];
  568.  
  569.  
  570. # RETRIEVE THE 1 EXTM3U
  571. request = urllib2.Request(url)
  572. request.get_method = lambda : 'HEAD'
  573. response = urllib2.urlopen(request);
  574. data = response.read().decode("utf-8");
  575.  
  576.  
  577. data = data.splitlines();
  578. data = data[len(data) - 1];
  579.  
  580. # RETRIEVE THE 2 EXTM3U
  581. url = response.geturl().split('?')[0];
  582. url_base = url[: -(len(url) - url.rfind('/'))]
  583. return url_base + '/' + data;
  584.  
  585.  
  586. return url;
  587.  
  588.  
  589. def retrieve_matrixUrl(url, channel):
  590.  
  591. channel = channel.split('/');
  592. channel = channel[len(channel) -1];
  593.  
  594. url += '/stalker_portal/server/api/matrix.php?channel=' + channel + '&mac=' + mac;
  595.  
  596. # RETRIEVE THE 1 EXTM3U
  597. request = urllib2.Request(url)
  598. response = urllib2.urlopen(request);
  599. data = response.read().decode("utf-8");
  600.  
  601. _s1 = data.split(' ');
  602. data = _s1[0];
  603. if len(_s1)>1:
  604. data = _s1[len(_s1) -1];
  605.  
  606. return data;
  607.  
  608.  
  609.  
  610. def retriveVoD(portal_mac, url, serial, video):
  611.  
  612. setMac(portal_mac);
  613. setSerialNumber(serial);
  614.  
  615. s = video.split(' ');
  616. url = s[0];
  617. if len(s)>1:
  618. url = s[1];
  619.  
  620.  
  621. url = url.replace('TOMTOM:', 'http://');
  622.  
  623.  
  624. # RETRIEVE THE 1 EXTM3U
  625. request = urllib2.Request(url)
  626. response = urllib2.urlopen(request);
  627. url = response.geturl();
  628.  
  629.  
  630. # RETRIEVE THE 1 EXTM3U
  631. request = urllib2.Request(url)
  632. #request.get_method = lambda : 'HEAD'
  633. response = urllib2.urlopen(request);
  634. data = response.read().decode("utf-8");
  635. data = data.splitlines();
  636. data = data[len(data) - 1];
  637.  
  638. # RETRIEVE THE 2 EXTM3U
  639. url = response.geturl().split('?')[0];
  640. url_base = url[: -(len(url) - url.rfind('/'))]
  641. return url_base + '/' + data;
  642.  
  643. def clearCache(url, path):
  644.  
  645. portalurl = "_".join(re.findall("[a-zA-Z0-9]+", url));
  646.  
  647. for root, dirs, files in os.walk(path):
  648. for file in files:
  649. if file.startswith(portalurl):
  650. os.remove(root + '/' + file);
  651.  
  652.  
  653. if __name__ == "__main__":
  654. print "HOLA";
  655. mac="00:1A:78:12:34:99";
  656. portal="/stalker_portal/server/load.php";
  657. path="http://p...content-available-to-author-only...r.tv"
  658. serial="DB580DD743BF2600DF6"
  659. data = getAllChannels(mac, portal, serial, path);
Runtime error #stdin #stdout #stderr 0.16s 49176KB
stdin
Standard input is empty
stdout
HOLA
stderr
/bin/sh: 1: cannot create /dev/null: Permission denied
/bin/sh: 1: cannot create /dev/null: Permission denied
/bin/sh: 1: cannot create /dev/null: Permission denied
/bin/sh: 1: cannot create /dev/null: Permission denied
/bin/sh: 1: cannot create /dev/null: Permission denied
/bin/sh: 1: cannot create /dev/null: Permission denied
Traceback (most recent call last):
  File "<builtin>/app_main.py", line 75, in run_toplevel
  File "prog.py", line 659, in <module>
    data = getAllChannels(mac, portal, serial, path);
  File "prog.py", line 294, in getAllChannels
    setSerialNumber(serial);
  File "prog.py", line 48, in setSerialNumber
    elif serial['custom'] == False:
TypeError: string index must be an integer, not str