Guest User

ufctv.py updated for automated download and streaming

a guest
Jun 15th, 2016
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.76 KB | None | 0 0
  1. """
  2. A simple little script for getting at the m3u8 for ufc.tv videos
  3. For free and ethical stream viewing free from proprietary players
  4. This version has been tailored for those using windows and allows an automated
  5. download and streaming function
  6. *NOTE*
  7. For the automated streaming and downloading functions to work you must have
  8. livestreamer installed.
  9.  
  10. Doesn't circumvent geo-blocks or login requirements
  11. You can get around the ufc.tv geo blocks via DNS proxies
  12.  
  13. I have this saved as ufctv in a bin dir on my $PATH, so I can call it from wherever
  14.  
  15. To login, run: ufctv login
  16. That will begin an interactive login prompt
  17. The login details themselves aren't saved, just the cookies for the session
  18. And the active session is reset any time you login with the "Keep Me Signed In" box anywhere else
  19.  
  20. To get a video's m3u8: ufctv m3u8 $UFCTV-URL
  21. So for example if I want to go back and watch Belfort vs Hendo 3
  22. % ufctv m3u8 http://www.ufc.tv/video/belfort-vs-henderson-3
  23. From there you an do what you wish with the m3u8!
  24.  
  25. You may wish to pipe the result direct to mpv or vlc whichever is your default player(which lets you seek around and switch between qualities)
  26. % ufctv stream http://www.ufc.tv/video/belfort-vs-henderson-3
  27.  
  28. Or start ripping with livestreamer
  29. % ufctv dl http://www.ufc.tv/video/belfort-vs-henderson-3
  30. This will open livestreamer and automatically begin downloading the stream as an mp4
  31. You can also rip the stream with ffmpeg, though I've found livestreamer does it a bit cleaner
  32.  
  33. You may also wish to expand the program to add commands to do this for you instead of via shell piping
  34. """
  35.  
  36. import argparse
  37. import getpass
  38. import json
  39. import os
  40. import pickle
  41. import re
  42. import subprocess
  43. import sys
  44.  
  45. from requests import session
  46.  
  47. def main():
  48. parser = argparse.ArgumentParser(description=
  49. """
  50. This is a command line tool to help enjoy quality UFC Fight Pass
  51. content in an ethical manner that respects your freedoms
  52. """)
  53.  
  54. parser.add_argument('operation',
  55. choices=['login', 'm3u8', 'dl', 'stream'])
  56.  
  57. parser.add_argument('rest', nargs='*')
  58.  
  59. args = parser.parse_args()
  60.  
  61. op = args.operation
  62. if op == 'login':
  63. return ufctv_login()
  64.  
  65. if len(args.rest) < 1:
  66. print("Missing argument: video_url", file=sys.stderr)
  67. return 1
  68.  
  69. vid_url = args.rest[0]
  70. uri = get_m3u8(vid_url)
  71. if uri is None:
  72. return 2
  73.  
  74. if args.operation == 'm3u8':
  75. print(uri)
  76. return 0
  77. if args.operation == 'dl':
  78. from urllib.parse import urlparse
  79. parsed = urlparse(vid_url)
  80. filename = parsed.path
  81. filename = filename.replace("/video/", "")
  82. subprocess.Popen(['livestreamer', "hlsvariant://" + uri, "best", "-o", filename + ".mp4"])
  83. return 0
  84. if args.operation == 'stream':
  85. subprocess.Popen(['livestreamer', "hlsvariant://" + uri, "best"])
  86. return 0
  87. def fake_mobile_session():
  88. with session() as c:
  89. load_cookies(c)
  90. c.headers.update({'User-Agent': (
  91. "Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us)"
  92. " AppleWebKit/528.18 (KHTML, like Gecko)"
  93. " Version/4.0 Mobile/7A341 Safari/528.16")})
  94. return c
  95.  
  96. def get_m3u8_by_id(session, vid_id):
  97. puburi = "http://www.ufc.tv/service/publishpoint?type=video&id={}&format=json"
  98. r = session.get(puburi.format(vid_id))
  99. stream_info = json.loads(r.text)
  100. if 'path' not in stream_info:
  101. return None
  102. return stream_info['path'].replace("_iphone", "")
  103.  
  104. def get_m3u8(uri):
  105. with fake_mobile_session() as c:
  106. r = c.get(uri)
  107.  
  108. vid_id = find_video_id(r.text)
  109. if vid_id is None:
  110. print("Failed to find video ID in page.", file=sys.stderr)
  111. return None
  112.  
  113. if not logged_in(r.text):
  114. print("Goof Alert: You are not logged in to UFC.TV", file=sys.stderr)
  115.  
  116. if not video_allowed(r.text):
  117. print("Video is not available", file=sys.stderr)
  118. return None
  119.  
  120. res = get_m3u8_by_id(c, vid_id)
  121. save_cookies(c)
  122. return res
  123.  
  124. ufctv_sesssion_path = os.path.expanduser("~/.ufctv")
  125.  
  126. def save_cookies(session):
  127. with open(ufctv_sesssion_path, 'wb') as f:
  128. pickle.dump(session.cookies, f)
  129.  
  130. def load_cookies(session):
  131. if not os.path.isfile(ufctv_sesssion_path):
  132. print("No saved cookies file found -- starting from scratch", file=sys.stderr)
  133. return
  134.  
  135. with open(ufctv_sesssion_path, 'rb') as f:
  136. session.cookies.update(pickle.load(f))
  137.  
  138. def video_allowed(page_html):
  139. return '<div class="noAccess">' not in page_html
  140.  
  141. def logged_in(page_html):
  142. return "Sign Out" in page_html
  143.  
  144. def ufctv_login():
  145. with fake_mobile_session() as c:
  146. login(c)
  147. save_cookies(c)
  148.  
  149. def login(sesh):
  150. username = input("Please enter your ufc.tv username: ")
  151. password = getpass.getpass("Please enter your ufc.tv password: ")
  152. longchoice = input("Tick the 'Keep Me Signed In' box for a long lasting session? [y/n] ")
  153. longsesh = 'true' if longchoice is 'y' else 'false'
  154.  
  155. login = {
  156. 'username': username,
  157. 'password': password,
  158. 'cookielink': longsesh
  159. }
  160.  
  161. r = sesh.post("https://www.ufc.tv/secure/authenticate", data=login)
  162.  
  163. if 'loginsuccess' not in r.text:
  164. print("Login failure -- full response:\n{}\n".format(r.text), file=sys.stderr)
  165. return False
  166.  
  167. return True
  168.  
  169. def find_video_id(page_html):
  170. m = re.search("rel=\"image_src\" href=\".*?([0-9]+?)_.*?\.(jpg|png)\"", page_html)
  171. if m is None:
  172. return m
  173. return m.group(1)
  174.  
  175. if __name__ == "__main__":
  176. sys.exit(main())
Add Comment
Please, Sign In to add comment