|
1 | 1 | import re |
2 | 2 | import os |
3 | 3 | import zipfile |
| 4 | +import subprocess |
| 5 | +import sys |
| 6 | +from datetime import datetime, timedelta |
4 | 7 |
|
5 | 8 | PLUGIN_ROOT = os.path.dirname(os.path.abspath(__file__)) |
| 9 | +LIB_PATH = os.path.abspath(os.path.join(PLUGIN_ROOT, "..", "lib")) |
6 | 10 | FFMPEG_SETUP_LOCK = os.path.join(PLUGIN_ROOT, "ffmpeg_setup.lock") |
7 | 11 | URL_REGEX = ( |
8 | 12 | "((http|https)://)(www.)?" |
@@ -280,3 +284,74 @@ def extract_ffmpeg(): |
280 | 284 | return False, binaries_reason |
281 | 285 |
|
282 | 286 | return True, None |
| 287 | + |
| 288 | + |
| 289 | +def check_ytdlp_update_needed(check_interval_days=5): |
| 290 | + """ |
| 291 | + Check if yt-dlp library update is needed based on the last update timestamp. |
| 292 | + |
| 293 | + Args: |
| 294 | + check_interval_days (int): Number of days between update checks. |
| 295 | + |
| 296 | + Returns: |
| 297 | + bool: True if update is needed, False otherwise. |
| 298 | + """ |
| 299 | + |
| 300 | + # Path to yt-dlp package in lib folder |
| 301 | + lib_ytdlp_path = os.path.join(LIB_PATH, "yt_dlp") |
| 302 | + update_marker = os.path.join(LIB_PATH, ".ytdlp_last_update") |
| 303 | + |
| 304 | + # If yt-dlp doesn't exist in lib, update is needed |
| 305 | + if not os.path.exists(lib_ytdlp_path): |
| 306 | + return True |
| 307 | + |
| 308 | + # Check the update marker file |
| 309 | + if os.path.exists(update_marker): |
| 310 | + try: |
| 311 | + last_update = datetime.fromtimestamp(os.path.getmtime(update_marker)) |
| 312 | + if datetime.now() - last_update < timedelta(days=check_interval_days): |
| 313 | + return False |
| 314 | + except Exception: |
| 315 | + # If we can't read the marker, assume update is needed |
| 316 | + return True |
| 317 | + |
| 318 | + return True |
| 319 | + |
| 320 | + |
| 321 | +def update_ytdlp_library(): |
| 322 | + """ |
| 323 | + Update the bundled yt-dlp library in the lib folder. |
| 324 | + |
| 325 | + Returns: |
| 326 | + tuple: (success: bool, message: str) |
| 327 | + """ |
| 328 | + |
| 329 | + update_marker = os.path.join(LIB_PATH, ".ytdlp_last_update") |
| 330 | + |
| 331 | + # Try different pip commands in order of preference |
| 332 | + pip_commands = [ |
| 333 | + [sys.executable, "-m", "pip", "install", "--upgrade", "--target", LIB_PATH, "yt-dlp"], |
| 334 | + ["python", "-m", "pip", "install", "--upgrade", "--target", LIB_PATH, "yt-dlp"], |
| 335 | + ["pip", "install", "--upgrade", "--target", LIB_PATH, "yt-dlp"], |
| 336 | + ] |
| 337 | + |
| 338 | + last_error = None |
| 339 | + for cmd in pip_commands: |
| 340 | + try: |
| 341 | + subprocess.run(cmd, check=True, timeout=120) |
| 342 | + |
| 343 | + # Create/update the marker file |
| 344 | + os.makedirs(LIB_PATH, exist_ok=True) |
| 345 | + with open(update_marker, "w") as f: |
| 346 | + f.write("updated") |
| 347 | + |
| 348 | + return True, "yt-dlp library updated successfully" |
| 349 | + except (subprocess.CalledProcessError, subprocess.TimeoutExpired, FileNotFoundError) as e: |
| 350 | + last_error = e |
| 351 | + continue |
| 352 | + |
| 353 | + # All commands failed |
| 354 | + if isinstance(last_error, subprocess.TimeoutExpired): |
| 355 | + return False, "Update timed out after 2 minutes" |
| 356 | + else: |
| 357 | + return False, f"All pip commands failed. Last error: {str(last_error)}" |
0 commit comments