コード例 #1
0
def race(slug, **kwargs):
    races = api.races()
    if slug not in races:
        raise Error(_.RACE_NOT_FOUND)

    race = races[slug]
    folder = plugin.Folder(race['title'], no_items_label=_.NO_STREAMS)

    for stream in race['streams']:
        if not stream['slug']:
            continue

        item = plugin.Item(
            label = stream['label'],
            path  = plugin.url_for(play, slug=stream['slug']),
            playable = True,
        )

        if stream['live']:
            item.label = _(_.LIVE_LABEL, title=stream['label'])

            item.context.append((_.PLAY_FROM_LIVE, "PlayMedia({})".format(
                plugin.url_for(play, slug=stream['slug'], play_type=PLAY_FROM_LIVE, _is_live=True)
            )))

            item.context.append((_.PLAY_FROM_START, "PlayMedia({})".format(
                plugin.url_for(play, slug=stream['slug'], play_type=PLAY_FROM_START, _is_live=True)
            )))

            item.path = plugin.url_for(play, slug=stream['slug'], play_type=settings.getEnum('live_play_type', PLAY_FROM_TYPES, PLAY_FROM_ASK), _is_live=True)

        folder.add_items([item])

    return folder
コード例 #2
0
def check_alerts():
    alerts = userdata.get('alerts', [])
    if not alerts: return

    for game in Game.select().where(Game.id << alerts):
        if game.state == Game.LIVE:
            alerts.remove(game.id)

            _to_start = game.start - arrow.utcnow().timestamp

            if settings.getInt('alert_when') == Alert.STREAM_START:
                message = _.STREAM_STARTED
            elif settings.getInt('alert_when') == Alert.KICK_OFF and _to_start > 0 and _to_start <= SERVICE_TIME:
                message = _.KICKOFF
            else:
                continue

            if settings.getInt('alert_type') == Alert.NOTIFICATION:
                gui.notification(message, heading=game.title, time=5000, icon=game.image)

            elif gui.yes_no(message, heading=game.title, yeslabel=_.WATCH, nolabel=_.CLOSE):
                _get_play_item(game, Game.FULL, play_type=settings.getEnum('live_play_type', PLAY_FROM_TYPES, default=PLAY_FROM_ASK)).play()

        elif game.state != Game.UPCOMING:
            alerts.remove(game.id)

    userdata.set('alerts', alerts)
コード例 #3
0
def service():
    api.refresh_token()
    alerts = userdata.get('alerts', [])
    if not alerts:
        return

    now = arrow.now()
    notify = []
    _alerts = []

    for id in alerts:
        entity = api.entitiy(id)
        if not entity:
            continue

        start = arrow.get(entity.get('startTime'))

        if now > start and (now - start).total_seconds() <= 60 * 10:
            notify.append(entity)
        elif now < start:
            _alerts.append(id)

    userdata.set('alerts', _alerts)

    for entity in notify:
        if not gui.yes_no(_(_.EVENT_STARTED, event=entity['name']),
                          yeslabel=_.WATCH,
                          nolabel=_.CLOSE):
            continue

        with signals.throwable():
            play(id=entity['id'],
                 play_type=settings.getEnum('live_play_type',
                                            LIVE_PLAY_TYPES,
                                            default=FROM_CHOOSE))
コード例 #4
0
def _play_videos(videos):
    if not videos:
        plugin.exception('No videos found')

    default_audio = settings.getEnum('audio_lang', AUDIO_LANGS)

    if len(videos) == 1:
        chosen = videos[0]
    else:
        videos = sorted(videos, key=lambda x: x['language'])

        chosen = None
        for video in videos:
            if video['language']['iso_639_3'].lower() == default_audio:
                chosen = video
                break

        if not chosen:
            index = gui.select(_.SELECT_LANG,
                               [x['language']['name'] for x in videos])
            if index < 0:
                return

            chosen = videos[index]

    url, license_url = api.play(chosen['id'])
    item = plugin.Item(
        inputstream=inputstream.Widevine(license_url),
        path=url,
        headers=HEADERS,
        use_proxy=
        True,  # Needed for https://github.com/xbmc/inputstream.adaptive/pull/606
    )

    return item
コード例 #5
0
ファイル: plugin.py プロジェクト: matthuisman/slyguy.addons
def _process_rows(rows):
    items = []
    now = arrow.utcnow()

    for row in rows:
        try:
            thumb = IMG_URL.format(
                row.get('pictureID') or row['pictures']['16x9'])
        except:
            thumb = None

        start_time = arrow.get(row.get('startTime') or None)
        end_time = arrow.get(row.get('endTime') or None)
        now = arrow.utcnow()

        item = plugin.Item(
            label=row['name'],
            info={'plot': row.get('shortDescription')},
            art={'thumb': thumb},
            path=plugin.url_for(play, id=row['id']),
            playable=True,
            is_folder=False,
        )

        if row.get('resourceType') == 'epg/stations':
            item.path = plugin.url_for(play, id=row['id'], _is_live=True)

        elif start_time < now and end_time > now:
            item.label += _(_.LIVE, _bold=True)

            if row.get('customAttributes',
                       {}).get('isLinearChannelInLiveEvent') != 'true':
                item.context.append((_.PLAY_FROM_LIVE, "PlayMedia({})".format(
                    plugin.url_for(play,
                                   id=row['id'],
                                   play_type=PLAY_FROM_LIVE,
                                   _is_live=True))))

                item.context.append((_.PLAY_FROM_START, "PlayMedia({})".format(
                    plugin.url_for(play,
                                   id=row['id'],
                                   play_type=PLAY_FROM_START,
                                   _is_live=True))))

            item.path = plugin.url_for(play,
                                       id=row['id'],
                                       play_type=settings.getEnum(
                                           'live_play_type', PLAY_FROM_TYPES,
                                           PLAY_FROM_ASK),
                                       _is_live=True)

        elif start_time > now.shift(seconds=10):
            item.label += start_time.to('local').format(_.DATE_FORMAT)

        items.append(item)

    return items
コード例 #6
0
def editorial(id, title, **kwargs):
    folder = plugin.Folder(title)
    now = arrow.utcnow()

    live_play_type = settings.getEnum('live_play_type',
                                      PLAY_FROM_TYPES,
                                      default=PLAY_FROM_ASK)

    for row in api.editorial(id):
        is_live = row.get('isLive', False)
        is_linear = row.get('type') == 'linear-channel'

        item = plugin.Item(
            label=row['title'],
            info={
                'plot': row.get('description'),
                'duration': row.get('duration', 0),
            },
            art={'thumb': row.get('imageUrl') or DEFAULT_IMG},
            path=plugin.url_for(play, asset=row['id'], _is_live=is_live),
            playable=True,
            is_folder=False,
        )

        start_time = arrow.get(
            row['broadcastStartTime']) if 'broadcastStartTime' in row else None

        if start_time and start_time > now:
            item.label += start_time.to('local').format(_.DATE_FORMAT)

        elif is_linear:
            item.path = plugin.url_for(play, asset=row['id'], _is_live=is_live)

        elif is_live:
            item.label = _(_.LIVE, label=item.label)

            item.context.append((_.PLAY_FROM_LIVE, "PlayMedia({})".format(
                plugin.url_for(play,
                               asset=row['id'],
                               play_type=PLAY_FROM_LIVE,
                               _is_live=is_live))))

            item.context.append((_.PLAY_FROM_START, "PlayMedia({})".format(
                plugin.url_for(play,
                               asset=row['id'],
                               play_type=PLAY_FROM_START,
                               _is_live=is_live))))

            item.path = plugin.url_for(play,
                                       asset=row['id'],
                                       play_type=live_play_type,
                                       _is_live=is_live)

        folder.add_items(item)

    return folder
コード例 #7
0
ファイル: api.py プロジェクト: Raspifan2020/slyguy.addons
    def _create_session(self, force=False):
        self._config = self.get_config()
        platform = self._config['alpha_networks_dash'][REGION]

        self._session._base_url = platform['platform_url'] + '{}'
        self._session.headers.update({
            'X-AN-WebService-IdentityKey':
            platform['hss_key'],  # hss_key, hls_key, chromecast_key
        })

        if not self.logged_in or (not force and
                                  time.time() < userdata.get('token_expires')):
            return

        login_type = settings.getEnum('login_type',
                                      choices=LOGIN_TYPE,
                                      default=LOGIN_MULTI_IP)

        if login_type == LOGIN_MULTI_IP:
            # Single device, changing IP address (same as app)
            data = self._session.post('proxy/loginDevice',
                                      headers=self._auth_headers).json()

        elif login_type == LOGIN_MULTI_DEVICE:
            # Multiple device, static IP address
            data = self._session.post('proxy/casAvailableDevice',
                                      headers=self._auth_headers).json()

        elif login_type == LOGIN_PASSWORD:
            # Supports multiple devices and multiple IP address as long (as others also using password)
            data = {
                'password': userdata.get('password'),
                'deviceId': userdata.get('device_id'),
                'email': userdata.get('username'),
            }

            data = self._session.post('proxy/login', data=data).json()

        if data['error']:
            error = _(_.TOKEN_ERROR, msg=data['error']['message'])

            if data['error']['code'] == -1:
                self.logout()
                gui.refresh()

                if login_type == LOGIN_MULTI_IP:
                    error = _.LOGIN_MULTI_IP_ERROR
                elif login_type == LOGIN_MULTI_DEVICE:
                    error = _.LOGIN_MULTI_DEVICE_ERROR

            raise APIError(error)

        if 'deviceAuthToken' in data['result']:
            userdata.set('device_token', data['result']['deviceAuthToken'])

        self._set_auth(data['result']['newAuthToken'])
コード例 #8
0
def parse_game(game):
    item = plugin.Item(
        label=game.title,
        art={'thumb': game.image},
        info={
            'title': game.title,
            'plot': game.description,
            'duration': game.duration,
            'aired': game.aired,
        },
        playable=True,
    )

    if game.state in (Game.LIVE, Game.UPCOMING):
        item.path = plugin.url_for(play,
                                   slug=game.slug,
                                   game_type=Game.FULL,
                                   play_type=settings.getEnum(
                                       'live_play_type',
                                       PLAY_FROM_TYPES,
                                       default=PLAY_FROM_ASK),
                                   _is_live=True)

        item.context.append((_.WATCH_LIVE, "PlayMedia({0})".format(
            plugin.url_for(play,
                           slug=game.slug,
                           game_type=Game.FULL,
                           play_type=PLAY_FROM_LIVE,
                           _is_live=True))))

        item.context.append((_.WATCH_FROM_START, "PlayMedia({0})".format(
            plugin.url_for(play,
                           slug=game.slug,
                           game_type=Game.FULL,
                           play_type=PLAY_FROM_START,
                           _is_live=True))))

    elif game.state == Game.PROCESSING:
        item.path = plugin.url_for(play, slug=game.slug, game_type=Game.FULL)
        item.context.append((_.FULL_GAME, "PlayMedia({0})".format(item.path)))

    elif game.state == Game.PLAYED:
        item.path = plugin.url_for(play, slug=game.slug, game_type=Game.FULL)
        item.context.append((_.FULL_GAME, "PlayMedia({0})".format(item.path)))
        item.context.append((_.CONDENSED_GAME, "PlayMedia({0})".format(
            plugin.url_for(play, slug=game.slug, game_type=Game.CONDENSED))))

    if game.result:
        item.context.append(
            (_.SHOW_SCORE,
             "RunPlugin({0})".format(plugin.url_for(show_score,
                                                    slug=game.slug))))

    return item
コード例 #9
0
    def login(self, username, password):
        self.logout()
        self._create_session()

        data = {
            'password': password,
            'email': username,
        }

        data = self._session.post('proxy/login', data=data).json()
        if data['error']:
            raise APIError(_(_.LOGIN_ERROR, msg=data['error']['message']))

        auth_token = data['result']['newAuthToken']

        while True:
            selected = self._select_device(auth_token)
            if not selected:
                return

            data = {
                'password': password,
                'deviceId': selected['uniqueDeviceId'],
                'email': username,
            }

            data = self._session.post('proxy/login', data=data).json()
            if data['error']:
                gui.error(data['error']['message'])
            else:
                break

        auth_token   = data['result']['newAuthToken']
        device_token = data['result']['deviceAuthToken']
        userdata.set('device_token', device_token)

        data = {
            'name': selected['name'],
            'casDeviceId': selected['uniqueDeviceId'],
            'type': selected['type'],
        }

        data = self._session.post('proxy/casAuth', data=data, headers={'X-AN-WebService-CustomerAuthToken': auth_token, 'X-AN-WebService-DeviceAuthToken': device_token}).json()
        if data['error']:
            raise APIError(data['error']['message'])

        self._set_auth(data['result']['newAuthToken'])
        mem_cache.delete('channels')

        if settings.getEnum('login_type', choices=LOGIN_TYPE, default=LOGIN_MULTI_IP) == LOGIN_PASSWORD:
            userdata.set('password', password)
            userdata.set('device_id', selected['uniqueDeviceId'])
コード例 #10
0
ファイル: api.py プロジェクト: Raspifan2020/slyguy.addons
    def new_session(self):
        self._session = Session(HEADERS)
        self._cache_key = self._region = settings.getEnum('region', REGIONS, default=US)

        if self._region in X_FORWARDS:
            self._session.headers.update({'x-forwarded-for': X_FORWARDS[self._region]})

        elif self._region == CUSTOM:
            region_ip = settings.get('region_ip', '0.0.0.0')
            if region_ip != '0.0.0.0':
                self._session.headers.update({'x-forwarded-for': region_ip})
                self._cache_key = region_ip

        self._cache_key += str(settings.getBool('show_epg', False))
コード例 #11
0
def play(video_id, play_type=None, **kwargs):
    url = api.play(video_id)
    play_type = int(play_type) if play_type else settings.getEnum(
        'live_play_type', PLAY_FROM_TYPES, default=PLAY_FROM_ASK)
    is_live = ROUTE_LIVE_TAG in kwargs

    item = plugin.Item(
        path=url,
        inputstream=inputstream.HLS(live=is_live),
    )

    # if is_live and (play_type == PLAY_FROM_START or (play_type == PLAY_FROM_ASK and not gui.yes_no(_.PLAY_FROM, yeslabel=_.PLAY_FROM_LIVE, nolabel=_.PLAY_FROM_START))):
    #     item.properties['ResumeTime'] = '1'
    #     item.properties['TotalTime']  = '1'
    #     item.inputstream.force = True

    return item
コード例 #12
0
def service():
    alerts = userdata.get('alerts', [])
    if not alerts:
        return

    now = arrow.now()
    notify = []
    _alerts = []

    for id in alerts:
        asset = api.event(id)
        start = arrow.get(asset.get('preCheckTime', asset['transmissionTime']))

        #If we are streaming and started less than 10 minutes ago
        if asset.get('isStreaming',
                     False) and (now - start).total_seconds() <= 60 * 10:
            notify.append(asset)
        elif start > now:
            _alerts.append(id)

    userdata.set('alerts', _alerts)

    for asset in notify:
        if not gui.yes_no(_(_.EVENT_STARTED, event=asset['title']),
                          yeslabel=_.WATCH,
                          nolabel=_.CLOSE):
            continue

        with signals.throwable():
            start_from = 1
            start = arrow.get(asset['transmissionTime'])

            if start < now and 'preCheckTime' in asset:
                precheck = arrow.get(asset['preCheckTime'])
                if precheck < start:
                    start_from = (start - precheck).seconds

            play(id=asset['id'],
                 start_from=start_from,
                 play_type=settings.getEnum('live_play_type',
                                            LIVE_PLAY_TYPES,
                                            default=FROM_CHOOSE))
コード例 #13
0
def _parse_video(row):
    asset = row['asset']
    display = row['contentDisplay']
    alerts = userdata.get('alerts', [])

    now = arrow.now()
    start = arrow.get(asset['transmissionTime'])
    precheck = start

    if 'preCheckTime' in asset:
        precheck = arrow.get(asset['preCheckTime'])
        if precheck > start:
            precheck = start

    title = display['title'] or asset['title']
    if 'heroHeader' in display:
        title += ' [' + display['heroHeader'].replace(
            '${DATE_HUMANISED}',
            _makeHumanised(now, start).upper()).replace(
                '${TIME}', _makeTime(start)) + ']'

    item = plugin.Item(
        label=title,
        art={
            'thumb': _get_image(asset, 'video', 'thumb'),
            'fanart': _get_image(asset, 'video', 'fanart'),
        },
        info={
            'plot': display.get('description'),
            'plotoutline': display.get('description'),
            'mediatype': 'video',
        },
        playable=True,
        is_folder=False,
    )

    is_live = False
    play_type = settings.getEnum('live_play_type',
                                 PLAY_FROM_TYPES,
                                 default=PLAY_FROM_ASK)
    start_from = ((start - precheck).seconds)

    if start_from < 1:
        start_from = 1

    if now < start:
        is_live = True
        toggle_alert = plugin.url_for(alert,
                                      asset=asset['id'],
                                      title=asset['title'])

        if asset['id'] not in userdata.get('alerts', []):
            item.info['playcount'] = 0
            item.context.append(
                (_.SET_REMINDER, "RunPlugin({})".format(toggle_alert)))
        else:
            item.info['playcount'] = 1
            item.context.append(
                (_.REMOVE_REMINDER, "RunPlugin({})".format(toggle_alert)))

    elif asset['assetType'] == 'live-linear':
        is_live = True
        start_from = 0
        play_type = PLAY_FROM_LIVE

    elif asset['isLive'] and asset.get('isStreaming', False):
        is_live = True

        item.context.append((_.PLAY_FROM_LIVE, "PlayMedia({})".format(
            plugin.url_for(play,
                           id=asset['id'],
                           play_type=PLAY_FROM_LIVE,
                           _is_live=is_live))))

        item.context.append((_.PLAY_FROM_START, "PlayMedia({})".format(
            plugin.url_for(play,
                           id=asset['id'],
                           start_from=start_from,
                           play_type=PLAY_FROM_START,
                           _is_live=is_live))))

    item.path = plugin.url_for(play,
                               id=asset['id'],
                               start_from=start_from,
                               play_type=play_type,
                               _is_live=is_live)

    return item
コード例 #14
0
def parse_game(game):
    item = plugin.Item(
        label     = game.title,
        is_folder = False,
        playable  = game.state != Game.UPCOMING,
        art       = {'thumb': game.image},
        info      = {
            'title':    game.title,
            'plot':     game.description,
            'duration': game.duration,
            'aired':    game.aired,
        },
    )

    if game.state == Game.UPCOMING:
        item.path = plugin.url_for(alerts, slug=game.slug)

        if game.id not in userdata.get('alerts', []):
            item.info['playcount'] = 0
            item.context.append((_.SET_REMINDER, "RunPlugin({0})".format(item.path)))
        else:
            item.info['playcount'] = 1
            item.context.append((_.REMOVE_REMINDER, "RunPlugin({0})".format(item.path)))

    elif game.state == Game.LIVE:
        item.path = plugin.url_for(play, slug=game.slug, game_type=Game.FULL, play_type=settings.getEnum('live_play_type', PLAY_FROM_TYPES, default=PLAY_FROM_ASK), _is_live=True)

        item.context.append((_.WATCH_LIVE, "PlayMedia({0})".format(
            plugin.url_for(play, slug=game.slug, game_type=Game.FULL, play_type=PLAY_FROM_LIVE, _is_live=True)
        )))

        item.context.append((_.WATCH_FROM_START, "PlayMedia({0})".format(
            plugin.url_for(play, slug=game.slug, game_type=Game.FULL, play_type=PLAY_FROM_START, _is_live=True)
        )))

    elif game.state == Game.PROCESSING:
        item.path = plugin.url_for(play, slug=game.slug, game_type=Game.FULL)
        item.context.append((_.FULL_GAME, "PlayMedia({0})".format(item.path)))

    elif game.state == Game.PLAYED:
        item.path = plugin.url_for(play, slug=game.slug, game_type=Game.FULL)
        item.context.append((_.FULL_GAME, "PlayMedia({0})".format(item.path)))
        item.context.append((_.CONDENSED_GAME, "PlayMedia({0})".format(
            plugin.url_for(play, slug=game.slug, game_type=Game.CONDENSED)
        )))

    if game.result:
        item.context.append((_.SHOW_SCORE, "RunPlugin({0})".format(
            plugin.url_for(show_score, slug=game.slug)
        )))

    return item
コード例 #15
0
ファイル: plugin.py プロジェクト: Raspifan2020/slyguy.addons
def _process_entries(entries):
    items = []

    now = arrow.now()
    play_type = settings.getEnum('live_play_type', PLAY_FROM_TYPES, default=PLAY_FROM_ASK)

    for row in entries:
        if row.get('type') in ('posters', 'landscapes') and not row.get('hideTitle', False):
            items.append(plugin.Item(
                label = row['title'],
                #art   = {'thumb': row.get('thumbnail')},
                path  = plugin.url_for(parse, url=row['url'], title=row['title']),
            ))
        elif row.get('programType') == 'series':
            items.append(plugin.Item(
                label = row['title'],
                art   = {'thumb': _art(row['images']), 'fanart': _art(row['images'], 'fanart')},
                info  = {
                    'plot': row['description'],
                    'year': row['releaseYear'],
                },
                path = plugin.url_for(series, series_id=row['id']),
            ))

        elif row.get('programType') == 'movie':
            item = plugin.Item(
                label    = row['title'],
                info     = {
                    'plot': row['description'],
                    'year': row['releaseYear'],
                    'duration': row['runtime'],
                    'mediatype': 'movie',
                },
                art      = {'thumb': _art(row['images']), 'fanart': _art(row['images'], 'fanart')},
                playable = True,
                path     = _get_play_path(program_id=row['id']),
            )

            if row.get('liveStartDate'):
                is_live = False
                start_date = arrow.get(int(row['liveStartDate'])/1000)

                if row.get('liveEndDate'):
                    end_date = arrow.get(int(row['liveEndDate']/1000))
                else:
                    end_date = start_date

                if start_date > now:
                    item.label += ' [{}]'.format(start_date.humanize())
                elif start_date < now and end_date > now:
                    is_live = True
                    item.label += ' [B][LIVE][/B]'

                if 'episode' in row:
                    program_id = row['episode']['id']
                    if row['episode']['bonusFeature']:
                        item.info['duration'] = None
                else:
                    program_id = row['id']

                item.path = _get_play_path(program_id=program_id, play_type=play_type, _is_live=is_live)

                if is_live:
                    item.context.append((_.PLAY_FROM_LIVE, "PlayMedia({})".format(
                        _get_play_path(program_id=row['id'], play_type=PLAY_FROM_LIVE, _is_live=is_live)
                    )))

                    item.context.append((_.PLAY_FROM_START, "PlayMedia({})".format(
                        _get_play_path(program_id=row['id'], play_type=PLAY_FROM_START, _is_live=is_live)
                    )))

            items.append(item)

    return items
コード例 #16
0
def play(id, start_from=0, play_type=PLAY_FROM_LIVE, **kwargs):
    asset = api.stream(id)

    start_from = int(start_from)
    play_type = int(play_type)
    is_live = kwargs.get(ROUTE_LIVE_TAG) == ROUTE_LIVE_SUFFIX

    streams = [asset['recommendedStream']]
    streams.extend(asset['alternativeStreams'])
    streams = [s for s in streams if s['mediaFormat'] in SUPPORTED_FORMATS]

    if not streams:
        raise PluginError(_.NO_STREAM)

    prefer_cdn = settings.getEnum('prefer_cdn', AVAILABLE_CDNS)
    if prefer_cdn == CDN_AUTO:
        try:
            prefer_cdn = api.use_cdn(is_live)['useCDN']
        except Exception as e:
            log.debug('Failed to get preferred cdn')
            prefer_cdn = None

    providers = [prefer_cdn]
    providers.extend([s['provider'] for s in streams])

    streams = sorted(streams,
                     key=lambda k: (providers.index(k['provider']),
                                    SUPPORTED_FORMATS.index(k['mediaFormat'])))
    stream = streams[0]

    log.debug('Stream CDN: {provider} | Stream Format: {mediaFormat}'.format(
        **stream))

    item = plugin.Item(
        path=stream['manifest']['uri'],
        art=False,
        headers=HEADERS,
    )

    item.headers.update(
        {'authorization': 'Bearer {}'.format(userdata.get('access_token'))})

    if is_live and (play_type == PLAY_FROM_LIVE or
                    (play_type == PLAY_FROM_ASK
                     and gui.yes_no(_.PLAY_FROM,
                                    yeslabel=_.PLAY_FROM_LIVE,
                                    nolabel=_.PLAY_FROM_START))):
        play_type = PLAY_FROM_LIVE
        start_from = 0

    ## Cloudfront streams start from correct position
    if stream['provider'] == CDN_CLOUDFRONT and start_from:
        start_from = 1

    if stream['mediaFormat'] == FORMAT_DASH:
        item.inputstream = inputstream.MPD()

    elif stream['mediaFormat'] == FORMAT_HLS_TS:
        force = (is_live and play_type == PLAY_FROM_LIVE
                 and asset['assetType'] != 'live-linear')
        item.inputstream = inputstream.HLS(force=force, live=is_live)
        if force and not item.inputstream.check():
            raise PluginError(_.HLS_REQUIRED)

    elif stream['mediaFormat'] == FORMAT_HLS_FMP4:
        item.inputstream = inputstream.HLS(force=True, live=is_live)
        if not item.inputstream.check():
            raise PluginError(_.HLS_REQUIRED)

    elif stream['mediaFormat'] in (FORMAT_DRM_DASH, FORMAT_DRM_DASH_HEVC):
        item.inputstream = inputstream.Widevine(license_key=LICENSE_URL, )

    if start_from and not kwargs[ROUTE_RESUME_TAG]:
        item.properties['ResumeTime'] = start_from
        item.properties['TotalTime'] = start_from

    return item
コード例 #17
0
def play(asset_id, **kwargs):
    use_ia_hls = settings.getBool('use_ia_hls')
    stream_data = api.get_stream_data(asset_id)
    token = userdata.get('access_token')

    play_item = plugin.Item(
        art=False,
        headers={'Authorization': 'Bearer {}'.format(token)},
        cookies={
            'access_token': token,
            'client_id': CLIENT_ID
        },
    )

    is_drm = stream_data.get('course_is_drmed', False)

    hls_url = stream_data.get('hls_url')
    if hls_url and not is_drm:
        play_item.path = hls_url
        play_item.inputstream = inputstream.HLS(live=False)
        return play_item

    stream_urls = stream_data.get('stream_urls') or {}
    streams = stream_urls.get('Video') or stream_urls.get('Audio') or []

    CODECS = {
        'libx264': 'H.264',
        'libx265': 'H.265',
    }

    urls = []
    qualities = []
    for item in streams:
        if item['type'] != 'application/x-mpegURL':
            data = stream_data['data']['outputs'][item['label']]

            if data.get('migrated_from_non_labeled_conversions'):
                bandwidth, resolution = BANDWIDTH_MAP.get(int(item['label']))
                codecs, fps = '', ''
            else:
                fps = _(_.QUALITY_FPS, fps=float(data['frame_rate']))
                resolution = '{}x{}'.format(data['width'], data['height'])
                bandwidth = data[
                    'video_bitrate_in_kbps'] * 1000  #(or total_bitrate_in_kbps)
                codecs = CODECS.get(data.get('video_codec'), '')

            urls.append([bandwidth, item['file']])
            qualities.append([
                bandwidth,
                _(_.QUALITY_BITRATE,
                  bandwidth=float(bandwidth) / 1000000,
                  resolution=resolution,
                  fps=fps,
                  codecs=codecs)
            ])

    if not urls:
        for row in stream_data.get('media_sources') or []:
            if row['type'] == 'application/x-mpegURL' and 'encrypted-files' not in row[
                    'src']:
                urls.append([row['src'], inputstream.HLS(live=False)])

            if row['type'] == 'application/dash+xml':
                play_item.path = row['src']

                if is_drm:
                    token = stream_data['media_license_token']
                    ia = inputstream.Widevine(license_key=WV_URL.format(
                        token=token))
                else:
                    ia = inputstream.MPD()

                urls.append([row['src'], ia])

        if urls:
            urls = sorted(urls,
                          key=lambda x: isinstance(x[1], inputstream.Widevine))
            play_item.path = urls[0][0]
            play_item.inputstream = urls[0][1]
            if isinstance(play_item.inputstream, inputstream.Widevine):
                system, arch = get_system_arch()
                if system == 'Windows' or (system == 'Linux'
                                           and arch == 'armv7'):
                    gui.ok(_.VMP_WARNING)

            return play_item

    if not urls:
        raise plugin.Error(_.NO_STREAM_ERROR)

    quality = kwargs.get(QUALITY_TAG)
    if quality is None:
        quality = settings.getEnum('default_quality',
                                   QUALITY_TYPES,
                                   default=QUALITY_ASK)
    else:
        quality = int(quality)

    urls = sorted(urls, key=lambda s: s[0], reverse=True)
    qualities = sorted(qualities, key=lambda s: s[0], reverse=True)

    if quality == QUALITY_CUSTOM:
        quality = int(settings.getFloat('max_bandwidth') * 1000000)
    elif quality == QUALITY_ASK:
        quality = select_quality(qualities)

    if quality == QUALITY_BEST:
        quality = qualities[0][0]
    elif quality == QUALITY_LOWEST:
        quality = qualities[-1][0]

    play_item.path = urls[-1][1]
    for item in urls:
        if item[0] <= quality:
            play_item.path = item[1]
            break

    return play_item
コード例 #18
0
 def load(self):
     self._region = settings.getEnum('region_index', REGIONS, default=REGION_US)
コード例 #19
0
ファイル: plugin.py プロジェクト: Raspifan2020/slyguy.addons
def epg(output, **kwargs):
    region = settings.getEnum('region', REGIONS, default=US)

    if region not in (LOCAL, CUSTOM):
        epg_url = MH_EPG_URL.format(region=region)

        try:
            Session().chunked_dl(epg_url, output)
            if epg_url.endswith('.gz'):
                gzip_extract(output)
            return True
        except Exception as e:
            log.exception(e)
            log.debug(
                'Failed to get remote epg: {}. Fall back to scraping'.format(
                    epg_url))

    def process_epg(channels):
        count = 0
        for id in channels:
            channel = channels[id]
            for row in channel.get('programs', []):
                start = arrow.get(row['start']).to('utc')
                stop = arrow.get(row['stop']).to('utc')
                title = row['title']
                description = row['episode']['description']
                subtitle = row['episode']['name']
                category = row['episode']['genre']
                icon = None

                if subtitle.lower().strip() == title.lower().strip():
                    subtitle = None

                f.write(
                    u'<programme channel="{}" start="{}" stop="{}"><title>{}</title><desc>{}</desc>{}{}{}</programme>'
                    .format(
                        id,
                        start.format('YYYYMMDDHHmmss Z'),
                        stop.format('YYYYMMDDHHmmss Z'),
                        escape(title),
                        escape(description),
                        u'<icon src="{}"/>'.format(escape(icon))
                        if icon else '',
                        u'<sub-title>{}</sub-title>'.format(escape(subtitle))
                        if subtitle else '',
                        u'<category>{}</category>'.format(escape(category))
                        if category else '',
                    ))

                count += 1

        return count

    HOUR_SHIFT = 6
    now = arrow.now()
    start = now.replace(minute=0, second=0, microsecond=0).to('utc')
    stop = start.shift(hours=HOUR_SHIFT)
    END_TIME = start.shift(days=settings.getInt('epg_days', 3))

    with codecs.open(output, 'w', encoding='utf8') as f:
        f.write(u'<?xml version="1.0" encoding="utf-8" ?><tv>')

        channels = api.epg(start, stop)
        for id in channels:
            f.write(u'<channel id="{id}"/>'.format(id=id))

        added = process_epg(channels)
        while stop < END_TIME:
            start = stop
            stop = start.shift(hours=HOUR_SHIFT)

            channels = api.epg(start, stop)
            added = process_epg(channels)

            if added <= len(channels):
                break

        f.write(u'</tv>')
コード例 #20
0
ファイル: plugin.py プロジェクト: Raspifan2020/slyguy.addons
def _parse_video(asset):
    alerts = userdata.get('alerts', [])
    now = arrow.now()
    start = arrow.get(asset['transmissionTime'])
    precheck = start

    if asset['preCheckTime']:
        precheck = arrow.get(asset['preCheckTime'])
        if precheck > start:
            precheck = start

    # if 'heroHeader' in row['contentDisplay']:
    #     title += ' [' + row['contentDisplay']['heroHeader'].replace('${DATE_HUMANISED}', _makeHumanised(now, start).upper()).replace('${TIME}', _makeTime(start)) + ']'

    item = plugin.Item(
        label=asset['title'],
        art={
            'thumb': asset['thumb'],
            'fanart': asset['fanart'],
        },
        info={
            'plot': asset['plot'],
            'rating': asset.get('rating'),
            'season': asset.get('season'),
            'episode': asset.get('episode'),
            'tvshowtitle': asset.get('showtitle'),
            'duration': asset.get('duration'),
            'year': asset.get('year'),
            'mediatype': 'episode' if asset.get('episode') else 'movie',
        },
        playable=True,
        is_folder=False,
    )

    is_live = False
    play_type = settings.getEnum('live_play_type',
                                 PLAY_FROM_TYPES,
                                 default=PLAY_FROM_ASK)
    start_from = ((start - precheck).seconds)

    if start_from < 0:
        start_from = 0

    if now < start:
        is_live = True
        toggle_alert = plugin.url_for(alert,
                                      asset=asset['asset_id'],
                                      title=asset['title'])

        if asset['asset_id'] not in userdata.get('alerts', []):
            item.info['playcount'] = 0
            item.context.append(
                (_.SET_REMINDER, "RunPlugin({})".format(toggle_alert)))
        else:
            item.info['playcount'] = 1
            item.context.append(
                (_.REMOVE_REMINDER, "RunPlugin({})".format(toggle_alert)))

    elif asset['type'] == 'live-linear':
        is_live = True
        start_from = 0
        play_type = PLAY_FROM_START

    elif asset['playbackType'] == 'LIVE' and click['isStreaming']:
        is_live = True

        item.context.append((_.PLAY_FROM_LIVE, "PlayMedia({})".format(
            plugin.url_for(play,
                           id=asset['asset_id'],
                           play_type=PLAY_FROM_LIVE,
                           _is_live=is_live))))

        item.context.append((_.PLAY_FROM_START, "PlayMedia({})".format(
            plugin.url_for(play,
                           id=asset['asset_id'],
                           start_from=start_from,
                           play_type=PLAY_FROM_START,
                           _is_live=is_live))))

    item.path = plugin.url_for(play,
                               id=asset['asset_id'],
                               start_from=start_from,
                               play_type=play_type,
                               _is_live=is_live)

    return item