From 0eb112431bdbd4ffb907115aeb7ae633b62574fe Mon Sep 17 00:00:00 2001 From: Patrick Robertson Date: Tue, 4 Mar 2025 16:43:46 +0000 Subject: [PATCH] Auto-update yt-dlp based on generic_extractor.ytdlp_update_interval (default=5 days) --- .../modules/generic_extractor/__manifest__.py | 5 +++ .../generic_extractor/generic_extractor.py | 34 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/src/auto_archiver/modules/generic_extractor/__manifest__.py b/src/auto_archiver/modules/generic_extractor/__manifest__.py index caa3ae1..cb00902 100644 --- a/src/auto_archiver/modules/generic_extractor/__manifest__.py +++ b/src/auto_archiver/modules/generic_extractor/__manifest__.py @@ -64,5 +64,10 @@ via the command line using the `--dropins` option (TODO!). "default": "inf", "help": "Use to limit the number of videos to download when a channel or long page is being extracted. 'inf' means no limit.", }, + "ytdlp_update_interval": { + "default": 5, + "help": "How often to check for yt-dlp updates (days). If positive, will check and update yt-dlp every [num] days. Set it to -1 to disable, or 0 to always update on every run.", + "type": "int", + }, }, } diff --git a/src/auto_archiver/modules/generic_extractor/generic_extractor.py b/src/auto_archiver/modules/generic_extractor/generic_extractor.py index 47c03f6..289874f 100644 --- a/src/auto_archiver/modules/generic_extractor/generic_extractor.py +++ b/src/auto_archiver/modules/generic_extractor/generic_extractor.py @@ -1,5 +1,6 @@ import datetime, os, yt_dlp, pysubs2 import importlib +import subprocess from typing import Generator, Type from yt_dlp.extractor.common import InfoExtractor @@ -11,6 +12,39 @@ from auto_archiver.core import Metadata, Media class GenericExtractor(Extractor): _dropins = {} + def setup(self): + # check for file .ytdlp-update in the secrets folder + if self.ytdlp_update_interval < 0: + return + + path = os.path.join('secrets', '.ytdlp-update') + next_update_check = None + if os.path.exists(path): + with open(path, "r") as f: + next_update_check = datetime.datetime.fromisoformat(f.read()) + + if not next_update_check or next_update_check < datetime.datetime.now(): + self.update_ytdlp() + + next_update_check = datetime.datetime.now() + datetime.timedelta(days=self.ytdlp_update_interval) + with open(path, "w") as f: + f.write(next_update_check.isoformat()) + + def update_ytdlp(self): + logger.info("Checking and updating yt-dlp...") + try: + # try and update with pip (this works inside poetry environment and in a normal virtualenv) + result = subprocess.run(["pip", "install", "--upgrade", "yt-dlp"], check=True, capture_output=True) + + if "Successfully installed yt-dlp" in result.stdout.decode(): + logger.info("yt-dlp was updated successfully") + importlib.reload(yt_dlp) + else: + logger.info("yt-dlp already up to date") + + except Exception as e: + logger.error(f"Error updating yt-dlp: {e}") + def suitable_extractors(self, url: str) -> Generator[str, None, None]: """ Returns a list of valid extractors for the given URL"""