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)
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 )
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)
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 )
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 )
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 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)