Пример #1
0
class Garena(Plugin):
    API_INFO = "https://garena.live/api/channel_info_get"
    API_STREAM = "https://garena.live/api/channel_stream_get"

    _info_schema = validate.Schema({
        "reply":
        validate.any({
            "channel_id": int,
        }, None),
        "result":
        validate.text
    })
    _stream_schema = validate.Schema({
        "reply":
        validate.any(
            {
                "streams": [{
                    "url": validate.text,
                    "resolution": int,
                    "bitrate": int,
                    "format": int
                }]
            }, None),
        "result":
        validate.text
    })

    @classmethod
    def can_handle_url(self, url):
        return _url_re.match(url)

    def _post_api(self, api, payload, schema):
        res = http.post(api, json=payload)
        data = http.json(res, schema=schema)

        if data["result"] == "success":
            post_data = data["reply"]
            return post_data

    def _get_streams(self):
        match = _url_re.match(self.url)
        if match.group("alias"):
            payload = {"alias": match.group("alias")}
            info_data = self._post_api(self.API_INFO, payload,
                                       self._info_schema)
            channel_id = info_data["channel_id"]
        elif match.group("channel_id"):
            channel_id = int(match.group("channel_id"))

        if channel_id:
            payload = {"channel_id": channel_id}
            stream_data = self._post_api(self.API_STREAM, payload,
                                         self._stream_schema)
            for stream in stream_data["streams"]:
                n = "{0}p".format(stream["resolution"])
                if stream["format"] == 3:
                    s = HLSStream(self.session, stream["url"])
                    yield n, s
Пример #2
0
class LiveMe(Plugin):
    url_re = re.compile(r"https?://(www.)?liveme\.com/live\.html\?videoid=(\d+)")
    api_url = "https://live.ksmobile.net/live/queryinfo"
    api_schema = validate.Schema(validate.all({
        "status": "200",
        "data": {
            "video_info": {
                "videosource": validate.any('', validate.url()),
                "hlsvideosource": validate.any('', validate.url()),
            }
        }
    }, validate.get("data")))

    @classmethod
    def can_handle_url(cls, url):
        return cls.url_re.match(url) is not None

    def _random_t(self, t):
        return "".join(random.choice("ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678") for _ in range(t))

    def _make_stream(self, url):
        if url and url.endswith("flv"):
            return HTTPStream(self.session, url)
        elif url and url.endswith("m3u8"):
            return HLSStream(self.session, url)

    def _get_streams(self):
        url_params = dict(parse_qsl(urlparse(self.url).query))
        video_id = url_params.get("videoid")

        if video_id:
            vali = '{0}l{1}m{2}'.format(self._random_t(4), self._random_t(4), self._random_t(5))
            data = {
                'userid': 1,
                'videoid': video_id,
                'area': '',
                'h5': 1,
                'vali': vali
            }
            self.logger.debug("Found Video ID: {0}".format(video_id))
            res = http.post(self.api_url, data=data)
            data = http.json(res, schema=self.api_schema)
            hls = self._make_stream(data["video_info"]["hlsvideosource"])
            video = self._make_stream(data["video_info"]["videosource"])
            if hls:
                yield "live", hls
            if video:
                yield "live", video
Пример #3
0
class Streamable(Plugin):
    url_re = re.compile(r"https?://(?:www\.)?streamable\.com/(.+)")
    meta_re = re.compile(r'''var\s*videoObject\s*=\s*({.*});''')
    config_schema = validate.Schema(
        validate.transform(meta_re.search),
        validate.any(
            None,
            validate.all(
                validate.get(1), validate.transform(parse_json), {
                    "files": {
                        validate.text: {
                            "url": validate.url(),
                            "width": int,
                            "height": int,
                            "bitrate": int
                        }
                    }
                })))

    @classmethod
    def can_handle_url(cls, url):
        return cls.url_re.match(url) is not None

    def _get_streams(self):
        data = http.get(self.url, schema=self.config_schema)

        for info in data["files"].values():
            stream_url = update_scheme(self.url, info["url"])
            # pick the smaller of the two dimensions, for landscape v. portrait videos
            res = min(info["width"], info["height"])
            yield "{0}p".format(res), HTTPStream(self.session, stream_url)
Пример #4
0
class TV8(Plugin):
    """
    Support for the live stream on www.tv8.com.tr
    """
    url_re = re.compile(r"https?://www.tv8.com.tr/canli-yayin")

    player_config_re = re.compile(
        r"""
        configPlayer.source.media.push[ ]*\(
        [ ]*\{[ ]*'src':[ ]*"(.*?)",
        [ ]*type:[ ]*"application/x-mpegURL"[ ]*}[ ]*\);
    """, re.VERBOSE)
    player_config_schema = validate.Schema(
        validate.transform(player_config_re.search),
        validate.any(None, validate.all(validate.get(1), validate.url())))

    @classmethod
    def can_handle_url(cls, url):
        return cls.url_re.match(url) is not None

    def _get_streams(self):
        res = http.get(self.url)
        stream_url = self.player_config_schema.validate(res.text)
        if stream_url:
            return HLSStream.parse_variant_playlist(self.session, stream_url)
Пример #5
0
class RaiPlay(Plugin):
    url_re = re.compile(r"https?://(?:www\.)?raiplay\.it/dirette/(\w+)/?")
    stream_re = re.compile(r"data-video-url.*?=.*?\"([^\"]+)\"")
    stream_schema = validate.Schema(
        validate.all(
            validate.transform(stream_re.search),
            validate.any(None, validate.all(validate.get(1), validate.url()))))

    @classmethod
    def can_handle_url(cls, url):
        return cls.url_re.match(url) is not None

    def _get_streams(self):
        http.headers.update({"User-Agent": useragents.FIREFOX})
        channel = self.url_re.match(self.url).group(1)
        self.logger.debug("Found channel: {0}", channel)
        stream_url = http.get(self.url, schema=self.stream_schema)
        if stream_url:
            try:
                return HLSStream.parse_variant_playlist(
                    self.session, stream_url)
            except Exception as e:
                if "Missing #EXTM3U header" in str(e):
                    raise PluginError(
                        "The streaming of this content is available in Italy only."
                    )
                raise e
Пример #6
0
class Filmon(Plugin):
    url_re = re.compile(
        r"""https?://(?:\w+\.)?filmon.(?:tv|com)/
        (?:
            (tv|channel)/(?P<channel>[^/]+)|
            vod/view/(?P<vod_id>\d+)-|
            group/
        )
    """, re.VERBOSE)

    _channel_id_re = re.compile(r'''channel_id\s*?=\s*["']?(\d+)["']''')
    _channel_id_schema = validate.Schema(
        validate.transform(_channel_id_re.search),
        validate.any(None, validate.get(1)))

    quality_weights = {"high": 720, "low": 480}

    def __init__(self, url):
        super(Filmon, self).__init__(url)
        self.api = FilmOnAPI()

    @classmethod
    def can_handle_url(cls, url):
        return cls.url_re.match(url) is not None

    @classmethod
    def stream_weight(cls, key):
        weight = cls.quality_weights.get(key)
        if weight:
            return weight, "filmon"

        return Plugin.stream_weight(key)

    def _get_streams(self):
        url_m = self.url_re.match(self.url)

        vod_id = url_m and url_m.group("vod_id")

        if vod_id:
            self.logger.debug("vod_id: {0}".format(vod_id))
            data = self.api.vod(vod_id)
            for _, stream in data["streams"].items():
                yield stream["quality"], FilmOnHLS(self.session,
                                                   vod_id=vod_id,
                                                   quality=stream["quality"])

        else:
            channel = http.get(self.url, schema=self._channel_id_schema)
            if channel:
                self.logger.debug("channel_id: {0}".format(channel))
            else:
                channel = url_m and url_m.group("channel")
                self.logger.debug("channel: {0}".format(channel))

            data = self.api.channel(channel)
            for stream in data["streams"]:
                yield stream["quality"], FilmOnHLS(self.session,
                                                   channel=channel,
                                                   quality=stream["quality"])
Пример #7
0
class CDNBG(Plugin):
    url_re = re.compile(
        r"""
        https?://(?:www\.)?(?:
            tv\.bnt\.bg/\w+(?:/\w+)?|
            bitelevision\.com/live|
            nova\.bg/live|
            kanal3\.bg/live|
            bgonair\.bg/tvonline|
            tvevropa\.com/na-zhivo|
            bloombergtv.bg/video
        )/?
    """, re.VERBOSE)
    iframe_re = re.compile(
        r"iframe .*?src=\"((?:https?:)?//(?:\w+\.)?cdn.bg/live[^\"]+)\"",
        re.DOTALL)
    sdata_re = re.compile(
        r"sdata\.src.*?=.*?(?P<q>[\"'])(?P<url>http.*?)(?P=q)")
    hls_file_re = re.compile(
        r"(src|file): (?P<q>[\"'])(?P<url>(https?:)?//.+?m3u8.*?)(?P=q)")
    hls_src_re = re.compile(r"video src=(?P<url>http[^ ]+m3u8[^ ]*)")

    stream_schema = validate.Schema(
        validate.any(
            validate.all(validate.transform(sdata_re.search),
                         validate.get("url")),
            validate.all(validate.transform(hls_file_re.search),
                         validate.get("url")),
            validate.all(validate.transform(hls_src_re.search),
                         validate.get("url")),
        ))

    @classmethod
    def can_handle_url(cls, url):
        return cls.url_re.match(url) is not None

    def find_iframe(self, res):
        p = urlparse(self.url)
        for url in self.iframe_re.findall(res.text):
            if "googletagmanager" not in url:
                if url.startswith("//"):
                    return "{0}:{1}".format(p.scheme, url)
                else:
                    return url

    def _get_streams(self):
        http.headers = {"User-Agent": useragents.CHROME}
        res = http.get(self.url)
        iframe_url = self.find_iframe(res)

        if iframe_url:
            self.logger.debug("Found iframe: {0}", iframe_url)
            res = http.get(iframe_url, headers={"Referer": self.url})
            stream_url = update_scheme(self.url,
                                       self.stream_schema.validate(res.text))
            return HLSStream.parse_variant_playlist(
                self.session,
                stream_url,
                headers={"User-Agent": useragents.CHROME})
Пример #8
0
class RadioNet(Plugin):
    _url_re = re.compile(r"https?://(\w+)\.radio\.(net|at|de|dk|es|fr|it|pl|pt|se)")
    _stream_data_re = re.compile(r'\bstation\s*:\s*(\{.+\}),?\s*')

    _stream_schema = validate.Schema(
        validate.transform(_stream_data_re.search),
        validate.any(
            None,
            validate.all(
                validate.get(1),
                validate.transform(parse_json),
                {
                    'stationType': validate.text,
                    'streamUrls': validate.all([{
                        'bitRate': int,
                        'streamUrl': validate.url()
                    }])
                },
            )
        )
    )

    @classmethod
    def can_handle_url(cls, url):
        return cls._url_re.match(url)

    def _get_streams(self):
        streams = http.get(self.url, schema=self._stream_schema)
        if streams is None:
            return

        # Ignore non-radio streams (podcasts...)
        if streams['stationType'] != 'radio_station':
            return

        stream_urls = []
        for stream in streams['streamUrls']:
            if stream['streamUrl'] in stream_urls:
                continue

            if stream['bitRate'] > 0:
                bitrate = '{}k'.format(stream['bitRate'])
            else:
                bitrate = 'live'
            yield bitrate, HTTPStream(self.session, stream['streamUrl'])
            stream_urls.append(stream['streamUrl'])
Пример #9
0
class ard_live(Plugin):
    swf_url = "http://live.daserste.de/lib/br-player/swf/main.swf"
    _url_re = re.compile(r"https?://(www.)?daserste.de/", re.I)
    _player_re = re.compile(r'''dataURL\s*:\s*(?P<q>['"])(?P<url>.*?)(?P=q)''')
    _player_url_schema = validate.Schema(
        validate.transform(_player_re.search),
        validate.any(None, validate.all(validate.get("url"), validate.text)))
    _livestream_schema = validate.Schema(
        validate.xml_findall(".//assets"),
        validate.filter(lambda x: x.attrib.get("type") != "subtitles"),
        validate.get(0), validate.xml_findall(".//asset"), [
            validate.union({
                "url": validate.xml_findtext("./fileName"),
                "bitrate": validate.xml_findtext("./bitrateVideo")
            })
        ])

    @classmethod
    def can_handle_url(cls, url):
        return cls._url_re.match(url) is not None

    def _get_streams(self):
        data_url = http.get(self.url, schema=self._player_url_schema)
        if data_url:
            res = http.get(urljoin(self.url, data_url))
            stream_info = http.xml(res, schema=self._livestream_schema)

            for stream in stream_info:
                url = stream["url"]
                try:
                    if ".m3u8" in url:
                        for s in HLSStream.parse_variant_playlist(
                                self.session, url, name_key="bitrate").items():
                            yield s
                    elif ".f4m" in url:
                        for s in HDSStream.parse_manifest(
                                self.session,
                                url,
                                pvswf=self.swf_url,
                                is_akamai=True).items():
                            yield s
                    elif ".mp4" in url:
                        yield "{0}k".format(stream["bitrate"]), HTTPStream(
                            self.session, url)
                except IOError as err:
                    self.logger.warning("Error parsing stream: {0}", err)
Пример #10
0
class TVRPlus(Plugin):
    url_re = re.compile(r"https?://(?:www\.)tvrplus.ro/live-")
    hls_file_re = re.compile(
        r"""src:\s?(?P<q>["'])(?P<url>http.+?m3u8.*?)(?P=q)""")

    stream_schema = validate.Schema(
        validate.all(validate.transform(hls_file_re.search),
                     validate.any(None, validate.get("url"))), )

    @classmethod
    def can_handle_url(cls, url):
        return cls.url_re.match(url) is not None

    def _get_streams(self):
        stream_url = self.stream_schema.validate(http.get(self.url).text)
        if stream_url:
            headers = {"Referer": self.url}
            return HLSStream.parse_variant_playlist(self.session,
                                                    stream_url,
                                                    headers=headers)
Пример #11
0
class RTBF(Plugin):
    """Livecli Plugin for RTBF"""

    _url_re = re.compile(r"""https?://(?:www\.)rtbf\.be/auvio/""")

    api_live_url = "https://www.rtbf.be/embed/d/ajax/refresh?id={0}"

    _live_schema = validate.Schema(
        {
            "data": validate.any(
                None,
                [],
                {
                    "streamUrlHls": validate.text,
                },
            ),
        },
        validate.get("data"),
    )

    @classmethod
    def can_handle_url(cls, url):
        return cls._url_re.match(url)

    def _get_live_stream(self, live_id):
        res = http.get(self.api_live_url.format(live_id))
        live_data = http.json(res, schema=self._live_schema)
        if not live_data:
            self.logger.debug("No data found.")
            return

        for s in HLSStream.parse_variant_playlist(
                self.session, live_data["streamUrlHls"]).items():
            yield s

    def _get_streams(self):
        params = dict(parse_qsl(urlparse(self.url).query))
        live_id = params.get("lid")

        if live_id:
            return self._get_live_stream(live_id)
Пример #12
0
class INE(Plugin):
    url_re = re.compile(r"""https://streaming.ine.com/play\#?/
            ([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/?
            (.*?)""", re.VERBOSE)
    play_url = "https://streaming.ine.com/play/{vid}/watch"
    js_re = re.compile(r'''script type="text/javascript" src="(https://content.jwplatform.com/players/.*?)"''')
    jwplayer_re = re.compile(r'''jwConfig\s*=\s*(\{.*\});''', re.DOTALL)
    setup_schema = validate.Schema(
        validate.transform(jwplayer_re.search),
        validate.any(
            None,
            validate.all(
                validate.get(1),
                validate.transform(json.loads),
                {"playlist": [
                    {"sources": [{"file": validate.text,
                                  "type": validate.text}]}
                ]}
            )
        )
    )

    @classmethod
    def can_handle_url(cls, url):
        return cls.url_re.match(url) is not None

    def _get_streams(self):
        vid = self.url_re.match(self.url).group(1)
        self.logger.debug("Found video ID: {0}", vid)

        page = http.get(self.play_url.format(vid=vid))
        js_url_m = self.js_re.search(page.text)
        if js_url_m:
            js_url = js_url_m.group(1)
            self.logger.debug("Loading player JS: {0}", js_url)

            res = http.get(js_url)
            data = self.setup_schema.validate(res.text)
            for source in data["playlist"][0]["sources"]:
                if source["type"] == "hls":
                    return HLSStream.parse_variant_playlist(self.session, "https:" + source["file"])
Пример #13
0
class RaiPlay(Plugin):
    url_re = re.compile(r"https?://(?:www\.)?raiplay\.it/dirette/(\w+)/?")
    stream_re = re.compile(r"data-video-url.*?=.*?\"([^\"]+)\"")
    stream_schema = validate.Schema(
        validate.all(
            validate.transform(stream_re.search),
            validate.any(
                None,
                validate.all(validate.get(1), validate.url())
            )
        )
    )

    @classmethod
    def can_handle_url(cls, url):
        return cls.url_re.match(url) is not None

    def _get_streams(self):
        channel = self.url_re.match(self.url).group(1)
        self.logger.debug("Found channel: {0}", channel)
        stream_url = http.get(self.url, schema=self.stream_schema)
        if stream_url:
            return HLSStream.parse_variant_playlist(self.session, stream_url)
Пример #14
0
class CinerGroup(Plugin):
    """
    Support for the live stream on www.showtv.com.tr
    """
    url_re = re.compile(
        r"""https?://(?:www.)?
        (?:
            showtv.com.tr/canli-yayin(/showtv)?|
            haberturk.com/canliyayin|
            showmax.com.tr/canliyayin|
            showturk.com.tr/canli-yayin/showturk|
            bloomberght.com/tv|
            haberturk.tv/canliyayin
        )/?""", re.VERBOSE)
    stream_re = re.compile(
        r"""div .*? data-ht=(?P<quote>["'])(?P<data>.*?)(?P=quote)""",
        re.DOTALL)
    stream_data_schema = validate.Schema(
        validate.transform(stream_re.search),
        validate.any(
            None,
            validate.all(
                validate.get("data"), validate.transform(unquote),
                validate.transform(lambda x: x.replace("&quot;", '"')),
                validate.transform(json.loads),
                {"ht_stream_m3u8": validate.url()},
                validate.get("ht_stream_m3u8"))))

    @classmethod
    def can_handle_url(cls, url):
        return cls.url_re.match(url) is not None

    def _get_streams(self):
        res = http.get(self.url)
        stream_url = self.stream_data_schema.validate(res.text)
        if stream_url:
            return HLSStream.parse_variant_playlist(self.session, stream_url)
Пример #15
0
class FilmOnAPI(object):
    channel_url = "http://www.filmon.com/api-v2/channel/{0}?protocol=hls"
    vod_url = "http://www.filmon.com/vod/info/{0}"

    stream_schema = {
        "quality": validate.text,
        "url": validate.url(),
        "watch-timeout": int
    }
    api_schema = validate.Schema(
        {
            "data": {
                "streams":
                validate.any({validate.text: stream_schema}, [stream_schema])
            }
        }, validate.get("data"))

    def channel(self, channel):
        res = http.get(self.channel_url.format(channel))
        return http.json(res, schema=self.api_schema)

    def vod(self, vod_id):
        res = http.get(self.vod_url.format(vod_id))
        return http.json(res, schema=self.api_schema)
Пример #16
0
__livecli_docs__ = {
    "domains": [
        "camsoda.com",
    ],
    "geo_blocked": [],
    "notes": "",
    "live": True,
    "vod": False,
    "last_update": "2017-11-18",
}

_url_re = re.compile(r"http(s)?://(www\.)?camsoda\.com/(?P<username>[^\"\']+)")

_api_user_schema = validate.Schema({
    "status": validate.any(int, validate.text),
    validate.optional("user"): {
        "online": validate.any(int, validate.text),
        "chatstatus": validate.text,
    }
})

_api_video_schema = validate.Schema({
    "token": validate.text,
    "app": validate.text,
    "edge_servers": [validate.text],
    "stream_name": validate.text
})


class Camsoda(Plugin):
Пример #17
0
    "broken": True,
}

BALANCER_URL = "http://www.mips.tv:1935/loadbalancer"
PLAYER_URL = "http://mips.tv/embedplayer/{0}/1/500/400"
SWF_URL = "http://mips.tv/content/scripts/eplayer.swf"

_url_re = re.compile(r"http(s)?://(\w+.)?mips.tv/(?P<channel>[^/&?]+)")
_flashvars_re = re.compile(r"'FlashVars', '([^']+)'")
_rtmp_re = re.compile(r"redirect=(.+)")

_schema = validate.Schema(
    validate.transform(_flashvars_re.search),
    validate.any(
        None,
        validate.all(validate.get(1), validate.transform(parse_query), {
            "id": validate.transform(int),
            validate.optional("s"): validate.text
        })))
_rtmp_schema = validate.Schema(
    validate.transform(_rtmp_re.search),
    validate.get(1),
)


class Mips(Plugin):
    @classmethod
    def can_handle_url(self, url):
        return _url_re.match(url)

    @Plugin.broken()
    def _get_streams(self):
Пример #18
0
    {
        "chansub": {
            "restricted_bitrates":
            validate.all([validate.text],
                         validate.filter(lambda n: not re.match(
                             r"(.+_)?archives|live|chunked", n)))
        }
    }, validate.get("chansub"))
_user_schema = validate.Schema(
    {validate.optional("display_name"): validate.text},
    validate.get("display_name"))
_video_schema = validate.Schema({
    "chunks": {
        validate.text: [{
            "length": int,
            "url": validate.any(None, validate.url(scheme="http")),
            "upkeep": validate.any("pass", "fail", None)
        }]
    },
    "restrictions": {
        validate.text: validate.text
    },
    "start_offset": int,
    "end_offset": int,
})
_viewer_info_schema = validate.Schema(
    {validate.optional("login"): validate.text}, validate.get("login"))
_viewer_token_schema = validate.Schema(
    {validate.optional("token"): validate.text}, validate.get("token"))
_quality_options_schema = validate.Schema(
    {
Пример #19
0
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
        /l/(?P<channel>[^/]+)
""", re.VERBOSE)

_feed_json_re = re.compile(r'^\s*var\s*feed\s*=\s*(?P<feed>{.*})\s*;',
                           re.MULTILINE)

_feed_json_schema = validate.Schema(
    validate.all(
        validate.transform(_feed_json_re.search),
        validate.any(
            None,
            validate.all(validate.get('feed'),
                         validate.transform(json.loads)))))


class Huajiao(Plugin):
    @classmethod
    def can_handle_url(self, url):
        return _url_re.match(url)

    def _get_streams(self):
        match = _url_re.match(self.url)
        channel = match.group("channel")

        http.headers.update({"User-Agent": USER_AGENT})
        http.verify = False
Пример #20
0
_api_schema = validate.Schema({
    "error": bool,
    validate.optional("code"): validate.text,
    validate.optional("message"): validate.text,
    validate.optional("data"): object,
})
_media_schema = validate.Schema(
    {
        "stream_data":
        validate.any(
            None, {
                "streams":
                validate.all([{
                    "quality":
                    validate.any(validate.text, None),
                    "url":
                    validate.url(scheme="http",
                                 path=validate.endswith(".m3u8")),
                    validate.optional("video_encode_id"):
                    validate.text
                }])
            })
    }, validate.get("stream_data"))
_login_schema = validate.Schema({
    "auth":
    validate.text,
    "expires":
    validate.all(validate.text, validate.transform(parse_timestamp)),
    "user": {
        "username": validate.any(validate.text, None),
        "email": validate.text
Пример #21
0
class CanalPlus(Plugin):
    # NOTE : no live url for the moment
    API_URL = 'https://secure-service.canal-plus.com/video/rest/getVideos/cplus/{0}?format=json'
    HDCORE_VERSION = '3.1.0'
    # Secret parameter needed to download HTTP videos on canalplus.fr
    SECRET = 'pqzerjlsmdkjfoiuerhsdlfknaes'

    _url_re = re.compile(r'''
        (https|http)://
        (
            www.mycanal.fr/(.*)/(.*)/p/(?P<video_id>[0-9]+) |
            www\.cnews\.fr/.+
        )
''', re.VERBOSE)
    _video_id_re = re.compile(r'(\bdata-video="|<meta property="og:video" content=".+?&videoId=)(?P<video_id>[0-9]+)"')
    _mp4_bitrate_re = re.compile(r'.*_(?P<bitrate>[0-9]+k)\.mp4')
    _api_schema = validate.Schema({
        'ID_DM': validate.text,
        'TYPE': validate.text,
        'MEDIA': validate.Schema({
            'VIDEOS': validate.Schema({
                validate.text: validate.any(
                    validate.url(),
                    ''
                )
            })
        })
    })
    _user_agent = useragents.CHROME

    @classmethod
    def can_handle_url(cls, url):
        return CanalPlus._url_re.match(url)

    def _get_streams(self):
        # Get video ID and channel from URL
        match = self._url_re.match(self.url)
        video_id = match.group('video_id')
        if video_id is None:
            # Retrieve URL page and search for video ID
            res = http.get(self.url)
            match = self._video_id_re.search(res.text)
            if match is None:
                return
            video_id = match.group('video_id')

        res = http.get(self.API_URL.format(video_id))
        videos = http.json(res, schema=self._api_schema)
        parsed = []
        headers = {'User-Agent': self._user_agent}

        # Some videos may be also available on Dailymotion (especially on CNews)
        if videos['ID_DM'] != '':
            for stream in self.session.streams('https://www.dailymotion.com/video/' + videos['ID_DM']).items():
                yield stream

        for quality, video_url in list(videos['MEDIA']['VIDEOS'].items()):
            # Ignore empty URLs
            if video_url == '':
                continue

            # Ignore duplicate video URLs
            if video_url in parsed:
                continue
            parsed.append(video_url)

            try:
                # HDS streams don't seem to work for live videos
                if '.f4m' in video_url and 'LIVE' not in videos['TYPE']:
                    for stream in HDSStream.parse_manifest(self.session,
                                                           video_url,
                                                           params={'hdcore': self.HDCORE_VERSION},
                                                           headers=headers).items():
                        yield stream
                elif '.m3u8' in video_url:
                    for stream in HLSStream.parse_variant_playlist(self.session,
                                                                   video_url,
                                                                   headers=headers).items():
                        yield stream
                elif '.mp4' in video_url:
                    # Get bitrate from video filename
                    match = self._mp4_bitrate_re.match(video_url)
                    if match is not None:
                        bitrate = match.group('bitrate')
                    else:
                        bitrate = quality
                    yield bitrate, HTTPStream(self.session,
                                              video_url,
                                              params={'secret': self.SECRET},
                                              headers=headers)
            except IOError as err:
                if '403 Client Error' in str(err):
                    self.logger.error('Failed to access stream, may be due to geo-restriction')
Пример #22
0
class WebTV(Plugin):
    _url_re = re.compile(r"http(?:s)?://(\w+)\.web.tv/?")
    _sources_re = re.compile(r'"sources": (\[.*?\]),', re.DOTALL)
    _sources_schema = validate.Schema([{
        u"src":
        validate.any(
            validate.contains("m3u8"),
            validate.all(
                validate.text,
                validate.transform(lambda x: WebTV.decrypt_stream_url(x)),
                validate.contains("m3u8"))),
        u"type":
        validate.text,
        u"label":
        validate.text
    }])

    @classmethod
    def can_handle_url(cls, url):
        return cls._url_re.match(url) is not None

    @staticmethod
    def decrypt_stream_url(encoded_url):
        data = base64.b64decode(encoded_url)
        cipher_text = binascii.unhexlify(data[96:])

        decryptor = crypto_AES.new(binascii.unhexlify(data[32:96]),
                                   crypto_AES.MODE_CBC,
                                   binascii.unhexlify(data[:32]))

        return unpad_pkcs5(decryptor.decrypt(cipher_text)).decode("utf8")

    def _get_streams(self):
        """
        Find the streams for web.tv
        :return:
        """
        headers = {}
        res = http.get(self.url, headers=headers)
        headers["Referer"] = self.url

        sources = self._sources_re.findall(res.text)
        if len(sources):
            sdata = parse_json(sources[0], schema=self._sources_schema)
            for source in sdata:
                self.logger.debug("Found stream of type: {}", source[u'type'])
                if source[u'type'] == u"application/vnd.apple.mpegurl":
                    url = update_scheme(self.url, source[u"src"])

                    try:
                        # try to parse the stream as a variant playlist
                        variant = HLSStream.parse_variant_playlist(
                            self.session, url, headers=headers)
                        if variant:
                            for q, s in variant.items():
                                yield q, s
                        else:
                            # and if that fails, try it as a plain HLS stream
                            yield 'live', HLSStream(self.session,
                                                    url,
                                                    headers=headers)
                    except IOError:
                        self.logger.warning(
                            "Could not open the stream, perhaps the channel is offline"
                        )
Пример #23
0
    "geo_blocked": [
        "ES",
    ],
    "notes": "",
    "live": True,
    "vod": True,
    "last_update": "2015-03-13",
}

STREAM_INFO_URL = "http://dinamics.ccma.cat/pvideo/media.jsp?media=video&version=0s&idint={ident}&profile=pc&desplacament=0"
_url_re = re.compile(r"http://(?:www.)?ccma.cat/tv3/directe/(.+?)/")
_media_schema = validate.Schema({
    "geo":
    validate.text,
    "url":
    validate.url(scheme=validate.any("http"))
})
_channel_schema = validate.Schema(
    {"media": validate.any([_media_schema], _media_schema)})


class TV3Cat(Plugin):
    @classmethod
    def can_handle_url(self, url):
        match = _url_re.match(url)
        return match

    def _get_streams(self):

        match = _url_re.match(self.url)
        if match:
Пример #24
0
_live_schema = validate.Schema(
    validate.transform(_playlist_url_re.findall),
    [
        validate.union({
            "isSource": validate.all(validate.get(0), validate.transform(lambda s: s == "source")),
            "url": validate.all(validate.get(1), validate.url(scheme="http",
                                                              path=validate.endswith(".m3u8")))
        })
    ]
)
_movie_schema = validate.Schema(
    validate.transform(_movie_data_re.search),
    validate.any(
        None,
        validate.all(
            validate.get(1),
            validate.transform(parse_json),
            validate.get("contentUrl")
        )
    )
)


class OPENRECtv(Plugin):
    @classmethod
    def can_handle_url(cls, url):
        return _url_re.match(url) is not None

    @classmethod
    def stream_weight(cls, stream):
        if stream == "source":
            return 1080 + 1, "openrectv"
Пример #25
0
    https?://(?:\w+\.)?arte\.tv/(?:guide/)?
    (?P<language>[a-z]{2})/
    (?:
        (?:videos/)?(?P<video_id>(?!RC\-|videos)[^/]+?)/.+ | # VOD
        (?:direct|live)        # Live TV
    )
""", re.VERBOSE)

_video_schema = validate.Schema({
    "videoJsonPlayer": {
        "VSR": validate.any(
            [],
            {
                validate.text: {
                    "height": int,
                    "mediaType": validate.text,
                    "url": validate.text,
                    "versionShortLibelle": validate.text
                },
            },
        )
    }
})


class ArteTV(Plugin):
    @classmethod
    def can_handle_url(cls, url):
        return _url_re.match(url)

    def _create_stream(self, stream, language):
Пример #26
0
_room_key_re = re.compile(r'"room_key"\s*:\s*"(.+?)"')
_hostid_re = re.compile(r'\\"hostid\\"\s*:\s*\\"(.+?)\\"')
_param_re = re.compile(r'"param"\s*:\s*"(.+?)"\s*,\s*"time"')
_time_re = re.compile(r'"time"\s*:\s*(\d+)')
_sign_re = re.compile(r'"sign"\s*:\s*"(.+?)"')
_sd_re = re.compile(r'"SD"\s*:\s*"(\d+)"')
_hd_re = re.compile(r'"HD"\s*:\s*"(\d+)"')
_od_re = re.compile(r'"OD"\s*:\s*"(\d+)"')

_room_schema = validate.Schema(
    {
        "data":
        validate.any(
            validate.text, dict, {
                "videoinfo":
                validate.any(validate.text, {
                    "plflag_list": validate.text,
                    "plflag": validate.text
                })
            })
    }, validate.get("data"))


class Pandatv(Plugin):
    @classmethod
    def can_handle_url(cls, url):
        return _url_re.match(url)

    def _get_streams(self):
        match = _url_re.match(self.url)
        channel = match.group("channel")
Пример #27
0
    def test_any(self):
        assert validate(any(int, dict), 5) == 5
        assert validate(any(int, dict), {}) == {}

        assert validate(any(int), 4) == 4
Пример #28
0
class Dogan(Plugin):
    """
    Support for the live streams from Doğan Media Group channels
    """
    url_re = re.compile(
        r"""
        https?://(?:www.)?
        (?:teve2.com.tr/(?:canli-yayin|filmler/.*|programlar/.*)|
           kanald.com.tr/.*|
           cnnturk.com/canli-yayin|
           dreamtv.com.tr/canli-yayin|
           dreamturk.com.tr/canli)
    """, re.VERBOSE)
    playerctrl_re = re.compile(
        r'''<div[^>]*?ng-controller=(?P<quote>["'])(?:Live)?PlayerCtrl(?P=quote).*?>''',
        re.DOTALL)
    videoelement_re = re.compile(
        r'''<div[^>]*?id=(?P<quote>["'])video-element(?P=quote).*?>''',
        re.DOTALL)
    data_id_re = re.compile(
        r'''data-id=(?P<quote>["'])(?P<id>\w+)(?P=quote)''')
    content_id_re = re.compile(r'"content(?:I|i)d", "(\w+)"')
    content_api = "/actions/content/media/{id}"
    new_content_api = "/action/media/{id}"
    content_api_schema = validate.Schema({
        "Id": validate.text,
        "Media": {
            "Link": {
                "DefaultServiceUrl": validate.url(),
                validate.optional("ServiceUrl"):
                validate.any(validate.url(), ""),
                "SecurePath": validate.text,
            }
        }
    })

    @classmethod
    def can_handle_url(cls, url):
        return cls.url_re.match(url) is not None

    def _get_content_id(self):
        res = http.get(self.url)
        # find the contentId
        content_id_m = self.content_id_re.search(res.text)
        if content_id_m:
            return content_id_m.group(1)

        # find the PlayerCtrl div
        player_ctrl_m = self.playerctrl_re.search(res.text)
        if player_ctrl_m:
            # extract the content id from the player control data
            player_ctrl_div = player_ctrl_m.group(0)
            content_id_m = self.data_id_re.search(player_ctrl_div)
            if content_id_m:
                return content_id_m.group("id")

        # find <div id="video-element"
        videoelement_m = self.videoelement_re.search(res.text)
        if videoelement_m:
            # extract the content id from the player control data
            videoelement_div = videoelement_m.group(0)
            content_id_m = self.data_id_re.search(videoelement_div)
            if content_id_m:
                return content_id_m.group("id")

    def _get_hls_url(self, content_id):
        # make the api url relative to the current domain
        if "cnnturk" in self.url or "teve2.com.tr" in self.url:
            self.logger.debug("Using new content API url")
            api_url = urljoin(self.url,
                              self.new_content_api.format(id=content_id))
        else:
            api_url = urljoin(self.url, self.content_api.format(id=content_id))

        apires = http.get(api_url)

        stream_data = http.json(apires, schema=self.content_api_schema)
        d = stream_data["Media"]["Link"]
        return urljoin((d["ServiceUrl"] or d["DefaultServiceUrl"]),
                       d["SecurePath"])

    def _get_streams(self):
        content_id = self._get_content_id()
        if content_id:
            self.logger.debug(u"Loading content: {}", content_id)
            hls_url = self._get_hls_url(content_id)
            return HLSStream.parse_variant_playlist(self.session, hls_url)
        else:
            self.logger.error(u"Could not find the contentId for this stream")
Пример #29
0
RUURL = "b=chrome&p=win&v=56&f=0&d=1"

_url_re = re.compile(r"https?://www.rtvs.sk/televizia/live-[\w-]+")
_playlist_url_re = re.compile(r'"playlist": "([^"]+)"')

_playlist_schema = validate.Schema(
    [
        {
            "sources": [
                validate.any(
                    {
                        "type": "dash",
                        "file": validate.url(scheme="http")
                    }, {
                        "type": "hls",
                        "file": validate.url(scheme="http")
                    }, {
                        "type": "rtmp",
                        "file": validate.text,
                        "streamer": validate.url(scheme="rtmp")
                    }
                )
            ]
        }
    ],
    validate.get(0),
    validate.get("sources")
)


class Rtvs(Plugin):
Пример #30
0
API_SECRET = "95acd7f6cc3392f3"
SHOW_STATUS_ONLINE = 1
SHOW_STATUS_OFFLINE = 2
STREAM_WEIGHTS = {
    "source": 1080
}

_url_re = re.compile(r"""
    http(s)?://live.bilibili.com
    /(?P<channel>[^/]+)
""", re.VERBOSE)

_room_id_schema = validate.Schema(
    {
        "data": validate.any(None, {
            "room_id": int
        })
    },
    validate.get("data")
)


class Bilibili(Plugin):
    @classmethod
    def can_handle_url(self, url):
        return _url_re.match(url)

    @classmethod
    def stream_weight(cls, stream):
        if stream in STREAM_WEIGHTS:
            return STREAM_WEIGHTS[stream], "Bilibili"