Skip to content

Commit

Permalink
Force refresh (#383)
Browse files Browse the repository at this point in the history
* feat: add force refresh to update plex from sym library

* fix: iteration mutating bugfix

* fix: add validation for plex updating on update_folder

* fix: improve symlink type validation

* fix: attempt at fixing dequeue issue

---------

Co-authored-by: Spoked <Spoked@localhost>
  • Loading branch information
dreulavelle and Spoked authored Jun 11, 2024
1 parent b88c475 commit 73f437b
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 45 deletions.
12 changes: 10 additions & 2 deletions backend/program/libraries/symlink.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,11 @@ def process_items(directory: Path, item_class, item_type: str, is_anime: bool =
logger.error(f"Can't extract {item_type} imdb_id or title at path {path / filename}")
continue
item = item_class({'imdb_id': imdb_id.group(), 'title': title.group(1)})
item.update_folder = "updated"
if settings_manager.settings.force_refresh:
item.set("symlinked", True)
item.set("update_folder", path)
else:
item.set("update_folder", "updated")
if is_anime:
item.is_anime = True
yield item
Expand All @@ -87,7 +91,11 @@ def process_shows(directory: Path, item_type: str, is_anime: bool = False) -> Sh
logger.error(f"Can't extract episode number at path {directory / show / season / episode}")
continue
episode_item = Episode({'number': int(episode_number.group(1))})
episode_item.update_folder = "updated"
if settings_manager.settings.force_refresh:
episode_item.set("symlinked", True)
episode_item.set("update_folder", f"{directory}/{show}/{season}/{episode}")
else:
episode_item.set("update_folder", "updated")
if is_anime:
episode_item.is_anime = True
season_item.add_episode(episode_item)
Expand Down
19 changes: 15 additions & 4 deletions backend/program/program.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,14 +140,25 @@ def start(self):
logger.success("Iceberg is running!")

def _retry_library(self) -> None:
for _, item in self.media_items.get_incomplete_items().items():
if item.state not in (States.Completed, States.PartiallyCompleted) and item not in self.event_queue.queue:
self.event_queue.put(Event(emitted_by=self.__class__, item=item))
incomplete_items = list(self.media_items.get_incomplete_items().items())

try:
current_queue_items = set(self.event_queue.queue)
except RuntimeError as e:
logger.debug(f"Failed to retrieve current queue items: {e}")
return

for _, item in incomplete_items:
if item.state not in (States.Completed, States.PartiallyCompleted) and item not in current_queue_items:
try:
self.event_queue.put(Event(emitted_by=self.__class__, item=item))
except RuntimeError as e:
logger.debug(f"Failed to add item to event queue: {e}")

def _schedule_functions(self) -> None:
"""Schedule each service based on its update interval."""
scheduled_functions = {
self._retry_library: {"interval": 60 * 2},
self._retry_library: {"interval": 60 * 10},
}
for func, config in scheduled_functions.items():
self.scheduler.add_job(
Expand Down
1 change: 1 addition & 0 deletions backend/program/settings/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ class AppModel(Observable):
version: str = get_version()
debug: bool = True
log: bool = True
force_refresh: bool = False
plex: PlexLibraryModel = PlexLibraryModel()
symlink: SymlinkModel = SymlinkModel()
downloaders: DownloadersModel = DownloadersModel()
Expand Down
85 changes: 48 additions & 37 deletions backend/program/symlink.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,55 +107,27 @@ def create_initial_folders(self):
return False
return True

def run(self, item: Union[Movie, Episode, Season]):
def run(self, item: Union[Movie, Show, Season, Episode]):
"""Check if the media item exists and create a symlink if it does"""
if not item:
logger.error("Invalid item sent to Symlinker: None")
return

try:
if isinstance(item, Show):
all_symlinked = True
for season in item.seasons:
for episode in season.episodes:
if not episode.symlinked and episode.file and episode.folder:
if self._symlink(episode):
episode.set("symlinked", True)
episode.set("symlinked_at", datetime.now())
else:
all_symlinked = False
if all_symlinked:
logger.log("SYMLINKER", f"Symlinked all episodes for show {item.log_string}")
else:
logger.error(f"Failed to symlink some episodes for show {item.log_string}")
self._symlink_show(item)
elif isinstance(item, Season):
all_symlinked = True
successfully_symlinked_episodes = []
for episode in item.episodes:
if not episode.symlinked and episode.file and episode.folder:
if self._symlink(episode):
episode.set("symlinked", True)
episode.set("symlinked_at", datetime.now())
successfully_symlinked_episodes.append(episode)
else:
all_symlinked = False
if all_symlinked:
logger.log("SYMLINKER", f"Symlinked all episodes for {item.log_string}")
else:
for episode in successfully_symlinked_episodes:
logger.log("SYMLINKER", f"Symlink created for {episode.log_string}")
self._symlink_season(item)
elif isinstance(item, (Movie, Episode)):
if not item.symlinked and item.file and item.folder:
if self._symlink(item):
logger.log("SYMLINKER", f"Symlink created for {item.log_string}")
else:
logger.error(f"Failed to create symlink for {item.log_string}")
item.set("symlinked", True)
item.set("symlinked_at", datetime.now())
self._symlink_single(item)
except Exception as e:
logger.exception(f"Exception thrown when creating symlink for {item.log_string}: {e}")

item.set("symlinked_times", item.symlinked_times + 1)
yield item

@staticmethod
def should_submit(item: Union[Movie, Episode, Season]) -> bool:
def should_submit(item: Union[Movie, Show, Season, Episode]) -> bool:
"""Check if the item should be submitted for symlink creation."""

if isinstance(item, Show):
Expand Down Expand Up @@ -226,6 +198,45 @@ def should_submit(item: Union[Movie, Episode, Season]) -> bool:
logger.debug(f"Item {item.log_string} not submitted for symlink, file not found yet")
return False

def _symlink_show(self, show: Show):
all_symlinked = True
for season in show.seasons:
for episode in season.episodes:
if not episode.symlinked and episode.file and episode.folder:
if self._symlink(episode):
episode.set("symlinked", True)
episode.set("symlinked_at", datetime.now())
else:
all_symlinked = False
if all_symlinked:
logger.log("SYMLINKER", f"Symlinked all episodes for show {show.log_string}")
else:
logger.error(f"Failed to symlink some episodes for show {show.log_string}")

def _symlink_season(self, season: Season):
all_symlinked = True
successfully_symlinked_episodes = []
for episode in season.episodes:
if not episode.symlinked and episode.file and episode.folder:
if self._symlink(episode):
episode.set("symlinked", True)
episode.set("symlinked_at", datetime.now())
successfully_symlinked_episodes.append(episode)
else:
all_symlinked = False
if all_symlinked:
logger.log("SYMLINKER", f"Symlinked all episodes for {season.log_string}")
else:
for episode in successfully_symlinked_episodes:
logger.log("SYMLINKER", f"Symlink created for {episode.log_string}")

def _symlink_single(self, item: Union[Movie, Episode]):
if not item.symlinked and item.file and item.folder:
if self._symlink(item):
logger.log("SYMLINKER", f"Symlink created for {item.log_string}")
else:
logger.error(f"Failed to create symlink for {item.log_string}")

def _symlink(self, item: Union[Movie, Episode]) -> bool:
"""Create a symlink for the given media item if it does not already exist."""
extension = os.path.splitext(item.file)[1][1:]
Expand Down
4 changes: 2 additions & 2 deletions backend/program/updaters/plex.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,13 @@ def run(self, item: Union[Movie, Show, Season, Episode]) -> Generator[Union[Movi
for path in paths:
if isinstance(item, (Show, Season)):
for episode in items_to_update:
if path in episode.update_folder:
if episode.update_folder and path in episode.update_folder:
if self._update_section(section, episode):
updated_episodes.append(episode)
section_name = section.title
updated = True
elif isinstance(item, (Movie, Episode)):
if path in item.update_folder:
if item.update_folder and path in item.update_folder:
if self._update_section(section, item):
section_name = section.title
updated = True
Expand Down

0 comments on commit 73f437b

Please sign in to comment.