Advertisement
Guest User

ufc.py

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