コード例 #1
0
ファイル: plugin.py プロジェクト: Raspifan2020/slyguy.addons
def service():
    alerts = userdata.get('alerts', [])
    if not alerts:
        return

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

    for id in alerts:
        asset = api.asset(id)
        if 'broadcastStartTime' not in asset:
            continue

        start = arrow.get(asset['broadcastStartTime'])

        if now > start and (now - start).total_seconds() <= 60 * 10:
            notify.append(asset)
        elif now < start:
            _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():
            play(asset['id'])
コード例 #2
0
ファイル: api.py プロジェクト: Raspifan2020/slyguy.addons
    def login(self, username, password):
        try:
            payload = {
                'email': username,
                'password': password,
            }

            data = self._session.post(
                'https://api.watchnebula.com/api/v1/auth/login/',
                json=payload).json()
            key = data.get('key')

            if not key:
                msg = data['non_field_errors'][0]
                raise APIError(msg)

            userdata.set('key', key)
            self._set_auth(key)

            data = self._session.get(
                'https://api.watchnebula.com/api/v1/auth/user/',
                params={
                    'from': 'Android'
                },
                json={}).json()
            userdata.set('user_id', data['zobject_user_id'])

            self._token(force=True)
        except:
            self.logout()
            raise
コード例 #3
0
def search(query=None, page=1, **kwargs):
    page = int(page)

    if not query:
        query = gui.input(_.SEARCH, default=userdata.get('search', '')).strip()
        if not query:
            return

        userdata.set('search', query)

    data = api.search(query=query, page=page)
    rows = data.get('item', [])
    page_number = data['paginationMetadata']['pageNumber']
    page_size = data['paginationMetadata']['pageSize']
    total_items = data['paginationMetadata'].get('totalCount', 0)
    total_pages = int(math.ceil(float(total_items) / page_size))

    folder = plugin.Folder(
        _(_.SEARCH_FOR, query=query, page=page_number,
          total_pages=total_pages))

    items = _process_items(rows)
    folder.add_items(items)

    if total_pages > page_number:
        folder.add_item(
            label=_(_.NEXT_PAGE,
                    next=page_number + 1,
                    total_pages=total_pages,
                    _bold=True),
            path=plugin.url_for(search, query=query, page=page_number + 1),
        )

    return folder
コード例 #4
0
ファイル: plugin.py プロジェクト: Raspifan2020/slyguy.addons
def search(query=None, page=1, **kwargs):
    page  = int(page)

    if not query:
        query = gui.input(_.SEARCH, default=userdata.get('search', '')).strip()
        if not query:
            return

        userdata.set('search', query)

    folder = plugin.Folder(_(_.SEARCH_FOR, query=query))

    data = api.search(query, page=page)

    hits = [x['hit'] for x in data['hits']] if data['resultsType'] == 'real' else []
    items = _process_rows(hits)
    folder.add_items(items)

    if (data['meta']['page_size'] + data['meta']['offset']) < data['meta']['hits']:
        folder.add_item(
            label = _(_.NEXT_PAGE, page=page+1),
            path  = plugin.url_for(search, query=query, page=page+1),
            specialsort = 'bottom',
        )

    return folder
コード例 #5
0
ファイル: plugin.py プロジェクト: Raspifan2020/slyguy.addons
def service():
    alerts = userdata.get('alerts', [])
    if not alerts:
        return

    data = api.live_matches()
    if not data['live']:
        return

    notify = []

    for row in data['live']:
        if row['mid'] in alerts:
            alerts.remove(row['mid'])
            notify.append(row)

    userdata.set('alerts', alerts)

    for row in notify:
        if not gui.yes_no(_(_.MATCH_STARTED, match=row['subtitle']),
                          yeslabel=_.WATCH,
                          nolabel=_.CLOSE):
            continue

        with signals.throwable():
            sources = row['stream']['video_sources']
            priority = sources[0]['priority']

            item = _play_live(match_id=row['mid'], priority=1)
            item.play()
コード例 #6
0
    def set_profile(self, profile, pin=None):
        self._refresh_token()

        endpoint = self.get_config()['services']['account']['client'][
            'endpoints']['setActiveUserProfile']['href'].format(
                profileId=profile['profileId'])

        payload = {}
        if pin:
            payload['entryPin'] = str(pin)

        grant_data = self._session.put(endpoint, json=payload).json()
        self._check_errors(grant_data)

        payload = {
            'subject_token': grant_data['assertion'],
            'subject_token_type':
            'urn:bamtech:params:oauth:token-type:account',
            'platform': 'android',
            'grant_type': 'urn:ietf:params:oauth:grant-type:token-exchange',
        }

        self._oauth_token(payload)

        userdata.set(
            'profile_language',
            profile['attributes']['languagePreferences']['appLanguage'])
コード例 #7
0
    def login(self, username, password):
        self.require_token()

        payload = {
            'Action':
            '/View/Account/SubmitLogin',
            'jsonModel':
            json.dumps({
                'Username': username,
                'Password': password,
                'IsOnboarding': False,
                'IsVoucher': False,
            }),
            'captcha':
            '',
        }

        resp = self._session.post('/View/Account/SubmitLogin', json=payload)
        token = resp.cookies.get(TOKEN_COOKIE_KEY)

        if not token:
            raise APIError(_.LOGIN_ERROR)

        userdata.set('token', token)
        self._set_authentication()
コード例 #8
0
ファイル: api.py プロジェクト: matthuisman/slyguy.addons
    def _device_id(self):
        device_id = userdata.get('device_id')
        if device_id:
            return device_id

        device_id = settings.get('device_id')

        try:
            mac_address = uuid.getnode()
            if mac_address != uuid.getnode():
                mac_address = ''
        except:
            mac_address = ''

        system, arch = get_system_arch()
        device_id = device_id.format(username=userdata.get('username'),
                                     mac_address=mac_address,
                                     system=system).strip()

        if not device_id:
            device_id = uuid.uuid4()

        log.debug('Raw device id: {}'.format(device_id))
        device_id = hash_6(device_id, length=16)
        log.debug('Hashed device id: {}'.format(device_id))

        userdata.set('device_id', device_id)
        return device_id
コード例 #9
0
ファイル: plugin.py プロジェクト: Raspifan2020/slyguy.addons
def search_channel(query=None, radio=0, page=1, **kwargs):
    radio  = int(radio)
    page   = int(page)

    if not query:
        query = gui.input(_.SEARCH, default=userdata.get('search', '')).strip()
        if not query:
            return

        userdata.set('search', query)

    folder = plugin.Folder(_(_.SEARCH_FOR, query=query))

    page_size = settings.getInt('page_size', 0)
    db_query  = Channel.channel_list(radio=radio, page=page, search=query, page_size=page_size)

    items = _process_channels(db_query)
    folder.add_items(items)

    if len(items) == page_size:
        folder.add_item(
            label = _(_.NEXT_PAGE, page=page+1, _bold=True),
            path  = plugin.url_for(search_channel, query=query, radio=radio, page=page+1),
        )

    return folder
コード例 #10
0
def search(query=None, page=1, **kwargs):
    page = int(page)

    if not query:
        query = gui.input(_.SEARCH, default=userdata.get('search', '')).strip()
        if not query:
            return

        userdata.set('search', query)

    data = api.search(query=query, page=page)
    pages = data['pages']

    folder = plugin.Folder(
        _(_.SEARCH_FOR, query=query, page=page, total_pages=pages))

    items = _parse_contents(data.get('results', []))
    folder.add_items(items)

    if pages > page:
        folder.add_item(
            label=_(_.NEXT_PAGE, next=page + 1, total_pages=pages, _bold=True),
            path=plugin.url_for(search, query=query, page=page + 1),
        )

    return folder
コード例 #11
0
def search(**kwargs):
    query = gui.input(_.SEARCH, default=userdata.get('search', '')).strip()
    if not query:
        return

    userdata.set('search', query)

    folder = plugin.Folder(_(_.SEARCH_FOR, query=query))

    for row in api.search(query):
        item = plugin.Item(
            label=row['title'],
            art={'thumb': row['image'].get('LARGE')},
            info={},
        )

        if row['editorialItemType'] == 'Program':
            item.path = plugin.url_for(list_seasons, id=row['id'])
        elif row['editorialItemType'] == 'Video':
            item.path = plugin.url_for(play_video, id=row['id'])
            item.playable = True
        else:
            continue

        folder.add_items(item)

    return folder
コード例 #12
0
ファイル: plugin.py プロジェクト: matthuisman/slyguy.addons
def search(query=None, page=1, **kwargs):
    page = int(page)
    limit = 50

    if not query:
        query = gui.input(_.SEARCH, default=userdata.get('search', '')).strip()
        if not query:
            return

        userdata.set('search', query)

    folder = plugin.Folder(_(_.SEARCH_FOR, query=query, page=page))

    data = api.search(query, page=page, limit=limit)

    items = _process_entries(data['entries'])
    folder.add_items(items)

    if len(data['entries']) == limit:
        folder.add_item(
            label=_(_.NEXT_PAGE, next=page + 1, _bold=True),
            path=plugin.url_for(search, query=query, page=page + 1),
        )

    return folder
コード例 #13
0
    def _set_ob_token(self):
        password = userdata.get('pswd')

        if password:
            ticket = self.login(userdata.get('username'), password)
        else:
            resp = self._session.post(
                'https://auth.tab.co.nz/identity-service/api/v1/assertion/by-token',
                cookies={'OB-TGT': userdata.get('ob_tgt')})

            if resp.status_code == 403:
                raise APIError(_.GEO_ERROR)
            elif resp.status_code != 201:
                raise APIError(_.AUTH_ERROR)
            else:
                ticket = resp.json()['data']['ticket']

        resp = self._session.get(
            'https://api.tab.co.nz/account-service/api/v1/account/header',
            headers={'Authentication': ticket})

        if 'OB-TOKEN' not in self._session.cookies:
            raise APIError(_.AUTH_ERROR)

        userdata.set('ob_session', self._session.cookies['OB-SESSION'])
コード例 #14
0
def select_quality(qualities):
    options = []

    options.append([QUALITY_BEST, _.QUALITY_BEST])
    options.extend(qualities)
    options.append([QUALITY_LOWEST, _.QUALITY_LOWEST])

    values = [x[0] for x in options]
    labels = [x[1] for x in options]

    current = userdata.get('last_quality')

    default = -1
    if current:
        try:
            default = values.index(current)
        except:
            default = values.index(qualities[-1][0])

            for quality in qualities:
                if quality[0] <= current:
                    default = values.index(quality[0])
                    break

    index = gui.select(_.PLAYBACK_QUALITY,
                       labels,
                       preselect=default,
                       autoclose=10000)  #autoclose after 10seconds
    if index < 0:
        raise FailedPlayback('User cancelled quality select')

    userdata.set('last_quality', values[index])

    return values[index]
コード例 #15
0
def del_favourite(id, **kwargs):
    favourites = userdata.get('favourites') or []
    if id in favourites:
        favourites.remove(id)

    userdata.set('favourites', favourites)
    gui.refresh()
コード例 #16
0
def configure_merge(**kwargs):
    data = _app_data()
    data['regions'].pop(ALL, None)

    user_regions = userdata.get('merge_regions', [])
    avail_regions = sorted(
        data['regions'],
        key=lambda x: (data['regions'][x]['sort'], data['regions'][x]['name']))

    options = []
    preselect = []
    for index, code in enumerate(avail_regions):
        region = data['regions'][code]
        options.append(
            plugin.Item(label=region['name'], art={'thumb': region['logo']}))
        if code in user_regions:
            preselect.append(index)

    indexes = gui.select(heading=_.SELECT_REGIONS,
                         options=options,
                         multi=True,
                         useDetails=True,
                         preselect=preselect)
    if indexes is None:
        return

    user_regions = [avail_regions[i] for i in indexes]
    userdata.set('merge_regions', user_regions)
コード例 #17
0
def configure_merge(**kwargs):
    user_providers = [x.lower() for x in userdata.get('merge_providers', [])]
    avail_providers = _providers(playlist=True)

    options = []
    values = []
    preselect = []
    for index, key in enumerate(
            sorted(avail_providers,
                   key=lambda x:
                   (avail_providers[x]['sort'], avail_providers[x]['name']))):
        provider = avail_providers[key]

        values.append(key)
        options.append(
            plugin.Item(label=provider['name'],
                        art={'thumb': provider['logo']}))
        if key in user_providers:
            preselect.append(index)

    indexes = gui.select(heading=_.SELECT_PROVIDERS,
                         options=options,
                         useDetails=True,
                         multi=True,
                         preselect=preselect)
    if indexes is None:
        return

    user_providers = [values[i] for i in indexes]
    userdata.set('merge_providers', user_providers)
コード例 #18
0
def search(query=None, page=1, **kwargs):
    page = int(page)

    if not query:
        query = gui.input(_.SEARCH, default=userdata.get('search', '')).strip()
        if not query:
            return
        userdata.set('search', query)

    data = api.filter_media('keyword', query, page=page)
    total_pages = int(data['paginator']['total_pages'])

    folder = plugin.Folder(
        _(_.SEARCH_FOR, query=query, page=page, total_pages=total_pages))

    for row in data['data']:
        item = _process_media(row)
        folder.add_items([item])

    if total_pages > page:
        folder.add_item(
            label=_(_.NEXT_PAGE, next_page=page + 1),
            path=plugin.url_for(search, query=query, page=page + 1),
        )

    return folder
コード例 #19
0
ファイル: api.py プロジェクト: matthuisman/slyguy.addons
    def _set_token(self, token):
        data = jwt_data(token)
        expires = min(int(time.time() + 86400), data['exp'] - 10)

        userdata.set('expires', expires)
        userdata.set('token', token)

        self._set_authentication()
コード例 #20
0
ファイル: plugin.py プロジェクト: Raspifan2020/slyguy.addons
def _set_profile(profile, notify=True):
    api.set_profile(profile['id'])

    if settings.getBool('kid_lockdown', False) and profile['isKidsProfile']:
        userdata.set('kid_lockdown', True)

    if notify:
        gui.notification(_.PROFILE_ACTIVATED, heading=userdata.get('profile_name'), icon=userdata.get('profile_icon'))
コード例 #21
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'])
コード例 #22
0
ファイル: api.py プロジェクト: matthuisman/slyguy.addons
    def _save_auth(self, cookies):
        expires = None
        for cookie in cookies:
            if expires is None or cookie.expires < expires:
                expires = cookie.expires

        userdata.set('expires', min(expires, int(time() + 86400)))
        userdata.set('auth_cookies', cookies.get_dict())

        self._set_authentication()
コード例 #23
0
    def new_session(self):
        self.logged_in = False

        host = settings.get('business_host') if settings.getBool(
            'business_account', False) else DEFAULT_HOST
        if host != userdata.get('host', DEFAULT_HOST):
            userdata.delete('access_token')
            userdata.set('host', host)

        self._session = Session(HEADERS, base_url=API_URL.format(host))
        self._set_authentication()
コード例 #24
0
ファイル: api.py プロジェクト: matthuisman/slyguy.addons
    def _parse_tokens(self, access_token, id_token):
        jwt = jwt_data(access_token)

        userdata.set('access_token', access_token)
        userdata.set('id_token', id_token)
        userdata.set('token_expires',
                     int(time.time()) + (jwt['exp'] - jwt['iat'] - 30))
        userdata.set('country', jwt['country'])
        userdata.set('package', jwt['package'])

        self._set_access_token(access_token)
コード例 #25
0
def alert(asset, title, **kwargs):
    alerts = userdata.get('alerts', [])

    if asset not in alerts:
        alerts.append(asset)
        gui.notification(title, heading=_.REMINDER_SET)
    else:
        alerts.remove(asset)
        gui.notification(title, heading=_.REMINDER_REMOVED)

    userdata.set('alerts', alerts)
    gui.refresh()
コード例 #26
0
def search(**kwargs):
    query = gui.input(_.SEARCH, default=userdata.get('search', '')).strip()
    if not query:
        return

    userdata.set('search', query)

    folder = plugin.Folder(_(_.SEARCH_FOR, query=query))
    rows = api.search(query)
    folder.add_items(_parse_rows(rows))

    return folder
コード例 #27
0
    def stop(self):
        if not self.started:
            return

        self._server.shutdown()
        self._server.server_close()
        self._server.socket.close()
        self._httpd_thread.join()
        self.started = False
        log.debug("API: Stopped")
        userdata.set('_playlist_url', '')
        userdata.set('_epg_url', '')
コード例 #28
0
def add_favourite(id, **kwargs):
    data = _app_data()
    channel = data['regions'][ALL]['channels'].get(id)
    if not channel:
        return

    favourites = userdata.get('favourites') or []
    if id not in favourites:
        favourites.append(id)

    userdata.set('favourites', favourites)
    gui.notification(_.MY_CHANNEL_ADDED, heading=channel['name'], icon=channel['logo'])
コード例 #29
0
def start():
    http = HTTP()

    monitor = xbmc.Monitor()
    restart_queued = False

    boot_merge = settings.getBool('boot_merge', False)
    set_kodi_string('_iptv_merge_force_run')

    while not monitor.waitForAbort(1):
        http.start() if settings.getBool('http_api', False) else http.stop()

        forced = get_kodi_string('_iptv_merge_force_run') or 0

        if forced or boot_merge or (settings.getBool('auto_merge', True) and time.time() - userdata.get('last_run', 0) > settings.getInt('reload_time_hours', 12) * 3600):
            set_kodi_string('_iptv_merge_force_run', '1')

            url = router.url_for('run_merge', forced=int(forced))
            dirs, files = xbmcvfs.listdir(url)
            result, msg = int(files[0][0]), unquote_plus(files[0][1:])
            if result:
                restart_queued = True

            userdata.set('last_run', int(time.time()))
            set_kodi_string('_iptv_merge_force_run')

        if restart_queued and settings.getBool('restart_pvr', False):
            if forced: progress = gui.progressbg(heading='Reloading IPTV Simple Client')

            if KODI_VERSION > 18:
                restart_queued = False
                try: xbmcaddon.Addon(IPTV_SIMPLE_ID).setSetting('m3uPathType', '0')
                except Exception as e: pass

            elif forced or (not xbmc.getCondVisibility('Pvr.IsPlayingTv') and not xbmc.getCondVisibility('Pvr.IsPlayingRadio')):
                restart_queued = False
                kodi_rpc('Addons.SetAddonEnabled', {'addonid': IPTV_SIMPLE_ID, 'enabled': False})

                wait_delay = 4
                for i in range(wait_delay):
                    if monitor.waitForAbort(1):
                        break
                    if forced: progress.update((i+1)*int(100/wait_delay))

                kodi_rpc('Addons.SetAddonEnabled', {'addonid': IPTV_SIMPLE_ID, 'enabled': True})

            if forced:
                progress.update(100)
                progress.close()

        boot_merge = False

    http.stop()
コード例 #30
0
def search(**kwargs):
    query = gui.input(_.SEARCH, default=userdata.get('search', '')).strip()
    if not query:
        return

    userdata.set('search', query)

    folder = plugin.Folder(_(_.SEARCH_FOR, query=query))
    provider = _providers()[ALL]
    items = _get_channels(provider['channels'], query=query)
    folder.add_items(items)
    return folder