mirror of https://github.com/streamlink/streamlink
parent
c0cf64a97b
commit
b325aff98d
|
@ -26,11 +26,13 @@ exclude =
|
|||
examples/,
|
||||
env/,
|
||||
src/streamlink/packages/flashmedia/,
|
||||
script/
|
||||
venv/,
|
||||
versioneer.py,
|
||||
win32/,
|
||||
per-file-ignores =
|
||||
src/streamlink/__init__.py:E402,F401,
|
||||
src/streamlink/plugin/api/useragents.py:E501,
|
||||
src/streamlink/plugins/__init__.py:F401,
|
||||
src/streamlink/stream/__init__.py:F401,
|
||||
src/streamlink_cli/utils/named_pipe.py:F401,
|
||||
|
|
|
@ -34,7 +34,8 @@ class BBCiPlayer(Plugin):
|
|||
state_re = re.compile(r'window.__IPLAYER_REDUX_STATE__\s*=\s*({.*});')
|
||||
account_locals_re = re.compile(r'window.bbcAccount.locals\s*=\s*({.*?});')
|
||||
hash = base64.b64decode(b"N2RmZjc2NzFkMGM2OTdmZWRiMWQ5MDVkOWExMjE3MTk5MzhiOTJiZg==")
|
||||
api_url = "https://open.live.bbc.co.uk/mediaselector/6/select/version/2.0/mediaset/{platform}/vpid/{vpid}/format/json/atk/{vpid_hash}/asn/1/"
|
||||
api_url = "https://open.live.bbc.co.uk/mediaselector/6/select/version/2.0/mediaset/" \
|
||||
"{platform}/vpid/{vpid}/format/json/atk/{vpid_hash}/asn/1/"
|
||||
platforms = ("pc", "iptv-all")
|
||||
session_url = "https://session.bbc.com/session"
|
||||
auth_url = "https://account.bbc.com/signin"
|
||||
|
|
|
@ -41,7 +41,11 @@ class BeatTV(Plugin):
|
|||
|
||||
if video_assets.get("mpeg"):
|
||||
for mpeg_stream in video_assets.get("mpeg"):
|
||||
q = mpeg_stream.get("renditionValue").strip("_") or "{}k".format(mpeg_stream.get("bitrate") // 1000) or "vod"
|
||||
q = (
|
||||
mpeg_stream.get("renditionValue").strip("_")
|
||||
or "{}k".format(mpeg_stream.get("bitrate") // 1000)
|
||||
or "vod"
|
||||
)
|
||||
yield q, HTTPStream(self.session, mpeg_stream["url"])
|
||||
|
||||
|
||||
|
|
|
@ -7,9 +7,17 @@ from streamlink.stream import HLSStream
|
|||
|
||||
class BFMTV(Plugin):
|
||||
_url_re = re.compile(r'https://.+\.(?:bfmtv|01net)\.com')
|
||||
_brightcove_video_re = re.compile(r'data-holder="video(?P<video_id>[0-9]+)" data-account="(?P<account_id>[0-9]+)"')
|
||||
_brightcove_video_alt_re = re.compile(r'data-account="(?P<account_id>[0-9]+).*?data-video-id="(?P<video_id>[0-9]+)"', re.DOTALL)
|
||||
_embed_video_url_re = re.compile(r"\$YOPLAYER\('liveStitching', {.+?file: '(?P<video_url>[^\"]+?)'.+?}\);", re.DOTALL)
|
||||
_brightcove_video_re = re.compile(
|
||||
r'data-holder="video(?P<video_id>[0-9]+)" data-account="(?P<account_id>[0-9]+)"'
|
||||
)
|
||||
_brightcove_video_alt_re = re.compile(
|
||||
r'data-account="(?P<account_id>[0-9]+).*?data-video-id="(?P<video_id>[0-9]+)"',
|
||||
re.DOTALL
|
||||
)
|
||||
_embed_video_url_re = re.compile(
|
||||
r"\$YOPLAYER\('liveStitching', {.+?file: '(?P<video_url>[^\"]+?)'.+?}\);",
|
||||
re.DOTALL
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def can_handle_url(cls, url):
|
||||
|
|
|
@ -107,7 +107,12 @@ class Bloomberg(Plugin):
|
|||
"authority": "www.bloomberg.com",
|
||||
"upgrade-insecure-requests": "1",
|
||||
"dnt": "1",
|
||||
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3"
|
||||
"accept": ";".join([
|
||||
"text/html,application/xhtml+xml,application/xml",
|
||||
"q=0.9,image/webp,image/apng,*/*",
|
||||
"q=0.8,application/signed-exchange",
|
||||
"v=b3"
|
||||
])
|
||||
})
|
||||
if "Are you a robot?" in res.text:
|
||||
log.error("Are you a robot?")
|
||||
|
|
|
@ -52,7 +52,9 @@ class BTSports(Plugin):
|
|||
def login(self, username, password):
|
||||
log.debug("Logging in as {0}".format(username))
|
||||
|
||||
redirect_to = "https://home.bt.com/ss/Satellite/secure/loginforward?view=btsport&redirectURL={0}".format(quote(self.url))
|
||||
redirect_to = "https://home.bt.com/ss/Satellite/secure/loginforward?view=btsport&redirectURL={0}".format(
|
||||
quote(self.url)
|
||||
)
|
||||
data = {
|
||||
"cookieExpp": "30",
|
||||
"Switch": "yes",
|
||||
|
|
|
@ -38,7 +38,8 @@ class ElTreceTV(Plugin):
|
|||
if not match:
|
||||
return
|
||||
entry_id = parse_json(match.group(1).replace(""", '"'))["entryId"]
|
||||
hls_url = "https://vodgc.com/p/111/sp/11100/playManifest/entryId/{0}/format/applehttp/protocol/https/a.m3u8".format(entry_id)
|
||||
hls_url = "https://vodgc.com/p/111/sp/11100/playManifest/entryId/" \
|
||||
"{0}/format/applehttp/protocol/https/a.m3u8".format(entry_id)
|
||||
return HLSStream.parse_variant_playlist(self.session, hls_url)
|
||||
except BaseException:
|
||||
self.logger.error("The requested VOD content is unavailable.")
|
||||
|
|
|
@ -53,7 +53,11 @@ class Experience(object):
|
|||
|
||||
res = self.session.http.request(method, url, *args, headers=headers, **kwargs)
|
||||
if "_Incapsula_Resource" in res.text:
|
||||
log.error("This page is protected by Incapsula, please see https://github.com/streamlink/streamlink/issues/2088 for a workaround.")
|
||||
log.error(
|
||||
"This page is protected by Incapsula, please see "
|
||||
"https://github.com/streamlink/streamlink/issues/2088"
|
||||
" for a workaround."
|
||||
)
|
||||
return
|
||||
return res
|
||||
|
||||
|
@ -205,7 +209,11 @@ class FunimationNow(Plugin):
|
|||
rlanguage = {"en": "english", "ja": "japanese"}.get(self.get_option("language").lower(),
|
||||
self.get_option("language").lower())
|
||||
if "_Incapsula_Resource" in res.text:
|
||||
log.error("This page is protected by Incapsula, please see https://github.com/streamlink/streamlink/issues/2088 for a workaround.")
|
||||
log.error(
|
||||
"This page is protected by Incapsula, please see "
|
||||
"https://github.com/streamlink/streamlink/issues/2088"
|
||||
" for a workaround."
|
||||
)
|
||||
return
|
||||
|
||||
if "Out of Territory" in res.text:
|
||||
|
|
|
@ -7,11 +7,12 @@ import json
|
|||
|
||||
from streamlink.plugin import Plugin
|
||||
from streamlink.plugin.api import validate
|
||||
from streamlink.plugin.api.useragents import CHROME as USER_AGENT
|
||||
from streamlink.stream import (HTTPStream, HLSStream)
|
||||
|
||||
USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36"
|
||||
HUAJIAO_URL = "http://www.huajiao.com/l/{}"
|
||||
LAPI_URL = "http://g2.live.360.cn/liveplay?stype=flv&channel={}&bid=huajiao&sn={}&sid={}&_rate=xd&ts={}&r={}&_ostype=flash&_delay=0&_sign=null&_ver=13"
|
||||
LAPI_URL = "http://g2.live.360.cn/liveplay?stype=flv&channel={}&bid=huajiao&sn={}&sid={}&_rate=xd&ts={}&r={}" \
|
||||
"&_ostype=flash&_delay=0&_sign=null&_ver=13"
|
||||
|
||||
_url_re = re.compile(r"""
|
||||
http(s)?://(www\.)?huajiao.com
|
||||
|
|
|
@ -12,8 +12,14 @@ class IDF1(Plugin):
|
|||
DACAST_TOKEN_URL = 'https://services.dacast.com/token/i/b/{}/{}/{}'
|
||||
|
||||
_url_re = re.compile(r'https?://www\.idf1\.fr/(videos/[^/]+/[^/]+\.html|live\b)')
|
||||
_video_id_re = re.compile(r"dacast\('(?P<broadcaster_id>\d+)_(?P<video_type>[a-z]+)_(?P<video_id>\d+)', 'replay_content', data\);")
|
||||
_video_id_alt_re = re.compile(r'<script src="https://player.dacast.com/js/player.js" id="(?P<broadcaster_id>\d+)_(?P<video_type>[cf])_(?P<video_id>\d+)"')
|
||||
_video_id_re = re.compile(r"""
|
||||
dacast\('(?P<broadcaster_id>\d+)_(?P<video_type>[a-z]+)_(?P<video_id>\d+)',\s*'replay_content',\s*data\);
|
||||
""", re.VERBOSE)
|
||||
_video_id_alt_re = re.compile(r'''
|
||||
<script\s+
|
||||
src="https://player.dacast.com/js/player.js"\s+
|
||||
id="(?P<broadcaster_id>\d+)_(?P<video_type>[cf])_(?P<video_id>\d+)"
|
||||
''', re.VERBOSE)
|
||||
_player_url = 'http://ssl.p.jwpcdn.com/player/v/7.12.6/jwplayer.flash.swf'
|
||||
|
||||
_api_schema = validate.Schema(
|
||||
|
@ -29,7 +35,9 @@ class IDF1(Plugin):
|
|||
'hls': validate.url(),
|
||||
'hds': validate.url()
|
||||
},
|
||||
validate.transform(lambda x: [update_scheme(IDF1.DACAST_API_URL, x['hls']), x['hds']] + [y['src'] for y in x.get('html5', [])])
|
||||
validate.transform(
|
||||
lambda x: [update_scheme(IDF1.DACAST_API_URL, x['hls']), x['hds']] + [y['src'] for y in x.get('html5', [])]
|
||||
)
|
||||
)
|
||||
|
||||
_token_schema = validate.Schema(
|
||||
|
@ -53,7 +61,10 @@ class IDF1(Plugin):
|
|||
video_type = match.group('video_type')
|
||||
video_id = match.group('video_id')
|
||||
|
||||
videos = self.session.http.get(self.DACAST_API_URL.format(broadcaster_id, video_type, video_id), schema=self._api_schema)
|
||||
videos = self.session.http.get(
|
||||
self.DACAST_API_URL.format(broadcaster_id, video_type, video_id),
|
||||
schema=self._api_schema
|
||||
)
|
||||
token = self.session.http.get(
|
||||
self.DACAST_TOKEN_URL.format(broadcaster_id, video_type, video_id),
|
||||
schema=self._token_schema,
|
||||
|
|
|
@ -96,7 +96,12 @@ class Livestream(Plugin):
|
|||
|
||||
play_url = stream_info.get("play_url")
|
||||
if play_url:
|
||||
swf_url = info.get("playerUri") or info.get("hdPlayerSwfUrl") or info.get("lsPlayerSwfUrl") or info.get("viewerPlusSwfUrl")
|
||||
swf_url = (
|
||||
info.get("playerUri")
|
||||
or info.get("hdPlayerSwfUrl")
|
||||
or info.get("lsPlayerSwfUrl")
|
||||
or info.get("viewerPlusSwfUrl")
|
||||
)
|
||||
if swf_url:
|
||||
if not swf_url.startswith("http"):
|
||||
if swf_url.startswith("//"):
|
||||
|
|
|
@ -15,7 +15,9 @@ class MLGTV(Plugin):
|
|||
CHANNEL_API = "https://www.majorleaguegaming.com/api/channel/{0}"
|
||||
|
||||
_player_config_re = re.compile(r"var playerConfig = (.+);")
|
||||
_player_embed_re = re.compile(r"""https?://player2\.majorleaguegaming\.com/api/v2/player/embed/live/\?ch=(?P<channel_id>[^"']+)""")
|
||||
_player_embed_re = re.compile(
|
||||
r"""https?://player2\.majorleaguegaming\.com/api/v2/player/embed/live/\?ch=(?P<channel_id>[^"']+)"""
|
||||
)
|
||||
_site_data_re = re.compile(r"window\.siteData = (?P<data>.+);")
|
||||
_stream_id_re = re.compile(r"<meta content='.+/([\w_-]+).+' property='og:video'>")
|
||||
|
||||
|
|
|
@ -23,8 +23,8 @@ class OlympicChannel(Plugin):
|
|||
page = self.session.http.get(self.url)
|
||||
asset = re.search(r'asse_.{32}', str(page._content)).group(0)
|
||||
post_data = '{"asset_url":"/api/assets/%s/"}' % asset
|
||||
stream_data = self.session.http.json(self.session.http.post(self._stream_get_url, data=post_data))['objects'][0]['level3']['streaming_url']
|
||||
return HLSStream.parse_variant_playlist(self.session, stream_data)
|
||||
stream_data = self.session.http.json(self.session.http.post(self._stream_get_url, data=post_data))
|
||||
return HLSStream.parse_variant_playlist(self.session, stream_data['objects'][0]['level3']['streaming_url'])
|
||||
|
||||
def _get_live_streams(self, lang, path):
|
||||
"""
|
||||
|
|
|
@ -5,7 +5,12 @@ from streamlink.plugin import Plugin, PluginError
|
|||
from streamlink.stream import HLSStream
|
||||
|
||||
_stream_url_re = re.compile(r'https?://tvthek\.orf\.at/(index\.php/)?live/(?P<title>[^/]+)/(?P<id>[0-9]+)')
|
||||
_vod_url_re = re.compile(r'https?://tvthek\.orf\.at/pro(gram|file)/(?P<showtitle>[^/]+)/(?P<showid>[0-9]+)/(?P<episodetitle>[^/]+)/(?P<epsiodeid>[0-9]+)(/(?P<segmenttitle>[^/]+)/(?P<segmentid>[0-9]+))?')
|
||||
_vod_url_re = re.compile(r'''
|
||||
https?://tvthek\.orf\.at/pro(gram|file)
|
||||
/(?P<showtitle>[^/]+)/(?P<showid>[0-9]+)
|
||||
/(?P<episodetitle>[^/]+)/(?P<epsiodeid>[0-9]+)
|
||||
(/(?P<segmenttitle>[^/]+)/(?P<segmentid>[0-9]+))?
|
||||
''', re.VERBOSE)
|
||||
_json_re = re.compile(r'<div class="jsb_ jsb_VideoPlaylist" data-jsb="(?P<json>[^"]+)">')
|
||||
|
||||
MODE_STREAM, MODE_VOD = 0, 1
|
||||
|
|
|
@ -15,7 +15,8 @@ class Pluzz(Plugin):
|
|||
GEO_URL = 'http://geo.francetv.fr/ws/edgescape.json'
|
||||
API_URL = 'http://sivideo.webservices.francetelevisions.fr/tools/getInfosOeuvre/v2/?idDiffusion={0}'
|
||||
TOKEN_URL = 'http://hdfauthftv-a.akamaihd.net/esi/TA?url={0}'
|
||||
SWF_PLAYER_URL = 'https://staticftv-a.akamaihd.net/player/bower_components/player_flash/dist/FranceTVNVPVFlashPlayer.akamai-7301b6035a43c4e29b7935c9c36771d2.swf'
|
||||
SWF_PLAYER_URL = 'https://staticftv-a.akamaihd.net/player/bower_components/player_flash/dist/' \
|
||||
'FranceTVNVPVFlashPlayer.akamai-7301b6035a43c4e29b7935c9c36771d2.swf'
|
||||
|
||||
_url_re = re.compile(r'''
|
||||
https?://(
|
||||
|
|
|
@ -13,12 +13,23 @@ class RTBF(Plugin):
|
|||
TOKEN_URL = 'https://token.rtbf.be/'
|
||||
RADIO_STREAM_URL = 'http://www.rtbfradioplayer.be/radio/liveradio/rtbf/radios/{}/config.json'
|
||||
|
||||
_url_re = re.compile(r'https?://(?:www\.)?(?:rtbf\.be/auvio/.*\?l?id=(?P<video_id>[0-9]+)#?|rtbfradioplayer\.be/radio/liveradio/.+)')
|
||||
_stream_size_re = re.compile(r'https?://.+-(?P<size>\d+p?)\..+?$')
|
||||
_url_re = re.compile(
|
||||
r'https?://(?:www\.)?(?:rtbf\.be/auvio/.*\?l?id=(?P<video_id>[0-9]+)#?|rtbfradioplayer\.be/radio/liveradio/.+)'
|
||||
)
|
||||
_stream_size_re = re.compile(
|
||||
r'https?://.+-(?P<size>\d+p?)\..+?$'
|
||||
)
|
||||
|
||||
_video_player_re = re.compile(r'<iframe\s+class="embed-responsive-item\s+js-embed-iframe".*src="(?P<player_url>.+?)".*?</iframe>', re.DOTALL)
|
||||
_video_stream_data_re = re.compile(r'<div\s+id="js-embed-player"\s+class="js-embed-player\s+embed-player"\s+data-media="(.+?)"')
|
||||
_radio_id_re = re.compile(r'var currentStationKey = "(?P<radio_id>.+?)"')
|
||||
_video_player_re = re.compile(
|
||||
r'<iframe\s+class="embed-responsive-item\s+js-embed-iframe".*src="(?P<player_url>.+?)".*?</iframe>',
|
||||
re.DOTALL
|
||||
)
|
||||
_video_stream_data_re = re.compile(
|
||||
r'<div\s+id="js-embed-player"\s+class="js-embed-player\s+embed-player"\s+data-media="(.+?)"'
|
||||
)
|
||||
_radio_id_re = re.compile(
|
||||
r'var currentStationKey = "(?P<radio_id>.+?)"'
|
||||
)
|
||||
|
||||
_geo_schema = validate.Schema(
|
||||
{
|
||||
|
|
|
@ -15,7 +15,9 @@ class rtlxl(Plugin):
|
|||
def _get_streams(self):
|
||||
match = _url_re.match(self.url)
|
||||
uuid = match.group("uuid")
|
||||
videourlfeed = self.session.http.get('https://tm-videourlfeed.rtl.nl/api/url/{}?device=pc&drm&format=hls'.format(uuid)).text
|
||||
videourlfeed = self.session.http.get(
|
||||
'https://tm-videourlfeed.rtl.nl/api/url/{}?device=pc&drm&format=hls'.format(uuid)
|
||||
).text
|
||||
|
||||
videourlfeedjson = json.loads(videourlfeed)
|
||||
playlist_url = videourlfeedjson["url"]
|
||||
|
|
|
@ -25,7 +25,7 @@ class Stadium(Plugin):
|
|||
if data['LivestreamEnabled'] == '1':
|
||||
account_id = data['LivestreamArgs']['account_id']
|
||||
event_id = data['LivestreamArgs']['event_id']
|
||||
log.debug("Found account_id={account_id} and event_id={event_id}".format(account_id=account_id, event_id=event_id))
|
||||
log.debug("Found account_id={0} and event_id={1}".format(account_id, event_id))
|
||||
|
||||
url = self.API_URL.format(account_id=account_id, event_id=event_id)
|
||||
api_res = self.session.http.get(url)
|
||||
|
|
|
@ -19,7 +19,9 @@ class Streann(Plugin):
|
|||
base_url = "https://ott.streann.com"
|
||||
get_time_url = base_url + "/web/services/public/get-server-time"
|
||||
token_url = base_url + "/loadbalancer/services/web-players/{playerId}/token/{type}/{dataId}/{deviceId}"
|
||||
stream_url = base_url + "/loadbalancer/services/web-players/{type}s-reseller-secure/{dataId}/{playerId}/{token}/{resellerId}/playlist.m3u8?date={time}&device-type=web&device-name=web&device-os=web&device-id={deviceId}"
|
||||
stream_url = base_url + "/loadbalancer/services/web-players/{type}s-reseller-secure/{dataId}/{playerId}" \
|
||||
"/{token}/{resellerId}/playlist.m3u8?date={time}&device-type=web&device-name=web" \
|
||||
"&device-os=web&device-id={deviceId}"
|
||||
passphrase_re = re.compile(r'''CryptoJS\.AES\.decrypt\(.*?,\s*(['"])(?P<passphrase>(?:(?!\1).)*)\1\s*?\);''')
|
||||
|
||||
def __init__(self, url):
|
||||
|
|
|
@ -43,10 +43,17 @@ class TF1(Plugin):
|
|||
for sformat, url in self.get_stream_urls(channel):
|
||||
try:
|
||||
if sformat == "dash":
|
||||
for s in DASHStream.parse_manifest(self.session, url, headers={"User-Agent": useragents.CHROME}).items():
|
||||
for s in DASHStream.parse_manifest(
|
||||
self.session,
|
||||
url,
|
||||
headers={"User-Agent": useragents.CHROME}
|
||||
).items():
|
||||
yield s
|
||||
if sformat == "hls":
|
||||
for s in HLSStream.parse_variant_playlist(self.session, url).items():
|
||||
for s in HLSStream.parse_variant_playlist(
|
||||
self.session,
|
||||
url
|
||||
).items():
|
||||
yield s
|
||||
except PluginError as e:
|
||||
log.error("Could not open {0} stream".format(sformat))
|
||||
|
|
|
@ -11,7 +11,8 @@ log = logging.getLogger(__name__)
|
|||
|
||||
class TV3Cat(Plugin):
|
||||
_url_re = re.compile(r"http://(?:www.)?ccma.cat/tv3/directe/(.+?)/")
|
||||
_stream_info_url = "http://dinamics.ccma.cat/pvideo/media.jsp?media=video&version=0s&idint={ident}&profile=pc&desplacament=0"
|
||||
_stream_info_url = "http://dinamics.ccma.cat/pvideo/media.jsp" \
|
||||
"?media=video&version=0s&idint={ident}&profile=pc&desplacament=0"
|
||||
_media_schema = validate.Schema({
|
||||
"geo": validate.text,
|
||||
"url": validate.url(scheme=validate.any("http", "https"))
|
||||
|
|
|
@ -74,7 +74,11 @@ class WWENetwork(Plugin):
|
|||
data = self.session.http.json(res)
|
||||
|
||||
if "status" in data and data["status"] != 200:
|
||||
log.debug("API request failed: {0}:{1} ({2})".format(data["status"], data.get("code"), "; ".join(data.get("messages", []))))
|
||||
log.debug("API request failed: {0}:{1} ({2})".format(
|
||||
data["status"],
|
||||
data.get("code"),
|
||||
"; ".join(data.get("messages", []))
|
||||
))
|
||||
return data
|
||||
|
||||
def login(self, email, password):
|
||||
|
@ -151,7 +155,11 @@ class WWENetwork(Plugin):
|
|||
self.logger.debug("Found content ID: {0}", content_id)
|
||||
info = self._get_media_info(content_id)
|
||||
if info.get("hlsUrl"):
|
||||
for s in HLSStream.parse_variant_playlist(self.session, info["hlsUrl"], start_offset=start_point).items():
|
||||
for s in HLSStream.parse_variant_playlist(
|
||||
self.session,
|
||||
info["hlsUrl"],
|
||||
start_offset=start_point
|
||||
).items():
|
||||
yield s
|
||||
else:
|
||||
log.error("Could not find the HLS URL")
|
||||
|
|
|
@ -42,7 +42,11 @@ class YuppTV(Plugin):
|
|||
log.error("Failed to login to YuppTV")
|
||||
raise PluginError("cannot login")
|
||||
|
||||
res = self.session.http.post(self._login_url, data=dict(user=username, password=password, isMobile=0), headers={"Referer": self._signin_url})
|
||||
res = self.session.http.post(
|
||||
self._login_url,
|
||||
data=dict(user=username, password=password, isMobile=0),
|
||||
headers={"Referer": self._signin_url}
|
||||
)
|
||||
data = self.session.http.json(res)
|
||||
resp = data['Response']
|
||||
if resp["tempBoxid"]:
|
||||
|
|
|
@ -137,8 +137,10 @@ class zdf_mediathek(Plugin):
|
|||
res = self.session.http.get(zdf_json['content'], headers=headers)
|
||||
document = self.session.http.json(res, schema=_documents_schema)
|
||||
|
||||
stream_request_url = document["mainVideoContent"]["http://zdf.de/rels/target"]["http://zdf.de/rels/streams/ptmd-template"]
|
||||
stream_request_url = url_concat(API_URL, stream_request_url.format(playerId="ngplayer_2_3").replace(" ", ""))
|
||||
content = document["mainVideoContent"]
|
||||
target = content["http://zdf.de/rels/target"]
|
||||
template = target["http://zdf.de/rels/streams/ptmd-template"]
|
||||
stream_request_url = url_concat(API_URL, template.format(playerId="ngplayer_2_3").replace(" ", ""))
|
||||
|
||||
res = self.session.http.get(stream_request_url, headers=headers)
|
||||
res = self.session.http.json(res, schema=_schema)
|
||||
|
|
|
@ -223,7 +223,10 @@ class DASHStream(Stream):
|
|||
# filter by the first language that appears
|
||||
lang = audio[0] and audio[0].lang
|
||||
|
||||
log.debug("Available languages for DASH audio streams: {0} (using: {1})".format(", ".join(available_languages) or "NONE", lang or "n/a"))
|
||||
log.debug("Available languages for DASH audio streams: {0} (using: {1})".format(
|
||||
", ".join(available_languages) or "NONE",
|
||||
lang or "n/a"
|
||||
))
|
||||
|
||||
# if the language is given by the stream, filter out other languages that do not match
|
||||
if len(available_languages) > 1:
|
||||
|
|
|
@ -81,7 +81,9 @@ class StreamProcess(Stream):
|
|||
|
||||
return StreamProcessIO(self.session, process, process.stdout, timeout=self.timeout)
|
||||
else:
|
||||
raise StreamError("{0} is not installed or not supported on your system".format(os.path.basename(self.cmd)))
|
||||
raise StreamError(
|
||||
"{0} is not installed or not supported on your system".format(os.path.basename(self.cmd))
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def bake(cls, cmd, parameters=None, arguments=None, short_option_prefix="-", long_option_prefix="--"):
|
||||
|
@ -111,7 +113,8 @@ class StreamProcess(Stream):
|
|||
|
||||
return cmdline
|
||||
|
||||
def spawn(self, parameters=None, arguments=None, stderr=None, timeout=None, short_option_prefix="-", long_option_prefix="--"):
|
||||
def spawn(self, parameters=None, arguments=None, stderr=None, timeout=None,
|
||||
short_option_prefix="-", long_option_prefix="--"):
|
||||
"""
|
||||
Spawn the process defined in `cmd`
|
||||
|
||||
|
|
|
@ -51,7 +51,11 @@ def hours_minutes_seconds(value):
|
|||
def seconds_to_hhmmss(seconds):
|
||||
hours, seconds = divmod(seconds, 3600)
|
||||
minutes, seconds = divmod(seconds, 60)
|
||||
return "{0:02d}:{1:02d}:{2}".format(int(hours), int(minutes), "{0:02.1f}".format(seconds) if seconds % 1 else "{0:02d}".format(int(seconds)))
|
||||
return "{0:02d}:{1:02d}:{2}".format(
|
||||
int(hours),
|
||||
int(minutes),
|
||||
"{0:02.1f}".format(seconds) if seconds % 1 else "{0:02d}".format(int(seconds))
|
||||
)
|
||||
|
||||
|
||||
__all__ = [
|
||||
|
|
|
@ -10,7 +10,9 @@ DEFAULT_STREAM_METADATA = {
|
|||
"category": u"No Category",
|
||||
"game": u"No Game/Category"
|
||||
}
|
||||
SUPPORTED_PLAYERS = { # these are the players that streamlink knows how to set the window title for with `--title`. key names are used in help text
|
||||
# these are the players that streamlink knows how to set the window title for with `--title`.
|
||||
# key names are used in help text
|
||||
SUPPORTED_PLAYERS = {
|
||||
# name: possible binary names (linux/mac and windows)
|
||||
"vlc": ["vlc", "vlc.exe"],
|
||||
"mpv": ["mpv", "mpv.exe"],
|
||||
|
|
|
@ -340,7 +340,12 @@ def read_stream(stream, output, prebuffer, chunk_size=8192):
|
|||
is_http = isinstance(output, HTTPServer)
|
||||
is_fifo = is_player and output.namedpipe
|
||||
show_progress = isinstance(output, FileOutput) and output.fd is not stdout and sys.stdout.isatty()
|
||||
show_record_progress = hasattr(output, "record") and isinstance(output.record, FileOutput) and output.record.fd is not stdout and sys.stdout.isatty()
|
||||
show_record_progress = (
|
||||
hasattr(output, "record")
|
||||
and isinstance(output.record, FileOutput)
|
||||
and output.record.fd is not stdout
|
||||
and sys.stdout.isatty()
|
||||
)
|
||||
|
||||
stream_iterator = chain(
|
||||
[prebuffer],
|
||||
|
|
|
@ -78,8 +78,8 @@ class FileOutput(Output):
|
|||
class PlayerOutput(Output):
|
||||
PLAYER_TERMINATE_TIMEOUT = 10.0
|
||||
|
||||
def __init__(self, cmd, args=DEFAULT_PLAYER_ARGUMENTS, filename=None, quiet=True, kill=True, call=False, http=None,
|
||||
namedpipe=None, record=None, title=None):
|
||||
def __init__(self, cmd, args=DEFAULT_PLAYER_ARGUMENTS, filename=None, quiet=True, kill=True,
|
||||
call=False, http=None, namedpipe=None, record=None, title=None):
|
||||
super(PlayerOutput, self).__init__()
|
||||
self.cmd = cmd
|
||||
self.args = args
|
||||
|
@ -133,7 +133,8 @@ class PlayerOutput(Output):
|
|||
|
||||
@classmethod
|
||||
def _mpv_title_escape(cls, title_string):
|
||||
# mpv has a "disable property-expansion" token which must be handled in order to accurately represent $$ in title
|
||||
# mpv has a "disable property-expansion" token which must be handled
|
||||
# in order to accurately represent $$ in title
|
||||
if r'\$>' in title_string:
|
||||
processed_title = ""
|
||||
double_dollars = True
|
||||
|
@ -196,7 +197,8 @@ class PlayerOutput(Output):
|
|||
if self.player_name == "potplayer":
|
||||
if filename != "-":
|
||||
# PotPlayer - About - Command Line
|
||||
# You can specify titles for URLs by separating them with a backslash (\) at the end of URLs. ("http://...\title of this url")
|
||||
# You can specify titles for URLs by separating them with a backslash (\) at the end of URLs.
|
||||
# eg. "http://...\title of this url"
|
||||
self.title = self.title.replace('"', '')
|
||||
filename = filename[:-1] + '\\' + self.title + filename[-1]
|
||||
|
||||
|
|
|
@ -1,19 +1,26 @@
|
|||
from streamlink.plugins.adultswim import AdultSwim
|
||||
import unittest
|
||||
|
||||
from streamlink.plugins.adultswim import AdultSwim
|
||||
|
||||
|
||||
class TestPluginAdultSwim(unittest.TestCase):
|
||||
def test_can_handle_url(self):
|
||||
# should match
|
||||
self.assertTrue(AdultSwim.can_handle_url("http://www.adultswim.com/videos/streams/toonami"))
|
||||
self.assertTrue(AdultSwim.can_handle_url("http://www.adultswim.com/videos/streams/"))
|
||||
self.assertTrue(AdultSwim.can_handle_url("http://www.adultswim.com/videos/streams/last-stream-on-the-left"))
|
||||
self.assertTrue(AdultSwim.can_handle_url("http://www.adultswim.com/videos/specials/the-adult-swim-golf-classic-extended/"))
|
||||
self.assertTrue(AdultSwim.can_handle_url("http://www.adultswim.com/videos/streams/toonami-pre-flight/friday-december-30th-2016"))
|
||||
should_match = [
|
||||
"http://www.adultswim.com/videos/streams/toonami",
|
||||
"http://www.adultswim.com/videos/streams/",
|
||||
"http://www.adultswim.com/videos/streams/last-stream-on-the-left",
|
||||
"http://www.adultswim.com/videos/specials/the-adult-swim-golf-classic-extended/",
|
||||
"http://www.adultswim.com/videos/streams/toonami-pre-flight/friday-december-30th-2016"
|
||||
]
|
||||
for url in should_match:
|
||||
self.assertTrue(AdultSwim.can_handle_url(url))
|
||||
|
||||
# shouldn't match
|
||||
self.assertFalse(AdultSwim.can_handle_url("http://www.tvcatchup.com/"))
|
||||
self.assertFalse(AdultSwim.can_handle_url("http://www.youtube.com/"))
|
||||
should_not_match = [
|
||||
"http://www.tvcatchup.com/",
|
||||
"http://www.youtube.com/"
|
||||
]
|
||||
for url in should_not_match:
|
||||
self.assertFalse(AdultSwim.can_handle_url(url))
|
||||
|
||||
def _test_regex(self, url, expected):
|
||||
m = AdultSwim.url_re.match(url)
|
||||
|
|
|
@ -26,4 +26,5 @@ class TestPluginAlbavision:
|
|||
assert not Albavision.can_handle_url(url), "url should not be handled"
|
||||
|
||||
def test_transform(self):
|
||||
assert Albavision.transform_token(u'6b425761cc8a86569b1a05a9bf1870c95fca717dOK', 436171) == "6b425761cc8a86569b1a05a9bf1870c95fca717d"
|
||||
token = Albavision.transform_token(u'6b425761cc8a86569b1a05a9bf1870c95fca717dOK', 436171)
|
||||
assert token == "6b425761cc8a86569b1a05a9bf1870c95fca717d"
|
||||
|
|
|
@ -5,21 +5,28 @@ from streamlink.plugins.bfmtv import BFMTV
|
|||
|
||||
class TestPluginBFMTV(unittest.TestCase):
|
||||
def test_can_handle_url(self):
|
||||
# should match
|
||||
self.assertTrue(BFMTV.can_handle_url("https://www.bfmtv.com/mediaplayer/live-video/"))
|
||||
self.assertTrue(BFMTV.can_handle_url("https://bfmbusiness.bfmtv.com/mediaplayer/live-video/"))
|
||||
self.assertTrue(BFMTV.can_handle_url("https://www.bfmtv.com/mediaplayer/live-bfm-paris/"))
|
||||
self.assertTrue(BFMTV.can_handle_url("https://rmc.bfmtv.com/mediaplayer/live-audio/"))
|
||||
self.assertTrue(BFMTV.can_handle_url("https://rmcsport.bfmtv.com/mediaplayer/live-bfm-sport/"))
|
||||
self.assertTrue(BFMTV.can_handle_url("https://rmcdecouverte.bfmtv.com/mediaplayer-direct/"))
|
||||
self.assertTrue(BFMTV.can_handle_url("https://www.bfmtv.com/mediaplayer/replay/premiere-edition/"))
|
||||
self.assertTrue(BFMTV.can_handle_url("https://bfmbusiness.bfmtv.com/mediaplayer/replay/good-morning-business/"))
|
||||
self.assertTrue(BFMTV.can_handle_url("https://rmc.bfmtv.com/mediaplayer/replay/les-grandes-gueules/"))
|
||||
self.assertTrue(BFMTV.can_handle_url("https://rmc.bfmtv.com/mediaplayer/replay/after-foot/"))
|
||||
self.assertTrue(BFMTV.can_handle_url("https://www.01net.com/mediaplayer/replay/jtech/"))
|
||||
self.assertTrue(BFMTV.can_handle_url("https://www.bfmtv.com/politique/macron-et-le-pen-talonnes-par-fillon-et-melenchon-a-l-approche-du-premier-tour-1142070.html"))
|
||||
self.assertTrue(BFMTV.can_handle_url("https://rmcdecouverte.bfmtv.com/mediaplayer-replay/?id=6714&title=TOP%20GEAR%20:PASSION%20VINTAGE"))
|
||||
should_match = [
|
||||
"https://www.bfmtv.com/mediaplayer/live-video/",
|
||||
"https://bfmbusiness.bfmtv.com/mediaplayer/live-video/",
|
||||
"https://www.bfmtv.com/mediaplayer/live-bfm-paris/",
|
||||
"https://rmc.bfmtv.com/mediaplayer/live-audio/",
|
||||
"https://rmcsport.bfmtv.com/mediaplayer/live-bfm-sport/",
|
||||
"https://rmcdecouverte.bfmtv.com/mediaplayer-direct/",
|
||||
"https://www.bfmtv.com/mediaplayer/replay/premiere-edition/",
|
||||
"https://bfmbusiness.bfmtv.com/mediaplayer/replay/good-morning-business/",
|
||||
"https://rmc.bfmtv.com/mediaplayer/replay/les-grandes-gueules/",
|
||||
"https://rmc.bfmtv.com/mediaplayer/replay/after-foot/",
|
||||
"https://www.01net.com/mediaplayer/replay/jtech/",
|
||||
"https://www.bfmtv.com/politique/macron-et-le-pen-talonnes-par-fillon-et-melenchon-a-l-approche"
|
||||
+ "-du-premier-tour-1142070.html",
|
||||
"https://rmcdecouverte.bfmtv.com/mediaplayer-replay/?id=6714&title=TOP%20GEAR%20:PASSION%20VINTAGE"
|
||||
]
|
||||
for url in should_match:
|
||||
self.assertTrue(BFMTV.can_handle_url(url))
|
||||
|
||||
# shouldn't match
|
||||
self.assertFalse(BFMTV.can_handle_url("http://www.tvcatchup.com/"))
|
||||
self.assertFalse(BFMTV.can_handle_url("http://www.youtube.com/"))
|
||||
should_not_match = [
|
||||
"http://www.tvcatchup.com/",
|
||||
"http://www.youtube.com/"
|
||||
]
|
||||
for url in should_not_match:
|
||||
self.assertFalse(BFMTV.can_handle_url(url))
|
||||
|
|
|
@ -5,18 +5,25 @@ from streamlink.plugins.bloomberg import Bloomberg
|
|||
|
||||
class TestPluginBloomberg(unittest.TestCase):
|
||||
def test_can_handle_url(self):
|
||||
# should match
|
||||
self.assertTrue(Bloomberg.can_handle_url("https://www.bloomberg.com/live/us"))
|
||||
self.assertTrue(Bloomberg.can_handle_url("https://www.bloomberg.com/live/europe"))
|
||||
self.assertTrue(Bloomberg.can_handle_url("https://www.bloomberg.com/live/asia"))
|
||||
self.assertTrue(Bloomberg.can_handle_url("https://www.bloomberg.com/live/stream"))
|
||||
self.assertTrue(Bloomberg.can_handle_url("https://www.bloomberg.com/live/emea"))
|
||||
self.assertTrue(Bloomberg.can_handle_url("https://www.bloomberg.com/live/asia_stream"))
|
||||
self.assertTrue(Bloomberg.can_handle_url("https://www.bloomberg.com/news/videos/2017-04-17/wozniak-science-fiction-finally-becoming-reality-video"))
|
||||
self.assertTrue(Bloomberg.can_handle_url("http://www.bloomberg.com/news/videos/2017-04-17/russia-s-stake-in-a-u-s-north-korea-conflict-video"))
|
||||
should_match = [
|
||||
"https://www.bloomberg.com/live/us",
|
||||
"https://www.bloomberg.com/live/europe",
|
||||
"https://www.bloomberg.com/live/asia",
|
||||
"https://www.bloomberg.com/live/stream",
|
||||
"https://www.bloomberg.com/live/emea",
|
||||
"https://www.bloomberg.com/live/asia_stream",
|
||||
"https://www.bloomberg.com/news/videos/2017-04-17/wozniak-science-fiction-finally-becoming-reality-video",
|
||||
"http://www.bloomberg.com/news/videos/2017-04-17/russia-s-stake-in-a-u-s-north-korea-conflict-video"
|
||||
]
|
||||
for url in should_match:
|
||||
self.assertTrue(Bloomberg.can_handle_url(url))
|
||||
|
||||
# shouldn't match
|
||||
self.assertFalse(Bloomberg.can_handle_url("https://www.bloomberg.com/live/"))
|
||||
self.assertFalse(Bloomberg.can_handle_url("https://www.bloomberg.com/politics/articles/2017-04-17/french-race-up-for-grabs-days-before-voters-cast-first-ballots"))
|
||||
self.assertFalse(Bloomberg.can_handle_url("http://www.tvcatchup.com/"))
|
||||
self.assertFalse(Bloomberg.can_handle_url("http://www.youtube.com/"))
|
||||
should_not_match = [
|
||||
"https://www.bloomberg.com/live/",
|
||||
"https://www.bloomberg.com/politics/articles/2017-04-17/french-race-up-for-grabs-days-before-voters-cast"
|
||||
+ "-first-ballots",
|
||||
"http://www.tvcatchup.com/",
|
||||
"http://www.youtube.com/"
|
||||
]
|
||||
for url in should_not_match:
|
||||
self.assertFalse(Bloomberg.can_handle_url(url))
|
||||
|
|
|
@ -5,20 +5,27 @@ from streamlink.plugins.canalplus import CanalPlus
|
|||
|
||||
class TestPluginCanalPlus(unittest.TestCase):
|
||||
def test_can_handle_url(self):
|
||||
# should match
|
||||
self.assertTrue(CanalPlus.can_handle_url("https://www.mycanal.fr/docus-infos/l-info-du-vrai-du-13-12-politique-les-affaires-reprennent/p/1473830"))
|
||||
self.assertTrue(CanalPlus.can_handle_url("https://www.mycanal.fr/sport/infosport-laurey-et-claudia/p/1473752"))
|
||||
self.assertTrue(CanalPlus.can_handle_url("https://www.mycanal.fr/docus-infos/ses-debuts-a-madrid-extrait-le-k-benzema/p/1469050"))
|
||||
self.assertTrue(CanalPlus.can_handle_url("https://www.mycanal.fr/d8-docs-mags/au-revoir-johnny-hallyday-le-doc/p/1473054"))
|
||||
# shouldn't match
|
||||
self.assertFalse(CanalPlus.can_handle_url("http://www.cnews.fr/direct"))
|
||||
self.assertFalse(CanalPlus.can_handle_url("http://www.cnews.fr/politique/video/des-electeurs-toujours-autant-indecis-174769"))
|
||||
self.assertFalse(CanalPlus.can_handle_url("http://www.cnews.fr/magazines/plus-de-recul/de-recul-du-14042017-174594"))
|
||||
self.assertFalse(CanalPlus.can_handle_url("http://www.canalplus.fr/"))
|
||||
self.assertFalse(CanalPlus.can_handle_url("http://www.c8.fr/"))
|
||||
self.assertFalse(CanalPlus.can_handle_url("http://replay.c8.fr/"))
|
||||
self.assertFalse(CanalPlus.can_handle_url("http://www.cstar.fr/"))
|
||||
self.assertFalse(CanalPlus.can_handle_url("http://replay.cstar.fr/"))
|
||||
self.assertFalse(CanalPlus.can_handle_url("http://www.cnews.fr/"))
|
||||
self.assertFalse(CanalPlus.can_handle_url("http://www.tvcatchup.com/"))
|
||||
self.assertFalse(CanalPlus.can_handle_url("http://www.youtube.com/"))
|
||||
should_match = [
|
||||
"https://www.mycanal.fr/docus-infos/l-info-du-vrai-du-13-12-politique-les-affaires-reprennent/p/1473830",
|
||||
"https://www.mycanal.fr/sport/infosport-laurey-et-claudia/p/1473752",
|
||||
"https://www.mycanal.fr/docus-infos/ses-debuts-a-madrid-extrait-le-k-benzema/p/1469050",
|
||||
"https://www.mycanal.fr/d8-docs-mags/au-revoir-johnny-hallyday-le-doc/p/1473054"
|
||||
]
|
||||
for url in should_match:
|
||||
self.assertTrue(CanalPlus.can_handle_url(url))
|
||||
|
||||
should_not_match = [
|
||||
"http://www.cnews.fr/direct",
|
||||
"http://www.cnews.fr/politique/video/des-electeurs-toujours-autant-indecis-174769",
|
||||
"http://www.cnews.fr/magazines/plus-de-recul/de-recul-du-14042017-174594",
|
||||
"http://www.canalplus.fr/",
|
||||
"http://www.c8.fr/",
|
||||
"http://replay.c8.fr/",
|
||||
"http://www.cstar.fr/",
|
||||
"http://replay.cstar.fr/",
|
||||
"http://www.cnews.fr/",
|
||||
"http://www.tvcatchup.com/",
|
||||
"http://www.youtube.com/"
|
||||
]
|
||||
for url in should_not_match:
|
||||
self.assertFalse(CanalPlus.can_handle_url(url))
|
||||
|
|
|
@ -5,12 +5,19 @@ from streamlink.plugins.cnews import CNEWS
|
|||
|
||||
class TestPluginCNEWS(unittest.TestCase):
|
||||
def test_can_handle_url(self):
|
||||
# should match
|
||||
self.assertTrue(CNEWS.can_handle_url("http://www.cnews.fr/le-direct"))
|
||||
self.assertTrue(CNEWS.can_handle_url("http://www.cnews.fr/direct"))
|
||||
self.assertTrue(CNEWS.can_handle_url("http://www.cnews.fr/emission/2018-06-12/meteo-du-12062018-784730"))
|
||||
self.assertTrue(CNEWS.can_handle_url("http://www.cnews.fr/emission/2018-06-12/le-journal-des-faits-divers-du-12062018-784704"))
|
||||
# shouldn't match
|
||||
self.assertFalse(CNEWS.can_handle_url("http://www.cnews.fr/"))
|
||||
self.assertFalse(CNEWS.can_handle_url("http://www.tvcatchup.com/"))
|
||||
self.assertFalse(CNEWS.can_handle_url("http://www.youtube.com/"))
|
||||
should_match = [
|
||||
"http://www.cnews.fr/le-direct",
|
||||
"http://www.cnews.fr/direct",
|
||||
"http://www.cnews.fr/emission/2018-06-12/meteo-du-12062018-784730",
|
||||
"http://www.cnews.fr/emission/2018-06-12/le-journal-des-faits-divers-du-12062018-784704"
|
||||
]
|
||||
for url in should_match:
|
||||
self.assertTrue(CNEWS.can_handle_url(url))
|
||||
|
||||
should_not_match = [
|
||||
"http://www.cnews.fr/",
|
||||
"http://www.tvcatchup.com/",
|
||||
"http://www.youtube.com/"
|
||||
]
|
||||
for url in should_not_match:
|
||||
self.assertFalse(CNEWS.can_handle_url(url))
|
||||
|
|
|
@ -5,17 +5,23 @@ from streamlink.plugins.crunchyroll import Crunchyroll
|
|||
|
||||
class TestPluginCrunchyroll(unittest.TestCase):
|
||||
def test_can_handle_url(self):
|
||||
# should match
|
||||
self.assertTrue(Crunchyroll.can_handle_url("http://www.crunchyroll.com/idol-incidents/episode-1-why-become-a-dietwoman-728233"))
|
||||
self.assertTrue(Crunchyroll.can_handle_url("http://www.crunchyroll.com/ru/idol-incidents/episode-1-why-become-a-dietwoman-728233"))
|
||||
self.assertTrue(Crunchyroll.can_handle_url("http://www.crunchyroll.com/idol-incidents/media-728233"))
|
||||
self.assertTrue(Crunchyroll.can_handle_url("http://www.crunchyroll.com/fr/idol-incidents/media-728233"))
|
||||
self.assertTrue(Crunchyroll.can_handle_url("http://www.crunchyroll.com/media-728233"))
|
||||
self.assertTrue(Crunchyroll.can_handle_url("http://www.crunchyroll.com/de/media-728233"))
|
||||
self.assertTrue(Crunchyroll.can_handle_url("http://www.crunchyroll.fr/media-728233"))
|
||||
self.assertTrue(Crunchyroll.can_handle_url("http://www.crunchyroll.fr/es/media-728233"))
|
||||
should_match = [
|
||||
"http://www.crunchyroll.com/idol-incidents/episode-1-why-become-a-dietwoman-728233",
|
||||
"http://www.crunchyroll.com/ru/idol-incidents/episode-1-why-become-a-dietwoman-728233",
|
||||
"http://www.crunchyroll.com/idol-incidents/media-728233",
|
||||
"http://www.crunchyroll.com/fr/idol-incidents/media-728233",
|
||||
"http://www.crunchyroll.com/media-728233",
|
||||
"http://www.crunchyroll.com/de/media-728233",
|
||||
"http://www.crunchyroll.fr/media-728233",
|
||||
"http://www.crunchyroll.fr/es/media-728233"
|
||||
]
|
||||
for url in should_match:
|
||||
self.assertTrue(Crunchyroll.can_handle_url(url))
|
||||
|
||||
# shouldn't match
|
||||
self.assertFalse(Crunchyroll.can_handle_url("http://www.crunchyroll.com/gintama"))
|
||||
self.assertFalse(Crunchyroll.can_handle_url("http://www.crunchyroll.es/gintama"))
|
||||
self.assertFalse(Crunchyroll.can_handle_url("http://www.youtube.com/"))
|
||||
should_not_match = [
|
||||
"http://www.crunchyroll.com/gintama",
|
||||
"http://www.crunchyroll.es/gintama",
|
||||
"http://www.youtube.com/"
|
||||
]
|
||||
for url in should_not_match:
|
||||
self.assertFalse(Crunchyroll.can_handle_url(url))
|
||||
|
|
|
@ -1,22 +1,27 @@
|
|||
import unittest
|
||||
|
||||
from streamlink import Streamlink
|
||||
from streamlink.plugins.delfi import Delfi
|
||||
|
||||
|
||||
class TestPluginDelfi(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.session = Streamlink()
|
||||
|
||||
def test_can_handle_url(self):
|
||||
# should match
|
||||
self.assertTrue(Delfi.can_handle_url("http://www.delfi.lt/video/sportas/kroatiska-tvarka-kaliningrade-laisvai-liejosi-gerimai-dainos-sokiai-ir-ziezirbos.d?id=78322857"))
|
||||
self.assertTrue(Delfi.can_handle_url("https://www.delfi.lt/video/sportas/zalgiris-atsidure-per-pergale-nuo-lkl-aukso.d?id=78321125"))
|
||||
self.assertTrue(Delfi.can_handle_url("https://www.delfi.lt/video/laidos/nba/warriors-cempioniskomis-tapusios-ketvirtos-finalo-rungtynes.d?id=78246059"))
|
||||
self.assertTrue(Delfi.can_handle_url("http://rahvahaal.delfi.ee/news/videod/video-joviaalne-piduline-kaotab-raekoja-platsil-ilutulestiku-ule-kontrolli-ja-raketid-lendavad-rahva-sekka?id=82681069"))
|
||||
self.assertTrue(Delfi.can_handle_url("http://www.delfi.lv/delfi-tv-ar-jani-domburu/pilnie-raidijumi/delfi-tv-ar-jani-domburu-atbild-veselibas-ministre-anda-caksa-pilna-intervija?id=49515013"))
|
||||
should_match = [
|
||||
"http://www.delfi.lt/video/sportas/kroatiska-tvarka-kaliningrade-laisvai-liejosi-gerimai-dainos"
|
||||
+ "-sokiai-ir-ziezirbos.d?id=78322857",
|
||||
"https://www.delfi.lt/video/sportas/zalgiris-atsidure-per-pergale-nuo-lkl-aukso.d?id=78321125",
|
||||
"https://www.delfi.lt/video/laidos/nba/warriors-cempioniskomis-tapusios-ketvirtos-finalo"
|
||||
+ "-rungtynes.d?id=78246059",
|
||||
"http://rahvahaal.delfi.ee/news/videod/video-joviaalne-piduline-kaotab-raekoja-platsil-ilutulestiku"
|
||||
+ "-ule-kontrolli-ja-raketid-lendavad-rahva-sekka?id=82681069",
|
||||
"http://www.delfi.lv/delfi-tv-ar-jani-domburu/pilnie-raidijumi/delfi-tv-ar-jani-domburu-atbild"
|
||||
+ "-veselibas-ministre-anda-caksa-pilna-intervija?id=49515013"
|
||||
]
|
||||
for url in should_match:
|
||||
self.assertTrue(Delfi.can_handle_url(url))
|
||||
|
||||
def test_can_handle_url_negative(self):
|
||||
# shouldn't match
|
||||
self.assertFalse(Delfi.can_handle_url("http://www.tvcatchup.com/"))
|
||||
self.assertFalse(Delfi.can_handle_url("http://www.youtube.com/"))
|
||||
should_not_match = [
|
||||
"http://www.tvcatchup.com/",
|
||||
"http://www.youtube.com/"
|
||||
]
|
||||
for url in should_not_match:
|
||||
self.assertFalse(Delfi.can_handle_url(url))
|
||||
|
|
|
@ -7,14 +7,20 @@ from streamlink.plugins.deutschewelle import DeutscheWelle
|
|||
|
||||
class TestPluginDeutscheWelle(unittest.TestCase):
|
||||
def test_can_handle_url(self):
|
||||
# should match
|
||||
self.assertTrue(DeutscheWelle.can_handle_url("http://www.dw.com/en/media-center/live-tv/s-100825"))
|
||||
self.assertTrue(DeutscheWelle.can_handle_url("http://www.dw.com/fr/médiathèque/direct-tv/s-100948?channel=5"))
|
||||
self.assertTrue(DeutscheWelle.can_handle_url("http://www.dw.com/de/tim-bendzko-deutsch-pop-darling-auf-tour/av-39101077"))
|
||||
self.assertTrue(DeutscheWelle.can_handle_url("http://www.dw.com/de/trump-sagt-nein-die-welt-schüttelt-den-kopf/av-39096724"))
|
||||
self.assertTrue(DeutscheWelle.can_handle_url("http://www.dw.com/el/ο-τραμπ-θεωρεί-την-ευρώπη-ανταγωνιστή-όχι-εταίρο/av-39103742"))
|
||||
self.assertTrue(DeutscheWelle.can_handle_url("http://www.dw.com/ar/أي-البروتينات-صحية-الحيوانية-أم-النباتية/av-39095317"))
|
||||
should_match = [
|
||||
"http://www.dw.com/en/media-center/live-tv/s-100825",
|
||||
"http://www.dw.com/fr/médiathèque/direct-tv/s-100948?channel=5",
|
||||
"http://www.dw.com/de/tim-bendzko-deutsch-pop-darling-auf-tour/av-39101077",
|
||||
"http://www.dw.com/de/trump-sagt-nein-die-welt-schüttelt-den-kopf/av-39096724",
|
||||
"http://www.dw.com/el/ο-τραμπ-θεωρεί-την-ευρώπη-ανταγωνιστή-όχι-εταίρο/av-39103742",
|
||||
"http://www.dw.com/ar/أي-البروتينات-صحية-الحيوانية-أم-النباتية/av-39095317",
|
||||
]
|
||||
for url in should_match:
|
||||
self.assertTrue(DeutscheWelle.can_handle_url(url))
|
||||
|
||||
# shouldn't match
|
||||
self.assertFalse(DeutscheWelle.can_handle_url("http://www.tvcatchup.com/"))
|
||||
self.assertFalse(DeutscheWelle.can_handle_url("http://www.youtube.com/"))
|
||||
should_not_match = [
|
||||
"http://www.tvcatchup.com/",
|
||||
"http://www.youtube.com/"
|
||||
]
|
||||
for url in should_not_match:
|
||||
self.assertFalse(DeutscheWelle.can_handle_url(url))
|
||||
|
|
|
@ -5,23 +5,29 @@ from streamlink.plugins.euronews import Euronews
|
|||
|
||||
class TestPluginEuronews(unittest.TestCase):
|
||||
def test_can_handle_url(self):
|
||||
# should match
|
||||
self.assertTrue(Euronews.can_handle_url("http://www.euronews.com/live"))
|
||||
self.assertTrue(Euronews.can_handle_url("http://fr.euronews.com/live"))
|
||||
self.assertTrue(Euronews.can_handle_url("http://de.euronews.com/live"))
|
||||
self.assertTrue(Euronews.can_handle_url("http://it.euronews.com/live"))
|
||||
self.assertTrue(Euronews.can_handle_url("http://es.euronews.com/live"))
|
||||
self.assertTrue(Euronews.can_handle_url("http://pt.euronews.com/live"))
|
||||
self.assertTrue(Euronews.can_handle_url("http://ru.euronews.com/live"))
|
||||
self.assertTrue(Euronews.can_handle_url("http://ua.euronews.com/live"))
|
||||
self.assertTrue(Euronews.can_handle_url("http://tr.euronews.com/live"))
|
||||
self.assertTrue(Euronews.can_handle_url("http://gr.euronews.com/live"))
|
||||
self.assertTrue(Euronews.can_handle_url("http://hu.euronews.com/live"))
|
||||
self.assertTrue(Euronews.can_handle_url("http://fa.euronews.com/live"))
|
||||
self.assertTrue(Euronews.can_handle_url("http://arabic.euronews.com/live"))
|
||||
self.assertTrue(Euronews.can_handle_url("http://www.euronews.com/2017/05/10/peugeot-expects-more-opel-losses-this-year"))
|
||||
self.assertTrue(Euronews.can_handle_url("http://fr.euronews.com/2017/05/10/l-ag-de-psa-approuve-le-rachat-d-opel"))
|
||||
should_match = [
|
||||
"http://www.euronews.com/live",
|
||||
"http://fr.euronews.com/live",
|
||||
"http://de.euronews.com/live",
|
||||
"http://it.euronews.com/live",
|
||||
"http://es.euronews.com/live",
|
||||
"http://pt.euronews.com/live",
|
||||
"http://ru.euronews.com/live",
|
||||
"http://ua.euronews.com/live",
|
||||
"http://tr.euronews.com/live",
|
||||
"http://gr.euronews.com/live",
|
||||
"http://hu.euronews.com/live",
|
||||
"http://fa.euronews.com/live",
|
||||
"http://arabic.euronews.com/live",
|
||||
"http://www.euronews.com/2017/05/10/peugeot-expects-more-opel-losses-this-year",
|
||||
"http://fr.euronews.com/2017/05/10/l-ag-de-psa-approuve-le-rachat-d-opel"
|
||||
]
|
||||
for url in should_match:
|
||||
self.assertTrue(Euronews.can_handle_url(url))
|
||||
|
||||
# shouldn't match
|
||||
self.assertFalse(Euronews.can_handle_url("http://www.tvcatchup.com/"))
|
||||
self.assertFalse(Euronews.can_handle_url("http://www.youtube.com/"))
|
||||
should_not_match = [
|
||||
"http://www.tvcatchup.com/",
|
||||
"http://www.youtube.com/"
|
||||
]
|
||||
for url in should_not_match:
|
||||
self.assertFalse(Euronews.can_handle_url(url))
|
||||
|
|
|
@ -5,16 +5,22 @@ from streamlink.plugins.gulli import Gulli
|
|||
|
||||
class TestPluginGulli(unittest.TestCase):
|
||||
def test_can_handle_url(self):
|
||||
# should match
|
||||
self.assertTrue(Gulli.can_handle_url("http://replay.gulli.fr/Direct"))
|
||||
self.assertTrue(Gulli.can_handle_url("http://replay.gulli.fr/dessins-animes/My-Little-Pony-les-amies-c-est-magique/VOD68328764799000"))
|
||||
self.assertTrue(Gulli.can_handle_url("https://replay.gulli.fr/emissions/In-Ze-Boite2/VOD68639028668000"))
|
||||
self.assertTrue(Gulli.can_handle_url("https://replay.gulli.fr/series/Power-Rangers-Dino-Super-Charge/VOD68612908435000"))
|
||||
should_match = [
|
||||
"http://replay.gulli.fr/Direct",
|
||||
"http://replay.gulli.fr/dessins-animes/My-Little-Pony-les-amies-c-est-magique/VOD68328764799000",
|
||||
"https://replay.gulli.fr/emissions/In-Ze-Boite2/VOD68639028668000",
|
||||
"https://replay.gulli.fr/series/Power-Rangers-Dino-Super-Charge/VOD68612908435000"
|
||||
]
|
||||
for url in should_match:
|
||||
self.assertTrue(Gulli.can_handle_url(url))
|
||||
|
||||
# shouldn't match
|
||||
self.assertFalse(Gulli.can_handle_url("http://replay.gulli.fr/"))
|
||||
self.assertFalse(Gulli.can_handle_url("http://replay.gulli.fr/dessins-animes"))
|
||||
self.assertFalse(Gulli.can_handle_url("http://replay.gulli.fr/emissions"))
|
||||
self.assertFalse(Gulli.can_handle_url("http://replay.gulli.fr/series"))
|
||||
self.assertFalse(Gulli.can_handle_url("http://www.tvcatchup.com/"))
|
||||
self.assertFalse(Gulli.can_handle_url("http://www.youtube.com/"))
|
||||
should_not_match = [
|
||||
"http://replay.gulli.fr/",
|
||||
"http://replay.gulli.fr/dessins-animes",
|
||||
"http://replay.gulli.fr/emissions",
|
||||
"http://replay.gulli.fr/series",
|
||||
"http://www.tvcatchup.com/",
|
||||
"http://www.youtube.com/"
|
||||
]
|
||||
for url in should_not_match:
|
||||
self.assertFalse(Gulli.can_handle_url(url))
|
||||
|
|
|
@ -5,12 +5,18 @@ from streamlink.plugins.live_russia_tv import LiveRussia
|
|||
|
||||
class TestPluginLiveRussiaTv(unittest.TestCase):
|
||||
def test_can_handle_url(self):
|
||||
# should match
|
||||
self.assertTrue(LiveRussia.can_handle_url('https://live.russia.tv/channel/1'))
|
||||
self.assertTrue(LiveRussia.can_handle_url('https://live.russia.tv/channel/199'))
|
||||
self.assertTrue(LiveRussia.can_handle_url('https://live.russia.tv/'))
|
||||
self.assertTrue(LiveRussia.can_handle_url('https://live.russia.tv/video/show/brand_id/60473/episode_id/2187772/video_id/2204594'))
|
||||
should_match = [
|
||||
"https://live.russia.tv/channel/1",
|
||||
"https://live.russia.tv/channel/199",
|
||||
"https://live.russia.tv/",
|
||||
"https://live.russia.tv/video/show/brand_id/60473/episode_id/2187772/video_id/2204594"
|
||||
]
|
||||
for url in should_match:
|
||||
self.assertTrue(LiveRussia.can_handle_url(url))
|
||||
|
||||
def test_can_handle_url_negative(self):
|
||||
self.assertFalse(LiveRussia.can_handle_url('http://live.france.tv/somethingelse'))
|
||||
self.assertFalse(LiveRussia.can_handle_url('https://youtube.com/watch?v=4567uj'))
|
||||
should_not_match = [
|
||||
"http://live.france.tv/somethingelse",
|
||||
"https://youtube.com/watch?v=4567uj"
|
||||
]
|
||||
for url in should_not_match:
|
||||
self.assertFalse(LiveRussia.can_handle_url(url))
|
||||
|
|
|
@ -5,11 +5,17 @@ from streamlink.plugins.liveme import LiveMe
|
|||
|
||||
class TestPluginLiveMe(unittest.TestCase):
|
||||
def test_can_handle_url(self):
|
||||
# should match
|
||||
self.assertTrue(LiveMe.can_handle_url('http://www.liveme.com/live.html?videoid=12312312312312312312'))
|
||||
self.assertTrue(LiveMe.can_handle_url('http://www.liveme.com/live.html?videoid=23123123123123123123&countryCode=undefined'))
|
||||
should_match = [
|
||||
"http://www.liveme.com/live.html?videoid=12312312312312312312",
|
||||
"http://www.liveme.com/live.html?videoid=23123123123123123123&countryCode=undefined"
|
||||
]
|
||||
for url in should_match:
|
||||
self.assertTrue(LiveMe.can_handle_url(url))
|
||||
|
||||
# shouldn't match
|
||||
self.assertFalse(LiveMe.can_handle_url('http://www.liveme.com/'))
|
||||
self.assertFalse(LiveMe.can_handle_url('http://www.liveme.com/explore.html'))
|
||||
self.assertFalse(LiveMe.can_handle_url('http://www.liveme.com/media/play'))
|
||||
should_not_match = [
|
||||
"http://www.liveme.com/",
|
||||
"http://www.liveme.com/explore.html",
|
||||
"http://www.liveme.com/media/play"
|
||||
]
|
||||
for url in should_not_match:
|
||||
self.assertFalse(LiveMe.can_handle_url(url))
|
||||
|
|
|
@ -24,7 +24,7 @@ class TestPluginMixer(unittest.TestCase):
|
|||
Mjunoon.bind(session, "test")
|
||||
script_text = """
|
||||
<script id="playerScript" src="playerAssets/js/player.js?v=2.2&streamUrl=https://vod.mjunoon.tv:8181/live/41/41.m3u8&streamUrl=https://vod.mjunoon.tv:8181/live/17/17.m3u8"></script>
|
||||
"""
|
||||
""" # noqa: E501
|
||||
parse_variant_playlist.items.return_value = [("test", Mock())]
|
||||
with requests_mock.Mocker() as rmock:
|
||||
rmock.get("https://mjunoon.tv/news-live", text=script_text)
|
||||
|
|
|
@ -5,31 +5,38 @@ from streamlink.plugins.pluzz import Pluzz
|
|||
|
||||
class TestPluginPluzz(unittest.TestCase):
|
||||
def test_can_handle_url(self):
|
||||
# should match
|
||||
self.assertTrue(Pluzz.can_handle_url("https://www.france.tv/france-2/direct.html"))
|
||||
self.assertTrue(Pluzz.can_handle_url("https://www.france.tv/france-3/direct.html"))
|
||||
self.assertTrue(Pluzz.can_handle_url("https://www.france.tv/france-3-franche-comte/direct.html"))
|
||||
self.assertTrue(Pluzz.can_handle_url("https://www.france.tv/france-4/direct.html"))
|
||||
self.assertTrue(Pluzz.can_handle_url("https://www.france.tv/france-5/direct.html"))
|
||||
self.assertTrue(Pluzz.can_handle_url("https://www.france.tv/france-o/direct.html"))
|
||||
self.assertTrue(Pluzz.can_handle_url("https://www.france.tv/franceinfo/direct.html"))
|
||||
self.assertTrue(Pluzz.can_handle_url("https://www.france.tv/france-2/journal-20h00/141003-edition-du-lundi-8-mai-2017.html"))
|
||||
self.assertTrue(Pluzz.can_handle_url("https://www.france.tv/france-o/underground/saison-1/132187-underground.html"))
|
||||
self.assertTrue(Pluzz.can_handle_url("http://www.ludo.fr/heros/the-batman"))
|
||||
self.assertTrue(Pluzz.can_handle_url("http://www.ludo.fr/heros/il-etait-une-fois-la-vie"))
|
||||
self.assertTrue(Pluzz.can_handle_url("http://www.zouzous.fr/heros/oui-oui"))
|
||||
self.assertTrue(Pluzz.can_handle_url("http://www.zouzous.fr/heros/marsupilami-1"))
|
||||
self.assertTrue(Pluzz.can_handle_url("http://france3-regions.francetvinfo.fr/bourgogne-franche-comte/tv/direct/franche-comte"))
|
||||
self.assertTrue(Pluzz.can_handle_url("http://sport.francetvinfo.fr/roland-garros/direct"))
|
||||
self.assertTrue(Pluzz.can_handle_url("http://sport.francetvinfo.fr/roland-garros/live-court-3"))
|
||||
self.assertTrue(Pluzz.can_handle_url("http://sport.francetvinfo.fr/roland-garros/andy-murray-gbr-1-andrey-kuznetsov-rus-1er-tour-court-philippe-chatrier"))
|
||||
self.assertTrue(Pluzz.can_handle_url("https://www.francetvinfo.fr/en-direct/tv.html"))
|
||||
should_match = [
|
||||
"https://www.france.tv/france-2/direct.html",
|
||||
"https://www.france.tv/france-3/direct.html",
|
||||
"https://www.france.tv/france-3-franche-comte/direct.html",
|
||||
"https://www.france.tv/france-4/direct.html",
|
||||
"https://www.france.tv/france-5/direct.html",
|
||||
"https://www.france.tv/france-o/direct.html",
|
||||
"https://www.france.tv/franceinfo/direct.html",
|
||||
"https://www.france.tv/france-2/journal-20h00/141003-edition-du-lundi-8-mai-2017.html",
|
||||
"https://www.france.tv/france-o/underground/saison-1/132187-underground.html",
|
||||
"http://www.ludo.fr/heros/the-batman",
|
||||
"http://www.ludo.fr/heros/il-etait-une-fois-la-vie",
|
||||
"http://www.zouzous.fr/heros/oui-oui",
|
||||
"http://www.zouzous.fr/heros/marsupilami-1",
|
||||
"http://france3-regions.francetvinfo.fr/bourgogne-franche-comte/tv/direct/franche-comte",
|
||||
"http://sport.francetvinfo.fr/roland-garros/direct",
|
||||
"http://sport.francetvinfo.fr/roland-garros/live-court-3",
|
||||
"http://sport.francetvinfo.fr/roland-garros/andy-murray-gbr-1-andrey-kuznetsov-rus-1er-tour-court"
|
||||
+ "-philippe-chatrier",
|
||||
"https://www.francetvinfo.fr/en-direct/tv.html"
|
||||
]
|
||||
for url in should_match:
|
||||
self.assertTrue(Pluzz.can_handle_url(url))
|
||||
|
||||
# shouldn't match
|
||||
self.assertFalse(Pluzz.can_handle_url("http://www.france.tv/"))
|
||||
self.assertFalse(Pluzz.can_handle_url("http://pluzz.francetv.fr/"))
|
||||
self.assertFalse(Pluzz.can_handle_url("http://www.ludo.fr/"))
|
||||
self.assertFalse(Pluzz.can_handle_url("http://www.ludo.fr/jeux"))
|
||||
self.assertFalse(Pluzz.can_handle_url("http://www.zouzous.fr/"))
|
||||
self.assertFalse(Pluzz.can_handle_url("http://www.tvcatchup.com/"))
|
||||
self.assertFalse(Pluzz.can_handle_url("http://www.youtube.com/"))
|
||||
should_not_match = [
|
||||
"http://www.france.tv/",
|
||||
"http://pluzz.francetv.fr/",
|
||||
"http://www.ludo.fr/",
|
||||
"http://www.ludo.fr/jeux",
|
||||
"http://www.zouzous.fr/",
|
||||
"http://www.tvcatchup.com/",
|
||||
"http://www.youtube.com/"
|
||||
]
|
||||
for url in should_not_match:
|
||||
self.assertFalse(Pluzz.can_handle_url(url))
|
||||
|
|
|
@ -5,24 +5,31 @@ from streamlink.plugins.ruv import Ruv
|
|||
|
||||
class TestPluginRuv(unittest.TestCase):
|
||||
def test_can_handle_url(self):
|
||||
# should match
|
||||
self.assertTrue(Ruv.can_handle_url("ruv.is/ruv"))
|
||||
self.assertTrue(Ruv.can_handle_url("http://ruv.is/ruv"))
|
||||
self.assertTrue(Ruv.can_handle_url("http://ruv.is/ruv/"))
|
||||
self.assertTrue(Ruv.can_handle_url("https://ruv.is/ruv/"))
|
||||
self.assertTrue(Ruv.can_handle_url("http://www.ruv.is/ruv"))
|
||||
self.assertTrue(Ruv.can_handle_url("http://www.ruv.is/ruv/"))
|
||||
self.assertTrue(Ruv.can_handle_url("ruv.is/ruv2"))
|
||||
self.assertTrue(Ruv.can_handle_url("ruv.is/ras1"))
|
||||
self.assertTrue(Ruv.can_handle_url("ruv.is/ras2"))
|
||||
self.assertTrue(Ruv.can_handle_url("ruv.is/rondo"))
|
||||
self.assertTrue(Ruv.can_handle_url("http://www.ruv.is/spila/ruv/ol-2018-ishokki-karla/20180217"))
|
||||
self.assertTrue(Ruv.can_handle_url("http://www.ruv.is/spila/ruv/frettir/20180217"))
|
||||
should_match = [
|
||||
"ruv.is/ruv",
|
||||
"http://ruv.is/ruv",
|
||||
"http://ruv.is/ruv/",
|
||||
"https://ruv.is/ruv/",
|
||||
"http://www.ruv.is/ruv",
|
||||
"http://www.ruv.is/ruv/",
|
||||
"ruv.is/ruv2",
|
||||
"ruv.is/ras1",
|
||||
"ruv.is/ras2",
|
||||
"ruv.is/rondo",
|
||||
"http://www.ruv.is/spila/ruv/ol-2018-ishokki-karla/20180217",
|
||||
"http://www.ruv.is/spila/ruv/frettir/20180217"
|
||||
]
|
||||
for url in should_match:
|
||||
self.assertTrue(Ruv.can_handle_url(url))
|
||||
|
||||
# shouldn't match
|
||||
self.assertFalse(Ruv.can_handle_url("rruv.is/ruv"))
|
||||
self.assertFalse(Ruv.can_handle_url("ruv.is/ruvnew"))
|
||||
self.assertFalse(Ruv.can_handle_url("https://www.bloomberg.com/live/"))
|
||||
self.assertFalse(Ruv.can_handle_url("https://www.bloomberg.com/politics/articles/2017-04-17/french-race-up-for-grabs-days-before-voters-cast-first-ballots"))
|
||||
self.assertFalse(Ruv.can_handle_url("http://www.tvcatchup.com/"))
|
||||
self.assertFalse(Ruv.can_handle_url("http://www.youtube.com/"))
|
||||
should_not_match = [
|
||||
"rruv.is/ruv",
|
||||
"ruv.is/ruvnew",
|
||||
"https://www.bloomberg.com/live/",
|
||||
"https://www.bloomberg.com/politics/articles/2017-04-17/french-race-up-for-grabs-days-before-voters"
|
||||
+ "-cast-first-ballots",
|
||||
"http://www.tvcatchup.com/",
|
||||
"http://www.youtube.com/"
|
||||
]
|
||||
for url in should_not_match:
|
||||
self.assertFalse(Ruv.can_handle_url(url))
|
||||
|
|
|
@ -32,7 +32,7 @@ class TestPluginSchoolism(unittest.TestCase):
|
|||
src: "https://s3.amazonaws.com/schoolism-encoded/44/subtitles/2/2-2.vtt",
|
||||
}]
|
||||
}];
|
||||
"""
|
||||
""" # noqa: E501
|
||||
|
||||
data = Schoolism.playlist_schema.validate(with_subs)
|
||||
|
||||
|
@ -44,7 +44,7 @@ class TestPluginSchoolism(unittest.TestCase):
|
|||
{sources:[{type:"application/x-mpegurl",src:"https://d8u31iyce9xic.cloudfront.net/14/1/part1.m3u8?Policy=TOKEN&Signature=TOKEN&Key-Pair-Id=TOKEN",title:"Gesture Drawing - Lesson 1 - Part 1",playlistTitle:"Part 1",}],},
|
||||
{sources:[{type:"application/x-mpegurl",src:"https://d8u31iyce9xic.cloudfront.net/14/1/part2.m3u8?Policy=TOKEN&Signature=TOKEN&Key-Pair-Id=TOKEN",title:"Gesture Drawing - Lesson 1 - Part 2",playlistTitle:"Part 2",}]}
|
||||
];
|
||||
"""
|
||||
""" # noqa: E501
|
||||
|
||||
data = Schoolism.playlist_schema.validate(without_subs)
|
||||
|
||||
|
|
|
@ -5,8 +5,14 @@ import unittest
|
|||
class TestPluginSenateGov(unittest.TestCase):
|
||||
def test_can_handle_url(self):
|
||||
# should match
|
||||
self.assertTrue(SenateGov.can_handle_url("https://www.foreign.senate.gov/hearings/business-meeting-082218"))
|
||||
self.assertTrue(SenateGov.can_handle_url("https://www.senate.gov/isvp/?comm=foreign&type=arch&stt=21:50&filename=foreign082218&auto_play=false&wmode=transparent&poster=https%3A%2F%2Fwww%2Eforeign%2Esenate%2Egov%2Fthemes%2Fforeign%2Fimages%2Fvideo-poster-flash-fit%2Epng"))
|
||||
self.assertTrue(SenateGov.can_handle_url(
|
||||
"https://www.foreign.senate.gov/hearings/business-meeting-082218"
|
||||
))
|
||||
self.assertTrue(SenateGov.can_handle_url(
|
||||
"https://www.senate.gov/isvp/?comm=foreign&type=arch&stt=21:50&filename=foreign082218&auto_play=false"
|
||||
"&wmode=transparent&poster=https%3A%2F%2Fwww%2Eforeign%2Esenate%2Egov%2Fthemes%2Fforeign%2Fimages"
|
||||
"%2Fvideo-poster-flash-fit%2Epng"
|
||||
))
|
||||
|
||||
# shouldn't match
|
||||
self.assertFalse(SenateGov.can_handle_url("http://www.tvcatchup.com/"))
|
||||
|
|
|
@ -6,13 +6,16 @@ from streamlink.plugins.streann import Streann
|
|||
class TestPluginStreann(unittest.TestCase):
|
||||
def test_can_handle_url(self):
|
||||
should_match = [
|
||||
'https://ott.streann.com/streaming/player.html?U2FsdGVkX1/BPZsbal3VWfGa7sWzTIlFtDEU+hyCEHP9MavCxtCfL1G8nXtK5LHSsgFYhG3Nw9UilT1fx3H+lf5R54SLHAU6BKP/n7kjJBDF0HBFblSUHmApiEf5BrU3coECX9RQcRaOY+uLtkeyEktvlrQ5nhg2QRw5x1IjkxFD0Rk5/ylTYxMqnu8snxRe2p09iJLi9E6cG8eXSHZby2We+pyV0obzGDbI2Jpyh4dFL646strLxFraeAJq5+mfpTqK10XZQi3sXA1/ULDH5lz+I9bZW4q/wZtlEdyA0CuB9LpDvCM11imLIhthGnRz',
|
||||
"https://ott.streann.com/streaming/player.html?U2FsdGVkX1/BPZsbal3VWfGa7sWzTIlFtDEU+hyCEHP9Ma"
|
||||
+ "vCxtCfL1G8nXtK5LHSsgFYhG3Nw9UilT1fx3H+lf5R54SLHAU6BKP/n7kjJBDF0HBFblSUHmApiEf5BrU3coECX9RQcR"
|
||||
+ "aOY+uLtkeyEktvlrQ5nhg2QRw5x1IjkxFD0Rk5/ylTYxMqnu8snxRe2p09iJLi9E6cG8eXSHZby2We+pyV0obzGDbI2J"
|
||||
+ "pyh4dFL646strLxFraeAJq5+mfpTqK10XZQi3sXA1/ULDH5lz+I9bZW4q/wZtlEdyA0CuB9LpDvCM11imLIhthGnRz",
|
||||
]
|
||||
for url in should_match:
|
||||
self.assertTrue(Streann.can_handle_url(url))
|
||||
|
||||
should_not_match = [
|
||||
'https://ott.streann.com',
|
||||
"https://ott.streann.com",
|
||||
]
|
||||
for url in should_not_match:
|
||||
self.assertFalse(Streann.can_handle_url(url))
|
||||
|
|
|
@ -5,24 +5,29 @@ from streamlink.plugins.swisstxt import Swisstxt
|
|||
|
||||
class TestPluginSwisstxt(unittest.TestCase):
|
||||
def test_can_handle_url(self):
|
||||
# should match
|
||||
self.assertTrue(Swisstxt.can_handle_url("http://www.srf.ch/sport/resultcenter/tennis?eventId=338052"))
|
||||
self.assertTrue(Swisstxt.can_handle_url("http://live.rsi.ch/tennis.html?eventId=338052"))
|
||||
self.assertTrue(Swisstxt.can_handle_url("http://live.rsi.ch/sport.html?eventId=12345"))
|
||||
should_match = [
|
||||
"http://www.srf.ch/sport/resultcenter/tennis?eventId=338052",
|
||||
"http://live.rsi.ch/tennis.html?eventId=338052",
|
||||
"http://live.rsi.ch/sport.html?eventId=12345"
|
||||
]
|
||||
for url in should_match:
|
||||
self.assertTrue(Swisstxt.can_handle_url(url))
|
||||
|
||||
# shouldn't match
|
||||
# regular srgssr sites
|
||||
self.assertFalse(Swisstxt.can_handle_url("http://srf.ch/play/tv/live"))
|
||||
self.assertFalse(Swisstxt.can_handle_url("http://www.rsi.ch/play/tv/live#?tvLiveId=livestream_La1"))
|
||||
self.assertFalse(Swisstxt.can_handle_url("http://rsi.ch/play/tv/live?tvLiveId=livestream_La1"))
|
||||
self.assertFalse(Swisstxt.can_handle_url("http://www.rtr.ch/play/tv/live"))
|
||||
self.assertFalse(Swisstxt.can_handle_url("http://rtr.ch/play/tv/live"))
|
||||
self.assertFalse(Swisstxt.can_handle_url("http://rts.ch/play/tv/direct#?tvLiveId=3608506"))
|
||||
self.assertFalse(Swisstxt.can_handle_url("http://www.srf.ch/play/tv/live#?tvLiveId=c49c1d64-9f60-0001-1c36-43c288c01a10"))
|
||||
self.assertFalse(Swisstxt.can_handle_url("http://www.rts.ch/sport/direct/8328501-tennis-open-daustralie.html"))
|
||||
self.assertFalse(Swisstxt.can_handle_url("http://www.rts.ch/play/tv/tennis/video/tennis-open-daustralie?id=8328501"))
|
||||
|
||||
# other sites
|
||||
self.assertFalse(Swisstxt.can_handle_url("http://www.crunchyroll.com/gintama"))
|
||||
self.assertFalse(Swisstxt.can_handle_url("http://www.crunchyroll.es/gintama"))
|
||||
self.assertFalse(Swisstxt.can_handle_url("http://www.youtube.com/"))
|
||||
should_not_match = [
|
||||
# regular srgssr sites
|
||||
"http://srf.ch/play/tv/live",
|
||||
"http://www.rsi.ch/play/tv/live#?tvLiveId=livestream_La1",
|
||||
"http://rsi.ch/play/tv/live?tvLiveId=livestream_La1",
|
||||
"http://www.rtr.ch/play/tv/live",
|
||||
"http://rtr.ch/play/tv/live",
|
||||
"http://rts.ch/play/tv/direct#?tvLiveId=3608506",
|
||||
"http://www.srf.ch/play/tv/live#?tvLiveId=c49c1d64-9f60-0001-1c36-43c288c01a10",
|
||||
"http://www.rts.ch/sport/direct/8328501-tennis-open-daustralie.html",
|
||||
"http://www.rts.ch/play/tv/tennis/video/tennis-open-daustralie?id=8328501",
|
||||
# other sites
|
||||
"http://www.crunchyroll.com/gintama",
|
||||
"http://www.crunchyroll.es/gintama",
|
||||
"http://www.youtube.com/"
|
||||
]
|
||||
for url in should_not_match:
|
||||
self.assertFalse(Swisstxt.can_handle_url(url))
|
||||
|
|
|
@ -5,15 +5,22 @@ from streamlink.plugins.tv5monde import TV5Monde
|
|||
|
||||
class TestPluginTV5Monde(unittest.TestCase):
|
||||
def test_can_handle_url(self):
|
||||
# should match
|
||||
self.assertTrue(TV5Monde.can_handle_url("http://live.tv5monde.com/fbs.html"))
|
||||
self.assertTrue(TV5Monde.can_handle_url("http://information.tv5monde.com/les-jt/monde"))
|
||||
self.assertTrue(TV5Monde.can_handle_url("http://information.tv5monde.com/info/legislatives-en-france-carnet-de-campagne-a-montreal-172631"))
|
||||
self.assertTrue(TV5Monde.can_handle_url("http://www.tv5mondeplusafrique.com/video_karim_ben_khelifa_je_ne_suis_pas_votre_negre_oumou_sangare_4658602.html"))
|
||||
self.assertTrue(TV5Monde.can_handle_url("http://www.tv5mondeplus.com/toutes-les-videos/information/tv5monde-le-journal-edition-du-02-06-17-11h00"))
|
||||
self.assertTrue(TV5Monde.can_handle_url("http://focus.tv5monde.com/prevert/le-roi-et-loiseau/"))
|
||||
should_match = [
|
||||
"http://live.tv5monde.com/fbs.html",
|
||||
"http://information.tv5monde.com/les-jt/monde",
|
||||
"http://information.tv5monde.com/info/legislatives-en-france-carnet-de-campagne-a-montreal-172631",
|
||||
"http://www.tv5mondeplusafrique.com/video_karim_ben_khelifa_je_ne_suis_pas_votre_negre_oumou_sangare"
|
||||
+ "_4658602.html",
|
||||
"http://www.tv5mondeplus.com/toutes-les-videos/information/tv5monde-le-journal-edition-du-02-06-17-11h00",
|
||||
"http://focus.tv5monde.com/prevert/le-roi-et-loiseau/"
|
||||
]
|
||||
for url in should_match:
|
||||
self.assertTrue(TV5Monde.can_handle_url(url))
|
||||
|
||||
# shouldn't match
|
||||
self.assertFalse(TV5Monde.can_handle_url("http://www.tv5.ca/"))
|
||||
self.assertFalse(TV5Monde.can_handle_url("http://www.tvcatchup.com/"))
|
||||
self.assertFalse(TV5Monde.can_handle_url("http://www.youtube.com/"))
|
||||
should_not_match = [
|
||||
"http://www.tv5.ca/",
|
||||
"http://www.tvcatchup.com/",
|
||||
"http://www.youtube.com/"
|
||||
]
|
||||
for url in should_not_match:
|
||||
self.assertFalse(TV5Monde.can_handle_url(url))
|
||||
|
|
|
@ -62,7 +62,11 @@ class TestPluginTVPlayer(unittest.TestCase):
|
|||
# test the url is used correctly
|
||||
self.session.http.get.assert_called_with("http://tvplayer.com/watch/dave")
|
||||
# test that the correct API call is made
|
||||
mock_get_stream_data.assert_called_with(resource="bbcone", channel_id="89", token="1324567894561268987948596154656418448489159")
|
||||
mock_get_stream_data.assert_called_with(
|
||||
resource="bbcone",
|
||||
channel_id="89",
|
||||
token="1324567894561268987948596154656418448489159"
|
||||
)
|
||||
# test that the correct URL is used for the HLSStream
|
||||
hlsstream.parse_variant_playlist.assert_called_with(ANY, "http://test.se/stream1")
|
||||
|
||||
|
|
|
@ -11,21 +11,29 @@ class TestPluginUSTVNow(unittest.TestCase):
|
|||
self.assertFalse(USTVNow.can_handle_url("http://www.tvplayer.com"))
|
||||
|
||||
def test_encrypt_data(self):
|
||||
|
||||
key = "80035ad42d7d-bb08-7a14-f726-78403b29"
|
||||
iv = "3157b5680927cc4a"
|
||||
|
||||
self.assertEqual(
|
||||
b"uawIc5n+TnmsmR+aP2iEDKG/eMKji6EKzjI4mE+zMhlyCbHm7K4hz7IDJDWwM3aE+Ro4ydSsgJf4ZInnoW6gqvXvG0qB/J2WJeypTSt4W124zkJpvfoJJmGAvBg2t0HT",
|
||||
USTVNow.encrypt_data(b'{"login_id":"test@test.com","login_key":"testtest1234","login_mode":"1","manufacturer":"123"}', key, iv)
|
||||
b"uawIc5n+TnmsmR+aP2iEDKG/eMKji6EKzjI4mE+zMhlyCbHm7K4hz7IDJDWwM3aE+Ro4ydSsgJf4ZInnoW6gqvXvG0qB"
|
||||
+ b"/J2WJeypTSt4W124zkJpvfoJJmGAvBg2t0HT",
|
||||
USTVNow.encrypt_data(
|
||||
b'{"login_id":"test@test.com","login_key":"testtest1234","login_mode":"1","manufacturer":"123"}',
|
||||
key,
|
||||
iv
|
||||
)
|
||||
)
|
||||
|
||||
def test_decrypt_data(self):
|
||||
|
||||
key = "80035ad42d7d-bb08-7a14-f726-78403b29"
|
||||
iv = "3157b5680927cc4a"
|
||||
|
||||
self.assertEqual(
|
||||
b'{"status":false,"error":{"code":-2,"type":"","message":"Invalid credentials.","details":{}}}',
|
||||
USTVNow.decrypt_data(b"KcRLETVAmHlosM0OyUd5hdTQ6WhBRTe/YRAHiLJWrzf94OLkSueXTtQ9QZ1fjOLCbpX2qteEPUWVnzvvSgVDkQmRUttN/royoxW2aL0gYQSoH1NWoDV8sIgvS5vDiQ85", key, iv)
|
||||
USTVNow.decrypt_data(
|
||||
b"KcRLETVAmHlosM0OyUd5hdTQ6WhBRTe/YRAHiLJWrzf94OLkSueXTtQ9QZ1fjOLCbpX2qteEPUWVnzvvSgVDkQmRUttN"
|
||||
+ b"/royoxW2aL0gYQSoH1NWoDV8sIgvS5vDiQ85",
|
||||
key,
|
||||
iv
|
||||
)
|
||||
)
|
||||
|
|
|
@ -17,7 +17,8 @@ class TestPluginViasat(unittest.TestCase):
|
|||
"https://tv3play.tv3.ee/sisu/inglite-aeg/902432?autostart=true",
|
||||
"https://tvplay.skaties.lv/parraides/darma-un-gregs/902597?autostart=true&collection=719",
|
||||
"https://tvplay.skaties.lv/parraides/kungfu-panda/900510?autostart=true",
|
||||
"https://www.tv3.lt/naujiena/938699/ispudingiausi-kobe-bryanto-karjeros-epizodai-monstriski-dejimai-ir-pergalingi-metimai",
|
||||
"https://www.tv3.lt/naujiena/938699/ispudingiausi-kobe-bryanto-karjeros-epizodai-monstriski-dejimai-ir"
|
||||
+ "-pergalingi-metimai",
|
||||
"https://www.tv6play.no/programmer/underholdning/paradise-hotel-sverige/sesong-8/episode-19",
|
||||
"https://www.tv6play.no/programmer/underholdning/paradise-hotel/sesong-9/822763",
|
||||
"https://www.viafree.dk/",
|
||||
|
|
|
@ -5,16 +5,23 @@ from streamlink.plugins.vrtbe import VRTbe
|
|||
|
||||
class TestPluginVRTbe(unittest.TestCase):
|
||||
def test_can_handle_url(self):
|
||||
# LIVE
|
||||
self.assertTrue(VRTbe.can_handle_url("https://www.vrt.be/vrtnu/kanalen/canvas/"))
|
||||
self.assertTrue(VRTbe.can_handle_url("https://www.vrt.be/vrtnu/kanalen/een/"))
|
||||
self.assertTrue(VRTbe.can_handle_url("https://www.vrt.be/vrtnu/kanalen/ketnet/"))
|
||||
should_match = [
|
||||
# LIVE
|
||||
"https://www.vrt.be/vrtnu/kanalen/canvas/",
|
||||
"https://www.vrt.be/vrtnu/kanalen/een/",
|
||||
"https://www.vrt.be/vrtnu/kanalen/ketnet/",
|
||||
# VOD
|
||||
"https://www.vrt.be/vrtnu/a-z/belfast-zoo/1/belfast-zoo-s1a14/",
|
||||
"https://www.vrt.be/vrtnu/a-z/sporza--korfbal/2017/sporza--korfbal-s2017-sporza-korfbal/",
|
||||
"https://www.vrt.be/vrtnu/a-z/de-grote-peter-van-de-veire-ochtendshow/2017/de-grote-peter-van-de-veire"
|
||||
+ "-ochtendshow-s2017--en-parels-voor-de-zwijnen-ook/"
|
||||
]
|
||||
for url in should_match:
|
||||
self.assertTrue(VRTbe.can_handle_url(url))
|
||||
|
||||
# VOD
|
||||
self.assertTrue(VRTbe.can_handle_url("https://www.vrt.be/vrtnu/a-z/belfast-zoo/1/belfast-zoo-s1a14/"))
|
||||
self.assertTrue(VRTbe.can_handle_url("https://www.vrt.be/vrtnu/a-z/sporza--korfbal/2017/sporza--korfbal-s2017-sporza-korfbal/"))
|
||||
self.assertTrue(VRTbe.can_handle_url("https://www.vrt.be/vrtnu/a-z/de-grote-peter-van-de-veire-ochtendshow/2017/de-grote-peter-van-de-veire-ochtendshow-s2017--en-parels-voor-de-zwijnen-ook/"))
|
||||
|
||||
# shouldn't match
|
||||
self.assertFalse(VRTbe.can_handle_url("https://example.com/"))
|
||||
self.assertFalse(VRTbe.can_handle_url("http://www.local.local/"))
|
||||
should_not_match = [
|
||||
"https://example.com/",
|
||||
"http://www.local.local/"
|
||||
]
|
||||
for url in should_not_match:
|
||||
self.assertFalse(VRTbe.can_handle_url(url))
|
||||
|
|
|
@ -5,42 +5,49 @@ from streamlink.plugins.zattoo import Zattoo
|
|||
|
||||
class TestPluginZattoo(unittest.TestCase):
|
||||
def test_can_handle_url(self):
|
||||
# mirrors
|
||||
self.assertTrue(Zattoo.can_handle_url('https://iptv.glattvision.ch/watch/ard'))
|
||||
self.assertTrue(Zattoo.can_handle_url('https://mobiltv.quickline.com/watch/ard'))
|
||||
self.assertTrue(Zattoo.can_handle_url('https://player.waly.tv/watch/ard'))
|
||||
self.assertTrue(Zattoo.can_handle_url('https://tvplus.m-net.de/watch/ard'))
|
||||
self.assertTrue(Zattoo.can_handle_url('https://www.bbv-tv.net/watch/ard'))
|
||||
self.assertTrue(Zattoo.can_handle_url('https://www.meinewelt.cc/watch/ard'))
|
||||
self.assertTrue(Zattoo.can_handle_url('https://www.myvisiontv.ch/watch/ard'))
|
||||
self.assertTrue(Zattoo.can_handle_url('https://www.netplus.tv/watch/ard'))
|
||||
self.assertTrue(Zattoo.can_handle_url('https://www.quantum-tv.com/watch/ard'))
|
||||
self.assertTrue(Zattoo.can_handle_url('https://www.saktv.ch/watch/ard'))
|
||||
self.assertTrue(Zattoo.can_handle_url('https://www.vtxtv.ch/watch/ard'))
|
||||
self.assertTrue(Zattoo.can_handle_url('http://tvonline.ewe.de/watch/daserste'))
|
||||
self.assertTrue(Zattoo.can_handle_url('http://tvonline.ewe.de/watch/zdf'))
|
||||
self.assertTrue(Zattoo.can_handle_url('https://nettv.netcologne.de/watch/daserste'))
|
||||
self.assertTrue(Zattoo.can_handle_url('https://nettv.netcologne.de/watch/zdf'))
|
||||
self.assertTrue(Zattoo.can_handle_url('https://www.1und1.tv/watch/daserste'))
|
||||
self.assertTrue(Zattoo.can_handle_url('https://www.1und1.tv/watch/zdf'))
|
||||
# zattoo live
|
||||
self.assertTrue(Zattoo.can_handle_url('https://zattoo.com/watch/daserste'))
|
||||
self.assertTrue(Zattoo.can_handle_url('https://zattoo.com/watch/zdf'))
|
||||
self.assertTrue(Zattoo.can_handle_url('https://zattoo.com/live/zdf'))
|
||||
self.assertTrue(Zattoo.can_handle_url('https://zattoo.com/channels?channel=daserste'))
|
||||
self.assertTrue(Zattoo.can_handle_url('https://zattoo.com/channels/favorites?channel=zdf'))
|
||||
self.assertTrue(Zattoo.can_handle_url('https://zattoo.com/channels/zattoo?channel=zdf'))
|
||||
# zattoo vod
|
||||
self.assertTrue(Zattoo.can_handle_url('https://zattoo.com/ondemand/watch/ibR2fpisWFZGvmPBRaKnFnuT-alarm-am-airport'))
|
||||
self.assertTrue(Zattoo.can_handle_url('https://zattoo.com/ondemand/watch/G8S7JxcewY2jEwAgMzvFWK8c-berliner-schnauzen'))
|
||||
self.assertTrue(Zattoo.can_handle_url('https://zattoo.com/ondemand?video=x4hUTiCv4FLAA72qLvahiSFp'))
|
||||
# zattoo recording
|
||||
self.assertTrue(Zattoo.can_handle_url('https://zattoo.com/ondemand/watch/srf_zwei/110223896-die-schweizermacher/52845783/1455130800000/1455137700000/6900000'))
|
||||
self.assertTrue(Zattoo.can_handle_url('https://zattoo.com/watch/tve/130920738-viaje-al-centro-de-la-tele/96847859/1508777100000/1508779800000/0'))
|
||||
self.assertTrue(Zattoo.can_handle_url('https://zattoo.com/recordings?recording=186466965'))
|
||||
should_match = [
|
||||
# mirrors
|
||||
"https://iptv.glattvision.ch/watch/ard",
|
||||
"https://mobiltv.quickline.com/watch/ard",
|
||||
"https://player.waly.tv/watch/ard",
|
||||
"https://tvplus.m-net.de/watch/ard",
|
||||
"https://www.bbv-tv.net/watch/ard",
|
||||
"https://www.meinewelt.cc/watch/ard",
|
||||
"https://www.myvisiontv.ch/watch/ard",
|
||||
"https://www.netplus.tv/watch/ard",
|
||||
"https://www.quantum-tv.com/watch/ard",
|
||||
"https://www.saktv.ch/watch/ard",
|
||||
"https://www.vtxtv.ch/watch/ard",
|
||||
"http://tvonline.ewe.de/watch/daserste",
|
||||
"http://tvonline.ewe.de/watch/zdf",
|
||||
"https://nettv.netcologne.de/watch/daserste",
|
||||
"https://nettv.netcologne.de/watch/zdf",
|
||||
"https://www.1und1.tv/watch/daserste",
|
||||
"https://www.1und1.tv/watch/zdf",
|
||||
# zattoo live
|
||||
"https://zattoo.com/watch/daserste",
|
||||
"https://zattoo.com/watch/zdf",
|
||||
"https://zattoo.com/live/zdf",
|
||||
"https://zattoo.com/channels?channel=daserste",
|
||||
"https://zattoo.com/channels/favorites?channel=zdf",
|
||||
"https://zattoo.com/channels/zattoo?channel=zdf",
|
||||
# zattoo vod
|
||||
"https://zattoo.com/ondemand/watch/ibR2fpisWFZGvmPBRaKnFnuT-alarm-am-airport",
|
||||
"https://zattoo.com/ondemand/watch/G8S7JxcewY2jEwAgMzvFWK8c-berliner-schnauzen",
|
||||
"https://zattoo.com/ondemand?video=x4hUTiCv4FLAA72qLvahiSFp",
|
||||
# zattoo recording
|
||||
"https://zattoo.com/ondemand/watch/srf_zwei/110223896-die-schweizermacher/52845783/1455130800000"
|
||||
+ "/1455137700000/6900000",
|
||||
"https://zattoo.com/watch/tve/130920738-viaje-al-centro-de-la-tele/96847859/1508777100000/1508779800000/0",
|
||||
"https://zattoo.com/recordings?recording=186466965"
|
||||
]
|
||||
for url in should_match:
|
||||
self.assertTrue(Zattoo.can_handle_url(url))
|
||||
|
||||
def test_can_handle_url_negative(self):
|
||||
# shouldn't match
|
||||
self.assertFalse(Zattoo.can_handle_url('https://ewe.de'))
|
||||
self.assertFalse(Zattoo.can_handle_url('https://netcologne.de'))
|
||||
self.assertFalse(Zattoo.can_handle_url('https://zattoo.com'))
|
||||
should_not_match = [
|
||||
"https://ewe.de",
|
||||
"https://netcologne.de",
|
||||
"https://zattoo.com"
|
||||
]
|
||||
for url in should_not_match:
|
||||
self.assertFalse(Zattoo.can_handle_url(url))
|
||||
|
|
|
@ -50,7 +50,8 @@ class TestHLS(unittest.TestCase):
|
|||
|
||||
playlistEnd = ""
|
||||
if aesIv is not None:
|
||||
playlistEnd = playlistEnd + "#EXT-X-KEY:METHOD=AES-128,URI=\"encryption_key.key\",IV=0x{0},KEYFORMAT=identity,KEYFORMATVERSIONS=1\n".format(hexlify(aesIv).decode("UTF-8"))
|
||||
ext_x_key = "#EXT-X-KEY:METHOD=AES-128,URI=\"{uri}\",IV=0x{iv},KEYFORMAT=identity,KEYFORMATVERSIONS=1\n"
|
||||
playlistEnd = playlistEnd + ext_x_key.format(uri="encryption_key.key", iv=hexlify(aesIv).decode("UTF-8"))
|
||||
|
||||
for i in range(4):
|
||||
playlistEnd = playlistEnd + "#EXTINF:1.000,\n{0}\n".format(streamNameTemplate.format(i))
|
||||
|
|
|
@ -7,54 +7,62 @@ from tests.resources import text
|
|||
|
||||
|
||||
class TestHLSPlaylist(unittest.TestCase):
|
||||
|
||||
def test_load(self):
|
||||
with text("hls/test_1.m3u8") as m3u8_fh:
|
||||
playlist = load(m3u8_fh.read(), "http://test.se/")
|
||||
|
||||
self.assertEqual(playlist.media,
|
||||
[Media(uri='http://test.se/audio/stereo/en/128kbit.m3u8', type='AUDIO', group_id='stereo', language='en',
|
||||
name='English', default=True, autoselect=True, forced=False, characteristics=None),
|
||||
Media(uri='http://test.se/audio/stereo/none/128kbit.m3u8', type='AUDIO', group_id='stereo',
|
||||
language='dubbing', name='Dubbing', default=False, autoselect=True, forced=False,
|
||||
characteristics=None),
|
||||
Media(uri='http://test.se/audio/surround/en/320kbit.m3u8', type='AUDIO', group_id='surround', language='en',
|
||||
name='English', default=True, autoselect=True, forced=False, characteristics=None),
|
||||
Media(uri='http://test.se/audio/stereo/none/128kbit.m3u8', type='AUDIO', group_id='surround',
|
||||
language='dubbing', name='Dubbing', default=False, autoselect=True, forced=False,
|
||||
characteristics=None),
|
||||
Media(uri='http://test.se/subtitles_de.m3u8', type='SUBTITLES', group_id='subs', language='de',
|
||||
name='Deutsch', default=False, autoselect=True, forced=False, characteristics=None),
|
||||
Media(uri='http://test.se/subtitles_en.m3u8', type='SUBTITLES', group_id='subs', language='en',
|
||||
name='English', default=True, autoselect=True, forced=False, characteristics=None),
|
||||
Media(uri='http://test.se/subtitles_es.m3u8', type='SUBTITLES', group_id='subs', language='es',
|
||||
name='Espanol', default=False, autoselect=True, forced=False, characteristics=None),
|
||||
Media(uri='http://test.se/subtitles_fr.m3u8', type='SUBTITLES', group_id='subs', language='fr',
|
||||
name='Français', default=False, autoselect=True, forced=False,
|
||||
characteristics=None)])
|
||||
self.assertEqual(
|
||||
playlist.media,
|
||||
[
|
||||
Media(uri='http://test.se/audio/stereo/en/128kbit.m3u8', type='AUDIO', group_id='stereo',
|
||||
language='en', name='English', default=True, autoselect=True, forced=False,
|
||||
characteristics=None),
|
||||
Media(uri='http://test.se/audio/stereo/none/128kbit.m3u8', type='AUDIO', group_id='stereo',
|
||||
language='dubbing', name='Dubbing', default=False, autoselect=True, forced=False,
|
||||
characteristics=None),
|
||||
Media(uri='http://test.se/audio/surround/en/320kbit.m3u8', type='AUDIO', group_id='surround',
|
||||
language='en', name='English', default=True, autoselect=True, forced=False,
|
||||
characteristics=None),
|
||||
Media(uri='http://test.se/audio/stereo/none/128kbit.m3u8', type='AUDIO', group_id='surround',
|
||||
language='dubbing', name='Dubbing', default=False, autoselect=True, forced=False,
|
||||
characteristics=None),
|
||||
Media(uri='http://test.se/subtitles_de.m3u8', type='SUBTITLES', group_id='subs', language='de',
|
||||
name='Deutsch', default=False, autoselect=True, forced=False, characteristics=None),
|
||||
Media(uri='http://test.se/subtitles_en.m3u8', type='SUBTITLES', group_id='subs', language='en',
|
||||
name='English', default=True, autoselect=True, forced=False, characteristics=None),
|
||||
Media(uri='http://test.se/subtitles_es.m3u8', type='SUBTITLES', group_id='subs', language='es',
|
||||
name='Espanol', default=False, autoselect=True, forced=False, characteristics=None),
|
||||
Media(uri='http://test.se/subtitles_fr.m3u8', type='SUBTITLES', group_id='subs', language='fr',
|
||||
name='Français', default=False, autoselect=True, forced=False, characteristics=None)
|
||||
]
|
||||
)
|
||||
|
||||
self.assertEqual([p.stream_info for p in playlist.playlists],
|
||||
[StreamInfo(bandwidth=258157.0, program_id='1', codecs=['avc1.4d400d', 'mp4a.40.2'],
|
||||
resolution=Resolution(width=422, height=180), audio='stereo', video=None,
|
||||
subtitles='subs'),
|
||||
StreamInfo(bandwidth=520929.0, program_id='1', codecs=['avc1.4d4015', 'mp4a.40.2'],
|
||||
resolution=Resolution(width=638, height=272), audio='stereo', video=None,
|
||||
subtitles='subs'),
|
||||
StreamInfo(bandwidth=831270.0, program_id='1', codecs=['avc1.4d4015', 'mp4a.40.2'],
|
||||
resolution=Resolution(width=638, height=272), audio='stereo', video=None,
|
||||
subtitles='subs'),
|
||||
StreamInfo(bandwidth=1144430.0, program_id='1', codecs=['avc1.4d401f', 'mp4a.40.2'],
|
||||
resolution=Resolution(width=958, height=408), audio='surround', video=None,
|
||||
subtitles='subs'),
|
||||
StreamInfo(bandwidth=1558322.0, program_id='1', codecs=['avc1.4d401f', 'mp4a.40.2'],
|
||||
resolution=Resolution(width=1277, height=554), audio='surround', video=None,
|
||||
subtitles='subs'),
|
||||
StreamInfo(bandwidth=4149264.0, program_id='1', codecs=['avc1.4d4028', 'mp4a.40.2'],
|
||||
resolution=Resolution(width=1921, height=818), audio='surround', video=None,
|
||||
subtitles='subs'),
|
||||
StreamInfo(bandwidth=6214307.0, program_id='1', codecs=['avc1.4d4028', 'mp4a.40.2'],
|
||||
resolution=Resolution(width=1921, height=818), audio='surround', video=None,
|
||||
subtitles='subs'),
|
||||
StreamInfo(bandwidth=10285391.0, program_id='1', codecs=['avc1.4d4033', 'mp4a.40.2'],
|
||||
resolution=Resolution(width=4096, height=1744), audio='surround', video=None,
|
||||
subtitles='subs')])
|
||||
self.assertEqual(
|
||||
[p.stream_info for p in playlist.playlists],
|
||||
[
|
||||
StreamInfo(bandwidth=258157.0, program_id='1', codecs=['avc1.4d400d', 'mp4a.40.2'],
|
||||
resolution=Resolution(width=422, height=180), audio='stereo', video=None,
|
||||
subtitles='subs'),
|
||||
StreamInfo(bandwidth=520929.0, program_id='1', codecs=['avc1.4d4015', 'mp4a.40.2'],
|
||||
resolution=Resolution(width=638, height=272), audio='stereo', video=None,
|
||||
subtitles='subs'),
|
||||
StreamInfo(bandwidth=831270.0, program_id='1', codecs=['avc1.4d4015', 'mp4a.40.2'],
|
||||
resolution=Resolution(width=638, height=272), audio='stereo', video=None,
|
||||
subtitles='subs'),
|
||||
StreamInfo(bandwidth=1144430.0, program_id='1', codecs=['avc1.4d401f', 'mp4a.40.2'],
|
||||
resolution=Resolution(width=958, height=408), audio='surround', video=None,
|
||||
subtitles='subs'),
|
||||
StreamInfo(bandwidth=1558322.0, program_id='1', codecs=['avc1.4d401f', 'mp4a.40.2'],
|
||||
resolution=Resolution(width=1277, height=554), audio='surround', video=None,
|
||||
subtitles='subs'),
|
||||
StreamInfo(bandwidth=4149264.0, program_id='1', codecs=['avc1.4d4028', 'mp4a.40.2'],
|
||||
resolution=Resolution(width=1921, height=818), audio='surround', video=None,
|
||||
subtitles='subs'),
|
||||
StreamInfo(bandwidth=6214307.0, program_id='1', codecs=['avc1.4d4028', 'mp4a.40.2'],
|
||||
resolution=Resolution(width=1921, height=818), audio='surround', video=None,
|
||||
subtitles='subs'),
|
||||
StreamInfo(bandwidth=10285391.0, program_id='1', codecs=['avc1.4d4033', 'mp4a.40.2'],
|
||||
resolution=Resolution(width=4096, height=1744), audio='surround', video=None,
|
||||
subtitles='subs')
|
||||
]
|
||||
)
|
||||
|
|
|
@ -26,7 +26,8 @@ class CommandLineTestCase(unittest.TestCase):
|
|||
@patch('streamlink_cli.output.sleep')
|
||||
@patch('subprocess.Popen')
|
||||
@patch('sys.argv')
|
||||
def _test_args(self, args, commandline, mock_argv, mock_popen, mock_sleep, mock_setup_streamlink, passthrough=False, exit_code=0):
|
||||
def _test_args(self, args, commandline, mock_argv, mock_popen, mock_sleep, mock_setup_streamlink,
|
||||
passthrough=False, exit_code=0):
|
||||
mock_argv.__getitem__.side_effect = lambda x: args[x]
|
||||
|
||||
def side_effect(results):
|
||||
|
|
|
@ -32,50 +32,77 @@ class TestCommandLineWithTitlePOSIX(CommandLineTestCase):
|
|||
@unittest.skipIf(not is_win32, "test only applicable on Windows")
|
||||
class TestCommandLineWithTitleWindows(CommandLineTestCase):
|
||||
def test_open_player_with_title_vlc(self):
|
||||
self._test_args(["streamlink", "-p", "c:\\Program Files\\VideoLAN\\vlc.exe", "--title", "{title}", "http://test.se", "test"],
|
||||
"c:\\Program Files\\VideoLAN\\vlc.exe --input-title-format \"Test Title\" -")
|
||||
self._test_args(
|
||||
["streamlink", "-p", "c:\\Program Files\\VideoLAN\\vlc.exe",
|
||||
"--title", "{title}", "http://test.se", "test"],
|
||||
"c:\\Program Files\\VideoLAN\\vlc.exe --input-title-format \"Test Title\" -"
|
||||
)
|
||||
|
||||
@unittest.skipIf(is_py3, "Encoding is different in Python 2")
|
||||
def test_open_player_with_unicode_author_vlc_py2(self):
|
||||
self._test_args(["streamlink", "-p", "c:\\Program Files\\VideoLAN\\vlc.exe", "--title", "{author}", "http://test.se", "test"],
|
||||
"c:\\Program Files\\VideoLAN\\vlc.exe --input-title-format \"" + u"Tѥst Āuƭhǿr".encode(get_filesystem_encoding()) + "\" -")
|
||||
self._test_args(
|
||||
["streamlink", "-p", "c:\\Program Files\\VideoLAN\\vlc.exe",
|
||||
"--title", "{author}", "http://test.se", "test"],
|
||||
"c:\\Program Files\\VideoLAN\\vlc.exe --input-title-format \""
|
||||
+ u"Tѥst Āuƭhǿr".encode(get_filesystem_encoding())
|
||||
+ "\" -"
|
||||
)
|
||||
|
||||
@unittest.skipIf(not is_py3, "Encoding is different in Python 2")
|
||||
def test_open_player_with_unicode_author_vlc_py3(self):
|
||||
self._test_args(["streamlink", "-p", "c:\\Program Files\\VideoLAN\\vlc.exe", "--title", "{author}", "http://test.se", "test"],
|
||||
u"c:\\Program Files\\VideoLAN\\vlc.exe --input-title-format \"Tѥst Āuƭhǿr\" -")
|
||||
self._test_args(
|
||||
["streamlink", "-p", "c:\\Program Files\\VideoLAN\\vlc.exe",
|
||||
"--title", "{author}", "http://test.se", "test"],
|
||||
u"c:\\Program Files\\VideoLAN\\vlc.exe --input-title-format \"Tѥst Āuƭhǿr\" -"
|
||||
)
|
||||
|
||||
def test_open_player_with_default_title_vlc(self):
|
||||
self._test_args(["streamlink", "-p", "c:\\Program Files\\VideoLAN\\vlc.exe", "http://test.se", "test"],
|
||||
"c:\\Program Files\\VideoLAN\\vlc.exe --input-title-format http://test.se -")
|
||||
self._test_args(
|
||||
["streamlink", "-p", "c:\\Program Files\\VideoLAN\\vlc.exe", "http://test.se", "test"],
|
||||
"c:\\Program Files\\VideoLAN\\vlc.exe --input-title-format http://test.se -"
|
||||
)
|
||||
|
||||
def test_open_player_with_default_arg_vlc(self):
|
||||
self._test_args(["streamlink", "-p", "c:\\Program Files\\VideoLAN\\vlc.exe --argh", "http://test.se", "test"],
|
||||
"c:\\Program Files\\VideoLAN\\vlc.exe --argh --input-title-format http://test.se -")
|
||||
self._test_args(
|
||||
["streamlink", "-p", "c:\\Program Files\\VideoLAN\\vlc.exe --argh", "http://test.se", "test"],
|
||||
"c:\\Program Files\\VideoLAN\\vlc.exe --argh --input-title-format http://test.se -"
|
||||
)
|
||||
|
||||
# PotPlayer
|
||||
def test_open_player_with_title_pot(self):
|
||||
self._test_args(["streamlink", "-p", "\"c:\\Program Files\\DAUM\\PotPlayer\\PotPlayerMini64.exe\"",
|
||||
"--title", "{title}", "http://test.se/stream", "hls", "--player-passthrough", "hls"],
|
||||
"\"c:\\Program Files\\DAUM\\PotPlayer\\PotPlayerMini64.exe\" \"http://test.se/playlist.m3u8\\Test Title\"",
|
||||
passthrough=True)
|
||||
self._test_args(
|
||||
["streamlink", "-p", "\"c:\\Program Files\\DAUM\\PotPlayer\\PotPlayerMini64.exe\"",
|
||||
"--title", "{title}", "http://test.se/stream", "hls", "--player-passthrough", "hls"],
|
||||
"\"c:\\Program Files\\DAUM\\PotPlayer\\PotPlayerMini64.exe\" \"http://test.se/playlist.m3u8\\Test Title\"",
|
||||
passthrough=True
|
||||
)
|
||||
|
||||
@unittest.skipIf(is_py3, "Encoding is different in Python 2")
|
||||
def test_open_player_with_unicode_author_pot_py2(self):
|
||||
self._test_args(["streamlink", "-p", "\"c:\\Program Files\\DAUM\\PotPlayer\\PotPlayerMini64.exe\"",
|
||||
"--title", "{author}", "http://test.se/stream", "hls", "--player-passthrough", "hls"],
|
||||
"\"c:\\Program Files\\DAUM\\PotPlayer\\PotPlayerMini64.exe\" \"http://test.se/playlist.m3u8\\" + u"Tѥst Āuƭhǿr".encode(get_filesystem_encoding()) + "\"",
|
||||
passthrough=True)
|
||||
self._test_args(
|
||||
["streamlink", "-p", "\"c:\\Program Files\\DAUM\\PotPlayer\\PotPlayerMini64.exe\"",
|
||||
"--title", "{author}", "http://test.se/stream", "hls", "--player-passthrough", "hls"],
|
||||
"\"c:\\Program Files\\DAUM\\PotPlayer\\PotPlayerMini64.exe\" \"http://test.se/playlist.m3u8\\"
|
||||
+ u"Tѥst Āuƭhǿr".encode(get_filesystem_encoding())
|
||||
+ "\"",
|
||||
passthrough=True
|
||||
)
|
||||
|
||||
@unittest.skipIf(not is_py3, "Encoding is different in Python 2")
|
||||
def test_open_player_with_unicode_author_pot_py3(self):
|
||||
self._test_args(["streamlink", "-p", "\"c:\\Program Files\\DAUM\\PotPlayer\\PotPlayerMini64.exe\"",
|
||||
"--title", "{author}", "http://test.se/stream", "hls", "--player-passthrough", "hls"],
|
||||
u"\"c:\\Program Files\\DAUM\\PotPlayer\\PotPlayerMini64.exe\" \"http://test.se/playlist.m3u8\\Tѥst Āuƭhǿr\"",
|
||||
passthrough=True)
|
||||
self._test_args(
|
||||
["streamlink", "-p", "\"c:\\Program Files\\DAUM\\PotPlayer\\PotPlayerMini64.exe\"",
|
||||
"--title", "{author}", "http://test.se/stream", "hls", "--player-passthrough", "hls"],
|
||||
u"\"c:\\Program Files\\DAUM\\PotPlayer\\PotPlayerMini64.exe\" "
|
||||
+ u"\"http://test.se/playlist.m3u8\\Tѥst Āuƭhǿr\"",
|
||||
passthrough=True
|
||||
)
|
||||
|
||||
def test_open_player_with_default_title_pot(self):
|
||||
self._test_args(["streamlink", "-p", "\"c:\\Program Files\\DAUM\\PotPlayer\\PotPlayerMini64.exe\"",
|
||||
"http://test.se/stream", "hls", "--player-passthrough", "hls"],
|
||||
"\"c:\\Program Files\\DAUM\\PotPlayer\\PotPlayerMini64.exe\" \"http://test.se/playlist.m3u8\\http://test.se/stream\"",
|
||||
passthrough=True)
|
||||
self._test_args(
|
||||
["streamlink", "-p", "\"c:\\Program Files\\DAUM\\PotPlayer\\PotPlayerMini64.exe\"",
|
||||
"http://test.se/stream", "hls", "--player-passthrough", "hls"],
|
||||
"\"c:\\Program Files\\DAUM\\PotPlayer\\PotPlayerMini64.exe\" "
|
||||
+ "\"http://test.se/playlist.m3u8\\http://test.se/stream\"",
|
||||
passthrough=True
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue