Exemple #1
0
 def exported(self, pathitems=None):
     """List all items that are exported to the Kodi library"""
     chunked_video_list, perpetual_range_selector = lib_utils.list_contents(self.perpetual_range_start)
     if chunked_video_list:
         self._exported_directory(pathitems, chunked_video_list, perpetual_range_selector)
     else:
         ui.show_notification(common.get_local_string(30111))
         xbmcplugin.endOfDirectory(G.PLUGIN_HANDLE, succeeded=False)
Exemple #2
0
 def _activate_profile(self, guid):
     pin_result = verify_profile_pin(guid)
     if not pin_result:
         if pin_result is not None:
             ui.show_notification(common.get_local_string(30106), time=8000)
         return False
     common.make_call('activate_profile', guid)
     return True
 def set_autoupdate_device(self, pathitems):  # pylint: disable=unused-argument
     """Set the current device to manage auto-update of the shared-library (MySQL)"""
     if _check_auto_update_running():
         return
     random_uuid = common.get_random_uuid()
     G.LOCAL_DB.set_value('client_uuid', random_uuid)
     G.SHARED_DB.set_value('auto_update_device_uuid', random_uuid)
     ui.show_notification(common.get_local_string(30209), time=8000)
Exemple #4
0
def play(videoid):
    """Play an episode or movie as specified by the path"""
    common.info('Playing {}', videoid)
    is_up_next_enabled = g.ADDON.getSettingBool('UpNextNotifier_enabled')
    metadata = [{}, {}]
    try:
        metadata = api.metadata(videoid)
        common.debug('Metadata is {}', metadata)
    except MetadataNotAvailable:
        common.warn('Metadata not available for {}', videoid)

    # Parental control PIN
    pin_result = _verify_pin(metadata[0].get('requiresPin', False))
    if not pin_result:
        if pin_result is not None:
            ui.show_notification(common.get_local_string(30106), time=10000)
        xbmcplugin.endOfDirectory(g.PLUGIN_HANDLE, succeeded=False)
        return

    list_item = get_inputstream_listitem(videoid)
    infos, art = infolabels.add_info_for_playback(videoid, list_item,
                                                  is_up_next_enabled)

    # Workaround for resuming strm files from library
    resume_position = infos.get('resume', {}).get('position') \
        if g.IS_SKIN_CALL and g.ADDON.getSettingBool('ResumeManager_enabled') else None
    if resume_position:
        index_selected = ui.ask_for_resume(
            resume_position) if g.ADDON.getSettingBool(
                'ResumeManager_dialog') else None
        if index_selected == -1:
            xbmcplugin.setResolvedUrl(handle=g.PLUGIN_HANDLE,
                                      succeeded=False,
                                      listitem=list_item)
            return
        if index_selected == 1:
            resume_position = None

    xbmcplugin.setResolvedUrl(handle=g.PLUGIN_HANDLE,
                              succeeded=True,
                              listitem=list_item)

    upnext_info = get_upnext_info(videoid, (infos, art),
                                  metadata) if is_up_next_enabled else None

    common.debug('Sending initialization signal')
    common.send_signal(common.Signals.PLAYBACK_INITIATED, {
        'videoid': videoid.to_dict(),
        'infos': infos,
        'art': art,
        'timeline_markers': get_timeline_markers(metadata[0]),
        'upnext_info': upnext_info,
        'resume_position': resume_position
    },
                       non_blocking=True)
    xbmcplugin.setResolvedUrl(handle=g.PLUGIN_HANDLE,
                              succeeded=True,
                              listitem=list_item)
def _display_search_results(search_term):
    search_results = api.search(search_term)
    if search_results.videos:
        listings.build_video_listing(search_results,
                                     g.MAIN_MENU_ITEMS['search'])
        return
    else:
        ui.show_notification(common.get_local_string(30013))
        xbmcplugin.endOfDirectory(g.PLUGIN_HANDLE, succeeded=False)
Exemple #6
0
 def check_autoupdate_device(self, pathitems):  # pylint: disable=unused-argument
     """Check if the current device manage the auto-updates of the shared-library (MySQL)"""
     uuid = G.SHARED_DB.get_value('auto_update_device_uuid')
     if uuid is None:
         msg = common.get_local_string(30212)
     else:
         client_uuid = G.LOCAL_DB.get_value('client_uuid')
         msg = common.get_local_string(30210 if client_uuid == uuid else 30211)
     ui.show_notification(msg, time=8000)
 def logout(self):
     """Logout of the current account and reset the session"""
     common.debug('Logging out of current account')
     cookies.delete(self.account_hash)
     self._get('logout')
     common.purge_credentials()
     common.info('Logout successful')
     ui.show_notification(common.get_local_string(30113))
     self._init_session()
Exemple #8
0
 def library_playback_set_profile(self, pathitems=None):  # pylint: disable=unused-argument
     """Save the GUID for the playback from Kodi library"""
     G.LOCAL_DB.set_value('library_playback_profile_guid',
                          self.params['profile_guid'])
     profile_name = G.LOCAL_DB.get_profile_config(
         'profileName', '???', self.params['profile_guid'])
     common.container_refresh()
     ui.show_notification(profile_name,
                          title=common.get_local_string(30052))
Exemple #9
0
 def purge_cache(self, pathitems=None):  # pylint: disable=unused-argument
     """Clear the cache. If on_disk param is supplied, also clear cached
     items from disk"""
     g.CACHE.invalidate(self.params.get('on_disk', False))
     if self.params.get('on_disk', False):
         common.delete_file(
             'resources.lib.services.playback.stream_continuity.ndb')
     if not self.params.get('no_notification', False):
         ui.show_notification(common.get_local_string(30135))
Exemple #10
0
 def sync_mylist_sel_profile(self, pathitems):  # pylint: disable=unused-argument
     """
     Set the current profile for the synchronization of Netflix "My List" with the Kodi library
     """
     g.SHARED_DB.set_value('sync_mylist_profile_guid',
                           g.LOCAL_DB.get_active_profile_guid())
     profile_name = g.LOCAL_DB.get_profile_config('profileName', '')
     ui.show_notification(
         common.get_local_string(30223).format(profile_name), time=10000)
Exemple #11
0
 def library_playback_remove_profile(self, pathitems):  # pylint: disable=unused-argument
     """Remove the GUID for the playback from Kodi library"""
     G.LOCAL_DB.set_value('library_playback_profile_guid', '')
     profile_name = G.LOCAL_DB.get_profile_config(
         'profileName', '???', self.params['profile_guid'])
     G.IS_CONTAINER_REFRESHED = True
     common.container_refresh()
     ui.show_notification(profile_name,
                          title=common.get_local_string(30053))
 def trailer(self, videoid):
     """Get the trailer list"""
     video_list = api.supplemental_video_list(videoid, 'trailers')
     if video_list.videos:
         url = common.build_url(['supplemental', videoid.value, videoid.mediatype, 'trailers'],
                                mode=g.MODE_DIRECTORY)
         xbmc.executebuiltin('Container.Update({})'.format(url))
     else:
         ui.show_notification(common.get_local_string(30111))
def activate_profile(guid):
    """Activate a profile and ask the PIN if required"""
    pin_result = verify_profile_pin(guid)
    if not pin_result:
        if pin_result is not None:
            ui.show_notification(common.get_local_string(30106), time=8000)
        return False
    common.make_call('activate_profile', guid)
    return True
Exemple #14
0
 def autoselect_remove_profile(self, pathitems):  # pylint: disable=unused-argument
     """Remove the GUID from auto-selection"""
     G.LOCAL_DB.set_value('autoselect_profile_guid', '')
     profile_name = G.LOCAL_DB.get_profile_config(
         'profileName', '???', self.params['profile_guid'])
     G.IS_CONTAINER_REFRESHED = True
     common.container_refresh()
     ui.show_notification(profile_name,
                          title=common.get_local_string(30056))
Exemple #15
0
 def autoselect_set_profile(self, pathitems):  # pylint: disable=unused-argument
     """Save the GUID for profile auto-selection"""
     G.LOCAL_DB.set_value('autoselect_profile_guid',
                          self.params['profile_guid'])
     profile_name = G.LOCAL_DB.get_profile_config(
         'profileName', '???', self.params['profile_guid'])
     common.container_refresh()
     ui.show_notification(profile_name,
                          title=common.get_local_string(30055))
Exemple #16
0
 def api_error_wrapper(*args, **kwargs):
     try:
         return func(*args, **kwargs)
     except APIError as exc:
         # This error is raised only when in the API response data the key 'status' has 'error' value
         # (see _raise_api_error in session/http_requests.py)
         LOG.error('{} the API call has returned an error: {}',
                   func.__name__, exc)
         ui.show_notification(common.get_local_string(30118).format(exc))
Exemple #17
0
def _display_search_results(pathitems, perpetual_range_start, dir_update_listing):
    search_term = pathitems[2]
    search_results = api.search(search_term, perpetual_range_start)
    if search_results.videos:
        listings.build_video_listing(search_results, g.MAIN_MENU_ITEMS['search'], pathitems)
        _handle_endofdirectory(dir_update_listing)
    else:
        ui.show_notification(common.get_local_string(30013))
        xbmcplugin.endOfDirectory(g.PLUGIN_HANDLE, succeeded=False)
Exemple #18
0
def search_query(row_id, perpetual_range_start, dir_update_listing):
    """Perform the research"""
    # Get item from database
    search_item = G.LOCAL_DB.get_search_item(row_id)
    if not search_item:
        ui.show_error_info('Search error', 'Item not found in the database.')
        return False
    # Update the last access data (move on top last used items)
    if not perpetual_range_start:
        G.LOCAL_DB.update_search_item_last_access(row_id)
    # Perform the path call
    menu_data = G.MAIN_MENU_ITEMS['search']
    search_type = search_item['Type']
    if search_type == 'text':
        call_args = {
            'menu_data': menu_data,
            'search_term': search_item['Value'],
            'pathitems': ['search', 'search', row_id],
            'perpetual_range_start': perpetual_range_start
        }
        list_data, extra_data = common.make_call('get_video_list_search', call_args)
    elif search_type == 'audio_lang':
        call_args = {
            'menu_data': menu_data,
            'pathitems': ['search', 'search', row_id],
            'perpetual_range_start': perpetual_range_start,
            'context_name': 'spokenAudio',
            'context_id': common.convert_from_string(search_item['Parameters'], dict)['lang_code']
        }
        list_data, extra_data = common.make_call('get_video_list_sorted_sp', call_args)
    elif search_type == 'subtitles_lang':
        call_args = {
            'menu_data': menu_data,
            'pathitems': ['search', 'search', row_id],
            'perpetual_range_start': perpetual_range_start,
            'context_name': 'subtitles',
            'context_id': common.convert_from_string(search_item['Parameters'], dict)['lang_code']
        }
        list_data, extra_data = common.make_call('get_video_list_sorted_sp', call_args)
    elif search_type == 'genre_id':
        call_args = {
            'menu_data': menu_data,
            'pathitems': ['search', 'search', row_id],
            'perpetual_range_start': perpetual_range_start,
            'context_name': 'genres',
            'context_id': common.convert_from_string(search_item['Parameters'], dict)['genre_id']
        }
        list_data, extra_data = common.make_call('get_video_list_sorted_sp', call_args)
    else:
        raise NotImplementedError('Search type {} not implemented'.format(search_type))
    # Show the results
    if not list_data:
        ui.show_notification(common.get_local_string(30407))
        return False
    _search_results_directory(search_item['Value'], menu_data, list_data, extra_data, dir_update_listing)
    return True
Exemple #19
0
 def exported(self, pathitems=None):
     """List all items that are exported to the Kodi library"""
     # pylint: disable=unused-argument
     library_contents = library.list_contents()
     if library_contents:
         listings.build_video_listing(api.custom_video_list(library_contents), g.MAIN_MENU_ITEMS['exported'])
         _handle_endofdirectory(self.dir_update_listing)
     else:
         ui.show_notification(common.get_local_string(30013))
         xbmcplugin.endOfDirectory(g.PLUGIN_HANDLE, succeeded=False)
Exemple #20
0
 def purge_cache(self, pathitems=None):  # pylint: disable=unused-argument
     """Clear the cache. If on_disk param is supplied, also clear cached items from disk"""
     g.CACHE.invalidate(self.params.get('on_disk', False))
     common.send_signal(signal=common.Signals.INVALIDATE_SERVICE_CACHE,
                        data={
                            'on_disk': self.params.get('on_disk', False),
                            'bucket_names': None
                        })
     if not self.params.get('no_notification', False):
         ui.show_notification(common.get_local_string(30135))
 def _tick_and_wait_for_abort(self):
     try:
         self.library_updater.on_service_tick()
         G.CACHE_MANAGEMENT.on_service_tick()
     except Exception as exc:  # pylint: disable=broad-except
         import traceback
         from resources.lib.kodi.ui import show_notification
         LOG.error(traceback.format_exc())
         show_notification(': '.join((exc.__class__.__name__, str(exc))))
     return G.SETTINGS_MONITOR.waitForAbort(1)
Exemple #22
0
 def _tick_and_wait_for_abort(self):
     try:
         self.controller.on_service_tick()
         self.library_updater.on_service_tick()
     except Exception as exc:  # pylint: disable=broad-except
         import traceback
         from resources.lib.kodi.ui import show_notification
         error(traceback.format_exc())
         show_notification(': '.join((exc.__class__.__name__, unicode(exc))))
     return self.controller.waitForAbort(1)
Exemple #23
0
 def _tick_and_wait_for_abort(self):
     # pylint: disable=broad-except
     try:
         self.controller.on_playback_tick()
         self.library_updater.on_tick()
     except Exception as exc:
         common.error(traceback.format_exc())
         ui.show_notification(': '.join(
             (exc.__class__.__name__, exc.message)))
     return self.controller.waitForAbort(1)
Exemple #24
0
 def check_autoupdate_device(self, pathitems):
     """Check if the current device manage the auto-updates of the shared-library (MySQL)"""
     uuid = g.SHARED_DB.get_value('auto_update_device_uuid')
     if uuid is None:
         msg = common.get_local_string(30212)
     else:
         current_device_uuid = common.get_device_uuid()
         msg = common.get_local_string(30210) \
             if current_device_uuid == uuid else common.get_local_string(30211)
     ui.show_notification(msg, time=8000)
Exemple #25
0
def _search_add_bygenreid(search_type, genre_id):
    # If the genre ID exists, the title of the list will be returned
    title = api.get_genre_title(genre_id)
    if not title:
        ui.show_notification(common.get_local_string(30407))
        return None
    # In this case the 'value' is used only as title for the ListItem and not for the query
    title += ' [{}]'.format(genre_id)
    row_id = G.LOCAL_DB.insert_search_item(search_type, title, {'genre_id': genre_id})
    return row_id
def update_lolomo_context(context_name):
    """Update the lolomo list by context"""
    lolomo_root = g.LOCAL_DB.get_value('lolomo_root_id', '', TABLE_SESSION)

    context_index = g.LOCAL_DB.get_value(
        'lolomo_{}_index'.format(context_name.lower()), '', TABLE_SESSION)
    context_id = g.LOCAL_DB.get_value(
        'lolomo_{}_id'.format(context_name.lower()), '', TABLE_SESSION)

    if not context_index:
        common.warn(
            'Update lolomo context {} skipped due to missing lolomo index',
            context_name)
        return
    path = [['lolomos', lolomo_root, 'refreshListByContext']]
    # The fourth parameter is like a request-id, but it doesn't seem to match to
    # serverDefs/date/requestId of reactContext (g.LOCAL_DB.get_value('request_id', table=TABLE_SESSION))
    # nor to request_id of the video event request
    # has a kind of relationship with renoMessageId suspect with the logblob but i'm not sure because my debug crashed,
    # and i am no longer able to trace the source.
    # I noticed also that this request can also be made with the fourth parameter empty,
    # but it still doesn't update the continueWatching list of lolomo, that is strange because of no error
    params = [
        common.enclose_quotes(context_id), context_index,
        common.enclose_quotes(context_name), ''
    ]
    # path_suffixs = [
    #    [['trackIds', 'context', 'length', 'genreId', 'videoId', 'displayName', 'isTallRow', 'isShowAsARow',
    #      'impressionToken', 'showAsARow', 'id', 'requestId']],
    #    [{'from': 0, 'to': 100}, 'reference', 'summary'],
    #    [{'from': 0, 'to': 100}, 'reference', 'title'],
    #    [{'from': 0, 'to': 100}, 'reference', 'titleMaturity'],
    #    [{'from': 0, 'to': 100}, 'reference', 'userRating'],
    #    [{'from': 0, 'to': 100}, 'reference', 'userRatingRequestId'],
    #    [{'from': 0, 'to': 100}, 'reference', 'boxarts', '_342x192', 'jpg'],
    #    [{'from': 0, 'to': 100}, 'reference', 'promoVideo']
    # ]
    callargs = {
        'callpaths': path,
        'params': params,
        # 'path_suffixs': path_suffixs
    }
    try:
        response = common.make_http_call('callpath_request', callargs)
        common.debug('refreshListByContext response: {}', response)
        # The call response return the new context id of the previous invalidated lolomo context_id
        # and if path_suffixs is added return also the new video list data
    except Exception:  # pylint: disable=broad-except
        if not common.is_debug_verbose():
            return
        ui.show_notification(
            title=common.get_local_string(30105),
            msg='An error prevented the update the lolomo context on netflix',
            time=10000)
Exemple #27
0
def update_my_list(videoid, operation, params):
    """Call API to update my list with either add or remove action"""
    common.debug('My List: {} {}', operation, videoid)
    common.make_call(
        'post',
        {'component': 'update_my_list',
         'data': {
             'operation': operation,
             'videoId': videoid.value}})
    ui.show_notification(common.get_local_string(30119))
    _update_mylist_cache(videoid, operation, params)
 def _prefetch_login(self):
     """Check if we have stored credentials.
     If so, do the login before the user requests it"""
     try:
         common.get_credentials()
         if not self._is_logged_in():
             self._login()
     except MissingCredentialsError:
         common.info('Login prefetch: No stored credentials are available')
     except LoginFailedError:
         ui.show_notification(common.get_local_string(30009))
Exemple #29
0
def login():
    """Perform a login"""
    g.CACHE.invalidate()
    try:
        ui.ask_credentials()
        common.make_call('login')
    except (MissingCredentialsError, LoginFailedError) as exc:
        msg = 30009 if isinstance(exc, LoginFailedError) else 30112
        ui.show_notification(common.get_local_string(msg))
        return False
    return True
Exemple #30
0
 def logout(self):
     """Logout of the current account and reset the session"""
     common.debug('Logging out of current account')
     cookies.delete(self.account_hash)
     self._get('logout')
     common.purge_credentials()
     common.info('Logout successful')
     ui.show_notification(common.get_local_string(30113))
     self._init_session()
     xbmc.executebuiltin('XBMC.Container.Update(path,replace)')  # Clean path history
     xbmc.executebuiltin('XBMC.ActivateWindow(Home)')