View difference between Paste ID: hyLt2Yse and BDGdbawe
SHOW: | | - or go back to the newest paste.
1-
#!/usr/local/bin/python3
1+
#!/usr/bin/env 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|png)\"", page_html)
157
    if m is None:
158
        return m
159
    return m.group(1)
160
161
if __name__ == "__main__": 
162
    sys.exit(main())