예제 #1
0
    def album(self, item, e_item):
        ''' Update object to kodi.
        '''
        server_address = self.server.auth.get_server_info(
            self.server.auth.server_id)['address']
        API = api.API(item, server_address)
        obj = self.objects.map(item, 'Album')
        update = True

        try:
            obj['AlbumId'] = e_item[0]
        except TypeError:
            update = False
            obj['AlbumId'] = None
            LOG.debug("AlbumId %s not found", obj['Id'])
        else:
            if self.validate_album(
                    *values(obj, QU.get_album_by_id_obj)) is None:

                update = False
                LOG.info("AlbumId %s missing from kodi. repairing the entry.",
                         obj['AlbumId'])

        obj['Rating'] = 0
        obj['LastScraped'] = datetime.datetime.now().strftime(
            '%Y-%m-%d %H:%M:%S')
        obj['Genres'] = obj['Genres'] or []
        obj['Genre'] = " / ".join(obj['Genres'])
        obj['Bio'] = API.get_overview(obj['Bio'])
        obj['Artists'] = " / ".join(obj['Artists'] or [])
        obj['Artwork'] = API.get_all_artwork(
            self.objects.map(item, 'ArtworkMusic'), True)
        obj['Thumb'] = obj['Artwork']['Primary']

        if obj['Thumb']:
            obj['Thumb'] = "<thumb>%s</thumb>" % obj['Thumb']

        if update:
            self.album_update(obj)
        else:
            self.album_add(obj)

        self.artist_link(obj)
        self.artist_discography(obj)
        self.update_album(*values(obj, QU.update_album_obj))
        self.add_genres(*values(obj, QU.add_genres_obj))
        self.artwork.add(obj['Artwork'], obj['AlbumId'], "album")
        self.item_ids.append(obj['Id'])
예제 #2
0
    def next_up(self):

        item = self.get_file_info(self.get_playing_file())
        objects = Objects()

        if item['Type'] != 'Episode' or not item.get('CurrentEpisode'):
            return

        next_items = item['Server'].jellyfin.get_adjacent_episodes(
            item['CurrentEpisode']['tvshowid'], item['Id'])

        for index, next_item in enumerate(next_items['Items']):
            if next_item['Id'] == item['Id']:

                try:
                    next_item = next_items['Items'][index + 1]
                except IndexError:
                    LOG.warning("No next up episode.")

                    return

                break
        server_address = item['Server'].auth.get_server_info(
            item['Server'].auth.server_id)['address']
        API = api.API(next_item, server_address)
        data = objects.map(next_item, "UpNext")
        artwork = API.get_all_artwork(objects.map(next_item, 'ArtworkParent'),
                                      True)
        data['art'] = {
            'tvshow.poster': artwork.get('Series.Primary'),
            'tvshow.fanart': None,
            'thumb': artwork.get('Primary')
        }
        if artwork['Backdrop']:
            data['art']['tvshow.fanart'] = artwork['Backdrop'][0]

        next_info = {
            'play_info': {
                'ItemIds': [data['episodeid']],
                'ServerId': item['ServerId'],
                'PlayCommand': 'PlayNow'
            },
            'current_episode': item['CurrentEpisode'],
            'next_episode': data
        }

        LOG.info("--[ next up ] %s", next_info)
        event("upnext_data", next_info, hexlify=True)
예제 #3
0
    def window_artwork(self, prop, view_id):

        if not self.server.logged_in:
            window('%s.artwork' % prop, clear=True)

        elif self.server.logged_in and self.media_folders is not None:
            for library in self.media_folders:

                if library['Id'] == view_id and 'Primary' in library.get('ImageTags', {}):
                    server_address = self.server.auth.get_server_info(self.server.auth.server_id)['address']
                    artwork = api.API(None, server_address).get_artwork(view_id, 'Primary')
                    window('%s.artwork' % prop, artwork)

                    break
            else:
                window('%s.artwork' % prop, clear=True)
예제 #4
0
    def get_user(self, client):
        ''' Save user info.
        '''
        self.user = client['api'].get_user()
        self.config = client['api'].get_system_info()

        settings('username', self.user['Name'])
        settings('SeasonSpecials.bool',
                 self.config.get('DisplaySpecialsWithinSeasons', True))

        if 'PrimaryImageTag' in self.user:
            window(
                'EmbyUserImage',
                api.API(self.user,
                        client['auth/server-address']).get_user_artwork(
                            self.user['Id']))
예제 #5
0
    def run(self):
        with self.lock, self.database as kodidb, Database('jellyfin') as jellyfindb:
            while True:

                try:
                    item = self.queue.get(timeout=1)
                except Queue.Empty:
                    break

                default_args = (self.server, jellyfindb, kodidb, self.direct_path)
                if item['Type'] == 'Movie':
                    obj = Movies(*default_args).movie
                elif item['Type'] == 'Boxset':
                    obj = Movies(*default_args).boxset
                elif item['Type'] == 'Series':
                    obj = TVShows(*default_args).tvshow
                elif item['Type'] == 'Season':
                    obj = TVShows(*default_args).season
                elif item['Type'] == 'Episode':
                    obj = TVShows(*default_args).episode
                elif item['Type'] == 'MusicVideo':
                    obj = MusicVideos(*default_args).musicvideo
                elif item['Type'] == 'MusicAlbum':
                    obj = Music(*default_args).album
                elif item['Type'] == 'MusicArtist':
                    obj = Music(*default_args).artist
                elif item['Type'] == 'AlbumArtist':
                    obj = Music(s*default_args).albumartist
                elif item['Type'] == 'Audio':
                    obj = Music(*default_args).song

                try:
                    if obj(item) and self.notify:
                        self.notify_output.put((item['Type'], api.API(item).get_naming()))
                except LibraryException as error:
                    if error.status == 'StopCalled':
                        break
                except Exception as error:
                    LOG.exception(error)

                self.queue.task_done()

                if window('jellyfin_should_stop.bool'):
                    break

        LOG.info("--<[ q:updated/%s ]", id(self))
        self.is_done = True
예제 #6
0
    def artist(self, item, e_item, library):

        ''' If item does not exist, entry will be added.
            If item exists, entry will be updated.
        '''
        server_data = self.server.auth.get_server_info(self.server.auth.server_id)
        server_address = self.server.auth.get_server_address(server_data, server_data['LastConnectionMode'])
        API = api.API(item, server_address)
        obj = self.objects.map(item, 'Artist')
        update = True

        try:
            obj['ArtistId'] = e_item[0]
        except TypeError:
            update = False
            obj['ArtistId'] = None
            LOG.debug("ArtistId %s not found", obj['Id'])
        else:
            if self.validate_artist(*values(obj, QU.get_artist_by_id_obj)) is None:

                update = False
                LOG.info("ArtistId %s missing from kodi. repairing the entry.", obj['ArtistId'])

        obj['LibraryId'] = library['Id']
        obj['LibraryName'] = library['Name']
        obj['LastScraped'] = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        obj['ArtistType'] = "MusicArtist"
        obj['Genre'] = " / ".join(obj['Genres'] or [])
        obj['Bio'] = API.get_overview(obj['Bio'])
        obj['Artwork'] = API.get_all_artwork(self.objects.map(item, 'ArtworkMusic'), True)
        obj['Thumb'] = obj['Artwork']['Primary']
        obj['Backdrops'] = obj['Artwork']['Backdrop'] or ""

        if obj['Thumb']:
            obj['Thumb'] = "<thumb>%s</thumb>" % obj['Thumb']

        if obj['Backdrops']:
            obj['Backdrops'] = "<fanart>%s</fanart>" % obj['Backdrops'][0]

        if update:
            self.artist_update(obj)
        else:
            self.artist_add(obj)

        self.update(obj['Genre'], obj['Bio'], obj['Thumb'], obj['Backdrops'], obj['LastScraped'], obj['ArtistId'])
        self.artwork.add(obj['Artwork'], obj['ArtistId'], "artist")
        self.item_ids.append(obj['Id'])
예제 #7
0
    def listitem_channel(self, obj, listitem, item):
        ''' Set listitem for channel content.
        '''
        API = api.API(item, self.server)

        obj['Title'] = "%s - %s" % (obj['Title'], obj['ProgramName'])
        obj['Runtime'] = round(float((obj['Runtime'] or 0) / 10000000.0), 6)
        obj['PlayCount'] = API.get_playcount(obj['Played'],
                                             obj['PlayCount']) or 0
        obj['Overlay'] = 7 if obj['Played'] else 6
        obj['Artwork']['Primary'] = obj['Artwork']['Primary'] \
            or "special://home/addons/plugin.video.jellyfin/resources/icon.png"
        obj['Artwork']['Thumb'] = obj['Artwork']['Thumb'] \
            or "special://home/addons/plugin.video.jellyfin/resources/fanart.png"
        obj['Artwork']['Backdrop'] = obj['Artwork']['Backdrop'] \
            or ["special://home/addons/plugin.video.jellyfin/resources/fanart.png"]

        metadata = {
            'title': obj['Title'],
            'originaltitle': obj['Title'],
            'playcount': obj['PlayCount'],
            'overlay': obj['Overlay']
        }

        listitem.setArt({
            'icon': obj['Artwork']['Thumb'],
            'thumb': obj['Artwork']['Primary'],
        })
        self.set_artwork(obj['Artwork'], listitem, obj['Type'])

        if obj['Artwork']['Primary']:
            listitem.setArt({
                'thumb': obj['Artwork']['Primary'],
            })

        if not obj['Artwork']['Backdrop']:
            listitem.setArt({'fanart': obj['Artwork']['Primary']})

        listitem.setProperty('totaltime', str(obj['Runtime']))
        listitem.setProperty('IsPlayable', 'true')
        listitem.setProperty('IsFolder', 'false')

        listitem.setLabel(obj['Title'])
        listitem.setInfo('video', metadata)
        listitem.setContentLookup(False)
예제 #8
0
def get_fanart(item_id, path, server_id=None):
    ''' Get extra fanart for listitems. This is called by skinhelper.
        Images are stored locally, due to the Kodi caching system.
    '''
    if not item_id and 'plugin.video.emby' in path:
        item_id = path.split('/')[-2]

    if not item_id:
        return

    LOG.info("[ extra fanart ] %s", item_id)
    get_server(server_id)
    objects = objects.Objects()
    list_li = []
    directory = xbmc.translatePath("special://thumbnails/emby/%s/" %
                                   item_id).decode('utf-8')

    if not xbmcvfs.exists(directory):

        xbmcvfs.mkdirs(directory)
        item = EMBY['api'].get_item(item_id)
        obj = objects.map(item, 'Artwork')
        backdrops = api.API(item,
                            EMBY['auth/server-address']).get_all_artwork(obj)
        tags = obj['BackdropTags']

        for index, backdrop in enumerate(backdrops):

            tag = tags[index]
            fanart = os.path.join(directory, "fanart%s.jpg" % tag)
            li = xbmcgui.ListItem(tag, path=fanart)
            xbmcvfs.copy(backdrop, fanart)
            list_li.append((fanart, li, False))
    else:
        LOG.debug("cached backdrop found")
        dirs, files = xbmcvfs.listdir(directory)

        for file in files:
            fanart = os.path.join(directory, file.decode('utf-8'))
            li = xbmcgui.ListItem(file, path=fanart)
            list_li.append((fanart, li, False))

    xbmcplugin.addDirectoryItems(int(sys.argv[1]), list_li, len(list_li))
    xbmcplugin.endOfDirectory(int(sys.argv[1]))
예제 #9
0
def get_fanart(item_id, path, server_id=None):

    ''' Get extra fanart for listitems. This is called by skinhelper.
        Images are stored locally, due to the Kodi caching system.
    '''
    if not item_id and 'plugin.video.jellyfin' in path:
        item_id = path.split('/')[-2]

    if not item_id:
        return

    LOG.info("[ extra fanart ] %s", item_id)
    objects = Objects()
    list_li = []
    directory = xbmc.translatePath("special://thumbnails/jellyfin/%s/" % item_id)
    server = TheVoid('GetServerAddress', {'ServerId': server_id}).get()

    if not xbmcvfs.exists(directory):

        xbmcvfs.mkdirs(directory)
        item = TheVoid('GetItem', {'ServerId': server_id, 'Id': item_id}).get()
        obj = objects.map(item, 'Artwork')
        backdrops = api.API(item, server).get_all_artwork(obj)
        tags = obj['BackdropTags']

        for index, backdrop in enumerate(backdrops):

            tag = tags[index]
            fanart = os.path.join(directory, "fanart%s.jpg" % tag)
            li = xbmcgui.ListItem(tag, path=fanart)
            xbmcvfs.copy(backdrop, fanart)
            list_li.append((fanart, li, False))
    else:
        LOG.debug("cached backdrop found")
        dirs, files = xbmcvfs.listdir(directory)

        for file in files:
            fanart = os.path.join(directory, file)
            li = xbmcgui.ListItem(file, path=fanart)
            list_li.append((fanart, li, False))

    xbmcplugin.addDirectoryItems(PROCESS_HANDLE, list_li, len(list_li))
    xbmcplugin.endOfDirectory(PROCESS_HANDLE)
예제 #10
0
    def listitem_photo(self, obj, listitem, item):
        API = api.API(item, self.server)

        obj['Overview'] = API.get_overview(obj['Overview'])
        obj['FileDate'] = "%s.%s.%s" % tuple(
            reversed(obj['FileDate'].split('T')[0].split('-')))

        metadata = {'title': obj['Title']}
        listitem.setProperty('path', obj['Artwork']['Primary'])
        listitem.setThumbnailImage(obj['Artwork']['Primary'])
        listitem.setIconImage(
            obj['Artwork']['Primary']
            or "special://home/addons/plugin.video.emby/icon.png")
        listitem.setArt({
            'fanart':
            obj['Artwork']['Primary']
            or "special://home/addons/plugin.video.emby/fanart.jpg"
        })

        if obj['Type'] == 'Photo':
            metadata.update({
                'picturepath': obj['Artwork']['Primary'],
                'date': obj['FileDate'],
                'exif:width': str(obj.get('Width', 0)),
                'exif:height': str(obj.get('Height', 0)),
                'size': obj['Size'],
                'exif:cameramake': obj['CameraMake'],
                'exif:cameramodel': obj['CameraModel'],
                'exif:exposuretime': str(obj['ExposureTime']),
                'exif:focallength': str(obj['FocalLength'])
            })
            listitem.setProperty('plot', obj['Overview'])
            listitem.setProperty('IsFolder', 'false')
        else:
            if obj['Artwork']['Backdrop']:
                listitem.setArt({'fanart': obj['Artwork']['Backdrop'][0]})

            listitem.setProperty('IsFolder', 'true')

        listitem.setProperty('IsPlayable', 'false')
        listitem.setLabel(obj['Title'])
        listitem.setInfo('pictures', metadata)
        listitem.setContentLookup(False)
예제 #11
0
    def window_artwork(self, prop, view_id):

        if not self.server['connected']:
            window('%s.artwork' % prop, clear=True)

        elif self.server['connected'] and self.media_folders is not None:
            for library in self.media_folders:

                if library['Id'] == view_id and 'Primary' in library.get(
                        'ImageTags', {}):

                    artwork = api.API(
                        None, self.server['auth/server-address']).get_artwork(
                            view_id, 'Primary')
                    window('%s.artwork' % prop, artwork)

                    break
            else:
                window('%s.artwork' % prop, clear=True)
예제 #12
0
    def boxset(self, item, e_item):
        ''' If item does not exist, entry will be added.
            If item exists, entry will be updated.

            Process movies inside boxset.
            Process removals from boxset.
        '''
        server_data = self.server.auth.get_server_info(
            self.server.auth.server_id)
        server_address = self.server.auth.get_server_address(
            server_data, server_data['LastConnectionMode'])
        API = api.API(item, server_address)
        obj = self.objects.map(item, 'Boxset')

        obj['Overview'] = API.get_overview(obj['Overview'])

        try:
            obj['SetId'] = e_item[0]
            self.update_boxset(*values(obj, QU.update_set_obj))
        except TypeError as error:

            LOG.debug("SetId %s not found", obj['Id'])
            obj['SetId'] = self.add_boxset(*values(obj, QU.add_set_obj))

        self.boxset_current(obj)
        obj['Artwork'] = API.get_all_artwork(self.objects.map(item, 'Artwork'))

        for movie in obj['Current']:

            temp_obj = dict(obj)
            temp_obj['Movie'] = movie
            temp_obj['MovieId'] = obj['Current'][temp_obj['Movie']]
            self.remove_from_boxset(*values(temp_obj, QU.delete_movie_set_obj))
            self.jellyfin_db.update_parent_id(
                *values(temp_obj, QUEM.delete_parent_boxset_obj))
            LOG.info("DELETE from boxset [%s] %s: %s", temp_obj['SetId'],
                     temp_obj['Title'], temp_obj['MovieId'])

        self.artwork.add(obj['Artwork'], obj['SetId'], "set")
        self.jellyfin_db.add_reference(
            *values(obj, QUEM.add_reference_boxset_obj))
        LOG.info("UPDATE boxset [%s] %s", obj['SetId'], obj['Title'])
예제 #13
0
    def run(self):

        with self.lock:
            with self.database as kodidb:
                with Database('emby') as embydb:

                    while True:

                        try:
                            item = self.queue.get(timeout=1)
                        except Queue.Empty:
                            break

                        if item['Type'] in ('Series', 'Season', 'Episode'):
                            obj = MEDIA[item['Type']](
                                self.args[0],
                                embydb,
                                kodidb,
                                self.args[1],
                                verify=True)[item['Type']]
                        else:
                            obj = MEDIA[item['Type']](
                                self.args[0], embydb, kodidb,
                                self.args[1])[item['Type']]

                        try:
                            if obj(item) and self.notify:
                                self.notify_output.put(
                                    (item['Type'], api.API(item).get_naming()))
                        except LibraryException as error:
                            if error.status == 'StopCalled':
                                break
                        except Exception as error:
                            LOG.exception(error)

                        self.queue.task_done()

                        if window('emby_should_stop.bool'):
                            break

        LOG.info("--<[ q:updated/%s ]", id(self))
        self.is_done = True
예제 #14
0
    def additional_users(self, server):

        ''' Setup additional users images.
        '''
        for i in range(10):
            window('JellyfinAdditionalUserImage.%s' % i, clear=True)

        try:
            session = server.jellyfin.get_device(self.device_id)
        except Exception as error:
            LOG.exception(error)

            return

        for index, user in enumerate(session[0]['AdditionalUsers']):

            info = server.jellyfin.get_user(user['UserId'])
            image = api.API(info, server.config.data['auth.server']).get_user_artwork(user['UserId'])
            window('JellyfinAdditionalUserImage.%s' % index, image)
            window('JellyfinAdditionalUserPosition.%s' % user['UserId'], str(index))
예제 #15
0
    def listitem_photo(self, obj, listitem, item):
        API = api.API(item, self.server)

        obj['Overview'] = API.get_overview(obj['Overview'])
        obj['FileDate'] = "%s.%s.%s" % tuple(reversed(obj['FileDate'].split('T')[0].split('-')))

        metadata = {
            'title': obj['Title']
        }
        listitem.setProperty('path', obj['Artwork']['Primary'])
        listitem.setArt({
            'thumb': obj['Artwork']['Primary'],
        })

        if obj['Type'] == 'Photo':
            metadata.update({
                'picturepath': obj['Artwork']['Primary'],
                'date': obj['FileDate'],
                'exif:width': str(obj.get('Width', 0)),
                'exif:height': str(obj.get('Height', 0)),
                'size': obj['Size'],
                'exif:cameramake': obj['CameraMake'],
                'exif:cameramodel': obj['CameraModel'],
                'exif:exposuretime': str(obj['ExposureTime']),
                'exif:focallength': str(obj['FocalLength'])
            })
            listitem.setProperty('plot', obj['Overview'])
            listitem.setProperty('IsFolder', 'false')
            listitem.setArt({
                'icon': 'DefaultPicture.png',
            })
        else:
            listitem.setProperty('IsFolder', 'true')
            listitem.setArt({
                'icon': 'DefaultFolder.png',
            })

        listitem.setProperty('IsPlayable', 'false')
        listitem.setLabel(obj['Title'])
        listitem.setInfo('pictures', metadata)
        listitem.setContentLookup(False)
예제 #16
0
    def set_playlist(self,
                     item,
                     listitem,
                     db_id=None,
                     transcode=False,
                     *args,
                     **kwargs):
        ''' Verify seektime, set intros, set main item and set additional parts.
            Detect the seektime for video type content.
            Verify the default video action set in Kodi for accurate resume behavior.
        '''
        seektime = window('emby.resume.bool')
        window('emby.resume', clear=True)

        if item['MediaType'] in ('Video', 'Audio'):
            resume = item['UserData'].get('PlaybackPositionTicks')

            if resume:
                if get_play_action() == "Resume":
                    seektime = True

                if transcode and not seektime:
                    choice = self.resume_dialog(
                        api.API(item, self.server).adjust_resume(
                            (resume or 0) / 10000000.0))

                    if choice is None:
                        raise Exception("User backed out of resume dialog.")

                    seektime = False if not choice else True

        if settings('enableCinema.bool') and not seektime:
            self._set_intros(item)

        self.set_listitem(item, listitem, db_id, seektime)
        playutils.set_properties(item, item['PlaybackInfo']['Method'],
                                 self.server_id)
        self.stack.append([item['PlaybackInfo']['Path'], listitem])

        if item.get('PartCount'):
            self._set_additional_parts(item['Id'])
예제 #17
0
    def trailer(self, obj):

        try:
            if obj['LocalTrailer']:

                trailer = self.server['api'].get_local_trailers(obj['Id'])
                API = api.API(trailer, self.server['auth/server-address'])

                if self.direct_path:
                    obj['Trailer'] = API.get_file_path(trailer[0]['Path'])
                else:
                    obj['Trailer'] = "plugin://plugin.video.emby/trailer?id=%s&mode=play" % trailer[
                        0]['Id']

            elif obj['Trailer']:
                obj['Trailer'] = "plugin://plugin.video.youtube/play/?video_id=%s" % obj[
                    'Trailer'].rsplit('=', 1)[1]
        except Exception as error:

            LOG.error("Failed to get trailer: %s", error)
            obj['Trailer'] = None
예제 #18
0
    def run(self):

        with self.lock:
            with self.database as kodidb:
                with Database('emby') as embydb:

                    while True:

                        try:
                            item = self.queue.get(timeout=1)
                        except Queue.Empty:
                            break

                        obj = MEDIA[item['Type']](
                            self.library.server, embydb, kodidb,
                            self.library.direct_path)['UserData']
                        self.library.update_progress_dialog(
                            api.API(item).get_naming())

                        try:
                            obj(item)
                        except LibraryException as error:

                            if error.status in ('StopCalled',
                                                'StopWriteCalled'):
                                self.queue.put(item)

                                break
                        except Exception as error:
                            LOG.exception(error)

                        self.queue.task_done()

                        if window('emby_should_stop.bool'):
                            break

        LOG.info("--<[ q:userdata/%s ]", id(self))
        self.is_done = True
    def season(self, item, show_id=None):
        ''' If item does not exist, entry will be added.
            If item exists, entry will be updated.

            If the show is empty, try to remove it.
        '''
        server_data = self.server.auth.get_server_info(
            self.server.auth.server_id)
        server_address = self.server.auth.get_server_address(
            server_data, server_data['LastConnectionMode'])
        API = api.API(item, server_address)
        obj = self.objects.map(item, 'Season')

        obj['ShowId'] = show_id

        if obj['ShowId'] is None:

            try:
                obj['ShowId'] = self.jellyfin_db.get_item_by_id(
                    *values(obj, QUEM.get_item_series_obj))[0]
            except (KeyError, TypeError):
                LOG.error("Unable to add series %s", obj['SeriesId'])

                return False

        obj['SeasonId'] = self.get_season(*values(obj, QU.get_season_obj))
        obj['Artwork'] = API.get_all_artwork(self.objects.map(item, 'Artwork'))

        if obj['Location'] != "Virtual":
            self.jellyfin_db.add_reference(
                *values(obj, QUEM.add_reference_season_obj))
            self.item_ids.append(obj['Id'])

        self.artwork.add(obj['Artwork'], obj['SeasonId'], "season")
        LOG.info("UPDATE season [%s/%s] %s: %s", obj['ShowId'],
                 obj['SeasonId'], obj['Title'] or obj['Index'], obj['Id'])
예제 #20
0
    def userdata(self, item, e_item):
        ''' This updates: Favorite, LastPlayedDate, Playcount, PlaybackPositionTicks
            Poster with progress bar
        '''
        server_data = self.server.auth.get_server_info(
            self.server.auth.server_id)
        server_address = self.server.auth.get_server_address(
            server_data, server_data['LastConnectionMode'])
        API = api.API(item, server_address)
        obj = self.objects.map(item, 'MovieUserData')

        try:
            obj['MovieId'] = e_item[0]
            obj['FileId'] = e_item[1]
        except TypeError:
            return

        obj['Resume'] = API.adjust_resume((obj['Resume'] or 0) / 10000000.0)
        obj['Runtime'] = round(float((obj['Runtime'] or 0) / 10000000.0), 6)
        obj['PlayCount'] = API.get_playcount(obj['Played'], obj['PlayCount'])

        if obj['DatePlayed']:
            obj['DatePlayed'] = Local(obj['DatePlayed']).split('.')[0].replace(
                'T', " ")

        if obj['Favorite']:
            self.get_tag(*values(obj, QU.get_tag_movie_obj))
        else:
            self.remove_tag(*values(obj, QU.delete_tag_movie_obj))

        LOG.debug("New resume point %s: %s", obj['Id'], obj['Resume'])
        self.add_playstate(*values(obj, QU.add_bookmark_obj))
        self.jellyfin_db.update_reference(
            *values(obj, QUEM.update_reference_obj))
        LOG.info("USERDATA movie [%s/%s] %s: %s", obj['FileId'],
                 obj['MovieId'], obj['Id'], obj['Title'])
예제 #21
0
    def song(self, item, e_item):
        ''' Update object to kodi.
        '''
        API = api.API(item, self.server['auth/server-address'])
        obj = self.objects.map(item, 'Song')
        update = True

        try:
            obj['SongId'] = e_item[0]
            obj['PathId'] = e_item[2]
            obj['AlbumId'] = e_item[3]
        except TypeError as error:

            update = False
            obj['SongId'] = self.create_entry_song()
            LOG.debug("SongId %s not found", obj['Id'])
        else:
            if self.validate_song(*values(obj, QU.get_song_by_id_obj)) is None:

                update = False
                LOG.info("SongId %s missing from kodi. repairing the entry.",
                         obj['SongId'])

        self.get_song_path_filename(obj, API)

        obj['Rating'] = 0
        obj['Genres'] = obj['Genres'] or []
        obj['PlayCount'] = API.get_playcount(obj['Played'], obj['PlayCount'])
        obj['Runtime'] = (obj['Runtime'] or 0) / 10000000.0
        obj['Genre'] = " / ".join(obj['Genres'])
        obj['Artists'] = " / ".join(obj['Artists'] or [])
        obj['AlbumArtists'] = obj['AlbumArtists'] or []
        obj['Index'] = obj['Index'] or 0
        obj['Disc'] = obj['Disc'] or 1
        obj['EmbedCover'] = False
        obj['Comment'] = API.get_overview(obj['Comment'])
        obj['Artwork'] = API.get_all_artwork(
            self.objects.map(item, 'ArtworkMusic'), True)

        if obj['DateAdded']:
            obj['DateAdded'] = Local(obj['DateAdded']).split('.')[0].replace(
                'T', " ")

        if obj['DatePlayed']:
            obj['DatePlayed'] = Local(obj['DatePlayed']).split('.')[0].replace(
                'T', " ")

        if obj['Disc'] != 1:
            obj['Index'] = obj['Disc'] * 2**16 + obj['Index']

        if update:
            self.song_update(obj)
        else:
            self.song_add(obj)

        self.link_song_album(*values(obj, QU.update_song_album_obj))
        self.add_role(*values(obj, QU.update_role_obj))  # defaultt role
        self.song_artist_link(obj)
        self.song_artist_discography(obj)

        obj['strAlbumArtists'] = " / ".join(obj['AlbumArtists'])
        self.get_album_artist(*values(obj, QU.get_album_artist_obj))

        self.add_genres(*values(obj, QU.update_genre_song_obj))
        self.artwork.add(obj['Artwork'], obj['SongId'], "song")
        self.item_ids.append(obj['Id'])

        if obj['SongAlbumId'] is None:
            self.artwork.add(obj['Artwork'], obj['AlbumId'], "album")

        return not update
예제 #22
0
    def tvshow(self, item, e_item, library):
        ''' If item does not exist, entry will be added.
            If item exists, entry will be updated.

            If the show is empty, try to remove it.
            Process seasons.
            Apply series pooling.
        '''
        API = api.API(item, self.server['auth/server-address'])
        obj = self.objects.map(item, 'Series')
        update = True

        if not settings('syncEmptyShows.bool') and not obj['RecursiveCount']:

            LOG.info("Skipping empty show %s: %s", obj['Title'], obj['Id'])
            self.remove(obj['Id'])

            return False

        try:
            obj['ShowId'] = e_item[0]
            obj['PathId'] = e_item[2]
        except TypeError as error:

            update = False
            LOG.debug("ShowId %s not found", obj['Id'])
            obj['ShowId'] = self.create_entry()
        else:
            if self.get(*values(obj, QU.get_tvshow_obj)) is None:

                update = False
                LOG.info("ShowId %s missing from kodi. repairing the entry.",
                         obj['ShowId'])

        obj['Path'] = API.get_file_path(obj['Path'])
        obj['LibraryId'] = library['Id']
        obj['LibraryName'] = library['Name']
        obj['Genres'] = obj['Genres'] or []
        obj['People'] = obj['People'] or []
        obj['Mpaa'] = API.get_mpaa(obj['Mpaa'])
        obj['Studios'] = [
            API.validate_studio(studio) for studio in (obj['Studios'] or [])
        ]
        obj['Genre'] = " / ".join(obj['Genres'])
        obj['People'] = API.get_people_artwork(obj['People'])
        obj['Plot'] = API.get_overview(obj['Plot'])
        obj['Studio'] = " / ".join(obj['Studios'])
        obj['Artwork'] = API.get_all_artwork(self.objects.map(item, 'Artwork'))

        self.get_path_filename(obj)

        if obj['Premiere']:
            obj['Premiere'] = str(obj['Premiere']).split('.')[0].replace(
                'T', " ")

        tags = []
        tags.extend(obj['Tags'] or [])
        tags.append(obj['LibraryName'])

        if obj['Favorite']:
            tags.append('Favorite tvshows')

        obj['Tags'] = tags

        if update:
            self.tvshow_update(obj)
        else:
            self.tvshow_add(obj)

        self.link(*values(obj, QU.update_tvshow_link_obj))
        self.update_path(*values(obj, QU.update_path_tvshow_obj))
        self.add_tags(*values(obj, QU.add_tags_tvshow_obj))
        self.add_people(*values(obj, QU.add_people_tvshow_obj))
        self.add_genres(*values(obj, QU.add_genres_tvshow_obj))
        self.add_studios(*values(obj, QU.add_studios_tvshow_obj))
        self.artwork.add(obj['Artwork'], obj['ShowId'], "tvshow")
        self.item_ids.append(obj['Id'])

        season_episodes = {}

        for season in self.server['api'].get_seasons(obj['Id'])['Items']:

            if season['SeriesId'] != obj['Id']:
                obj['SeriesId'] = season['SeriesId']
                self.item_ids.append(season['SeriesId'])

                try:
                    self.emby_db.get_item_by_id(
                        *values(obj, QUEM.get_item_series_obj))[0]

                    if self.update_library:
                        season_episodes[season['Id']] = season['SeriesId']
                except TypeError:

                    self.emby_db.add_reference(
                        *values(obj, QUEM.add_reference_pool_obj))
                    LOG.info("POOL %s [%s/%s]", obj['Title'], obj['Id'],
                             obj['SeriesId'])
                    season_episodes[season['Id']] = season['SeriesId']

            try:
                self.emby_db.get_item_by_id(season['Id'])[0]
                self.item_ids.append(season['Id'])
            except TypeError:
                self.season(season, obj['ShowId'])
        else:
            season_id = self.get_season(
                *values(obj, QU.get_season_special_obj))
            self.artwork.add(obj['Artwork'], season_id, "season")

        for season in season_episodes:
            for episodes in server.get_episode_by_season(
                    season_episodes[season], season):

                for episode in episodes['Items']:
                    self.episode(episode)
예제 #23
0
    def userdata(self, item, e_item):
        ''' This updates: Favorite, LastPlayedDate, Playcount, PlaybackPositionTicks
            Poster with progress bar

            Make sure there's no other bookmarks created by widget.
            Create additional entry for widgets. This is only required for plugin/episode.
        '''
        API = api.API(item, self.server['auth/server-address'])
        obj = self.objects.map(item, 'EpisodeUserData')

        try:
            obj['KodiId'] = e_item[0]
            obj['FileId'] = e_item[1]
            obj['Media'] = e_item[4]
        except TypeError:
            return

        if obj['Media'] == "tvshow":

            if obj['Favorite']:
                self.get_tag(*values(obj, QU.get_tag_episode_obj))
            else:
                self.remove_tag(*values(obj, QU.delete_tag_episode_obj))

        elif obj['Media'] == "episode":

            obj['Resume'] = API.adjust_resume(
                (obj['Resume'] or 0) / 10000000.0)
            obj['Runtime'] = round(float((obj['Runtime'] or 0) / 10000000.0),
                                   6)
            obj['PlayCount'] = API.get_playcount(obj['Played'],
                                                 obj['PlayCount'])

            if obj['DatePlayed']:
                obj['DatePlayed'] = obj['DatePlayed'].split('.')[0].replace(
                    'T', " ")

            if obj['DateAdded']:
                obj['DateAdded'] = obj['DateAdded'].split('.')[0].replace(
                    'T', " ")

            self.add_playstate(*values(obj, QU.add_bookmark_obj))

            if not self.direct_path and not obj['Resume']:

                temp_obj = dict(obj)
                temp_obj['Filename'] = self.get_filename(
                    *values(temp_obj, QU.get_file_obj))
                temp_obj['Path'] = "plugin://plugin.video.emby.tvshows/"
                self.remove_file(*values(temp_obj, QU.delete_file_obj))

            elif not self.direct_path and obj['Resume']:

                temp_obj = dict(obj)
                temp_obj['Filename'] = self.get_filename(
                    *values(temp_obj, QU.get_file_obj))
                temp_obj['PathId'] = self.get_path(
                    "plugin://plugin.video.emby.tvshows/")
                temp_obj['FileId'] = self.add_file(
                    *values(temp_obj, QU.add_file_obj))
                self.update_file(*values(temp_obj, QU.update_file_obj))
                self.add_playstate(*values(temp_obj, QU.add_bookmark_obj))

        self.emby_db.update_reference(*values(obj, QUEM.update_reference_obj))
        LOG.info("USERDATA %s [%s/%s] %s: %s", obj['Media'], obj['FileId'],
                 obj['KodiId'], obj['Id'], obj['Title'])
예제 #24
0
    def episode(self, item, e_item):
        ''' If item does not exist, entry will be added.
            If item exists, entry will be updated.

            Create additional entry for widgets.
            This is only required for plugin/episode.
        '''
        API = api.API(item, self.server['auth/server-address'])
        obj = self.objects.map(item, 'Episode')
        update = True

        if obj['Location'] == "Virtual":
            LOG.info("Skipping virtual episode %s: %s", obj['Title'],
                     obj['Id'])

            return

        elif obj['SeriesId'] is None:
            LOG.info("Skipping episode %s with missing SeriesId", obj['Id'])

            return

        try:
            obj['EpisodeId'] = e_item[0]
            obj['FileId'] = e_item[1]
            obj['PathId'] = e_item[2]
        except TypeError as error:

            update = False
            LOG.debug("EpisodeId %s not found", obj['Id'])
            obj['EpisodeId'] = self.create_entry_episode()
        else:
            if self.get_episode(*values(obj, QU.get_episode_obj)) is None:

                update = False
                LOG.info(
                    "EpisodeId %s missing from kodi. repairing the entry.",
                    obj['EpisodeId'])

        obj['Path'] = API.get_file_path(obj['Path'])
        obj['Index'] = obj['Index'] or -1
        obj['Writers'] = " / ".join(obj['Writers'] or [])
        obj['Directors'] = " / ".join(obj['Directors'] or [])
        obj['Plot'] = API.get_overview(obj['Plot'])
        obj['Resume'] = API.adjust_resume((obj['Resume'] or 0) / 10000000.0)
        obj['Runtime'] = round(float((obj['Runtime'] or 0) / 10000000.0), 6)
        obj['People'] = API.get_people_artwork(obj['People'] or [])
        obj['DateAdded'] = obj['DateAdded'].split('.')[0].replace('T', " ")
        obj['DatePlayed'] = None if not obj['DatePlayed'] else obj[
            'DatePlayed'].split('.')[0].replace('T', " ")
        obj['PlayCount'] = API.get_playcount(obj['Played'], obj['PlayCount'])
        obj['Artwork'] = API.get_all_artwork(self.objects.map(item, 'Artwork'))
        obj['Video'] = API.video_streams(obj['Video'] or [], obj['Container'])
        obj['Audio'] = API.audio_streams(obj['Audio'] or [])
        obj['Streams'] = API.media_streams(obj['Video'], obj['Audio'],
                                           obj['Subtitles'])

        self.get_episode_path_filename(obj)

        if obj['Premiere']:
            obj['Premiere'] = obj['Premiere'].split('.')[0].replace('T', " ")

        if obj['Season'] is None:
            if obj['AbsoluteNumber']:

                obj['Season'] = 1
                obj['Index'] = obj['AbsoluteNumber']
            else:
                obj['Season'] = 0

        if obj['AirsAfterSeason']:

            obj['AirsBeforeSeason'] = obj['AirsAfterSeason']
            obj['AirsBeforeEpisode'] = 4096  # Kodi default number for afterseason ordering

        if obj['MultiEpisode']:
            obj['Title'] = "| %02d | %s" % (obj['MultiEpisode'], obj['Title'])

        if not self.get_show_id(obj):
            return False

        obj['SeasonId'] = self.get_season(
            *values(obj, QU.get_season_episode_obj))

        if update:
            self.episode_update(obj)
        else:
            self.episode_add(obj)

        self.update_path(*values(obj, QU.update_path_episode_obj))
        self.update_file(*values(obj, QU.update_file_obj))
        self.add_people(*values(obj, QU.add_people_episode_obj))
        self.add_streams(*values(obj, QU.add_streams_obj))
        self.add_playstate(*values(obj, QU.add_bookmark_obj))
        self.artwork.update(obj['Artwork']['Primary'], obj['EpisodeId'],
                            "episode", "thumb")
        self.item_ids.append(obj['Id'])

        if not self.direct_path and obj['Resume']:

            temp_obj = dict(obj)
            temp_obj['Path'] = "plugin://plugin.video.emby.tvshows/"
            temp_obj['PathId'] = self.get_path(
                *values(temp_obj, QU.get_path_obj))
            temp_obj['FileId'] = self.add_file(
                *values(temp_obj, QU.add_file_obj))
            self.update_file(*values(temp_obj, QU.update_file_obj))
            self.add_playstate(*values(temp_obj, QU.add_bookmark_obj))

        return not update
예제 #25
0
    def musicvideo(self, item, e_item, library):
        ''' If item does not exist, entry will be added.
            If item exists, entry will be updated.

            If we don't get the track number from Emby, see if we can infer it
            from the sortname attribute.
        '''
        API = api.API(item, self.server['auth/server-address'])
        obj = self.objects.map(item, 'MusicVideo')
        update = True

        try:
            obj['MvideoId'] = e_item[0]
            obj['FileId'] = e_item[1]
            obj['PathId'] = e_item[2]
        except TypeError as error:

            update = False
            LOG.debug("MvideoId for %s not found", obj['Id'])
            obj['MvideoId'] = self.create_entry()
        else:
            if self.get(*values(obj, QU.get_musicvideo_obj)) is None:

                update = False
                LOG.info("MvideoId %s missing from kodi. repairing the entry.",
                         obj['MvideoId'])

        obj['Path'] = API.get_file_path(obj['Path'])
        obj['LibraryId'] = library['Id']
        obj['LibraryName'] = library['Name']
        obj['Genres'] = obj['Genres'] or []
        obj['ArtistItems'] = obj['ArtistItems'] or []
        obj['Studios'] = [
            API.validate_studio(studio) for studio in (obj['Studios'] or [])
        ]
        obj['Plot'] = API.get_overview(obj['Plot'])
        obj['DateAdded'] = Local(obj['DateAdded']).split('.')[0].replace(
            'T', " ")
        obj['DatePlayed'] = None if not obj['DatePlayed'] else Local(
            obj['DatePlayed']).split('.')[0].replace('T', " ")
        obj['PlayCount'] = API.get_playcount(obj['Played'], obj['PlayCount'])
        obj['Resume'] = API.adjust_resume((obj['Resume'] or 0) / 10000000.0)
        obj['Runtime'] = round(float((obj['Runtime'] or 0) / 10000000.0), 6)
        obj['Premiere'] = Local(
            obj['Premiere']) if obj['Premiere'] else datetime.date(
                obj['Year'] or 2021, 1, 1)
        obj['Genre'] = " / ".join(obj['Genres'])
        obj['Studio'] = " / ".join(obj['Studios'])
        obj['Artists'] = " / ".join(obj['Artists'] or [])
        obj['Directors'] = " / ".join(obj['Directors'] or [])
        obj['Video'] = API.video_streams(obj['Video'] or [], obj['Container'])
        obj['Audio'] = API.audio_streams(obj['Audio'] or [])
        obj['Streams'] = API.media_streams(obj['Video'], obj['Audio'],
                                           obj['Subtitles'])
        obj['Artwork'] = API.get_all_artwork(self.objects.map(item, 'Artwork'))

        self.get_path_filename(obj)

        if obj['Premiere']:
            obj['Premiere'] = str(obj['Premiere']).split('.')[0].replace(
                'T', " ")

        for artist in obj['ArtistItems']:
            artist['Type'] = "Artist"

        obj['People'] = obj['People'] or [] + obj['ArtistItems']
        obj['People'] = API.get_people_artwork(obj['People'])

        if obj['Index'] is None and obj['SortTitle'] is not None:
            search = re.search(r'^\d+\s?', obj['SortTitle'])

            if search:
                obj['Index'] = search.group()

        tags = []
        tags.extend(obj['Tags'] or [])
        tags.append(obj['LibraryName'])

        if obj['Favorite']:
            tags.append('Favorite musicvideos')

        obj['Tags'] = tags

        if update:
            self.musicvideo_update(obj)
        else:
            self.musicvideo_add(obj)

        self.update_path(*values(obj, QU.update_path_mvideo_obj))
        self.update_file(*values(obj, QU.update_file_obj))
        self.add_tags(*values(obj, QU.add_tags_mvideo_obj))
        self.add_genres(*values(obj, QU.add_genres_mvideo_obj))
        self.add_studios(*values(obj, QU.add_studios_mvideo_obj))
        self.add_playstate(*values(obj, QU.add_bookmark_obj))
        self.add_people(*values(obj, QU.add_people_mvideo_obj))
        self.add_streams(*values(obj, QU.add_streams_obj))
        self.artwork.add(obj['Artwork'], obj['MvideoId'], "musicvideo")
        self.item_ids.append(obj['Id'])

        return not update
    def set_listitem(self,
                     item,
                     listitem,
                     db_id=None,
                     seektime=None,
                     intro=False):

        objects = Objects()
        API = api.API(item, self.server)

        if item['Type'] in ('MusicArtist', 'MusicAlbum', 'Audio'):

            obj = objects.map(item, 'BrowseAudio')
            obj['DbId'] = db_id
            obj['Artwork'] = API.get_all_artwork(
                objects.map(item, 'ArtworkMusic'), True)
            self.listitem_music(obj, listitem, item)

        elif item['Type'] in ('Photo', 'PhotoAlbum'):

            obj = objects.map(item, 'BrowsePhoto')
            obj['Artwork'] = API.get_all_artwork(objects.map(item, 'Artwork'))
            self.listitem_photo(obj, listitem, item)

        elif item['Type'] in ('TvChannel', ):

            obj = objects.map(item, 'BrowseChannel')
            obj['Artwork'] = API.get_all_artwork(objects.map(item, 'Artwork'))
            self.listitem_channel(obj, listitem, item)

        else:
            obj = objects.map(item, 'BrowseVideo')
            obj['DbId'] = db_id
            obj['Artwork'] = API.get_all_artwork(
                objects.map(item, 'ArtworkParent'), True)

            if intro:
                obj['Artwork']['Primary'] = "&KodiCinemaMode=true"

            self.listitem_video(obj, listitem, item, seektime, intro)

            if 'PlaybackInfo' in item:

                if seektime:
                    item['PlaybackInfo']['CurrentPosition'] = obj['Resume']

                if 'SubtitleUrl' in item['PlaybackInfo']:

                    LOG.info("[ subtitles ] %s",
                             item['PlaybackInfo']['SubtitleUrl'])
                    listitem.setSubtitles(
                        [item['PlaybackInfo']['SubtitleUrl']])

                if item['Type'] == 'Episode':

                    item['PlaybackInfo']['CurrentEpisode'] = objects.map(
                        item, "UpNext")
                    item['PlaybackInfo']['CurrentEpisode']['art'] = {
                        'tvshow.poster': obj['Artwork'].get('Series.Primary'),
                        'thumb': obj['Artwork'].get('Primary'),
                        'tvshow.fanart': None
                    }
                    if obj['Artwork']['Backdrop']:
                        item['PlaybackInfo']['CurrentEpisode']['art'][
                            'tvshow.fanart'] = obj['Artwork']['Backdrop'][0]

        listitem.setContentLookup(False)
    def listitem_video(self, obj, listitem, item, seektime=None, intro=False):
        ''' Set listitem for video content. That also include streams.
        '''
        API = api.API(item, self.server)
        is_video = obj['MediaType'] in ('Video', 'Audio')  # audiobook

        obj['Genres'] = " / ".join(obj['Genres'] or [])
        obj['Studios'] = [
            API.validate_studio(studio) for studio in (obj['Studios'] or [])
        ]
        obj['Studios'] = " / ".join(obj['Studios'])
        obj['Mpaa'] = API.get_mpaa(obj['Mpaa'])
        obj['People'] = obj['People'] or []
        obj['Countries'] = " / ".join(obj['Countries'] or [])
        obj['Directors'] = " / ".join(obj['Directors'] or [])
        obj['Writers'] = " / ".join(obj['Writers'] or [])
        obj['Plot'] = API.get_overview(obj['Plot'])
        obj['ShortPlot'] = API.get_overview(obj['ShortPlot'])
        obj['DateAdded'] = obj['DateAdded'].split('.')[0].replace('T', " ")
        obj['Rating'] = obj['Rating'] or 0
        obj['FileDate'] = "%s.%s.%s" % tuple(
            reversed(obj['DateAdded'].split('T')[0].split('-')))
        obj['Runtime'] = round(float((obj['Runtime'] or 0) / 10000000.0), 6)
        obj['Resume'] = API.adjust_resume((obj['Resume'] or 0) / 10000000.0)
        obj['PlayCount'] = API.get_playcount(obj['Played'],
                                             obj['PlayCount']) or 0
        obj['Overlay'] = 7 if obj['Played'] else 6
        obj['Video'] = API.video_streams(obj['Video'] or [], obj['Container'])
        obj['Audio'] = API.audio_streams(obj['Audio'] or [])
        obj['Streams'] = API.media_streams(obj['Video'], obj['Audio'],
                                           obj['Subtitles'])
        obj['ChildCount'] = obj['ChildCount'] or 0
        obj['RecursiveCount'] = obj['RecursiveCount'] or 0
        obj['Unwatched'] = obj['Unwatched'] or 0
        obj['Artwork']['Backdrop'] = obj['Artwork']['Backdrop'] or []
        obj['Artwork']['Thumb'] = obj['Artwork']['Thumb'] or ""

        if not intro and not obj['Type'] == 'Trailer':
            obj['Artwork']['Primary'] = obj['Artwork']['Primary'] \
                    or "special://home/addons/plugin.video.jellyfin/resources/icon.png"
        else:
            obj['Artwork']['Primary'] = obj['Artwork']['Primary'] \
                    or obj['Artwork']['Thumb'] \
                    or (obj['Artwork']['Backdrop'][0] \
                    if len(obj['Artwork']['Backdrop']) \
                    else "special://home/addons/plugin.video.jellyfin/resources/fanart.png")
            obj['Artwork']['Primary'] += "&KodiTrailer=true" \
                    if obj['Type'] == 'Trailer' else "&KodiCinemaMode=true"
            obj['Artwork']['Backdrop'] = [obj['Artwork']['Primary']]

        self.set_artwork(obj['Artwork'], listitem, obj['Type'])

        if intro or obj['Type'] == 'Trailer':
            listitem.setArt(
                {'poster': ""}
            )  # Clear the poster value for intros / trailers to prevent issues in skins

        listitem.setIconImage('DefaultVideo.png')
        listitem.setThumbnailImage(obj['Artwork']['Primary'])

        if obj['Premiere']:
            obj['Premiere'] = obj['Premiere'].split('T')[0]

        if obj['DatePlayed']:
            obj['DatePlayed'] = obj['DatePlayed'].split('.')[0].replace(
                'T', " ")

        metadata = {
            'title': obj['Title'],
            'originaltitle': obj['Title'],
            'sorttitle': obj['SortTitle'],
            'country': obj['Countries'],
            'genre': obj['Genres'],
            'year': obj['Year'],
            'rating': obj['Rating'],
            'playcount': obj['PlayCount'],
            'overlay': obj['Overlay'],
            'director': obj['Directors'],
            'mpaa': obj['Mpaa'],
            'plot': obj['Plot'],
            'plotoutline': obj['ShortPlot'],
            'studio': obj['Studios'],
            'tagline': obj['Tagline'],
            'writer': obj['Writers'],
            'premiered': obj['Premiere'],
            'votes': obj['Votes'],
            'dateadded': obj['DateAdded'],
            'aired': obj['Year'],
            'date': obj['FileDate'],
            'dbid': obj['DbId']
        }
        listitem.setCast(API.get_actors())

        if obj['Premiere']:
            metadata['date'] = obj['Premiere']

        if obj['Type'] == 'Episode':
            metadata.update({
                'mediatype': "episode",
                'tvshowtitle': obj['SeriesName'],
                'season': obj['Season'] or 0,
                'sortseason': obj['Season'] or 0,
                'episode': obj['Index'] or 0,
                'sortepisode': obj['Index'] or 0,
                'lastplayed': obj['DatePlayed'],
                'duration': obj['Runtime'],
                'aired': obj['Premiere'],
            })

        elif obj['Type'] == 'Season':
            metadata.update({
                'mediatype': "season",
                'tvshowtitle': obj['SeriesName'],
                'season': obj['Index'] or 0,
                'sortseason': obj['Index'] or 0
            })
            listitem.setProperty('NumEpisodes', str(obj['RecursiveCount']))
            listitem.setProperty('WatchedEpisodes',
                                 str(obj['RecursiveCount'] - obj['Unwatched']))
            listitem.setProperty('UnWatchedEpisodes', str(obj['Unwatched']))
            listitem.setProperty('IsFolder', 'true')

        elif obj['Type'] == 'Series':

            if obj['Status'] != 'Ended':
                obj['Status'] = None

            metadata.update({
                'mediatype': "tvshow",
                'tvshowtitle': obj['Title'],
                'status': obj['Status']
            })
            listitem.setProperty('TotalSeasons', str(obj['ChildCount']))
            listitem.setProperty('TotalEpisodes', str(obj['RecursiveCount']))
            listitem.setProperty('WatchedEpisodes',
                                 str(obj['RecursiveCount'] - obj['Unwatched']))
            listitem.setProperty('UnWatchedEpisodes', str(obj['Unwatched']))
            listitem.setProperty('IsFolder', 'true')

        elif obj['Type'] == 'Movie':
            metadata.update({
                'mediatype': "movie",
                'imdbnumber': obj['UniqueId'],
                'lastplayed': obj['DatePlayed'],
                'duration': obj['Runtime'],
                'userrating': obj['CriticRating']
            })

        elif obj['Type'] == 'MusicVideo':
            metadata.update({
                'mediatype': "musicvideo",
                'album': obj['Album'],
                'artist': obj['Artists'] or [],
                'lastplayed': obj['DatePlayed'],
                'duration': obj['Runtime']
            })

        elif obj['Type'] == 'BoxSet':
            metadata['mediatype'] = "set"
            listitem.setProperty('IsFolder', 'true')
        else:
            metadata.update({
                'mediatype': "video",
                'lastplayed': obj['DatePlayed'],
                'year': obj['Year'],
                'duration': obj['Runtime']
            })

        if is_video:

            listitem.setProperty('totaltime', str(obj['Runtime']))
            listitem.setProperty('IsPlayable', 'true')
            listitem.setProperty('IsFolder', 'false')

            if obj['Resume'] and seektime != False:
                listitem.setProperty('resumetime', str(obj['Resume']))
                listitem.setProperty(
                    'StartPercent',
                    str(((obj['Resume'] / obj['Runtime']) * 100) - 0.40))
            else:
                listitem.setProperty('resumetime', '0')

            for track in obj['Streams']['video']:
                listitem.addStreamInfo(
                    'video', {
                        'duration': obj['Runtime'],
                        'aspect': track['aspect'],
                        'codec': track['codec'],
                        'width': track['width'],
                        'height': track['height']
                    })

            for track in obj['Streams']['audio']:
                listitem.addStreamInfo('audio', {
                    'codec': track['codec'],
                    'channels': track['channels']
                })

            for track in obj['Streams']['subtitle']:
                listitem.addStreamInfo('subtitle', {'language': track})

        listitem.setLabel(obj['Title'])
        listitem.setInfo('video', metadata)
        listitem.setContentLookup(False)
예제 #28
0
    def album(self, item, e_item):
        ''' Update object to kodi.
        '''
        server_address = self.server.auth.get_server_info(
            self.server.auth.server_id)['address']
        API = api.API(item, server_address)
        obj = self.objects.map(item, 'Album')
        update = True

        try:
            obj['AlbumId'] = e_item[0]
            obj['LibraryId'] = e_item[6]
            obj['LibraryName'] = self.jellyfin_db.get_view_name(
                obj['LibraryId'])
        except TypeError:
            update = False

            library = self.library or find_library(self.server, item)
            if not library:
                # This item doesn't belong to a whitelisted library
                return

            obj['AlbumId'] = None
            obj['LibraryId'] = library['Id']
            obj['LibraryName'] = library['Name']
            LOG.debug("AlbumId %s not found", obj['Id'])
        else:
            if self.validate_album(
                    *values(obj, QU.get_album_by_id_obj)) is None:

                update = False
                LOG.info("AlbumId %s missing from kodi. repairing the entry.",
                         obj['AlbumId'])

        obj['Rating'] = 0
        obj['LastScraped'] = datetime.datetime.now().strftime(
            '%Y-%m-%d %H:%M:%S')
        obj['Genres'] = obj['Genres'] or []
        obj['Genre'] = " / ".join(obj['Genres'])
        obj['Bio'] = API.get_overview(obj['Bio'])
        obj['Artists'] = " / ".join(obj['Artists'] or [])
        obj['Artwork'] = API.get_all_artwork(
            self.objects.map(item, 'ArtworkMusic'), True)
        obj['Thumb'] = obj['Artwork']['Primary']
        obj['DateAdded'] = item.get('DateCreated')

        if obj['DateAdded']:
            obj['DateAdded'] = Local(obj['DateAdded']).split('.')[0].replace(
                'T', " ")

        if obj['Thumb']:
            obj['Thumb'] = "<thumb>%s</thumb>" % obj['Thumb']

        if update:
            self.album_update(obj)
        else:
            self.album_add(obj)

        self.artist_link(obj)
        self.artist_discography(obj)
        self.update_album(*values(obj, QU.update_album_obj))
        self.add_genres(*values(obj, QU.add_genres_obj))
        self.artwork.add(obj['Artwork'], obj['AlbumId'], "album")
        self.item_ids.append(obj['Id'])
예제 #29
0
    def movie(self, item, e_item, library):
        ''' If item does not exist, entry will be added.
            If item exists, entry will be updated.
        '''
        server_data = self.server.auth.get_server_info(
            self.server.auth.server_id)
        server_address = self.server.auth.get_server_address(
            server_data, server_data['LastConnectionMode'])
        API = api.API(item, server_address)
        obj = self.objects.map(item, 'Movie')
        update = True

        try:
            obj['MovieId'] = e_item[0]
            obj['FileId'] = e_item[1]
            obj['PathId'] = e_item[2]
        except TypeError:
            update = False
            LOG.debug("MovieId %s not found", obj['Id'])
            obj['MovieId'] = self.create_entry()
        else:
            if self.get(*values(obj, QU.get_movie_obj)) is None:

                update = False
                LOG.info("MovieId %s missing from kodi. repairing the entry.",
                         obj['MovieId'])

        if not settings('syncRottenTomatoes.bool'):
            obj['CriticRating'] = None

        obj['Path'] = API.get_file_path(obj['Path'])
        obj['LibraryId'] = library['Id']
        obj['LibraryName'] = library['Name']
        obj['Genres'] = obj['Genres'] or []
        obj['Studios'] = [
            API.validate_studio(studio) for studio in (obj['Studios'] or [])
        ]
        obj['People'] = obj['People'] or []
        obj['Genre'] = " / ".join(obj['Genres'])
        obj['Writers'] = " / ".join(obj['Writers'] or [])
        obj['Directors'] = " / ".join(obj['Directors'] or [])
        obj['Plot'] = API.get_overview(obj['Plot'])
        obj['Mpaa'] = API.get_mpaa(obj['Mpaa'])
        obj['Resume'] = API.adjust_resume((obj['Resume'] or 0) / 10000000.0)
        obj['Runtime'] = round(float((obj['Runtime'] or 0) / 10000000.0), 6)
        obj['People'] = API.get_people_artwork(obj['People'])
        obj['DateAdded'] = Local(obj['DateAdded']).split('.')[0].replace(
            'T', " ")
        obj['DatePlayed'] = None if not obj['DatePlayed'] else Local(
            obj['DatePlayed']).split('.')[0].replace('T', " ")
        obj['PlayCount'] = API.get_playcount(obj['Played'], obj['PlayCount'])
        obj['Artwork'] = API.get_all_artwork(self.objects.map(item, 'Artwork'))
        obj['Video'] = API.video_streams(obj['Video'] or [], obj['Container'])
        obj['Audio'] = API.audio_streams(obj['Audio'] or [])
        obj['Streams'] = API.media_streams(obj['Video'], obj['Audio'],
                                           obj['Subtitles'])

        self.get_path_filename(obj)
        self.trailer(obj)

        if obj['Countries']:
            self.add_countries(*values(obj, QU.update_country_obj))

        tags = []
        tags.extend(obj['Tags'] or [])
        tags.append(obj['LibraryName'])

        if obj['Favorite']:
            tags.append('Favorite movies')

        obj['Tags'] = tags

        if update:
            self.movie_update(obj)
        else:
            self.movie_add(obj)

        self.update_path(*values(obj, QU.update_path_movie_obj))
        self.update_file(*values(obj, QU.update_file_obj))
        self.add_tags(*values(obj, QU.add_tags_movie_obj))
        self.add_genres(*values(obj, QU.add_genres_movie_obj))
        self.add_studios(*values(obj, QU.add_studios_movie_obj))
        self.add_playstate(*values(obj, QU.add_bookmark_obj))
        self.add_people(*values(obj, QU.add_people_movie_obj))
        self.add_streams(*values(obj, QU.add_streams_obj))
        self.artwork.add(obj['Artwork'], obj['MovieId'], "movie")
        self.item_ids.append(obj['Id'])

        return not update
예제 #30
0
    def tvshow(self, item, e_item):
        ''' If item does not exist, entry will be added.
            If item exists, entry will be updated.

            If the show is empty, try to remove it.
            Process seasons.
            Apply series pooling.
        '''
        server_address = self.server.auth.get_server_info(
            self.server.auth.server_id)['address']
        API = api.API(item, server_address)
        obj = self.objects.map(item, 'Series')
        update = True

        try:
            obj['ShowId'] = e_item[0]
            obj['PathId'] = e_item[2]
            obj['LibraryId'] = e_item[6]
            obj['LibraryName'] = self.jellyfin_db.get_view_name(
                obj['LibraryId'])
        except TypeError:
            update = False
            LOG.debug("ShowId %s not found", obj['Id'])

            library = self.library or find_library(self.server, item)
            if not library:
                # This item doesn't belong to a whitelisted library
                return

            obj['ShowId'] = self.create_entry()
            obj['LibraryId'] = library['Id']
            obj['LibraryName'] = library['Name']
        else:
            if self.get(*values(obj, QU.get_tvshow_obj)) is None:

                update = False
                LOG.info("ShowId %s missing from kodi. repairing the entry.",
                         obj['ShowId'])

        obj['Path'] = API.get_file_path(obj['Path'])
        obj['Genres'] = obj['Genres'] or []
        obj['People'] = obj['People'] or []
        obj['Mpaa'] = API.get_mpaa(obj['Mpaa'])
        obj['Studios'] = [
            API.validate_studio(studio) for studio in (obj['Studios'] or [])
        ]
        obj['Genre'] = " / ".join(obj['Genres'])
        obj['People'] = API.get_people_artwork(obj['People'])
        obj['Plot'] = API.get_overview(obj['Plot'])
        obj['Studio'] = " / ".join(obj['Studios'])
        obj['Artwork'] = API.get_all_artwork(self.objects.map(item, 'Artwork'))

        if obj['Status'] != 'Ended':
            obj['Status'] = None

        self.get_path_filename(obj)

        if obj['Premiere']:
            obj['Premiere'] = str(Local(
                obj['Premiere'])).split('.')[0].replace('T', " ")

        tags = []
        tags.extend(obj['Tags'] or [])
        tags.append(obj['LibraryName'])

        if obj['Favorite']:
            tags.append('Favorite tvshows')

        obj['Tags'] = tags

        if update:
            self.tvshow_update(obj)
        else:
            self.tvshow_add(obj)

        self.link(*values(obj, QU.update_tvshow_link_obj))
        self.update_path(*values(obj, QU.update_path_tvshow_obj))
        self.add_tags(*values(obj, QU.add_tags_tvshow_obj))
        self.add_people(*values(obj, QU.add_people_tvshow_obj))
        self.add_genres(*values(obj, QU.add_genres_tvshow_obj))
        self.add_studios(*values(obj, QU.add_studios_tvshow_obj))
        self.artwork.add(obj['Artwork'], obj['ShowId'], "tvshow")
        self.item_ids.append(obj['Id'])

        season_episodes = {}

        for season in self.server.jellyfin.get_seasons(obj['Id'])['Items']:

            if season['SeriesId'] != obj['Id']:
                obj['SeriesId'] = season['SeriesId']
                self.item_ids.append(season['SeriesId'])

                try:
                    self.jellyfin_db.get_item_by_id(
                        *values(obj, QUEM.get_item_series_obj))[0]

                    if self.update_library:
                        season_episodes[season['Id']] = season['SeriesId']
                except TypeError:

                    self.jellyfin_db.add_reference(
                        *values(obj, QUEM.add_reference_pool_obj))
                    LOG.info("POOL %s [%s/%s]", obj['Title'], obj['Id'],
                             obj['SeriesId'])
                    season_episodes[season['Id']] = season['SeriesId']

            try:
                self.jellyfin_db.get_item_by_id(season['Id'])[0]
                self.item_ids.append(season['Id'])
            except TypeError:
                self.season(season, obj['ShowId'])
        else:
            season_id = self.get_season(
                *values(obj, QU.get_season_special_obj))
            self.artwork.add(obj['Artwork'], season_id, "season")

        for season in season_episodes:
            for episodes in server.get_episode_by_season(
                    season_episodes[season], season):

                for episode in episodes['Items']:
                    self.episode(episode)