示例#1
0
    def _get_streams(self):
        res = self.session.http.get(self.url)

        m = self._playback_re.search(res.text)

        if m:
            hls_url = m.group(0)

            if is_py3:
                hls_url = bytes(unquote_plus(hls_url),
                                "utf-8").decode("unicode_escape")
            else:
                hls_url = unquote_plus(hls_url).decode("unicode_escape")
        else:
            if self._livestream_re.search(res.text) is not None:
                raise PluginError('Stream is offline')

            m = self._username_re.search(res.text)
            if m:
                hls_url = "https://live.prd.dlive.tv/hls/live/{}.m3u8".format(
                    m.group(0))
            else:
                raise PluginError('Could not find username')

        return HLSStream.parse_variant_playlist(self.session, hls_url)
示例#2
0
    def _get_streams(self):
        stream_info = self._get_stream_info()
        log.debug("Live stream info: {}".format(stream_info))

        if not stream_info["movie"]["live"]:
            raise PluginError("The live stream is offline")

        # Keys are already validated by schema above
        proto = stream_info["fmp4"]["proto"]
        host = stream_info["fmp4"]["host"]
        movie_id = stream_info["movie"]["id"]

        if stream_info["fmp4"]["source"]:
            mode = "main"  # High quality
        elif stream_info["fmp4"]["mobilesource"]:
            mode = "mobilesource"  # Medium quality
        else:
            mode = "base"  # Low quality

        if (proto == '') or (host == '') or (not movie_id):
            raise PluginError("No stream available for user {}".format(
                self.channel))

        real_stream_url = self._STREAM_REAL_URL.format(proto=proto,
                                                       host=host,
                                                       movie_id=movie_id,
                                                       mode=mode)
        log.debug("Real stream url: {}".format(real_stream_url))

        return {
            mode: TwitCastingStream(session=self.session, url=real_stream_url)
        }
示例#3
0
    def _get_token(self, path):
        res = self.session.http.get(self.url)
        m = self.app_id_js_url_re.search(res.text)
        app_id_js_url = m and m.group(1)
        if not app_id_js_url:
            raise PluginError("Could not determine app_id_js_url")
        log.debug("app_id_js_url={0}".format(app_id_js_url))

        res = self.session.http.get(app_id_js_url)
        m = self.app_id_re.search(res.text)
        app_id = m and m.group(1)
        if not app_id:
            raise PluginError("Could not determine app_id")
        log.debug("app_id={0}".format(app_id))

        res = self.session.http.get(self.token_url, params=dict(
            format='json',
            appId=app_id,
            path=path,
        ))

        token_data = self.session.http.json(res, schema=self._token_schema)
        if 'error' in token_data:
            raise PluginError(token_data['error']['message'])

        return token_data['token']
示例#4
0
    def _get_streams(self):
        url_type = self.match.group(1)
        log.debug("URL type={0}".format(url_type))

        res = self.session.http.get(self.url)

        if url_type != "live":
            m = self.video_name_re.search(res.text)
            video_name = m and m.group(1)
            if not video_name:
                raise PluginError('Could not determine video_name')
            log.debug("Video name={0}".format(video_name))

        m = self.main_js_url_re.search(res.text)
        main_js_path = m and m.group(1)
        if not main_js_path:
            raise PluginError('Could not determine main_js_path')
        log.debug("Main JS path={0}".format(main_js_path))

        res = self.session.http.get(urljoin(self.url, main_js_path))

        m = self.user_id_re.search(res.text)
        user_id = m and m.group(1)
        if not user_id:
            raise PluginError('Could not determine user_id')
        log.debug("User ID={0}".format(user_id))

        if url_type == "live":
            return self._get_live(user_id)
        else:
            return self._get_vod(user_id, video_name)
示例#5
0
    def _get_vod(self, user_id, video_name):
        res = self.session.http.get(urljoin(self.api_url,
                                            "getVideoByFileName"),
                                    params=dict(userId=user_id,
                                                videoName=video_name,
                                                serverType="web",
                                                callback="x"))

        vod_data = self.session.http.json(res, schema=self.vod_schema)

        if video_name == vod_data['ShowTitle']:
            host, base_path = self.server_addr_re.search(
                vod_data['ServerAddress']).groups()
            if not host or not base_path:
                raise PluginError("Could not split 'ServerAddress' components")

            base_file, file_ext = self.media_file_re.search(
                vod_data['MediaFile']).groups()
            if not base_file or not file_ext:
                raise PluginError("Could not split 'MediaFile' components")

            media_path = "{0}{1}{2}{3}{4}{5}".format(
                base_path, vod_data['MediaRoot'], base_file,
                vod_data['Bitrates'], file_ext, vod_data['StreamingType'])
            log.debug("Media path={0}".format(media_path))

            vod_url = urlunparse((vod_data['ProtocolType'], host, media_path,
                                  '', vod_data['Token'], ''))
            log.debug("URL={0}".format(vod_url))

            return HLSStream.parse_variant_playlist(self.session, vod_url)
示例#6
0
    def _get_streams(self):
        if _stream_url_re.match(self.url):
            mode = MODE_STREAM
        else:
            mode = MODE_VOD

        res = http.get(self.url)
        match = _json_re.search(res.text)
        if match:
            data = json.loads(_json_re.search(res.text).group('json'))
        else:
            raise PluginError("Could not extract JSON metadata")

        streams = {}
        try:
            if mode == MODE_STREAM:
                sources = data['values']['episode'][
                    'livestream_playlist_data']['videos'][0]['sources']
            elif mode == MODE_VOD:
                sources = data['values']['segment']['playlist_item_array'][
                    'sources']
        except (KeyError, IndexError):
            raise PluginError("Could not extract sources")

        for source in sources:
            try:
                if source['delivery'] != 'hls':
                    continue
                url = source['src'].replace('\/', '/')
            except KeyError:
                continue
            stream = HLSStream.parse_variant_playlist(self.session, url)
            streams.update(stream)

        return streams
示例#7
0
    def _authenticate(self, email, password):
        csrf_token = http.get(LOGIN_PAGE_URL, schema=_csrf_token_schema)
        if not csrf_token:
            raise PluginError("Unable to find CSRF token")

        data = {
            "authenticity_token": csrf_token,
            "channel_id": "",
            "commit": "Login",
            "plan_id": "",
            "session[email]": email,
            "session[password]": password,
            "utf8": "\xE2\x9C\x93",  # Check Mark Character
        }

        res = http.post(LOGIN_POST_URL,
                        data=data,
                        acceptable_status=(200, 422))
        result = http.json(res, schema=_login_schema)

        errors = result.get("errors")
        if errors:
            errors = ", ".join(errors)
            raise PluginError("Unable to authenticate: {0}".format(errors))

        self.logger.info("Successfully logged in as {0}", result["email"])
示例#8
0
    def _get_streams(self):
        url_type, show_name, episode_name = self.match.groups()

        if url_type == 'streams' and not show_name:
            url_type = 'live-stream'
        elif not show_name:
            raise PluginError("Missing show_name for url_type: {0}".format(
                url_type,
            ))

        log.debug("URL type={0}".format(url_type))

        if url_type == 'live-stream':
            video_id = self._get_stream_data(url_type)
        elif url_type == 'streams':
            video_id = self._get_stream_data(show_name)
        elif url_type == 'videos':
            if show_name is None or episode_name is None:
                raise PluginError(
                    "Missing show_name or episode_name for url_type: {0}".format(
                        url_type,
                    )
                )
            video_id = self._get_video_data(episode_name)
        else:
            raise PluginError("Unrecognised url_type: {0}".format(url_type))

        if video_id is None:
            raise PluginError("Could not find video_id")
        log.debug("Video ID={0}".format(video_id))

        res = self.session.http.get(self.video_data_url.format(video_id))

        url_data = self.session.http.json(res, schema=self._api_schema)
        if 'unprotected' in url_data:
            url = url_data['unprotected']['url']
        elif 'bulkaes' in url_data:
            url_parsed = urlparse(url_data['bulkaes']['url'])
            token = self._get_token(url_parsed.path)
            url = urlunparse((
                url_parsed.scheme,
                url_parsed.netloc,
                url_parsed.path,
                url_parsed.params,
                "{0}={1}".format('hdnts', token),
                url_parsed.fragment,
            ))
        else:
            raise PluginError("Could not find a usable URL in url_data")

        log.debug("URL={0}".format(url))

        return HLSStream.parse_variant_playlist(self.session, url)
示例#9
0
    def _get_streams(self):
        match = _url_re.match(self.url)
        channel_name = match.group("channel")

        form = {
            "cid": channel_name,
            "watchTime": 0,
            "firstConnect": 1,
            "ip": "NaN"
        }
        res = http.post(API_URL, data=form, headers=HEADERS)
        params = parse_query(res.text, schema=_schema)

        if params["status"] <= 0:
            return

        if params["block_type"] != 0:
            if params["block_type"] == BLOCK_TYPE_VIEWING_LIMIT:
                msg = BLOCKED_MSG_FORMAT.format(
                    params.get("block_time", "UNKNOWN"),
                    params.get("reconnect_time", "UNKNOWN"))
                raise PluginError(msg)
            elif params["block_type"] == BLOCK_TYPE_NO_SLOTS:
                raise PluginError("No free slots available")
            else:
                raise PluginError("Blocked for unknown reasons")

        if "token" not in params:
            raise PluginError("Server seems busy, retry again later")

        streams = {}
        stream_names = ["sd"]
        if params["multibitrate"]:
            stream_names += ["hd"]

        for stream_name in stream_names:
            playpath = params["playpath"]
            if stream_name == "hd":
                playpath += "HI"

            stream = RTMPStream(
                self.session, {
                    "rtmp": "{0}/{1}".format(params["rtmp"], playpath),
                    "pageUrl": self.url,
                    "swfVfy": SWF_URL,
                    "weeb": params["token"],
                    "live": True
                })
            streams[stream_name] = stream

        return streams
示例#10
0
    def _get_streams(self):
        self.session.http.headers.update({
            'Referer':
            'http://www.abweb.com/BIS-TV-Online/bistvo-tele-universal.aspx'
        })

        login_username = self.get_option('username')
        login_password = self.get_option('password')

        if self.options.get('purge_credentials'):
            self.clear_cookies()
            self._authed = False
            log.info('All credentials were successfully removed.')

        if self._authed:
            log.info('Attempting to authenticate using cached cookies')
        elif not self._authed and not (login_username and login_password):
            log.error(
                'A login for ABweb is required, use --abweb-username USERNAME --abweb-password PASSWORD'
            )
            return
        elif not self._authed and not self._login(login_username,
                                                  login_password):
            return

        log.debug('get iframe_url')
        res = self.session.http.get(self.url)
        for iframe in itertags(res.text, 'iframe'):
            iframe_url = iframe.attributes.get('src')
            if iframe_url.startswith('/'):
                iframe_url = url_concat('https://www.abweb.com', iframe_url)
            else:
                iframe_url = update_scheme('https://', iframe_url)
            log.debug(f'iframe_url={iframe_url}')
            break
        else:
            raise PluginError('No iframe_url found.')

        self.session.http.headers.update({'Referer': iframe_url})
        res = self.session.http.get(iframe_url)
        m = self._hls_re.search(res.text)
        if not m:
            raise PluginError('No hls_url found.')

        hls_url = update_scheme('https://', m.group('url'))
        streams = HLSStream.parse_variant_playlist(self.session, hls_url)
        if streams:
            yield from streams.items()
        else:
            yield 'live', HLSStream(self.session, hls_url)
示例#11
0
    def _find_video_id(self, url):

        m = _url_re.match(url)
        if m.group("video_id"):
            log.debug("Video ID from URL")
            return m.group("video_id")

        res = self.session.http.get(url)
        datam = _ytdata_re.search(res.text)
        if datam:
            data = parse_json(datam.group(1))
            # find the videoRenderer object, where there is a LVE NOW badge
            for vid_ep in search_dict(data, 'currentVideoEndpoint'):
                video_id = vid_ep.get("watchEndpoint", {}).get("videoId")
                if video_id:
                    log.debug("Video ID from currentVideoEndpoint")
                    return video_id
            for x in search_dict(data, 'videoRenderer'):
                for bstyle in search_dict(x.get("badges", {}), "style"):
                    if bstyle == "BADGE_STYLE_TYPE_LIVE_NOW":
                        if x.get("videoId"):
                            log.debug("Video ID from videoRenderer (live)")
                            return x["videoId"]

        raise PluginError("Could not find a video on this page")
示例#12
0
    def _get_streams(self):
        if not self.login(self.get_option("email"),
                          self.get_option("password")):
            raise PluginError("Login failed")

        try:
            start_point = int(
                float(
                    dict(parse_qsl(urlparse(self.url).query)).get(
                        "startPoint", 0.0)))
            if start_point > 0:
                log.info("Stream will start at {0}".format(
                    seconds_to_hhmmss(start_point)))
        except ValueError:
            start_point = 0

        content_id = self._get_video_id()

        if content_id:
            log.debug("Found content ID: {0}".format(content_id))
            info = self._get_media_info(content_id)
            if info.get("hlsUrl"):
                yield from HLSStream.parse_variant_playlist(
                    self.session, info["hlsUrl"],
                    start_offset=start_point).items()
            else:
                log.error("Could not find the HLS URL")
示例#13
0
    def _get_stream_info(self, video_id, pl_id):
        info = None
        log.debug("Starting YoutubeDL process")
        try:
            ytdl = YoutubeDL(self.ytdl_options)
            url = "https://www.youtube.com/watch?v=%s" % video_id
            info = ytdl.extract_info(url,
                                     ie_key="Youtube",
                                     download=False,
                                     process=True)
            ua = info["formats"][-1]["http_headers"]["User-Agent"]
            self.session.http.headers.update({"User-Agent": ua})

            pl_path = self.get_option("playlist-dir")
            if pl_id and pl_path:
                if not os.path.isdir(pl_path):
                    os.makedirs(pl_path)
                    log.debug(
                        "Playlist directory '{0}' created".format(pl_path))

                url = "https://www.youtube.com/playlist?list=%s" % pl_id
                _info = ytdl.extract_info(url,
                                          ie_key="YoutubePlaylist",
                                          download=False,
                                          process=True)
                self._save2M3U(pl_path, _info, ua)
        except Exception as e:
            raise PluginError(e)

        return info
示例#14
0
    def get_token(self):
        """
        Get the token for USTVNow
        :return: a valid token
        """

        if not self._token:
            log.debug("Getting new session token")
            res = self.session.http.get(self._token_url,
                                        params={
                                            "tenant_code": self.TENANT_CODE,
                                            "box_id": self.box_id,
                                            "product": self.TENANT_CODE,
                                            "device_id": 5,
                                            "display_lang_code": "ENG",
                                            "device_sub_type": "",
                                            "timezone": "UTC"
                                        })

            data = res.json()
            if data['status']:
                self._token = data['response']['sessionId']
                log.debug("New token: {}".format(self._token))
            else:
                log.error(
                    "Token acquisition failed: {details} ({detail})".format(
                        **data['error']))
                raise PluginError("could not obtain token")

        return self._token
示例#15
0
    def _login(self, username, password):
        log.debug('Attempting to login.')

        data = {}
        for i in itertags(self.session.http.get(self.url_l).text, 'input'):
            data[i.attributes.get('name')] = i.attributes.get('value', '')

        if not data:
            raise PluginError('Missing input data on login website.')

        data.update({
            'ctl00$ContentPlaceHolder1$Login1$UserName': username,
            'ctl00$ContentPlaceHolder1$Login1$Password': password,
            'ctl00$ContentPlaceHolder1$Login1$LoginButton.x': '0',
            'ctl00$ContentPlaceHolder1$Login1$LoginButton.y': '0',
            'ctl00$ContentPlaceHolder1$Login1$RememberMe': 'on',
        })

        self.session.http.post(self.url_l, data=data)
        if (self.session.http.cookies.get('ASP.NET_SessionId') and self.session.http.cookies.get('.abportail1')):
            for cookie in self.session.http.cookies:
                # remove www from cookie domain
                cookie.domain = '.abweb.com'

            self.save_cookies(default_expires=3600 * 24)
            return True
        else:
            log.error('Failed to login, check your username/password')
            return False
示例#16
0
    def _get_vod_streams(self, vod_id):
        res = self.session.http.get(self.vod_url.format(vod_id))
        m = self.vod_data_re.search(res.text)
        vod_json = m and m.group(1)

        if vod_json is None:
            raise PluginError("Failed to get VOD data")

        vod_data = parse_json(vod_json, schema=self._vod_data_schema)

        self.author = vod_data['username']
        self.category = 'VOD'
        self.title = vod_data['title']

        vod_data = vod_data['vaddress']

        streams = {}
        for stream in vod_data:
            video_res = stream['vheight']

            if 'p' not in str(video_res):
                video_res = "{0}p".format(video_res)

            if video_res in streams:
                video_res = "{0}_alt".format(video_res)

            streams[video_res] = HLSStream(self.session, stream['url'])

        return streams
示例#17
0
 def _get_streams(self):
     self.session.http.headers.update({
         'User-Agent': useragents.FIREFOX,
         'Referer': self.url
     })
     match = _url_re.match(self.url)
     channel = match.group("channel")
     res_room_id = self.session.http.get(
         self.options.get("apihost") + ROOM_API.format(channel))
     log.debug(res_room_id.json())
     _room_id_json = res_room_id.json()
     try:
         room_id_json = self.session.http.json(res_room_id,
                                               schema=_room_id_schema)
     except:
         log.info("Error during processing json: %s", _room_id_json)
         raise
     self.room_id = room_id_json['room_id']
     if room_id_json['live_status'] != SHOW_STATUS_ONLINE:
         log.error("This video is not a live. (abort)")
         raise PluginError("This video is not a live. (abort)")
         return
     '''params = {
         'cid': room_id,
         'quality': '4',
         'platform': 'web',
     }'''
     name = "source"
     for url in self.update_playlist():
         #stream = BilibiliHLSStream.parse_variant_playlist(self.session, url)
         stream = BilibiliHLSStream(self.session, url)
         stream.plugin = self
         #for c in stream:
         #    stream[c].plugin = self
         yield name, stream
示例#18
0
    def _get_streams(self):
        nickname = self.match.group('nickname')
        res = self.session.http.get(f'https://wasd.tv/api/channels/nicknames/{nickname}')
        channel_id = self.session.http.json(res, schema=self._api_nicknames_schema)

        res = self.session.http.get(
            'https://wasd.tv/api/v2/media-containers',
            params={
                'media_container_status': 'RUNNING',
                'limit': '1',
                'offset': '0',
                'channel_id': channel_id,
                'media_container_type': 'SINGLE,COOP',
            }
        )

        json_res = self.session.http.json(res, schema=self._api_schema)
        log.trace('{0!r}'.format(json_res))
        if not json_res:
            raise PluginError('No data returned from URL={0}'.format(res.url))

        for stream in json_res['media_container_streams']:
            log.debug('media_container_status: {0}, media_container_online_status: {1}'.format(
                json_res['media_container_status'], json_res['media_container_online_status']))
            for stream in stream['stream_media']:
                if stream['media_status'] == 'STOPPED':
                    hls_url = stream['media_meta']['media_archive_url']
                elif stream['media_status'] == 'RUNNING':
                    hls_url = stream['media_meta']['media_url']

                yield from HLSStream.parse_variant_playlist(self.session, hls_url).items()
示例#19
0
 def _get_session_key(self, event_id):
     url = "{}/stream".format(_MEDIA_API_URL)
     params = {
         "eventId": event_id,
         "format": "json",
         "platform": "WEB_MEDIAPLAYER",
         "subject": "NHLTV",
         "_": now_ms(),
     }
     headers = {
         "Accept": "application/json",
         "Authorization": self._auth_token,
     }
     json = self.session.http.get(url, params=params,
                                  headers=headers).json()
     session_key = json.get("session_key")
     if not session_key:
         status = json.get("status_code")
         if status == -3500:
             log.debug(
                 "Plugin is being rate-limited for making too many session key requests."
             )
         raise PluginError("Could not obtain session key: {}".format(
             json.get("status_message")))
     # This session key is normally supposed to last for a single browser session.
     # If we repeatedly request new session keys we will get rate limited by the NHL.tv backend,
     # so we cache session keys for 2.5 hours (roughly the length of an NHL hockey game) to
     # aproximate normal behavior.
     self.cache.set("session_key", session_key, 9000)
示例#20
0
    def _get_streams(self):
        is_live = False

        self.video_id = self._find_video_id(self.url)
        log.debug(f"Using video ID: {self.video_id}")

        info = self._get_stream_info(self.video_id)
        if info and info.get("status") == "fail":
            log.error("Could not get video info: {0}".format(
                info.get("reason")))
            return
        elif not info:
            log.error("Could not get video info")
            return

        if info.get("player_response", {}).get("videoDetails",
                                               {}).get("isLive"):
            log.debug("This video is live.")
            is_live = True

        streams = {}
        protected = False
        if (info.get("player_response", {}).get("streamingData", {}).get(
                "adaptiveFormats", [{}])[0].get("cipher") or info.get(
                    "player_response", {}).get("streamingData", {}).get(
                        "adaptiveFormats", [{}])[0].get("signatureCipher") or
                info.get("player_response", {}).get("streamingData", {}).get(
                    "formats", [{}])[0].get("cipher")):
            protected = True
            log.debug("This video may be protected.")

        for stream_info in info.get("player_response",
                                    {}).get("streamingData",
                                            {}).get("formats", []):
            if "url" not in stream_info:
                continue
            stream = HTTPStream(self.session, stream_info["url"])
            name = stream_info["qualityLabel"]

            streams[name] = stream

        if not is_live:
            streams = self._create_adaptive_streams(info, streams)

        hls_manifest = info.get("player_response",
                                {}).get("streamingData",
                                        {}).get("hlsManifestUrl")
        if hls_manifest:
            try:
                hls_streams = HLSStream.parse_variant_playlist(
                    self.session, hls_manifest, namekey="pixels")
                streams.update(hls_streams)
            except IOError as err:
                log.warning(f"Failed to extract HLS streams: {err}")

        if not streams and protected:
            raise PluginError("This plugin does not support protected videos, "
                              "try youtube-dl instead")

        return streams
示例#21
0
    def _get_streams(self):
        streams = {}

        # streaming.media.ccc.de
        match = _url_streaming_media_re.match(self.url)
        if match:
            query_url = API_URL_STREAMING_MEDIA
            live_streams = parse_streaming_media_json(get_json(query_url),\
                                                      match.group('room'))

            for stream_name, stream_url in live_streams.items():
                if re.search(r"m3u8", live_streams[stream_name]):
                    streams[stream_name] = HLSStream(self.session,\
                                                        stream_url)
                else:
                    streams[stream_name] = HTTPStream(self.session,\
                                                        stream_url)

        # media.ccc.de
        elif _url_media_re.search(self.url):
            event_id = get_event_id(self.url)
            query_url = "%s/public/events/%i" % (API_URL_MEDIA, event_id)
            recordings = parse_media_json(get_json(query_url))

            for name, stream_url in recordings.items():
                streams[name] = HTTPStream(self.session, stream_url)

        if not streams:
            raise PluginError("This plugin does not support your "
                              "selected video.")

        return streams
示例#22
0
    def _find_video_id(self, url):

        m = _url_re.match(url)
        if m.group("video_id"):
            log.debug("Video ID from URL")
            return m.group("video_id")

        res = self.session.http.get(url)
        datam = _ytdata_re.search(res.text)
        if datam:
            data = parse_json(datam.group(1))
            # find the videoRenderer object, where there is a LVE NOW badge
            for vid_ep in search_dict(data, 'currentVideoEndpoint'):
                video_id = vid_ep.get("watchEndpoint", {}).get("videoId")
                if video_id:
                    log.debug("Video ID from currentVideoEndpoint")
                    return video_id
            for x in search_dict(data, 'videoRenderer'):
                for bstyle in search_dict(x.get("badges", {}), "style"):
                    if bstyle == "BADGE_STYLE_TYPE_LIVE_NOW":
                        if x.get("videoId"):
                            log.debug("Video ID from videoRenderer (live)")
                            return x["videoId"]

        if "/embed/live_stream" in url:
            for link in itertags(res.text, "link"):
                if link.attributes.get("rel") == "canonical":
                    canon_link = link.attributes.get("href")
                    if canon_link != url:
                        log.debug("Re-directing to canonical URL: {0}".format(canon_link))
                        return self._find_video_id(canon_link)

        raise PluginError("Could not find a video on this page")
示例#23
0
    def _get_swf_url(self):
        res = self.session.http.get(self.url)
        match = _swf_url_re.search(res.text)
        if not match:
            raise PluginError("Unable to find SWF URL in the HTML")

        return match.group(1)
示例#24
0
    def _create_api(self):
        """Creates a new CrunchyrollAPI object, initiates it's session and
        tries to authenticate it either by using saved credentials or the
        user's username and password.
        """
        if self.options.get("purge_credentials"):
            self.cache.set("session_id", None, 0)
            self.cache.set("auth", None, 0)
            self.cache.set("session_id", None, 0)

        current_time = datetime.datetime.utcnow()
        device_id = self._get_device_id()
        # use the crunchyroll locale as an override, for backwards compatibility
        locale = self.get_option("locale") or self.session.localization.language_code
        api = CrunchyrollAPI(
            self.options.get("session_id") or self.cache.get("session_id"), self.cache.get("auth"), locale
        )

        self.logger.debug("Creating session with locale: {0}", locale)
        try:
            api.session_id = api.start_session(device_id, schema=_session_schema)
        except CrunchyrollAPIError as err:
            if err.code == "bad_session":
                self.logger.debug("Current session has expired, creating a new one")
                api = CrunchyrollAPI(locale=locale)
                api.session_id = api.start_session(device_id, schema=_session_schema)
            else:
                raise err

        # Save session and hope it lasts for a few hours
        self.cache.set("session_id", api.session_id, 4 * 60 * 60)
        self.logger.debug("Session created")

        if api.auth:
            self.logger.debug("Using saved credentials")
        elif self.options.get("username"):
            try:
                self.logger.info("Attempting to login using username and password")
                login = api.login(
                    self.options.get("username"),
                    self.options.get("password"),
                    schema=_login_schema
                )
                api.auth = login["auth"]

                self.logger.info("Successfully logged in as '{0}'",
                                 login["user"]["username"] or login["user"]["email"])

                expires = (login["expires"] - current_time).total_seconds()
                self.cache.set("auth", login["auth"], expires)
            except CrunchyrollAPIError as err:
                raise PluginError(u"Authentication error: {0}".format(err.msg))
        else:
            self.logger.warning(
                "No authentication provided, you won't be able to access "
                "premium restricted content"
            )

        return api
示例#25
0
    def _get_streams(self):
        res = self._get_res(self.url)

        if self.match.group(
                "channel") and not self.match.group("channel_live"):
            initial = self._get_data_from_regex(res, self._re_ytInitialData,
                                                "initial data")
            video_id = self._data_video_id(initial)
            if video_id is None:
                log.error("Could not find videoId on channel page")
                return
            self.url = self._url_canonical.format(video_id=video_id)
            res = self._get_res(self.url)

        data = self._get_data_from_regex(res, self._re_ytInitialPlayerResponse,
                                         "initial player response")
        if not self._data_status(data):
            data = self._get_data_from_api(res)
            if not self._data_status(data, True):
                return

        self.id, self.author, self.category, self.title, is_live = self._schema_videodetails(
            data)
        log.debug(f"Using video ID: {self.id}")

        if is_live:
            log.debug("This video is live.")

        streams = {}
        hls_manifest, formats, adaptive_formats = self._schema_streamingdata(
            data)

        protected = next(
            (True for url, *_ in formats + adaptive_formats if url is None),
            False)
        if protected:
            log.debug("This video may be protected.")

        for url, label in formats:
            if url is None:
                continue
            streams[label] = HTTPStream(self.session, url)

        if not is_live:
            streams.update(self._create_adaptive_streams(adaptive_formats))

        if hls_manifest:
            streams.update(
                HLSStream.parse_variant_playlist(self.session,
                                                 hls_manifest,
                                                 name_key="pixels"))

        if not streams and protected:
            raise PluginError(
                "This plugin does not support protected videos, try youtube-dl instead"
            )

        return streams
示例#26
0
    def _get_streams(self):
        http.headers.update({'User-Agent': useragents.CHROME})
        is_live = False

        video_id = self._find_video_id(self.url)
        if not video_id:
            log.error("Could not find a video on this page")
            return

        log.debug("Using video ID: {0}", video_id)

        info = self._get_stream_info(video_id)
        if info and info.get("status") == "fail":
            log.error("Could not get video info: {0}".format(
                info.get("reason")))
            return
        elif not info:
            log.error("Could not get video info")
            return

        if info.get("livestream") == '1' or info.get("live_playback") == '1':
            log.debug("This video is live.")
            is_live = True

        formats = info.get("fmt_list")
        streams = {}
        protected = False
        for stream_info in info.get("url_encoded_fmt_stream_map", []):
            if stream_info.get("s"):
                protected = True
                continue

            stream = HTTPStream(self.session, stream_info["url"])
            name = formats.get(stream_info["itag"]) or stream_info["quality"]

            if stream_info.get("stereo3d"):
                name += "_3d"

            streams[name] = stream

        if not is_live:
            streams, protected = self._create_adaptive_streams(
                info, streams, protected)

        hls_playlist = info.get("hlsvp")
        if hls_playlist:
            try:
                hls_streams = HLSStream.parse_variant_playlist(
                    self.session, hls_playlist, namekey="pixels")
                streams.update(hls_streams)
            except IOError as err:
                log.warning("Failed to extract HLS streams: {0}", err)

        if not streams and protected:
            raise PluginError("This plugin does not support protected videos, "
                              "try youtube-dl instead")

        return streams
示例#27
0
    def _get_video_data(self, slug):
        m = self.truncate_url_re.search(self.url)
        if m and m.group(1):
            log.debug("Truncated URL={0}".format(m.group(1)))
        else:
            raise PluginError("Failed to truncate URL")

        res = self.session.http.get(m.group(1))
        m = self.json_data_re.search(res.text)
        if m and m.group(1):
            videos = parse_json(m.group(1), schema=self._video_data_schema)
        else:
            raise PluginError("Failed to get json_data")

        for video in videos:
            if 'slug' in videos[video]:
                if slug == videos[video]['slug'] and 'id' in videos[video]:
                    return videos[video]['id']
示例#28
0
    def policy_key(self, video_id):
        # Get the embedded player page
        res = self.session.http.get(self.player_url(video_id))

        policy_key_m = self.policy_key_re.search(res.text)
        policy_key = policy_key_m and policy_key_m.group("key")
        if not policy_key:
            raise PluginError("Could not find Brightcove policy key")

        return policy_key
示例#29
0
    def _get_streams(self):
        api = self._create_api()
        media_id = int(self.match.group("media_id"))

        try:
            # the media.stream_data field is required, no stream data is returned otherwise
            info = api.get_info(media_id,
                                fields=[
                                    "media.name", "media.series_name",
                                    "media.media_type", "media.stream_data"
                                ],
                                schema=_media_schema)
        except CrunchyrollAPIError as err:
            raise PluginError(f"Media lookup error: {err.msg}")

        if not info:
            return

        streams = {}

        self.title = info.get("name")
        self.author = info.get("series_name")
        self.category = info.get("media_type")

        info = info["stream_data"]

        # The adaptive quality stream sometimes a subset of all the other streams listed, ultra is no included
        has_adaptive = any(
            [s["quality"] == "adaptive" for s in info["streams"]])
        if has_adaptive:
            log.debug("Loading streams from adaptive playlist")
            for stream in filter(lambda x: x["quality"] == "adaptive",
                                 info["streams"]):
                for q, s in HLSStream.parse_variant_playlist(
                        self.session, stream["url"]).items():
                    # rename the bitrates to low, mid, or high. ultra doesn't seem to appear in the adaptive streams
                    name = STREAM_NAMES.get(q, q)
                    streams[name] = s

        # If there is no adaptive quality stream then parse each individual result
        for stream in info["streams"]:
            if stream["quality"] != "adaptive":
                # the video_encode_id indicates that the stream is not a variant playlist
                if "video_encode_id" in stream:
                    streams[stream["quality"]] = HLSStream(
                        self.session, stream["url"])
                else:
                    # otherwise the stream url is actually a list of stream qualities
                    for q, s in HLSStream.parse_variant_playlist(
                            self.session, stream["url"]).items():
                        # rename the bitrates to low, mid, or high. ultra doesn't seem to appear in the adaptive streams
                        name = STREAM_NAMES.get(q, q)
                        streams[name] = s

        return streams
示例#30
0
    def get_streams(self, video_id):
        log.debug(f"Finding streams for video: {video_id}")

        player_url = self.URL_PLAYER.format(
            account_id=self.account_id,
            player_id=self.player_id,
            video_id=video_id
        )

        policy_key = self.session.http.get(
            player_url,
            params={"videoId": video_id},
            schema=validate.Schema(
                validate.transform(re.compile(r"""policyKey\s*:\s*(?P<q>['"])(?P<key>[\w-]+)(?P=q)""").search),
                validate.any(None, validate.get("key"))
            )
        )
        if not policy_key:
            raise PluginError("Could not find Brightcove policy key")
        log.debug(f"Found policy key: {policy_key}")

        self.session.http.headers.update({"Referer": player_url})
        sources, self.title = self.session.http.get(
            self.URL_API.format(account_id=self.account_id, video_id=video_id),
            headers={"Accept": f"application/json;pk={policy_key}"},
            schema=validate.Schema(
                validate.parse_json(),
                {
                    "sources": [{
                        "src": validate.url(),
                        validate.optional("type"): str,
                        validate.optional("container"): str,
                        validate.optional("height"): int,
                        validate.optional("avg_bitrate"): int,
                    }],
                    validate.optional("name"): str,
                },
                validate.union_get("sources", "name")
            )
        )

        for source in sources:
            if source.get("type") in ("application/vnd.apple.mpegurl", "application/x-mpegURL"):
                yield from HLSStream.parse_variant_playlist(self.session, source.get("src")).items()

            elif source.get("container") == "MP4":
                # determine quality name
                if source.get("height"):
                    q = f"{source.get('height')}p"
                elif source.get("avg_bitrate"):
                    q = f"{source.get('avg_bitrate') // 1000}k"
                else:
                    q = "live"

                yield q, HTTPStream(self.session, source.get("src"))