Example #1
0
def dicsoverProviderLocally(handle, options):
    dialog = xbmcgui.Dialog()

    baseUrl = dialog.input(localise(32051))
    if not baseUrl:
        return None

    plexServer = PlexServer(baseUrl, timeout=plex.constants.REQUEST_TIMEOUT)
    if not plexServer:
        return None

    providerId = Server.BuildProviderId(plexServer.machineIdentifier)
    providerIconUrl = Server.BuildIconUrl(baseUrl)

    provider = xbmcmediaimport.MediaProvider(providerId,baseUrl, plexServer.friendlyName, providerIconUrl, plex.constants.SUPPORTED_MEDIA_TYPES, handle=handle)

    # store local authentication in settings
    providerSettings = provider.prepareSettings()
    if not providerSettings:
        return None

    providerSettings.setInt(plex.constants.SETTINGS_PROVIDER_AUTHENTICATION, plex.constants.SETTINGS_PROVIDER_AUTHENTICATION_OPTION_LOCAL)
    providerSettings.save()

    return provider
Example #2
0
def discoverProviderLocally(handle, options):
    baseUrl = xbmcgui.Dialog().input(localise(32050), 'http://')
    if not baseUrl:
        return None

    log('trying to discover an Emby server at {}...'.format(baseUrl))
    try:
        serverInfo = emby.api.server.Server.GetInfo(baseUrl)
        if not serverInfo:
            return None
    except:
        return None

    providerId = Server.BuildProviderId(serverInfo.id)
    providerIconUrl = Server.BuildIconUrl(baseUrl)
    provider = xbmcmediaimport.MediaProvider(
        providerId, baseUrl, serverInfo.name, providerIconUrl,
        emby.constants.SUPPORTED_MEDIA_TYPES)
    provider.setIconUrl(kodi.Api.downloadIcon(provider))

    # store local authentication in settings
    providerSettings = provider.prepareSettings()
    if not providerSettings:
        return None

    providerSettings.setString(
        emby.constants.SETTING_PROVIDER_AUTHENTICATION,
        emby.constants.SETTING_PROVIDER_AUTHENTICATION_OPTION_LOCAL)
    providerSettings.save()

    log('Local Emby server {} successfully discovered at {}'.format(
        mediaProvider2str(provider), baseUrl))

    return provider
Example #3
0
def linkMyPlexAccount(handle, options):
    # retrieve the media provider
    mediaProvider = xbmcmediaimport.getProvider(handle)
    if not mediaProvider:
        log('cannot retrieve media provider', xbmc.LOGERROR)
        return

    # get the media provider settings
    providerSettings = mediaProvider.prepareSettings()
    if not providerSettings:
        return

    plexAccount = linkToMyPlexAccount()
    if not plexAccount:
        return

    username = plexAccount.username
    if not username:
        log('no valid username available for the linked MyPlex account', xbmc.LOGWARNING)
        return

    # make sure the configured Plex Media Server is still accessible
    serverUrl = mediaProvider.getBasePath()
    matchingServer = None

    serverId = getServerId(mediaProvider.getIdentifier())

    # get all connected server resources
    serverResources = getServerResources(plexAccount)
    for server in serverResources:
        if server.clientIdentifier == serverId:
            matchingServer = server
            break

    if not matchingServer:
        log('no Plex Media Server matching {} found'.format(serverUrl), xbmc.LOGWARNING)
        xbmcgui.Dialog().ok(localise(32015), localise(32058))
        return

    xbmcgui.Dialog().ok(localise(32015), localise(32059).format(username))

    # change the settings
    providerSettings.setString(plex.constants.SETTINGS_PROVIDER_USERNAME, username)
    providerSettings.setString(plex.constants.SETTINGS_PROVIDER_TOKEN, matchingServer.accessToken)
def changeUrl(handle, _):
    # retrieve the media provider
    mediaProvider = xbmcmediaimport.getProvider(handle)
    if not mediaProvider:
        log('cannot retrieve media provider', xbmc.LOGERROR)
        return

    # get the media provider settings
    providerSettings = mediaProvider.prepareSettings()
    if not providerSettings:
        return

    urlCurrent = ProviderSettings.GetUrl(providerSettings)
    if not urlCurrent:
        log("cannot retrieve current URL from provider settings", xbmc.LOGERROR)
        return

    # ask the user for a new URL
    urlNew = xbmcgui.Dialog().input(localise(32045), urlCurrent)
    if not urlNew:
        return

    # store the new URL in the settings
    ProviderSettings.SetUrl(providerSettings, urlNew)

    # try to connect and authenticate with the new URL
    success = False
    try:
        success = Server(mediaProvider).Authenticate(force=True)
    except:
        pass

    dialog = xbmcgui.Dialog()
    title = mediaProvider.getFriendlyName()
    if success:
        dialog.ok(title, localise(32017))
    else:
        # ask the user whether to change the URL anyway
        changeUrlAnyway = dialog.yesno(title, localise(32066))
        if not changeUrlAnyway:
            # revert the settings to the previous / old URL
            ProviderSettings.SetUrl(providerSettings, urlCurrent)
def discoverProvider(handle, options):
    dialog = xbmcgui.Dialog()

    authenticationChoices = [
        localise(32036),  # local
        localise(32037)   # Emby Connect
    ]
    authenticationChoice = dialog.select(localise(32053), authenticationChoices)

    if authenticationChoice == 0:  # local
        provider = discoverProviderLocally(handle, options)
    elif authenticationChoice == 1:  # Emby Connect
        provider = discoverProviderWithEmbyConnect(handle, options)
    else:
        return

    if not provider:
        return

    xbmcmediaimport.setDiscoveredProvider(handle, True, provider)
Example #6
0
def forceSync(handle, options):
    # ask the user whether he is sure
    force = xbmcgui.Dialog().yesno(localise(32042), localise(32053))
    if not force:
        return

    # retrieve the media import
    mediaImport = xbmcmediaimport.getImport(handle)
    if not mediaImport:
        log('cannot retrieve media import', xbmc.LOGERROR)
        return

    # prepare the media provider settings
    importSettings = mediaImport.prepareSettings()
    if not importSettings:
        log('cannot prepare media import settings', xbmc.LOGERROR)
        return

    # reset the synchronization hash setting to force a full synchronization
    SynchronizationSettings.ResetHash(importSettings, save=False)
Example #7
0
def discoverProvider(handle, options):
    dialog = xbmcgui.Dialog()

    authenticationChoices = [
        localise(32013),  # local only
        localise(32014)   # MyPlex
    ]
    authenticationChoice = dialog.select(localise(32050), authenticationChoices)

    if authenticationChoice == 0:  # local only
        provider = dicsoverProviderLocally(handle, options)
    elif authenticationChoice == 1:  # MyPlex
        provider = dicsoverProviderWithMyPlex(handle, options)
    else:
        return

    if not provider:
        return

    xbmcmediaimport.setDiscoveredProvider(handle, True, provider)
Example #8
0
def linkToEmbyConnect(deviceId):
    dialog = xbmcgui.Dialog()

    pinLogin = EmbyConnect.PinLogin(deviceId=deviceId)
    if not pinLogin.pin:
        dialog.ok(localise(32038), localise(32054))
        log('failed to get PIN to link to Emby Connect', xbmc.LOGWARNING)
        return None

    # show the user the pin
    dialog.ok(localise(32038), localise(32055),
              '[COLOR FF52B54B]{}[/COLOR]'.format(pinLogin.pin))

    # check the status of the authentication
    while not pinLogin.finished:
        if pinLogin.checkLogin():
            break

        time.sleep(0.25)

    if pinLogin.expired:
        dialog.ok(localise(32038), localise(32056))
        log('linking to Emby Connect has expiried', xbmc.LOGWARNING)
        return None

    authResult = pinLogin.exchange()
    if not authResult:
        log(
            'no valid access token received from the linked Emby Connect account',
            xbmc.LOGWARNING)
        return None

    return authResult
def linkEmbyConnect(handle, _):
    # retrieve the media provider
    mediaProvider = xbmcmediaimport.getProvider(handle)
    if not mediaProvider:
        log('cannot retrieve media provider', xbmc.LOGERROR)
        return

    # get the media provider settings
    providerSettings = mediaProvider.prepareSettings()
    if not providerSettings:
        return

    # make sure we have a valid device ID
    deviceId = providerSettings.getString(emby.constants.SETTING_PROVIDER_DEVICEID)
    if not deviceId:
        deviceId = Request.GenerateDeviceId()
        providerSettings.setString(emby.constants.SETTING_PROVIDER_DEVICEID, deviceId)

    embyConnect = linkToEmbyConnect(deviceId)
    if not embyConnect:
        return

    # make sure the configured Emby server is still accessible
    serverUrl = ProviderSettings.GetUrl(providerSettings)
    matchingServer = None
    serverId = Server.GetServerId(mediaProvider.getIdentifier())

    # get all connected servers
    servers = EmbyConnect.GetServers(embyConnect.accessToken, embyConnect.userId)
    if not servers:
        log('no servers available for Emby Connect user id {}'.format(embyConnect.userId), xbmc.LOGWARNING)
        return

    for server in servers:
        if server.systemId == serverId:
            matchingServer = server
            break

    if not matchingServer:
        log('no Emby server matching {} found'.format(serverUrl), xbmc.LOGWARNING)
        xbmcgui.Dialog().ok(localise(32038), localise(32061))
        return

    # change the settings
    providerSettings.setString(emby.constants.SETTING_PROVIDER_EMBY_CONNECT_USER_ID, embyConnect.userId)
    providerSettings.setString(emby.constants.SETTING_PROVIDER_EMBY_CONNECT_ACCESS_KEY, matchingServer.accessKey)

    success = False
    try:
        success = Server(mediaProvider).Authenticate(force=True)
    except:
        pass

    if success:
        xbmcgui.Dialog().ok(localise(32038), localise(32062))
        log('successfully linked to Emby Connect server {} ({}) {}'.format(matchingServer.name, serverId, serverUrl))
    else:
        xbmcgui.Dialog().ok(localise(32038), localise(32061))
        log('failed to link to Emby Connect server {} ({}) {}'.format(matchingServer.name, serverId, serverUrl),
            xbmc.LOGWARNING)
Example #10
0
    def _ProcessMessageServer(self, messageType, data):
        if not self._settings.getBool(
                SETTING_PROVIDER_INTERFACE_SHOW_SERVER_MESSAGES):
            return

        if messageType == WS_MESSAGE_TYPE_SERVER_SHUTTING_DOWN:
            message = 32051
        elif messageType == WS_MESSAGE_TYPE_SERVER_RESTARTING:
            message = 32052
        else:
            return

        xbmcgui.Dialog().notification(
            'Emby Media Importer',
            localise(message).format(self._mediaProvider.getFriendlyName()),
            self._mediaProvider.getIconUrl())
Example #11
0
def settingOptionsFillerUsers(handle, _):
    # retrieve the media provider
    mediaProvider = xbmcmediaimport.getProvider(handle)
    if not mediaProvider:
        log('cannot retrieve media provider', xbmc.LOGERROR)
        return

    # get the provider's settings
    settings = mediaProvider.getSettings()

    users = [(localise(32015), emby.constants.SETTING_PROVIDER_USER_OPTION_MANUAL)]
    publicUsers = User.GetPublicUsers(ProviderSettings.GetUrl(settings),
                                      deviceId=settings.getString(emby.constants.SETTING_PROVIDER_DEVICEID))
    users.extend([(user.name, user.id) for user in publicUsers])

    # pass the list of users back to Kodi
    settings.setStringOptions(emby.constants.SETTING_PROVIDER_USER, users)
Example #12
0
def resetDeviceId(handle, _):
    # retrieve the media provider
    mediaProvider = xbmcmediaimport.getProvider(handle)
    if not mediaProvider:
        log('cannot retrieve media provider', xbmc.LOGERROR)
        return

    # get the media provider settings
    providerSettings = mediaProvider.prepareSettings()
    if not providerSettings:
        return

    deviceId = Request.GenerateDeviceId()
    log('created a new device identifier for {}: {}'.format(mediaProvider2str(mediaProvider), deviceId))

    providerSettings.setString(emby.constants.SETTING_PROVIDER_DEVICEID, deviceId)

    xbmcgui.Dialog().ok(mediaProvider.getFriendlyName(), localise(32063))
Example #13
0
def testConnection(handle, options):
    # retrieve the media provider
    mediaProvider = xbmcmediaimport.getProvider(handle)
    if not mediaProvider:
        log('cannot retrieve media provider', xbmc.LOGERROR)
        return

    success = False
    try:
        success = Server(mediaProvider).Authenticate()
    except:
        pass

    title = mediaProvider.getFriendlyName()
    line = 32019
    if success:
        line = 32018
    xbmcgui.Dialog().ok(title, localise(line))
Example #14
0
def testAuthentication(handle, _):
    # retrieve the media provider
    mediaProvider = xbmcmediaimport.getProvider(handle)
    if not mediaProvider:
        log('cannot retrieve media provider', xbmc.LOGERROR)
        return

    log('testing authentication with {}...'.format(mediaProvider2str(mediaProvider)))
    success = False
    try:
        success = Server(mediaProvider).Authenticate(force=True)
    except:
        pass

    line = 32018
    if success:
        line = 32017
    xbmcgui.Dialog().ok(mediaProvider.getFriendlyName(), localise(line))
Example #15
0
def discoverProvider(handle, options):
    baseUrl = xbmcgui.Dialog().input(localise(32050), 'http://')
    if not baseUrl:
        return

    log('trying to discover an Emby server at {}...'.format(baseUrl))
    try:
        serverInfo = emby.api.server.Server.GetInfo(baseUrl)
        if not serverInfo:
            return
    except:
        return

    providerId = Server.BuildProviderId(serverInfo.id)
    providerIconUrl = Server.BuildIconUrl(baseUrl)
    mediaProvider = xbmcmediaimport.MediaProvider(providerId, baseUrl, serverInfo.name, providerIconUrl, emby.constants.SUPPORTED_MEDIA_TYPES)
    mediaProvider.setIconUrl(kodi.Api.downloadIcon(mediaProvider))

    log('Emby server {} successfully discovered at {}'.format(mediaProvider2str(mediaProvider), baseUrl))

    xbmcmediaimport.setDiscoveredProvider(handle, True, mediaProvider)
Example #16
0
def linkToMyPlexAccount():
    dialog = xbmcgui.Dialog()

    pinLogin = MyPlexPinLogin()
    if not pinLogin.pin:
        dialog.ok(localise(32015), localise(32052))
        log('failed to get PIN to link MyPlex account', xbmc.LOGWARNING)
        return None

    # show the user the pin
    dialog.ok(localise(32015), localise(32053), '[COLOR FFE5A00D]{}[/COLOR]'.format(pinLogin.pin))

    # check the status of the authentication
    while not pinLogin.finished:
        if pinLogin.checkLogin():
            break

    if pinLogin.expired:
        dialog.ok(localise(32015), localise(32054))
        log('linking the MyPlex account has expiried', xbmc.LOGWARNING)
        return None

    if not pinLogin.token:
        log('no valid token received from the linked MyPlex account', xbmc.LOGWARNING)
        return None

    # login to MyPlex
    try:
        plexAccount = MyPlexAccount(token=pinLogin.token, timeout=plex.constants.REQUEST_TIMEOUT)
    except Exception as e:
        log('failed to connect to the linked MyPlex account: {}'.format(e), xbmc.LOGWARNING)
        return None
    if not plexAccount:
        log('failed to connect to the linked MyPlex account', xbmc.LOGWARNING)
        return None

    return plexAccount
Example #17
0
def dicsoverProviderWithMyPlex(handle, options):
    plexAccount = linkToMyPlexAccount()
    if not plexAccount:
        return None

    username = plexAccount.username
    if not username:
        log('no valid username available for the linked MyPlex account', xbmc.LOGWARNING)
        return None

    dialog = xbmcgui.Dialog()

    # get all connected server resources
    serverResources = getServerResources(plexAccount)
    if not serverResources:
        log('no servers available for MyPlex account {}'.format(username), xbmc.LOGWARNING)
        return None

    if len(serverResources) == 1:
        server = serverResources[0]
    else:
        # ask the user which server to use
        servers = [ resource.name for resource in serverResources ]
        serversChoice = dialog.select(localise(32055), servers)
        if serversChoice < 0 or serversChoice >= len(servers):
            return None

        server = serverResources[serversChoice]

    if not server:
        return None

    if not server.connections:
        # try to connect to the server
        plexServer = server.connect(timeout=plex.constants.REQUEST_TIMEOUT)
        if not plexServer:
            log('failed to connect to the Plex Media Server "{}"'.format(server.name), xbmc.LOGWARNING)
            return None

        baseUrl = plexServer.url('', includeToken=False)
    else:
        isLocal = False
        localConnections = [ connection for connection in server.connections if connection.local ]
        remoteConnections = [ connection for connection in server.connections if not connection.local and not connection.relay ]
        remoteRelayConnections = [ connection for connection in server.connections if not connection.local and connection.relay ]

        if localConnections:
            # ask the user whether to use a local or remote connection
            isLocal = dialog.yesno(localise(32056), localise(32057).format(server.name))

        urls = []
        if isLocal:
            urls.append(localConnections[0].httpuri)
        else:
            urls.extend([(conn.uri, False) for conn in remoteConnections])
            urls.extend([(conn.uri, True) for conn in remoteRelayConnections])
            urls.extend([(conn.uri, False) for conn in localConnections])

        baseUrl = None
        connectViaRelay = True
        # find a working connection / base URL
        for (url, isRelay) in urls:
            try:
                # don't try to connect via relay if the user has already declined it before
                if isRelay and not connectViaRelay:
                    log('ignoring relay connection to the Plex Media Server "{}" at {}'.format(server.name, url), xbmc.LOGDEBUG)
                    continue

                # try to connect to the server
                plexServer = PlexServer(baseurl=url, token=server.accessToken, timeout=plex.constants.REQUEST_TIMEOUT)

                # if this is a relay ask the user if using it is ok
                if isRelay:
                    connectViaRelay = dialog.yesno(localise(32056), localise(32061).format(server.name))
                    if not connectViaRelay:
                        log('ignoring relay connection to the Plex Media Server "{}" at {}'.format(server.name, url), xbmc.LOGDEBUG)
                        continue

                baseUrl = url
                break
            except:
                log('failed to connect to "{}" at {}'.format(server.name, url), xbmc.LOGDEBUG)
                continue

        if not baseUrl:
            dialog.ok(localise(32056), localise(32060).format(server.name))
            log('failed to connect to the Plex Media Server "{}" for MyPlex account {}'.format(server.name, username), xbmc.LOGWARNING)
            return None

    if not baseUrl:
        log('failed to determine the URL to access the Plex Media Server "{}" for MyPlex account {}'.format(server.name, username), xbmc.LOGWARNING)
        return None

    log('successfully connected to Plex Media Server "{}" for MyPlex account {} at {}'.format(server.name, username, baseUrl))

    providerId = plex.server.Server.BuildProviderId(server.clientIdentifier)
    providerIconUrl = plex.server.Server.BuildIconUrl(baseUrl)
    provider = xbmcmediaimport.MediaProvider(providerId, baseUrl, server.name, providerIconUrl, plex.constants.SUPPORTED_MEDIA_TYPES, handle=handle)

    # store MyPlex account details and token in settings
    providerSettings = provider.prepareSettings()
    if not providerSettings:
        return None

    providerSettings.setInt(plex.constants.SETTINGS_PROVIDER_AUTHENTICATION, plex.constants.SETTINGS_PROVIDER_AUTHENTICATION_OPTION_MYPLEX)
    providerSettings.setString(plex.constants.SETTINGS_PROVIDER_USERNAME, username)
    providerSettings.setString(plex.constants.SETTINGS_PROVIDER_TOKEN, server.accessToken)
    providerSettings.save()

    return provider
Example #18
0
def discoverProviderWithEmbyConnect(handle, options):
    deviceId = Request.GenerateDeviceId()

    embyConnect = linkToEmbyConnect(deviceId)
    if not embyConnect:
        return None

    dialog = xbmcgui.Dialog()

    # get all connected servers
    servers = EmbyConnect.GetServers(embyConnect.accessToken,
                                     embyConnect.userId)
    if not servers:
        log(
            'no servers available for Emby Connect user id {}'.format(
                embyConnect.userId), xbmc.LOGWARNING)
        return None

    if len(servers) == 1:
        server = servers[0]
    else:
        # ask the user which server to use
        serverChoices = [server.name for server in servers]
        serverChoice = dialog.select(localise(32057), serverChoices)
        if serverChoice < 0 or serverChoice >= len(serverChoices):
            return None

        server = server[serverChoice]

    if not server:
        return None

    urls = []
    if server.localUrl:
        # ask the user whether to use a local or remote connection
        isLocal = dialog.yesno(localise(32058),
                               localise(32059).format(server.name))
        if isLocal:
            urls.append(server.localUrl)

    if server.remoteUrl:
        urls.append(server.remoteUrl)

    baseUrl = None
    # find a working connection / base URL
    for url in urls:
        try:
            _ = emby.api.server.Server.GetInfo(url)
        except:
            log('failed to connect to "{}" at {}'.format(server.name, url),
                xbmc.LOGDEBUG)
            continue

        baseUrl = url
        break

    if not baseUrl:
        dialog.ok(localise(32058), localise(32060).format(server.name))
        log(
            'failed to connect to Emby server "{}" with Emby Connect user ID {}'
            .format(server.name, embyConnect.userId), xbmc.LOGWARNING)
        return None

    providerId = Server.BuildProviderId(server.systemId)
    providerIconUrl = Server.BuildIconUrl(baseUrl)
    provider = xbmcmediaimport.MediaProvider(
        providerId, baseUrl, server.name, providerIconUrl,
        emby.constants.SUPPORTED_MEDIA_TYPES)
    provider.setIconUrl(kodi.Api.downloadIcon(provider))

    # store Emby connect authentication in settings
    providerSettings = provider.prepareSettings()
    if not providerSettings:
        return None

    providerSettings.setString(
        emby.constants.SETTING_PROVIDER_AUTHENTICATION,
        emby.constants.SETTING_PROVIDER_AUTHENTICATION_OPTION_EMBY_CONNECT)
    providerSettings.setString(
        emby.constants.SETTING_PROVIDER_EMBY_CONNECT_USER_ID,
        embyConnect.userId)
    providerSettings.setString(
        emby.constants.SETTING_PROVIDER_EMBY_CONNECT_ACCESS_KEY,
        server.accessKey)
    providerSettings.setString(emby.constants.SETTING_PROVIDER_DEVICEID,
                               deviceId)
    providerSettings.save()

    log('Emby Connect server {} successfully discovered at {}'.format(
        mediaProvider2str(provider), baseUrl))

    return provider
Example #19
0
def execImport(handle, options):
    # parse all necessary options
    mediaTypes = mediaTypesFromOptions(options)
    if not mediaTypes:
        log('cannot execute "import" without media types', xbmc.LOGERROR)
        return

    # retrieve the media import
    mediaImport = xbmcmediaimport.getImport(handle)
    if not mediaImport:
        log('cannot retrieve media import', xbmc.LOGERROR)
        return

    # prepare and get the media import settings
    importSettings = mediaImport.prepareSettings()
    if not importSettings:
        log('cannot prepare media import settings', xbmc.LOGERROR)
        return

    # retrieve the media provider
    mediaProvider = mediaImport.getProvider()
    if not mediaProvider:
        log('cannot retrieve media provider', xbmc.LOGERROR)
        return

    log('importing {} items from {}...'.format(mediaTypes, mediaProvider2str(mediaProvider)))

    # prepare the media provider settings
    mediaProviderSettings = mediaProvider.prepareSettings()
    if not mediaProviderSettings:
        log('cannot prepare media provider settings', xbmc.LOGERROR)
        return

    # create an Emby server instance
    embyServer = Server(mediaProvider)

    # build the base URL to retrieve items
    baseUrl = embyServer.BuildUserUrl(emby.constants.URL_ITEMS)
    baseUrlOptions = {
        emby.constants.URL_QUERY_ITEMS_RECURSIVE: 'true',
        emby.constants.URL_QUERY_ITEMS_FIELDS: ','.join(EMBY_ITEM_FIELDS),
        emby.constants.URL_QUERY_ITEMS_EXCLUDE_LOCATION_TYPES: 'Virtual,Offline'
    }
    baseUrl = Url.addOptions(baseUrl, baseUrlOptions)

    # get all (matching) library views
    selectedViews = ImportSettings.GetLibraryViews(importSettings)
    views = getMatchingLibraryViews(embyServer, mediaTypes, selectedViews)
    if not views:
        log('cannot retrieve items without any library views', xbmc.LOGERROR)
        return

    # determine whether Direct Play is allowed
    allowDirectPlay = mediaProviderSettings.getBool(emby.constants.SETTING_PROVIDER_PLAYBACK_ALLOW_DIRECT_PLAY)

    # determine whether to import collections
    importCollections = importSettings.getBool(emby.constants.SETTING_IMPORT_IMPORT_COLLECTIONS)

    # determine the last sync time and whether we should perform a fast sync
    fastSync = False
    syncUrlOptions = {}

    # check if synchronization related settings have changed; if yes we have to perform a full synchronization
    if SynchronizationSettings.HaveChanged(mediaTypes, mediaProviderSettings, importSettings, save=True):
        log('forcing a full synchronization to import {} items from {} because some related settings have changed'
            .format(mediaTypes, mediaProvider2str(mediaProvider)))
    else:
        # check if we
        #   have already performed a (full) synchronization before
        #   should use the Kodi Companion Emby server plugin
        lastSync = mediaImport.getLastSynced()
        if lastSync and \
           mediaProviderSettings.getBool(emby.constants.SETTING_PROVIDER_SYNCHRONIZATION_USE_KODI_COMPANION):
            if KodiCompanion.IsInstalled(embyServer):
                fastSync = True

                # convert the last sync datetime string to ISO 8601
                lastSync = parser.parse(lastSync).astimezone(timezone.utc).isoformat(timespec='seconds')

                syncUrlOptions.update({
                    # only set MinDateLastSavedForUser because it already covers DateLastSaved, RatingLastModified
                    # and PlaystateLastModified. Setting both MinDateLastSaved and MinDateLastSavedForUser will
                    # cause issues, see
                    # https://emby.media/community/index.php?/topic/82258-retrieving-changeset-when-client-returns-online-mediaimport/
                    emby.constants.URL_QUERY_ITEMS_MIN_DATE_LAST_SAVED_FOR_USER: lastSync
                })
                log('using fast synchronization to import {} items from {} with Kodi companion plugin'
                    .format(mediaTypes, mediaProvider2str(mediaProvider)), xbmc.LOGDEBUG)

                # retrieving the sync queue from Kodi companion
                syncQueue = KodiCompanion.SyncQueue.GetItems(embyServer, lastSync)
            else:
                log('Kodi companion usage is enabled to import {} items from {} but the server plugin is not installed'
                    .format(mediaTypes, mediaProvider2str(mediaProvider)), xbmc.LOGWARNING)

    # loop over all media types to be imported
    for mediaType in mediaTypes:
        if shouldCancel(handle, showProgress=False):
            return

        if mediaType == xbmcmediaimport.MediaTypeVideoCollection and not importCollections:
            log('importing {} items from {} is disabled'.format(mediaType, mediaProvider2str(mediaProvider)),
                xbmc.LOGDEBUG)
            continue

        log('importing {} items from {}...'.format(mediaType, mediaProvider2str(mediaProvider)))

        mappedMediaType = kodi.Api.getEmbyMediaType(mediaType)
        if not mappedMediaType:
            log('cannot import unsupported media type "{}"'.format(mediaType), xbmc.LOGERROR)
            continue
        (_, embyMediaType, _, localizedMediaType) = mappedMediaType

        xbmcmediaimport.setProgressStatus(
            handle, localise(32001).format(localise(localizedMediaType)))

        urlOptions = syncUrlOptions.copy()
        urlOptions.update({
            emby.constants.URL_QUERY_ITEMS_INCLUDE_ITEM_TYPES: embyMediaType
        })
        url = Url.addOptions(baseUrl, urlOptions)

        boxsetUrlOptions = {
            emby.constants.URL_QUERY_ITEMS_INCLUDE_ITEM_TYPES: kodi.EMBY_MEDIATYPE_BOXSET
        }
        boxsetUrl = Url.addOptions(baseUrl, boxsetUrlOptions)

        totalItems = 0

        # handle library views
        for view in views:
            # retrieve BoxSets if configured
            boxsetMapping = {}
            if importCollections and mediaType == xbmcmediaimport.MediaTypeMovie:
                # get the number of media items in the view
                totalItemCount = getTotalItems(embyServer, url, mediaType, view.id)

                # only load BoxSets from views with media items
                if totalItemCount:
                    # retrieve all BoxSets / collections matching the current media type
                    boxsetObjs = importItems(handle, embyServer, boxsetUrl, mediaType, view.id, raw=True,
                                             showProgress=False, allowDirectPlay=allowDirectPlay)
                    for boxsetObj in boxsetObjs:
                        if emby.constants.PROPERTY_ITEM_ID not in boxsetObj or \
                            emby.constants.PROPERTY_ITEM_NAME not in boxsetObj:
                            continue

                        boxsetId = boxsetObj[emby.constants.PROPERTY_ITEM_ID]
                        boxsetName = boxsetObj[emby.constants.PROPERTY_ITEM_NAME]

                        # get all items belonging to the BoxSet
                        boxsetItems = importItems(handle, embyServer, url, mediaType, boxsetId,
                                                  embyMediaType=embyMediaType, viewName=boxsetName,
                                                  showProgress=False, allowDirectPlay=allowDirectPlay)

                        for boxsetItem in boxsetItems:
                            # reorder to map item paths to BoxSet names
                            boxsetMapping[boxsetItem.getPath()] = boxsetName

            # retrieve the actual media items
            log('importing {} items from "{}" view from {}...'
                .format(mediaType, view.name, mediaProvider2str(mediaProvider)))

            importItemsGen = importItemsGenerator(handle, embyServer, url, mediaType, view.id,
                                                  embyMediaType=embyMediaType, viewName=view.name,
                                                  allowDirectPlay=allowDirectPlay)

            for importedItems in importItemsGen:
                totalItems += len(importedItems)

                # assign BoxSets / collections to the retrieved items
                if boxsetMapping:
                    for index, item in enumerate(importedItems):
                        boxsetName = boxsetMapping.get(item.getPath(), None)
                        if boxsetName:
                            # set the BoxSet / collection
                            kodi.Api.setCollection(item, boxsetName)
                            importedItems[index] = item

                # pass the imported items back to Kodi
                xbmcmediaimport.addImportItems(handle, importedItems, mediaType)

        # in a fast sync we need to get the removed items from Kodi companion
        if fastSync:
            if totalItems:
                log('{} changed {} items imported from {}'
                    .format(totalItems, mediaType, mediaProvider2str(mediaProvider)))

            # handle removed items through Kodi companion's sync queue
            if syncQueue.itemsRemoved:
                # retrieve all local items matching the current media type from the current import
                localItems = xbmcmediaimport.getImportedItems(handle, mediaType)

                # match the local items against the changed items
                removedItems, = kodi.Api.matchImportedItemIdsToLocalItems(  # noqa: E501 # pylint: disable=unbalanced-tuple-unpacking
                    localItems, syncQueue.itemsRemoved)

                # erase all removed items matching the current media type from the sync queue
                syncQueue.itemsRemoved = \
                    [removedItem for removedItem in syncQueue.itemsRemoved if removedItem in removedItems]

                if removedItems:
                    log('{} previously imported {} items removed from {}'
                        .format(len(removedItems), mediaType, mediaProvider2str(mediaProvider)))
                    xbmcmediaimport.addImportItems(handle, removedItems, mediaType,
                                                   xbmcmediaimport.MediaImportChangesetTypeRemoved)
        else:
            log('{} {} items imported from {}'.format(totalItems, mediaType, mediaProvider2str(mediaProvider)))

    xbmcmediaimport.finishImport(handle, fastSync)
Example #20
0
def play(item, itemId, mediaProvider):
    if item.isFolder():
        log(
            '[context/play] cannot play folder item {}'.format(
                listItem2str(item, itemId)), xbmc.LOGERROR)
        return

    # create an Emby server instance
    embyServer = Server(mediaProvider)

    # retrieve all details of the item
    itemObj = Library.GetItem(embyServer, itemId)
    if not itemObj:
        log(
            '[context/play] cannot retrieve the details of {} from {}'.format(
                listItem2str(item, itemId), mediaProvider2str(mediaProvider)),
            xbmc.LOGERROR)
        return

    # cannot play folders
    if itemObj.get(emby.constants.PROPERTY_ITEM_IS_FOLDER):
        log(
            '[context/play] cannot play folder item {}'.format(
                listItem2str(item, itemId)), xbmc.LOGERROR)
        return

    playChoices = []
    playChoicesUrl = []

    # determine whether Direct Play is allowed
    mediaProviderSettings = mediaProvider.getSettings()
    allowDirectPlay = mediaProviderSettings.getBool(
        emby.constants.SETTING_PROVIDER_PLAYBACK_ALLOW_DIRECT_PLAY)

    # check if the item supports Direct Play and / or Direct Stream
    canDirectPlay = None
    directPlayUrl = None
    if allowDirectPlay:
        (canDirectPlay, directPlayUrl) = kodi.Api.getDirectPlayUrl(itemObj)

        if canDirectPlay and directPlayUrl:
            playChoices.append(localise(32101))
            playChoicesUrl.append(directPlayUrl)

    (canDirectStream,
     directStreamUrl) = kodi.Api.getDirectStreamUrl(embyServer, itemId,
                                                    itemObj)
    if canDirectStream:
        playChoices.append(localise(32102))
        playChoicesUrl.append(directStreamUrl)

    # if there are no options something went wrong
    if not playChoices:
        log(
            '[context/play] cannot play {} from {}'.format(
                listItem2str(item, itemId), mediaProvider2str(mediaProvider)),
            xbmc.LOGERROR)
        return

    # ask the user how to play
    playChoice = Dialog().contextmenu(playChoices)
    if playChoice < 0 or playChoice >= len(playChoices):
        return

    playUrl = playChoicesUrl[playChoice]

    # play the item
    log('[context/play] playing {} using "{}" ({}) from {}'.format(
        listItem2str(item, itemId), playChoices[playChoice], playUrl,
        mediaProvider2str(mediaProvider)))
    # overwrite the dynamic path of the ListItem
    item.setDynamicPath(playUrl)
    xbmc.Player().play(playUrl, item)
Example #21
0
def execImport(handle, options):
    if not 'path' in options:
        log('cannot execute "import" without path', xbmc.LOGERROR)
        return

    # parse all necessary options
    mediaTypes = mediaTypesFromOptions(options)
    if not mediaTypes:
        log('cannot execute "import" without media types', xbmc.LOGERROR)
        return

    # retrieve the media import
    mediaImport = xbmcmediaimport.getImport(handle)
    if not mediaImport:
        log('cannot retrieve media import', xbmc.LOGERROR)
        return

    # prepare and get the media import settings
    importSettings = mediaImport.prepareSettings()
    if not importSettings:
        log('cannot prepare media import settings', xbmc.LOGERROR)
        return

    # retrieve the media provider
    mediaProvider = mediaImport.getProvider()
    if not mediaProvider:
        log('cannot retrieve media provider', xbmc.LOGERROR)
        return

    # prepare the media provider settings
    if not mediaProvider.prepareSettings():
        log('cannot prepare media provider settings', xbmc.LOGERROR)
        return

    # create a Plex Media Server instance
    server = Server(mediaProvider)
    plexServer = server.PlexServer()
    plexLibrary = plexServer.library

    # get all (matching) library sections
    selectedLibrarySections = getLibrarySectionsFromSettings(importSettings)
    librarySections = getMatchingLibrarySections(plexServer, mediaTypes, selectedLibrarySections)
    if not librarySections:
        log('cannot retrieve {} items without any library section'.format(mediaTypes), xbmc.LOGERROR)
        return

    # loop over all media types to be imported
    progressTotal = len(mediaTypes)
    for progress, mediaType in enumerate(mediaTypes):
        if xbmcmediaimport.shouldCancel(handle, progress, progressTotal):
            return

        mappedMediaType = Api.getPlexMediaType(mediaType)
        if not mappedMediaType:
            log('cannot import unsupported media type "{}"'.format(mediaType), xbmc.LOGERROR)
            continue

        plexLibType = mappedMediaType['libtype']
        localizedMediaType = localise(mappedMediaType['label'])

        xbmcmediaimport.setProgressStatus(handle, localise(32001).format(localizedMediaType))

        log('importing {} items from {}'.format(mediaType, mediaProvider2str(mediaProvider)))

        # handle library sections
        plexItems = []
        sectionsProgressTotal = len(librarySections)
        for sectionsProgress, librarySection in enumerate(librarySections):
            if xbmcmediaimport.shouldCancel(handle, sectionsProgress, sectionsProgressTotal):
                return

            # get the library section from the Plex Media Server
            section = plexLibrary.sectionByID(librarySection['key'])
            if not section:
                log('cannot import {} items from unknown library section {}'.format(mediaType, librarySection), xbmc.LOGWARNING)
                continue

            # get all matching items from the library section
            try:
                plexSectionItems = section.search(libtype=plexLibType)
                plexItems.extend(plexSectionItems)
            except plexapi.exceptions.BadRequest as err:
                log('failed to retrieve {} items from {}: {}'.format(mediaType, mediaProvider2str(mediaProvider), err))
                return

        # parse all items
        items = []
        itemsProgressTotal = len(plexItems)
        for itemsProgress, plexItem in enumerate(plexItems):
            if xbmcmediaimport.shouldCancel(handle, itemsProgress, itemsProgressTotal):
                return

            item = Api.toFileItem(plexServer, plexItem, mediaType, plexLibType)
            if not item:
                continue

            items.append(item)

        if items:
            log('{} {} items imported from {}'.format(len(items), mediaType, mediaProvider2str(mediaProvider)))
            xbmcmediaimport.addImportItems(handle, items, mediaType)

    xbmcmediaimport.finishImport(handle)