playlist_manager: Check for re-orderings without doing them initially

Previously, we would only do reorderings if we were refreshing the playlist
for some other reason (eg. a video was inserted).

We want to refresh the playlist before attempting reorderings,
so we split the routine into two parts:
- A part that finds out-of-order videos and returns a list of moves to make.
- A part that executes those moves.

We do the former before AND after refreshing, and the latter only with the result from after.
pull/400/head
Mike Lang 4 months ago committed by Mike Lang
parent 0a55a74efd
commit 90a6b5ee17

@ -133,24 +133,30 @@ class PlaylistManager(object):
logging.debug(f"Found {len(matching)} matching videos for playlist {playlist_id}") logging.debug(f"Found {len(matching)} matching videos for playlist {playlist_id}")
# If we have nothing to add, short circuit without doing any API calls to save quota. # If we have nothing to add, short circuit without doing any API calls to save quota.
playlist = self.get_playlist(playlist_id)
matching_video_ids = {video.video_id for video in matching} matching_video_ids = {video.video_id for video in matching}
playlist_video_ids = {entry.video_id for entry in self.get_playlist(playlist_id)} playlist_video_ids = {entry.video_id for entry in playlist}
if not (matching_video_ids - playlist_video_ids): new_videos = matching_video_ids - playlist_video_ids
logging.debug("All videos already in playlist, nothing to do") reorderings = self.find_playlist_reorderings(videos, playlist, playlist_config)
if not (new_videos or reorderings):
logging.debug("All videos already correctly ordered in playlist, nothing to do")
return return
# Refresh our playlist state, if necessary. # Refresh our playlist state, if necessary.
self.refresh_playlist(playlist_id) self.refresh_playlist(playlist_id)
# Make sure first/last videos are correctly positioned
self.relocate_playlist_ends(videos, playlist)
# Get an updated list of new videos # Get an updated list of new videos
playlist = self.get_playlist(playlist_id)
matching_video_ids = {video.video_id for video in matching} matching_video_ids = {video.video_id for video in matching}
playlist_video_ids = {entry.video_id for entry in self.get_playlist(playlist_id)} playlist_video_ids = {entry.video_id for entry in self.get_playlist(playlist_id)}
# It shouldn't matter, but just for clarity let's sort them by event order # It shouldn't matter, but just for clarity let's sort them by event order
new_videos = sorted(matching_video_ids - playlist_video_ids, key=lambda v: v.start_time) new_videos = sorted(matching_video_ids - playlist_video_ids, key=lambda v: v.start_time)
# Perform any reorderings needed
reorderings = self.find_playlist_reorderings(videos, playlist, playlist_config)
for entry, index in reorderings:
self.reorder_in_playlist(playlist_id, entry, index)
# Insert each new video one at a time # Insert each new video one at a time
logging.debug(f"Inserting new videos for playlist {playlist_id}: {new_videos}") logging.debug(f"Inserting new videos for playlist {playlist_id}: {new_videos}")
for video in new_videos: for video in new_videos:
@ -158,22 +164,28 @@ class PlaylistManager(object):
self.insert_into_playlist(playlist_id, video.video_id, index) self.insert_into_playlist(playlist_id, video.video_id, index)
def relocate_playlist_ends(self, videos, playlist_id, playlist_config, playlist): def find_playlist_reorderings(self, videos, playlist, playlist_config):
"""Move first/last videos to the correct position if needed""" """Looks through the playlist for videos that should be reordered.
Returns a list of (entry, new index) to reorder.
Right now this is only checked for the first and last videos as per playlist_config,
all other misorderings are ignored."""
result = []
for index, entry in enumerate(playlist): for index, entry in enumerate(playlist):
if entry.video_id not in videos: if entry.video_id not in videos:
# Unknown videos should always remain in-place.
continue continue
video = videos[video_id] video = videos[video_id]
if video.id == playlist.first_event_id: if video.id == playlist.first_event_id:
index = 0 new_index = 0
elif video.id == playlist.last_event_id: elif video.id == playlist.last_event_id:
index = len(playlist) - 1 new_index = len(playlist) - 1
else: else:
continue continue
self.reorder_in_playlist(playlist_id, entry, index) if index != new_index:
result.append((entry, new_index))
return result
def refresh_playlist(self, playlist_id): def refresh_playlist(self, playlist_id):
"""Check playlist mirror is in a good state, and fetch it if it isn't. """Check playlist mirror is in a good state, and fetch it if it isn't.
@ -262,10 +274,6 @@ class PlaylistManager(object):
""" """
playlist = self.get_playlist(playlist_id) playlist = self.get_playlist(playlist_id)
assert entry in playlist, f"Tried to move entry {entry} which was not in our copy of {playlist_id}: {playlist}" assert entry in playlist, f"Tried to move entry {entry} which was not in our copy of {playlist_id}: {playlist}"
old_index = playlist.index(entry)
if old_index == new_index:
logging.debug(f"Not moving {entry.video_id} in {playlist_id} - already in position {new_index}")
return
logging.info(f"Moving {entry.video_id} (entry {entry.entry_id}) to new index {new_index})") logging.info(f"Moving {entry.video_id} (entry {entry.entry_id}) to new index {new_index})")
try: try:
@ -285,7 +293,6 @@ class PlaylistManager(object):
playlist.insert(new_index, entry) playlist.insert(new_index, entry)
class YoutubeAPI(object): class YoutubeAPI(object):
def __init__(self, client): def __init__(self, client):
self.client = client self.client = client

Loading…
Cancel
Save