Guest User

Untitled

a guest
Mar 4th, 2010
585
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import sys
  2. import re
  3.  
  4. try: ###su python 2.5 non esiste il modulo io
  5. import io, gzip
  6. except:
  7. import cStringIO, gzip
  8.  
  9. import subprocess
  10. import base64, random
  11.  
  12. try:
  13. import http.client as client
  14. except:
  15. import httplib as client
  16.  
  17. #####################################################################################
  18. #
  19. # rai.py - version 0.4a
  20. #
  21. #####################################################################################
  22. #
  23. # License GNU GPLv2
  24. #
  25. # This program is free software; you can redistribute it and/or
  26. # modify it under the terms of the GNU General Public License
  27. # as published by the Free Software Foundation; either version 2
  28. # of the License, or (at your option) any later version.
  29. #
  30. # This program is distributed in the hope that it will be useful,
  31. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  32. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  33. # GNU General Public License for more details.
  34. #
  35. # You should have received a copy of the GNU General Public License
  36. # along with this program; if not, write to the Free Software
  37. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  38. #
  39. ####################################################################################
  40. #
  41. #
  42. # USAGE python3 rai.py [-vlcdir=<dir>][-uagent=<user-agent>][--ttAuth=<encoded>][-progs=(<xml_filepath>)][(channel|video_on_demand)]
  43. #
  44. # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  45. # Notice:
  46. # channel = RaiUno | RaiDue | RaiTre | RaiQuattro
  47. # RaiNews24 | RaiSport+ | RaiStoria | RaiEdu | RaiGulp
  48. # RaiSatExtra | RaiSatPremium | RaiSatCinema | RaiSatYoyo
  49. # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  50. # Change Log
  51. # + 0.4a
  52. # - Updated ttAuth generation algorithm
  53. # - Improved efficency in "encode" functions
  54. # - Arguments management moved from "mms()" inner code into an explicit "arguments()" function
  55. # - The importable module is refactored from "mms()" to "playerURL()" now
  56. # - Defined an "authCode()" function witch returns ttAuth code
  57. # - Deprecated old "encode" functions
  58. # + 0.4
  59. # - Add tv channel programs list support (XML Format)
  60. # - Can now be imported as module, exposing "mms()"
  61. # - Add ttAuth argument useful for external software integration
  62. # - Bugfix in vlcdir argument: now automatically appends '/' character
  63. # - Refactoring
  64. # + 0.3
  65. # - Add Video-On-demand support
  66. # - Update of key in encode2 function
  67. # - Bugfix in encode2 fucntion: j-index rotation is setted by key length
  68. # - Refactoring
  69. #
  70. # + 0.2
  71. # - Update of ttAuth generation algorithm
  72. #
  73. # + 0.1
  74. # - Creation of ttAuth
  75.  
  76. vlc_dir = "/Applications/VLC.app/Contents/MacOS" ###la directory di default di vlc per mac
  77. progs_file = "programs.xml"
  78.  
  79. chan_name = ""
  80. ttAuth = ""
  81. stream = ""
  82. agent = "NSPlayer/11.08.0005.0000" ###un tentativo di camuffarsi da moonlight
  83.  
  84. isVoD = False
  85. isPrograms = False
  86.  
  87. urls = {
  88. "RaiUno": "http://mediapolis.rai.it/relinker/relinkerServlet.htm?cont=983",
  89. "RaiDue": "http://mediapolis.rai.it/relinker/relinkerServlet.htm?cont=984",
  90. "RaiTre": "http://mediapolis.rai.it/relinker/relinkerServlet.htm?cont=986",
  91. "Rai4": "http://mediapolis.rai.it/relinker/relinkerServlet.htm?cont=75708",
  92. "RaiSatCinema": "http://mediapolis.rai.it/relinker/relinkerServlet.htm?cont=72381",
  93. "RaiSatExtra": "http://mediapolis.rai.it/relinker/relinkerServlet.htm?cont=72382",
  94. "RaiSatPremium": "http://mediapolis.rai.it/relinker/relinkerServlet.htm?cont=72383",
  95. "RaiSatYoYo": "http://mediapolis.rai.it/relinker/relinkerServlet.htm?cont=72384",
  96. "RaiScuola": "http://mediapolis.rai.it/relinker/relinkerServlet.htm?cont=24268",
  97. "RaiStoria": "http://mediapolis.rai.it/relinker/relinkerServlet.htm?cont=24269",
  98. "RaiNews24": "http://mediapolis.rai.it/relinker/relinkerServlet.htm?cont=1",
  99. "RaiGulp": "http://mediapolis.rai.it/relinker/relinkerServlet.htm?cont=4119",
  100. "RaiSport+": "http://mediapolis.rai.it/relinker/relinkerServlet.htm?cont=4145",
  101. "RaiMed": "http://mediapolis.rai.it/relinker/relinkerServlet.htm?cont=87127",
  102. "EuroNews": "http://mediapolis.rai.it/relinker/relinkerServlet.htm?cont=113784",
  103. #"TG1" "http://link.rai.it/x/vod/ue/wmx/ultimo_tg1.asx",
  104. #"TG2" "http://link.rai.it/x/vod/ue/wmx/ultimo_tg2.asx",
  105. #"TG3" "http://link.rai.it/x/vod/ue/wmx/ultimo_tg3.asx",
  106. }
  107.  
  108. def videoURL(pageURL):
  109. re_page = "^http://(?P<host>[a-zA-Z0-9]*\.([a-zA-Z0-9]*\.)+[a-zA-Z0-9]*)(?P<path>/[\w\-\+\~\%\#\.\/\?\=]*)"
  110. match_page = re.match(re_page, pageURL).groupdict()
  111.  
  112. page_connection = client.HTTPConnection(match_page["host"])
  113. page_connection.putrequest("POST", match_page["path"])
  114. page_connection.putheader("User-Agent", agent)
  115. page_connection.putheader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
  116. page_connection.putheader("Accept-Language", "it-it,it;q=0.8,en-us;q=0.5,en;q=0.3")
  117. page_connection.putheader("Accept-Encoding", "gzip,deflate")
  118. page_connection.putheader("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7")
  119. page_connection.putheader("Keep-Alive", "115")
  120. page_connection.putheader("Connection", "keep-alive")
  121. page_connection.putheader("Cookie", "volume=0,5; ns_cookietest=true; ns_session=true")
  122. page_connection.putheader("Cache-Control", "max-age=0")
  123. page_connection.endheaders()
  124. page_response = page_connection.getresponse().read()
  125. page_connection.close()
  126. page = str(gzip.GzipFile(fileobj=io.BytesIO(page_response)).read(), "utf8")
  127. return re.search("(?P<video>http://mediapolis.rai.it.*)\"", page).groupdict()["video"]
  128.  
  129. def streamURL(pageURL):
  130. re_url = "^http://(?P<host>[a-zA-Z0-9]*\.([a-zA-Z0-9]*\.)+[a-zA-Z0-9]*)(?P<path>/[\w\-\+\~\%\#\.\/]*)\?cont\=(?P<chanid>\w*)"
  131. match_url = re.match(re_url, pageURL).groupdict()
  132.  
  133. global ttAuth
  134. if ttAuth == "":
  135. ttAuth = authCode(match_url["chanid"])
  136.  
  137. asx_connection = client.HTTPConnection(match_url["host"])
  138. asx_connection.putrequest("POST", match_url["path"]+"?cont="+match_url["chanid"])
  139. asx_connection.putheader("User-Agent", agent)
  140. asx_connection.putheader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
  141. asx_connection.putheader("Accept-Language", "it-it,it;q=0.8,en-us;q=0.5,en;q=0.3")
  142. asx_connection.putheader("Accept-Encoding", "gzip,deflate")
  143. asx_connection.putheader("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7")
  144. asx_connection.putheader("Connection", "keep-alive")
  145. asx_connection.putheader("Keep-Alive", "115")
  146. asx_connection.putheader("viaurl", "www.rai.tv")
  147. asx_connection.putheader("ttAuth", ttAuth)
  148. asx_connection.putheader("Content-Length", "0")
  149. asx_connection.endheaders()
  150. asx_response = asx_connection.getresponse().read()
  151. asx_connection.close()
  152. try: ###niente bytes su python 2.5
  153. asx = bytes.decode(asx_response)
  154. except:
  155. asx = str.decode(asx_response)
  156. return re.search("(?P<mms>mms://.*)\"", asx).groupdict()["mms"]
  157.  
  158. def raiDate():
  159. date_connection = client.HTTPConnection("videowall.rai.it")
  160. date_connection.putrequest("GET", "/cgi-bin/date")
  161. date_connection.putheader("User-Agent", agent)
  162. date_connection.putheader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
  163. date_connection.putheader("Accept-Language", "it-it,it;q=0.8,en-us;q=0.5,en;q=0.3")
  164. date_connection.putheader("Accept-Encoding", "gzip,deflate")
  165. date_connection.putheader("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7")
  166. date_connection.putheader("Connection", "keep-alive")
  167. date_connection.putheader("Keep-Alive", "115")
  168. date_connection.endheaders()
  169. date_response = date_connection.getresponse().read()
  170. date_connection.close();
  171. try: ###niente bytes su python 2.5
  172. return bytes.decode(date_response[:len(date_response)-1])
  173. except:
  174. return str.decode(date_response[:len(date_response)-1])
  175.  
  176. def raiPrograms(host, chan_name):
  177. if chan_name == "RaiQuattro": chan_name = "Rai4"
  178. if chan_name == "RaiSport+": chan_name = "RaiSportSatellite"
  179. if chan_name == "RaiStoria": chan_name = "RAIEDU2"
  180. if chan_name == "RaiSatExtra": chan_name = "Extra"
  181. if chan_name == "RaiSatPremium": chan_name = "Premium"
  182. if chan_name == "RaiSatCinema": chan_name = "CinemaWorld"
  183. if chan_name == "RaiSatYoyo": chan_name = "Yoyo"
  184.  
  185. xml_connection = client.HTTPConnection(host)
  186. xml_connection.putrequest("GET", "/dl/portale/html/palinsesti/static/"+chan_name+".html")
  187. xml_connection.putheader("User-Agent", agent)
  188. xml_connection.putheader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
  189. xml_connection.putheader("Accept-Language", "it-it,it;q=0.8,en-us;q=0.5,en;q=0.3")
  190. xml_connection.putheader("Accept-Encoding", "gzip,deflate")
  191. xml_connection.putheader("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7")
  192. xml_connection.putheader("Keep-Alive", "115")
  193. xml_connection.putheader("Connection", "keep-alive")
  194. xml_connection.endheaders()
  195. xml_response = xml_connection.getresponse().read()
  196. xml_connection.close()
  197. return str(gzip.GzipFile(fileobj=io.BytesIO(xml_response)).read(), "utf8")
  198.  
  199. def encode1(token):
  200. rnd = random.randint(0,10)
  201. return ''.join(chr(ord(ch) ^ rnd) for ch in token) + ";" + str(rnd)
  202.  
  203. def encode2(token, key="hMrxuE2T8V0WRW0VmHaKMoFwy1XRc+hK7eBX2tTLVTw="):
  204. return encode2b(token, key)
  205.  
  206. #DEPRECATED
  207. def encode2a(token, key="hMrxuE2T8V0WRW0VmHaKMoFwy1XRc+hK7eBX2tTLVTw="):
  208. encoded = ""
  209. i, j, lenkey = 0, 0, len(key)
  210. for ch in token:
  211. encoded += chr(ord(token[i]) ^ ord(key[j]))
  212. i, j = (i+1), (j+1)%lenkey
  213. return encoded
  214.  
  215. def encode2b(token, key="hMrxuE2T8V0WRW0VmHaKMoFwy1XRc+hK7eBX2tTLVTw="):
  216. try:
  217. encoded = io.StringIO()
  218. except:
  219. encoded = cStringIO.StringIO()
  220. i, j, lenkey = len(token)-1, 0, len(key)
  221. for ch in token:
  222. encoded.write(chr(ord(token[i]) ^ ord(key[j])))
  223. i, j = (i-1), (j+1)%lenkey
  224. return encoded.getvalue()[::-1]
  225.  
  226. #DEPRECATED
  227. def encode2c(token, key = "hMrxuE2T8V0WRW0VmHaKMoFwy1XRc+hK7eBX2tTLVTw="):
  228. length = len(token)
  229.  
  230. encoded = list("" for i in range(0, length))
  231. pool = list(chr(i) for i in range(0, 256))
  232.  
  233. j = 0
  234. for i in range(0, 256):
  235. j = (j + ord(pool[i]) + ord(key[i%length])) % 256
  236. pool[i], pool[j] = pool[j], pool[i]
  237.  
  238. j, index = 0, 0
  239. for i in range(0, length):
  240. index = (index+1) % 256
  241. j = (j + ord(pool[index])) % 256;
  242. pool[index], pool[j] = pool[j], pool[index]
  243.  
  244. k = (ord(pool[index]) + ord(pool[j])) % 256;
  245. encoded[i] = chr(ord(token[i]) ^ ord(pool[k]))
  246.  
  247. return ''.join(i for i in encoded)
  248.  
  249. def encode3(token):
  250. try:
  251. return base64.encodebytes(str.encode(token)).decode()
  252. except:
  253. return base64.encodestring(str.encode(token)).decode()
  254.  
  255. def authCode(chan):
  256. re_date = "^(?P<day>\d*)-(?P<month>\d*)-(?P<year>\d*)\s(?P<hour>\d*):(?P<minutes>\d*):(?P<seconds>\d*)"
  257. match_date = re.match(re_date, raiDate()).groupdict()
  258.  
  259. day, month, year = match_date["day"], match_date["month"], match_date["year"]
  260. hour, minutes, seconds = match_date["hour"], match_date["minutes"], match_date["seconds"]
  261.  
  262. rnd1 = str(random.randint(0, 1234))
  263. rnd2 = str(random.randint(0, 1234))
  264.  
  265. token = year+";"+chan+";"+day+"-"+month+"-"+rnd1+"-"+hour+"-"+minutes+"-"+seconds+"-"+rnd2
  266. return encode3(encode2(encode1(token)))
  267.  
  268. def arguments():
  269. global stream, chan_name
  270. global isVoD, isProgram
  271.  
  272. args = sys.argv[1:]
  273. for arg in args:
  274. if arg.startswith("-"):
  275. match_parm = re.match("^-(\w*)=(.*)", arg)
  276. if type(match_parm).__name__ == "NoneType":
  277. print("WARNING: "+arg+" is not a valid argument")
  278. continue
  279.  
  280. if match_parm.groups()[0] == "vlcdir":
  281. vlc_dir = match_parm.groups()[1]
  282.  
  283. elif match_parm.groups()[0] == "uagent":
  284. agent = match_parm.groups()[1]
  285.  
  286. elif match_parm.groups()[0] == "ttAuth":
  287. ttAuth = match_parm.groups()[1]
  288.  
  289. elif match_parm.groups()[0] == "progs":
  290. progs_file = match_parm.groups()[1]
  291. isPrograms = True
  292.  
  293. else:
  294. print("WARNING: unknown argument ("+match_parm.groups()[0]+")")
  295. else:
  296. try:
  297. stream = urls[arg]
  298. chan_name = arg
  299. isVoD = False
  300. except:
  301. stream = videoURL(arg)
  302. isVoD = True
  303. isPrograms = False
  304. break
  305.  
  306.  
  307. def playerURL():
  308. arguments()
  309.  
  310. global stream
  311. global isVoD
  312. if isVoD == False:
  313. return streamURL(stream)
  314. else:
  315. return stream
  316.  
  317.  
  318. if __name__ == '__main__':
  319. if isPrograms == True:
  320. xml_file = open(progs_file, "w")
  321. xml_file.write(raiPrograms("www.rai.tv", chan_name))
  322. xml_file.close()
  323.  
  324. #subprocess.Popen([vlc_dir+"/vlc", "--http-user-agent=\""+agent+"\"", playerURL()])
  325. print(playerURL()) ###ho commentato la riga sopra e aggiunto questa perché mi serve solo il link mms
RAW Paste Data Copied