Implement update for pot plugin.

pull/222/head
erinhmclark 2025-03-26 16:02:29 +00:00
rodzic 633290a9cc
commit d87c0dc3a9
1 zmienionych plików z 35 dodań i 39 usunięć

Wyświetl plik

@ -1,10 +1,13 @@
import shutil
import sys import sys
import datetime import datetime
import os import os
import importlib import importlib
import subprocess import subprocess
import zipfile
from typing import Generator, Type from typing import Generator, Type
from urllib.request import urlretrieve
import yt_dlp import yt_dlp
from yt_dlp.extractor.common import InfoExtractor from yt_dlp.extractor.common import InfoExtractor
@ -26,64 +29,56 @@ class GenericExtractor(Extractor):
_dropins = {} _dropins = {}
def setup(self): def setup(self):
self.check_ytdlp_update() self.in_docker = os.environ.get("RUNNING_IN_DOCKER")
self.check_for_extractor_updates()
self.setup_token_script() self.setup_token_script()
def check_ytdlp_update(self): def check_for_extractor_updates(self):
"""Handles checking and updating yt-dlp if necessary.""" """Checks whether yt-dlp or its plugins need updating and triggers a restart if so."""
# check for file .ytdlp-update in the secrets folder
if self.ytdlp_update_interval < 0: if self.ytdlp_update_interval < 0:
return return
use_secrets = os.path.exists("secrets") update_file = os.path.join("secrets" if os.path.exists("secrets") else "", ".ytdlp-update")
path = os.path.join("secrets" if use_secrets else "", ".ytdlp-update") next_check = None
next_update_check = None if os.path.exists(update_file):
if os.path.exists(path): with open(update_file, "r") as f:
with open(path, "r") as f: next_check = datetime.datetime.fromisoformat(f.read())
next_update_check = datetime.datetime.fromisoformat(f.read())
if not next_update_check or next_update_check < datetime.datetime.now(): if next_check and next_check > datetime.datetime.now():
updated = 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())
if not updated:
return return
yt_dlp_updated = self.update_package("yt-dlp")
bgutil_updated = self.update_package("bgutil-ytdlp-pot-provider")
# Write the new timestamp
with open(update_file, "w") as f:
next_check = datetime.datetime.now() + datetime.timedelta(days=self.ytdlp_update_interval)
f.write(next_check.isoformat())
if yt_dlp_updated or bgutil_updated:
if os.environ.get("AUTO_ARCHIVER_ALLOW_RESTART", "1") != "1": if os.environ.get("AUTO_ARCHIVER_ALLOW_RESTART", "1") != "1":
logger.warning( logger.warning("yt-dlp or plugin was updated — please restart auto-archiver manually")
"yt-dlp has been updated. Auto archiver should be restarted for these changes to take effect"
)
else: else:
logger.warning("Restarting auto-archiver to apply yt-dlp update") logger.warning("yt-dlp or plugin was updated — restarting auto-archiver")
logger.warning(" ======= RESTARTING ======= ") logger.warning(" ======= RESTARTING ======= ")
os.execv(sys.executable, [sys.executable] + sys.argv) os.execv(sys.executable, [sys.executable] + sys.argv)
def update_ytdlp(self): def update_package(self, package_name: str) -> bool:
logger.info("Checking and updating yt-dlp...") logger.info(f"Checking and updating {package_name}...")
logger.info(
f"Tip: change the 'ytdlp_update_interval' setting to control how often yt-dlp is updated. Set to -1 to disable or 0 to enable on every run. Current setting: {self.ytdlp_update_interval}"
)
from importlib.metadata import version as get_version from importlib.metadata import version as get_version
old_version = get_version("yt-dlp") old_version = get_version(package_name)
try: try:
# try and update with pip (this works inside poetry environment and in a normal virtualenv) result = subprocess.run(["pip", "install", "--upgrade", package_name], check=True, capture_output=True)
result = subprocess.run(["pip", "install", "--upgrade", "yt-dlp"], check=True, capture_output=True) if f"Successfully installed {package_name}" in result.stdout.decode():
new_version = importlib.metadata.version(package_name)
if "Successfully installed yt-dlp" in result.stdout.decode(): logger.info(f"{package_name} updated from {old_version} to {new_version}")
new_version = importlib.metadata.version("yt-dlp")
logger.info(f"yt-dlp successfully (from {old_version} to {new_version})")
return True return True
else: logger.info(f"{package_name} already up to date")
logger.info("yt-dlp already up to date") except Exception as e:
logger.error(f"Error updating {package_name}: {e}")
return False return False
except Exception as e:
logger.error(f"Error updating yt-dlp: {e}")
return False
def setup_token_script(self): def setup_token_script(self):
"""Setup PO Token provider https://github.com/Brainicism/bgutil-ytdlp-pot-provider.""" """Setup PO Token provider https://github.com/Brainicism/bgutil-ytdlp-pot-provider."""
@ -100,6 +95,7 @@ class GenericExtractor(Extractor):
pot_script = os.path.join("scripts", "potoken_provider", "bgutil-provider", "build", "generate_once.js") pot_script = os.path.join("scripts", "potoken_provider", "bgutil-provider", "build", "generate_once.js")
self.extractor_args.setdefault("youtube", {})["getpot_bgutil_script"] = pot_script self.extractor_args.setdefault("youtube", {})["getpot_bgutil_script"] = pot_script
def suitable_extractors(self, url: str) -> Generator[str, None, None]: def suitable_extractors(self, url: str) -> Generator[str, None, None]:
""" """
Returns a list of valid extractors for the given URL""" Returns a list of valid extractors for the given URL"""