Esempio n. 1
0
    def update_full(self,
                    data,
                    p_playlist,
                    p_sections_map,
                    t_list=None,
                    t_list_items=None):
        # Construct playlist mapper
        mapper = PlaylistMapper(self.current, p_sections_map)

        # Parse plex playlist items
        mapper.plex.load(p_playlist)

        # Parse trakt list items
        mapper.trakt.load(t_list, t_list_items)

        # Match playlist items and expand shows/seasons
        m_trakt, m_plex = mapper.match()

        log.debug(
            'Update - Mapper Result (%d items)\nt_items:\n%s\n\np_items:\n%s',
            len(m_trakt) + len(m_plex),
            '\n'.join(self.format_mapper_result(m_trakt)),
            '\n'.join(self.format_mapper_result(m_plex)))

        # Iterate over matched trakt items
        for key, index, (p_index, p_items), (t_index, t_items) in m_trakt:
            # Expand shows/seasons into episodes
            for p_item, t_item in self.expand(p_items, t_items):
                if not t_item:
                    continue

                # Get `SyncMedia` for `t_item`
                media = self.get_media(t_item)

                if media is None:
                    log.warn(
                        'Unable to identify media of "t_item" (p_item: %r, t_item: %r)',
                        p_item, t_item)
                    continue

                # Execute handler
                self.execute_handlers(self.mode,
                                      media,
                                      data,
                                      p_sections_map=p_sections_map,
                                      p_playlist=p_playlist,
                                      key=key,
                                      p_item=p_item,
                                      t_item=t_item)
Esempio n. 2
0
    def update_full(self, data, p_playlist, p_sections_map, t_list=None, t_list_items=None):
        # Construct playlist mapper
        mapper = PlaylistMapper(self.current, p_sections_map)

        # Parse plex playlist items
        mapper.plex.load(p_playlist)

        # Parse trakt list items
        mapper.trakt.load(t_list, t_list_items)

        # Match playlist items and expand shows/seasons
        m_trakt, m_plex = mapper.match()

        log.debug(
            'Update - Mapper Result (%d items)\nt_items:\n%s\n\np_items:\n%s',
            len(m_trakt) + len(m_plex),
            '\n'.join(self.format_mapper_result(m_trakt)),
            '\n'.join(self.format_mapper_result(m_plex))
        )

        # Iterate over matched trakt items
        for key, index, (p_index, p_items), (t_index, t_items) in m_trakt:
            # Expand shows/seasons into episodes
            for p_item, t_item in self.expand(p_items, t_items):
                if not t_item:
                    continue

                # Get `SyncMedia` for `t_item`
                media = self.get_media(t_item)

                if media is None:
                    log.warn('Unable to identify media of "t_item" (p_item: %r, t_item: %r)', p_item, t_item)
                    continue

                # Execute handler
                self.execute_handlers(
                    self.mode, media, data,

                    p_sections_map=p_sections_map,
                    p_playlist=p_playlist,

                    key=key,

                    p_item=p_item,
                    t_item=t_item
                )
Esempio n. 3
0
def test_basic():
    # Setup response fixtures
    responses.add(responses.GET,
                  'http://mock:32400/library/metadata/101/allLeaves',
                  body=read(
                      __file__,
                      "fixtures/plex/library/metadata/101/allLeaves.xml"),
                  status=200,
                  content_type='application/xml')

    responses.add(responses.GET,
                  'http://mock:32400/library/metadata/106/children',
                  body=read(__file__,
                            "fixtures/plex/library/metadata/106/children.xml"),
                  status=200,
                  content_type='application/xml')

    responses.add(responses.GET,
                  'http://mock:32400/library/metadata/107/children',
                  body=read(__file__,
                            "fixtures/plex/library/metadata/107/children.xml"),
                  status=200,
                  content_type='application/xml')

    responses.add(responses.GET,
                  'http://mock:32400/playlists/1',
                  body=read(__file__, "fixtures/plex/playlists/1.xml"),
                  status=200,
                  content_type='application/xml')

    responses.add(responses.GET,
                  'http://mock:32400/playlists/1/items',
                  body=read(__file__, "fixtures/plex/playlists/1/items.xml"),
                  status=200,
                  content_type='application/xml')

    responses.add(responses.GET,
                  'http://mock/users/one/lists/mixed',
                  body=read(__file__,
                            "fixtures/trakt/users/one/lists/mixed.json"),
                  status=200,
                  content_type='application/json')

    responses.add(responses.GET,
                  'http://mock/users/one/lists/1413325/items',
                  body=read(__file__,
                            "fixtures/trakt/users/one/lists/mixed/items.json"),
                  status=200,
                  content_type='application/json')

    # Build task
    task = SyncTask(account=None,
                    mode=None,
                    data=None,
                    media=None,
                    result=None,
                    status=None)

    # Update trakt table
    task.state.trakt.table.movies = {
        ('tmdb', '158852'): ('imdb', 'tt1964418'),
        ('tmdb', '284674'): ('imdb', 'tt2091478')
    }
    task.state.trakt.table.shows = {}

    # Update map
    # - Movies
    task.map.add_one('1', '3', ('imdb', 'tt1323594'))
    task.map.add_one('1', '5', ('imdb', 'tt1375666'))
    task.map.add_one('1', '6', ('imdb', 'tt0371746'))
    task.map.add_one('1', '7', ('imdb', 'tt1228705'))
    task.map.add_one('1', '9', ('imdb', 'tt0107290'))
    task.map.add_one('1', '12', ('imdb', 'tt0993846'))
    task.map.add_one('1', '434', ('imdb', 'tt0080684'))
    task.map.add_one('1', '433', ('imdb', 'tt0076759'))
    task.map.add_one('1', '435', ('imdb', 'tt0086190'))
    task.map.add_one('1', '440', ('imdb', 'tt1392190'))

    task.map.add_one('4', '484', ('tmdb', '284674'))
    task.map.add_one('4', '485', ('tmdb', '251653'))
    task.map.add_one('4', '486', ('tmdb', '158852'))
    # - Shows
    task.map.add_one('2', '88', ('tvdb', '84912'))
    task.map.add_one('2', '106', ('tvdb', '80348'))
    task.map.add_one('2', '101', ('tvdb', '79488'))

    # Build playlist mapper
    mapper = PlaylistMapper(task, {})

    # Load playlists
    mapper.plex.load(Plex['playlists'].get(1).first())
    mapper.trakt.load(Trakt['users/*/lists/*'].get('one', 'mixed'))

    # Match items between plex and trakt
    t_items, p_items = mapper.match()

    # Print items
    print_items(t_items)
    print_items(p_items)

    # Build dictionaries from items
    t_items = dict([(item[0], item[1:]) for item in t_items])

    p_items = dict([(item[0], item[1:]) for item in p_items])

    # Validate result
    assert t_items[(('imdb', 'tt0993846'), )][1] == (None, None)
    assert t_items[(('imdb', 'tt1375666'), )][1] == (None, None)
    assert t_items[(('tvdb', '79488'), 1, 2)][1] == (None, None)

    assert p_items[(('imdb', 'tt1228705'), )][2] == (None, None)
Esempio n. 4
0
    def update_changed(self, data, p_playlist, p_sections_map, t_list=None, t_list_items=None):
        # Retrieve changed items
        t_changes = self.get_changed_items(data)

        if not t_changes:
            log.debug('No changes detected in %r collection', data)
            return

        # Construct playlist mapper
        mapper = PlaylistMapper(self.current, p_sections_map)

        # Parse plex playlist items
        mapper.plex.load(p_playlist)

        # Parse trakt list items
        mapper.trakt.load(t_list, t_list_items)

        # Match playlist items and expand shows/seasons
        m_trakt, m_plex = mapper.match()

        log.debug(
            'Update - Mapper Result (%d items)\nt_items:\n%s\n\np_items:\n%s',
            len(m_trakt) + len(m_plex),
            '\n'.join(self.format_mapper_result(m_trakt)),
            '\n'.join(self.format_mapper_result(m_plex))
        )

        log.debug(
            'Update - Changes (%d keys)\n%s',
            len(t_changes),
            '\n'.join(self.format_changes(t_changes)),
        )

        # Iterate over matched trakt items
        for key, index, (p_index, p_items), (t_index, t_items) in m_trakt:
            # Expand shows/seasons into episodes
            for p_item, t_item in self.expand(p_items, t_items):
                if not t_item:
                    continue

                if len(key) < 1:
                    log.warn('Invalid "key" format: %r', key)
                    continue

                actions = list(t_changes.get(key[0], []))

                if not actions:
                    continue

                if len(actions) > 1:
                    log.warn('Multiple actions returned for %r: %r', key[0], actions)
                    continue

                # Get `SyncMedia` for `t_item`
                media = self.get_media(t_item)

                if media is None:
                    log.warn('Unable to identify media of "t_item" (p_item: %r, t_item: %r)', p_item, t_item)
                    continue

                # Execute handler
                self.execute_handlers(
                    self.mode, media, data,

                    action=actions[0],

                    p_sections_map=p_sections_map,
                    p_playlist=p_playlist,

                    key=key,

                    p_item=p_item,
                    t_item=t_item
                )
Esempio n. 5
0
    def update_changed(self, data, p_playlist, p_sections_map, t_list=None, t_list_items=None):
        # Retrieve changed items
        t_changes = self.get_changed_items(data)

        if not t_changes:
            log.debug('No changes detected in %r collection', data)
            return

        # Construct playlist mapper
        mapper = PlaylistMapper(self.current, p_sections_map)

        # Parse plex playlist items
        mapper.plex.load(p_playlist)

        # Parse trakt list items
        mapper.trakt.load(t_list, t_list_items)

        # Match playlist items and expand shows/seasons
        m_trakt, m_plex = mapper.match()

        log.debug(
            'Update - Mapper Result (%d items)\nt_items:\n%s\n\np_items:\n%s',
            len(m_trakt) + len(m_plex),
            '\n'.join(self.format_mapper_result(m_trakt)),
            '\n'.join(self.format_mapper_result(m_plex))
        )

        log.debug(
            'Update - Changes (%d keys)\n%s',
            len(t_changes),
            '\n'.join(self.format_changes(t_changes)),
        )

        # Iterate over matched trakt items
        for key, index, (p_index, p_items), (t_index, t_items) in m_trakt:
            # Expand shows/seasons into episodes
            for p_item, t_item in self.expand(p_items, t_items):
                if not t_item:
                    continue

                if len(key) < 1:
                    log.warn('Invalid "key" format: %r', key)
                    continue

                actions = list(t_changes.get(key[0], []))

                if not actions:
                    continue

                if len(actions) > 1:
                    log.warn('Multiple actions returned for %r: %r', key[0], actions)
                    continue

                # Get `SyncMedia` for `t_item`
                media = self.get_media(t_item)

                if media is None:
                    log.warn('Unable to identify media of "t_item" (p_item: %r, t_item: %r)', p_item, t_item)
                    continue

                # Execute handler
                self.execute_handlers(
                    media, data,

                    action=actions[0],

                    p_sections_map=p_sections_map,
                    p_playlist=p_playlist,

                    key=key,

                    p_item=p_item,
                    t_item=t_item
                )
Esempio n. 6
0
    def process_sort(self, data, p_playlist, p_sections_map, t_list,
                     t_list_items):
        # Construct playlist mapper
        mapper = PlaylistMapper(self.current, p_sections_map)

        # Parse plex playlist items
        mapper.plex.load(p_playlist)

        # Parse trakt list items
        mapper.trakt.load(t_list, t_list_items)

        # Match playlist items and expand shows/seasons
        m_trakt, m_plex = mapper.match()

        log.debug(
            'Sort - Mapper Result (%d items)\nt_items:\n%s\n\np_items:\n%s',
            len(m_trakt) + len(m_plex),
            '\n'.join(self.format_mapper_result(m_trakt)),
            '\n'.join(self.format_mapper_result(m_plex)))

        # Build a list of plex items (sorted by `p_index`)
        p_playlist_items = []

        for item in mapper.plex.items.itervalues():
            p_playlist_items.append(item)

        p_playlist_items = [
            i[1] for i in sorted(p_playlist_items, key=lambda i: i[0])
        ]

        # Iterate over trakt items, re-order plex items
        t_index = 0

        for key, _, (_, p_items), (_, t_items) in m_trakt:
            # Expand shows/seasons into episodes
            for p_item, t_item in self.expand(p_items, t_items):
                if not p_item:
                    continue

                if p_item not in p_playlist_items:
                    log.info('Unable to find %r in "p_playlist_items"', p_item)
                    t_index += 1
                    continue

                p_index = p_playlist_items.index(p_item)

                if p_index == t_index:
                    t_index += 1
                    continue

                p_after = p_playlist_items[t_index -
                                           1] if t_index > 0 else None

                log.info('[%2d:%2d] p_item: %r, t_item: %r (move after: %r)',
                         p_index, t_index, p_item, t_item, p_after)

                # Move item in plex playlist
                p_playlist.move(p_item.playlist_item_id,
                                p_after.playlist_item_id if p_after else None)

                # Remove item from current position
                if t_index > p_index:
                    p_playlist_items[p_index] = None
                else:
                    p_playlist_items.pop(p_index)

                # Insert at new position
                if p_playlist_items[t_index] is None:
                    p_playlist_items[t_index] = p_item
                else:
                    p_playlist_items.insert(t_index, p_item)

                t_index += 1
Esempio n. 7
0
    def process_sort(self, data, p_playlist, p_sections_map, t_list, t_list_items):
        # Construct playlist mapper
        mapper = PlaylistMapper(self.current, p_sections_map)

        # Parse plex playlist items
        mapper.plex.load(p_playlist)

        # Parse trakt list items
        mapper.trakt.load(t_list, t_list_items)

        # Match playlist items and expand shows/seasons
        m_trakt, m_plex = mapper.match()

        log.debug(
            'Sort - Mapper Result (%d items)\nt_items:\n%s\n\np_items:\n%s',
            len(m_trakt) + len(m_plex),
            '\n'.join(self.format_mapper_result(m_trakt)),
            '\n'.join(self.format_mapper_result(m_plex))
        )

        # Build a list of plex items (sorted by `p_index`)
        p_playlist_items = []

        for item in mapper.plex.items.itervalues():
            p_playlist_items.append(item)

        p_playlist_items = [
            i[1]
            for i in sorted(p_playlist_items, key=lambda i: i[0])
        ]

        # Iterate over trakt items, re-order plex items
        t_index = 0

        for key, _, (_, p_items), (_, t_items) in m_trakt:
            # Expand shows/seasons into episodes
            for p_item, t_item in self.expand(p_items, t_items):
                if not p_item:
                    continue

                if p_item not in p_playlist_items:
                    log.info('Unable to find %r in "p_playlist_items"', p_item)
                    t_index += 1
                    continue

                p_index = p_playlist_items.index(p_item)

                if p_index == t_index:
                    t_index += 1
                    continue

                p_after = p_playlist_items[t_index - 1] if t_index > 0 else None

                log.info('[%2d:%2d] p_item: %r, t_item: %r (move after: %r)',
                    p_index, t_index,
                    p_item, t_item,
                    p_after
                )

                # Move item in plex playlist
                p_playlist.move(
                    p_item.playlist_item_id,
                    p_after.playlist_item_id if p_after else None
                )

                # Remove item from current position
                if t_index > p_index:
                    p_playlist_items[p_index] = None
                else:
                    p_playlist_items.pop(p_index)

                # Insert at new position
                if p_playlist_items[t_index] is None:
                    p_playlist_items[t_index] = p_item
                else:
                    p_playlist_items.insert(t_index, p_item)

                t_index += 1
def test_basic():
    # Setup response fixtures
    responses.add(
        responses.GET, 'http://mock:32400/library/metadata/101/allLeaves',
        body=read(__file__, "fixtures/plex/library/metadata/101/allLeaves.xml"), status=200,
        content_type='application/xml'
    )

    responses.add(
        responses.GET, 'http://mock:32400/library/metadata/106/children',
        body=read(__file__, "fixtures/plex/library/metadata/106/children.xml"), status=200,
        content_type='application/xml'
    )

    responses.add(
        responses.GET, 'http://mock:32400/library/metadata/107/children',
        body=read(__file__, "fixtures/plex/library/metadata/107/children.xml"), status=200,
        content_type='application/xml'
    )

    responses.add(
        responses.GET, 'http://mock:32400/playlists/1',
        body=read(__file__, "fixtures/plex/playlists/1.xml"), status=200,
        content_type='application/xml'
    )

    responses.add(
        responses.GET, 'http://mock:32400/playlists/1/items',
        body=read(__file__, "fixtures/plex/playlists/1/items.xml"), status=200,
        content_type='application/xml'
    )

    responses.add(
        responses.GET, 'http://mock/users/one/lists/mixed',
        body=read(__file__, "fixtures/trakt/users/one/lists/mixed.json"), status=200,
        content_type='application/json'
    )

    responses.add(
        responses.GET, 'http://mock/users/one/lists/1413325/items',
        body=read(__file__, "fixtures/trakt/users/one/lists/mixed/items.json"), status=200,
        content_type='application/json'
    )

    # Build task
    task = SyncTask(
        account=None,

        mode=None,
        data=None,
        media=None,

        result=None,
        status=None
    )

    # Update trakt table
    task.state.trakt.table.movies = {
        ('tmdb', '158852'): ('imdb', 'tt1964418'),
        ('tmdb', '284674'): ('imdb', 'tt2091478')
    }
    task.state.trakt.table.shows = {}

    # Update map
    # - Movies
    task.map.add_one('1', '3',   ('imdb', 'tt1323594'))
    task.map.add_one('1', '5',   ('imdb', 'tt1375666'))
    task.map.add_one('1', '6',   ('imdb', 'tt0371746'))
    task.map.add_one('1', '7',   ('imdb', 'tt1228705'))
    task.map.add_one('1', '9',   ('imdb', 'tt0107290'))
    task.map.add_one('1', '12',  ('imdb', 'tt0993846'))
    task.map.add_one('1', '434', ('imdb', 'tt0080684'))
    task.map.add_one('1', '433', ('imdb', 'tt0076759'))
    task.map.add_one('1', '435', ('imdb', 'tt0086190'))
    task.map.add_one('1', '440', ('imdb', 'tt1392190'))

    task.map.add_one('4', '484', ('tmdb', '284674'))
    task.map.add_one('4', '485', ('tmdb', '251653'))
    task.map.add_one('4', '486', ('tmdb', '158852'))
    # - Shows
    task.map.add_one('2', '88',  ('tvdb', '84912'))
    task.map.add_one('2', '106', ('tvdb', '80348'))
    task.map.add_one('2', '101', ('tvdb', '79488'))

    # Build playlist mapper
    mapper = PlaylistMapper(task, {})

    # Load playlists
    mapper.plex.load(Plex['playlists'].get(1).first())
    mapper.trakt.load(Trakt['users/*/lists/*'].get('one', 'mixed'))

    # Match items between plex and trakt
    t_items, p_items = mapper.match()

    # Print items
    print_items(t_items)
    print_items(p_items)

    # Build dictionaries from items
    t_items = dict([
        (item[0], item[1:])
        for item in t_items
    ])

    p_items = dict([
        (item[0], item[1:])
        for item in p_items
    ])

    # Validate result
    assert t_items[(('imdb', 'tt0993846'),)][1] == (None, None)
    assert t_items[(('imdb', 'tt1375666'),)][1] == (None, None)
    assert t_items[(('tvdb', '79488'), 1, 2)][1] == (None, None)

    assert p_items[(('imdb', 'tt1228705'),)][2] == (None, None)