View difference between Paste ID: 4ZxTNWMC and hyLt2Yse
SHOW: | | - or go back to the newest paste.
1
#!/usr/bin/env python3
2
"""
3-
  A simple little script for getting at the m3u8 for ufc.tv videos
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
4+
	For free and ethical stream viewing free from proprietary players
5
6-
  Doesn't circumvent geo-blocks or login requirements
6+
	Doesn't circumvent geo-blocks or login requirements
7-
  You can get around the ufc.tv geo blocks via DNS proxies
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
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
11+
	To login, run: ufctv login
12-
  That will begin an interactive login prompt
12+
	That will begin an interactive login prompt
13-
  The login details themselves aren't saved, just the cookies for the session
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
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
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
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
18+
	% ufctv m3u8 http://www.ufc.tv/video/belfort-vs-henderson-3
19-
  From there you an do what you wish with the m3u8!
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)
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
22+
	% ufctv m3u8 http://www.ufc.tv/video/belfort-vs-henderson-3 | xargs mpv
23
24-
  Or start ripping with livestreamer
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
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
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
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=
43+
	parser = argparse.ArgumentParser(description=
44-
        """
44+
		"""
45-
        This is a command line tool to help enjoy quality UFC Fight Pass
45+
		This is a command line tool to help enjoy quality UFC Fight Pass
46-
        content in an ethical manner that respects your freedoms
46+
		content in an ethical manner that respects your freedoms
47-
        """)
47+
		""")
48
49-
    parser.add_argument('operation',
49+
	parser.add_argument('operation',
50-
        choices=['login', 'm3u8'])
50+
		choices=['login', 'm3u8'])
51
52-
    parser.add_argument('rest', nargs='*')
52+
	parser.add_argument('rest', nargs='*')
53
54-
    args = parser.parse_args()
54+
	args = parser.parse_args()
55
56-
    op = args.operation
56+
	op = args.operation
57-
    if op == 'login':
57+
	if op == 'login':
58-
        return ufctv_login()
58+
		return ufctv_login()
59
60-
    if len(args.rest) < 1:
60+
	if len(args.rest) < 1:
61-
        print("Missing argument: video_url", file=sys.stderr)
61+
		print("Missing argument: video_url", file=sys.stderr)
62-
        return 1
62+
		return 1
63
64-
    vid_url = args.rest[0]
64+
	vid_url = args.rest[0]
65-
    uri = get_m3u8(vid_url)
65+
	uri = get_m3u8(vid_url)
66-
    if uri is None: 
66+
	if uri is None: 
67-
        return 2
67+
		return 2
68
69-
    if args.operation == 'm3u8':
69+
	if args.operation == 'm3u8':
70-
        print(uri)
70+
		print(uri)
71-
        return 0
71+
		return 0
72
73
def fake_mobile_session():
74-
    with session() as c:
74+
	with session() as c:
75-
        load_cookies(c)
75+
		load_cookies(c)
76-
        c.headers.update({'User-Agent': (
76+
		c.headers.update({'User-Agent': (
77-
            "Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us)"
77+
			"Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us)"
78-
            " AppleWebKit/528.18 (KHTML, like Gecko)"
78+
			" AppleWebKit/528.18 (KHTML, like Gecko)"
79-
            " Version/4.0 Mobile/7A341 Safari/528.16")})
79+
			" Version/4.0 Mobile/7A341 Safari/528.16")})
80-
        return c
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"
83+
	puburi = "http://www.ufc.tv/service/publishpoint?type=video&id={}&format=json"
84-
    r = session.get(puburi.format(vid_id))
84+
	r = session.get(puburi.format(vid_id))
85-
    stream_info = json.loads(r.text)
85+
	stream_info = json.loads(r.text)
86-
    if 'path' not in stream_info:
86+
	if 'path' not in stream_info:
87-
        return None
87+
		return None
88-
    return stream_info['path'].replace("_iphone", "")
88+
	return stream_info['path'].replace("_iphone", "")
89
90
def get_m3u8(uri):
91-
    with fake_mobile_session() as c:
91+
	with fake_mobile_session() as c:
92-
        r = c.get(uri)
92+
		r = c.get(uri)
93
94-
        vid_id = find_video_id(r.text)
94+
		vid_id = find_video_id(r.text)
95-
        if vid_id is None: 
95+
		if vid_id is None: 
96-
            print("Failed to find video ID in page.", file=sys.stderr)
96+
			print("Failed to find video ID in page.", file=sys.stderr)
97-
            return None
97+
			return None
98
99-
        if not logged_in(r.text): 
99+
		if not logged_in(r.text): 
100-
            print("Goof Alert: You are not logged in to UFC.TV", file=sys.stderr)
100+
			print("Goof Alert: You are not logged in to UFC.TV", file=sys.stderr)
101
102-
        if not video_allowed(r.text):
102+
		if not video_allowed(r.text):
103-
            print("Video is not available", file=sys.stderr)
103+
			print("Video is not available", file=sys.stderr)
104-
            return None
104+
			return None
105
106-
        res = get_m3u8_by_id(c, vid_id)
106+
		res = get_m3u8_by_id(c, vid_id)
107-
        save_cookies(c)
107+
		save_cookies(c)
108-
        return res
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:
113+
	with open(ufctv_sesssion_path, 'wb') as f:
114-
        pickle.dump(session.cookies, f)
114+
		pickle.dump(session.cookies, f)
115
116
def load_cookies(session):
117-
    if not os.path.isfile(ufctv_sesssion_path):
117+
	if not os.path.isfile(ufctv_sesssion_path):
118-
        print("No saved cookies file found -- starting from scratch", file=sys.stderr)
118+
		print("No saved cookies file found -- starting from scratch", file=sys.stderr)
119-
        return
119+
		return
120
121-
    with open(ufctv_sesssion_path, 'rb') as f:
121+
	with open(ufctv_sesssion_path, 'rb') as f:
122-
        session.cookies.update(pickle.load(f))
122+
		session.cookies.update(pickle.load(f))
123
124
def video_allowed(page_html):
125-
    return '<div class="noAccess">' not in 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
128+
	return "Sign Out" in page_html
129
130
def ufctv_login():
131-
    with fake_mobile_session() as c:
131+
	with fake_mobile_session() as c:
132-
        login(c)
132+
		login(c)
133-
        save_cookies(c)
133+
		save_cookies(c)
134
135
def login(sesh):
136-
    username = input("Please enter your ufc.tv username: ")
136+
	username = input("Please enter your ufc.tv username: ")
137-
    password = getpass.getpass("Please enter your ufc.tv password: ")
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] ")
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'
139+
	longsesh = 'true' if longchoice is 'y' else 'false'
140
141-
    login = {
141+
	login = {
142-
        'username': username,
142+
		'username': username,
143-
        'password': password,
143+
		'password': password,
144-
        'cookielink': longsesh
144+
		'cookielink': longsesh
145-
    }
145+
	}
146
147-
    r = sesh.post("https://www.ufc.tv/secure/authenticate", data=login)
147+
	r = sesh.post("https://www.ufc.tv/secure/authenticate", data=login)
148
149-
    if 'loginsuccess' not in r.text:
149+
	if 'loginsuccess' not in r.text:
150-
        print("Login failure -- full response:\n{}\n".format(r.text), file=sys.stderr)
150+
		print("Login failure -- full response:\n{}\n".format(r.text), file=sys.stderr)
151-
        return False
151+
		return False
152
153-
    return True
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)
156+
	m = re.search("rel=\"image_src\" href=\".*?([0-9]+?)_.*?\.(jpg|png)\"", page_html)
157-
    if m is None:
157+
	if m is None:
158-
        return m
158+
		return m
159-
    return m.group(1)
159+
	return m.group(1)
160
161
if __name__ == "__main__": 
162-
    sys.exit(main())
162+
	sys.exit(main())