Guest User

ufctv.py

a guest
Jun 17th, 2017
71
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.22 KB | None | 0 0
  1. #!/usr/bin/env python3
  2.  
  3. """
  4. A simple little script for getting at the m3u8 for ufc.tv videos
  5. For free and ethical stream viewing free from proprietary players
  6.  
  7. I have this saved as ufctv in a bin dir on my $PATH, so I can call it from wherever
  8.  
  9. To login, run: ufctv login
  10. That will begin an interactive login prompt
  11. The login details themselves aren't saved, just the cookies for the session
  12. And the active session is reset any time you login with the "Keep Me Signed In" box anywhere else
  13.  
  14. To get a video's m3u8: ufctv m3u8 $UFCTV-URL
  15. So for example if I want to go back and watch Belfort vs Hendo 3
  16. % ufctv m3u8 http://www.ufc.tv/video/belfort-vs-henderson-3
  17. From there you an do what you wish with the m3u8!
  18.  
  19. You may wish to pipe the result direct to mpv (which lets you seek around and switch between qualities)
  20. % ufctv m3u8 http://www.ufc.tv/video/belfort-vs-henderson-3 | xargs mpv
  21.  
  22. Or start ripping with livestreamer
  23. % ufctv m3u8 http://www.ufc.tv/video/belfort-vs-henderson-3 | xargs -I M3U8 livestreamer hlsvariant://M3U8 best -o belf-vs-hend.ts
  24. You can also rip the stream with ffmpeg, though I've found livestreamer does it a bit cleaner
  25.  
  26. You may also wish to expand the program to add commands to do this for you instead of via shell piping
  27. """
  28.  
  29. import argparse
  30. import getpass
  31. import json
  32. import os
  33. import pickle
  34. import re
  35. import subprocess
  36. import sys
  37. import logging
  38.  
  39. from requests import session
  40.  
  41. ufctv_session_path = os.path.expanduser("~/.ufctv")
  42.  
  43. """
  44. Geo Block Elision
  45. Will only request first ufc.tv main page with proxy
  46. Nothing else will go through proxy
  47. Seems to work that way, thanks ukbro
  48.  
  49. Have to proxy the HTTPS base site now, HTTP site doesn't cross-pollinate with HTTPS
  50. Can use an HTTP, HTTPS, SOCKS4/5 proxy, all good
  51.  
  52. Added it as an argument now so you can just go
  53. --proxy "http://123.345.567.789:111"
  54. or whatever from command line
  55. """
  56. proxy_settings = {}
  57.  
  58. def main():
  59. logging.basicConfig(level=logging.INFO)
  60.  
  61. parser = argparse.ArgumentParser(description=
  62. """
  63. This is a command line tool to help enjoy quality UFC Fight Pass
  64. content in an ethical manner that respects your freedoms
  65. """)
  66.  
  67. parser.add_argument('operation',
  68. choices=['login', 'm3u8'])
  69.  
  70. parser.add_argument('video_url', nargs='?')
  71. parser.add_argument('-c', '--cam', default='0',
  72. help="Requests a different camera -- only works for PPVs!"
  73. )
  74. parser.add_argument('--proxy', help="Attempt to dodge geoblocking using a proxy")
  75.  
  76. args = parser.parse_args()
  77.  
  78. if args.proxy:
  79. proxy_settings['http'] = args.proxy
  80. proxy_settings['https'] = args.proxy
  81.  
  82. op = args.operation
  83. if op == 'login':
  84. return ufctv_login()
  85.  
  86. if not args.video_url:
  87. print("Missing argument: video_url", file=sys.stderr)
  88. return 1
  89.  
  90. uri = get_m3u8(args.video_url, args.cam)
  91. if uri is None:
  92. return 2
  93.  
  94. if args.operation == 'm3u8':
  95. print(uri)
  96. return 0
  97.  
  98. def ufctv_session():
  99. with session() as c:
  100. load_cookies(c)
  101. c.headers.update({'User-Agent': (
  102. "Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us)"
  103. " AppleWebKit/528.18 (KHTML, like Gecko)"
  104. " Version/4.0 Mobile/7A341 Safari/528.16")})
  105.  
  106. #let ufc.tv "feel the proxy"
  107. if 'https' in proxy_settings:
  108. c.get("https://www.ufc.tv/", proxies=proxy_settings)
  109.  
  110. return c
  111.  
  112. def get_m3u8_by_id(session, vid_id, cam):
  113. puburi = "https://www.ufc.tv/service/publishpoint"
  114. request = {
  115. 'format': 'json',
  116. 'type': 'video',
  117. 'id': vid_id,
  118. 'cam': cam
  119. }
  120.  
  121. r = session.post(puburi, data=request)
  122. stream_info = json.loads(r.text)
  123. if 'path' not in stream_info:
  124. print("No stream m3u8 found, sorry.", file=sys.stderr)
  125. return None
  126. return stream_info['path'].replace("_iphone", "")
  127.  
  128. def get_m3u8(uri, cam):
  129. with ufctv_session() as c:
  130. r = c.get(uri)
  131.  
  132. if not logged_in(r.text):
  133. print("Goof Alert: You are not logged in to UFC.TV", file=sys.stderr)
  134.  
  135. if video_geo_blocked(r.text):
  136. print("Geo-Block detected.", file=sys.stderr)
  137.  
  138. vid_id = find_video_id(r.text)
  139. if vid_id is None:
  140. print("Failed to find video ID in page.", file=sys.stderr)
  141. return None
  142.  
  143. if not video_allowed(r.text):
  144. print("Video is not available to you for whatever reason", file=sys.stderr)
  145. return None
  146.  
  147. return get_m3u8_by_id(c, vid_id, cam)
  148.  
  149. def save_cookies(session):
  150. with open(ufctv_session_path, 'wb') as f:
  151. pickle.dump(session.cookies, f)
  152.  
  153. def load_cookies(session):
  154. if not os.path.isfile(ufctv_session_path):
  155. return
  156.  
  157. with open(ufctv_session_path, 'rb') as f:
  158. session.cookies.update(pickle.load(f))
  159.  
  160. def video_geo_blocked(html):
  161. return '<div class="blackout-content">' in html
  162.  
  163. def video_allowed(page_html):
  164. return '<div class="noAccess">' not in page_html
  165.  
  166. def logged_in(page_html):
  167. return "var isLoggedIn = true;" in page_html
  168.  
  169. def ufctv_login():
  170. if os.path.isfile(ufctv_session_path):
  171. os.remove(ufctv_session_path)
  172.  
  173. with ufctv_session() as c:
  174. login(c)
  175. save_cookies(c)
  176.  
  177. def login(sesh):
  178. username = input("Please enter your ufc.tv username: ")
  179. password = getpass.getpass("Please enter your ufc.tv password: ")
  180. longchoice = input("Tick the 'Keep Me Signed In' box for a long lasting session? [y/n] ")
  181. longsesh = 'true' if longchoice is 'y' else 'false'
  182.  
  183. login = {
  184. 'username': username,
  185. 'password': password,
  186. 'cookielink': longsesh
  187. }
  188.  
  189. r = sesh.post("https://www.ufc.tv/secure/authenticate", data=login)
  190.  
  191. if 'loginsuccess' not in r.text:
  192. print("Login failure -- full response:\n{}\n".format(r.text), file=sys.stderr)
  193. return False
  194.  
  195. return True
  196.  
  197. def find_video_id(page_html):
  198. m = re.search("rel=\"image_src\" href=\".*?([0-9]+?)_.*?\.jpg\"", page_html)
  199. if m is None:
  200. return m
  201. return m.group(1)
  202.  
  203. if __name__ == "__main__":
  204. sys.exit(main())
Add Comment
Please, Sign In to add comment