From ad6b557d34b9da3002230333161241fab2068ed4 Mon Sep 17 00:00:00 2001 From: Nick Logozzo Date: Tue, 28 Jan 2025 10:27:50 -0500 Subject: [PATCH] feat: Better `yt-dlp` plugin management --- README.md | 2 + docs/po/parabolic.pot | 2 +- inno/setup.iss | 2 +- .../CMakeLists.txt | 3 +- .../CMakeLists.txt | 3 +- resources/chrome_cookies_unlock.py | 69 ------------------- resources/po/parabolic.pot | 2 +- resources/yt-dlp-plugins/README.md | 7 ++ .../postprocessor/chrome_cookies_unlock.py | 68 ++++++++++++++++++ 9 files changed, 84 insertions(+), 74 deletions(-) delete mode 100644 resources/chrome_cookies_unlock.py create mode 100644 resources/yt-dlp-plugins/README.md create mode 100644 resources/yt-dlp-plugins/yt-dlp-ChromeCookieUnlock/yt_dlp_plugins/postprocessor/chrome_cookies_unlock.py diff --git a/README.md b/README.md index 5e10a6d9b..630d5a0b0 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,8 @@ Ensure both `vcpkg` and `cmake` are installed on your system before building. A C++20 compiler is also required to build Parabolic. +**If building the GNOME version, `blueprint-compiler` must be installed from your system package manager as it is not available on `vcpkg`.** + ### Configuring vcpkg 1. Set the `VCPKG_ROOT` environment variable to the path of your vcpkg installation's root directory. #### Windows diff --git a/docs/po/parabolic.pot b/docs/po/parabolic.pot index da1937160..8e5f8e045 100644 --- a/docs/po/parabolic.pot +++ b/docs/po/parabolic.pot @@ -1,7 +1,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" -"POT-Creation-Date: 2025-01-28 09:34-0500\n" +"POT-Creation-Date: 2025-01-28 10:18-0500\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" diff --git a/inno/setup.iss b/inno/setup.iss index 8724b927f..0c50a26ab 100644 --- a/inno/setup.iss +++ b/inno/setup.iss @@ -60,7 +60,7 @@ Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{ [Files] Source: "vc_redist.x64.exe"; DestDir: "{app}\deps"; AfterInstall: SetupVC Source: "yt-dlp.exe"; DestDir: "{app}\Release"; Flags: ignoreversion -Source: "..\resources\chrome_cookies_unlock.py"; DestDir: "{app}\Release\yt-dlp-plugins\yt-dlp-ChromeCookieUnlock\yt_dlp_plugins\postprocessor"; Flags: ignoreversion +Source: "..\resources\yt-dlp-plugins\*"; DestDir: "{app}\Release\yt-dlp-plugins\"; Flags: ignoreversion recursesubdirs createallsubdirs Source: "ffmpeg.exe"; DestDir: "{app}\Release"; Flags: ignoreversion Source: "ffplay.exe"; DestDir: "{app}\Release"; Flags: ignoreversion Source: "ffprobe.exe"; DestDir: "{app}\Release"; Flags: ignoreversion diff --git a/org.nickvision.tubeconverter.gnome/CMakeLists.txt b/org.nickvision.tubeconverter.gnome/CMakeLists.txt index 2c9173760..725fe7379 100644 --- a/org.nickvision.tubeconverter.gnome/CMakeLists.txt +++ b/org.nickvision.tubeconverter.gnome/CMakeLists.txt @@ -37,7 +37,7 @@ if(NOT WIN32) if(BLUEPRINT_COMPILER_EXECUTABLE) add_custom_command(TARGET gnome_commands PRE_BUILD COMMAND "${BLUEPRINT_COMPILER_EXECUTABLE}" batch-compile "${CMAKE_CURRENT_BINARY_DIR}/ui" "${CMAKE_CURRENT_SOURCE_DIR}/blueprints" "${CMAKE_CURRENT_SOURCE_DIR}/blueprints/*.blp") else() - message(ERROR "blueprint-compiler not found, UI will not be compiled") + message(FATAL_ERROR "blueprint-compiler not found, UI will not be compiled") endif() if(HAS_GETTEXT) @@ -52,6 +52,7 @@ if(NOT WIN32) configure_file("${CMAKE_SOURCE_DIR}/resources/linux/${PROJECT_NAME}.metainfo.xml.in" "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.metainfo.xml" @ONLY) configure_file("${CMAKE_SOURCE_DIR}/resources/linux/${PROJECT_NAME}.service.in" "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.service" @ONLY) install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/" DESTINATION "${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME}") + install(DIRECTORY "${CMAKE_SOURCE_DIR}/resources/yt-dlp-plugins/" DESTINATION "${CMAKE_INSTALL_FULL_SYSCONFDIR}/yt-dlp-plugins" FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_NAME}" PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE DESTINATION "${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME}") install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}" PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE DESTINATION "${CMAKE_INSTALL_BINDIR}") install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.desktop" DESTINATION "${CMAKE_INSTALL_DATADIR}/applications") diff --git a/org.nickvision.tubeconverter.qt/CMakeLists.txt b/org.nickvision.tubeconverter.qt/CMakeLists.txt index 708b9c2a9..685513d48 100644 --- a/org.nickvision.tubeconverter.qt/CMakeLists.txt +++ b/org.nickvision.tubeconverter.qt/CMakeLists.txt @@ -80,6 +80,7 @@ if(LINUX) configure_file("${CMAKE_SOURCE_DIR}/resources/linux/${PROJECT_NAME}.in" "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}" @ONLY) configure_file("${CMAKE_SOURCE_DIR}/resources/linux/${PROJECT_NAME}.metainfo.xml.in" "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.metainfo.xml" @ONLY) install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/" DESTINATION "${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME}") + install(DIRECTORY "${CMAKE_SOURCE_DIR}/resources/yt-dlp-plugins/" DESTINATION "${CMAKE_INSTALL_FULL_SYSCONFDIR}/yt-dlp-plugins" FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_NAME}" PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE DESTINATION "${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME}") install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}" PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE DESTINATION "${CMAKE_INSTALL_BINDIR}") install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.desktop" DESTINATION "${CMAKE_INSTALL_DATADIR}/applications") @@ -93,4 +94,4 @@ if(LINUX) else() message(WARNING "update-desktop-database not found, desktop database will not be updated") endif() -endif() \ No newline at end of file +endif() diff --git a/resources/chrome_cookies_unlock.py b/resources/chrome_cookies_unlock.py deleted file mode 100644 index d0004c493..000000000 --- a/resources/chrome_cookies_unlock.py +++ /dev/null @@ -1,69 +0,0 @@ -# FROM: https://github.com/seproDev/yt-dlp-ChromeCookieUnlock - -import sys - -import yt_dlp.cookies - -original_func = yt_dlp.cookies._open_database_copy - -def unlock_chrome(database_path, tmpdir): - try: - return original_func(database_path, tmpdir) - except PermissionError: - unlock_cookies(database_path) - return original_func(database_path, tmpdir) - -yt_dlp.cookies._open_database_copy = unlock_chrome - - -# Adapted from https://gist.github.com/csm10495/e89e660ffee0030e8ef410b793ad6a7e -# By Charles Machalow under the MIT License - -from ctypes import windll, byref, create_unicode_buffer, pointer, WINFUNCTYPE -from ctypes.wintypes import DWORD, WCHAR, UINT - -ERROR_SUCCESS = 0 -ERROR_MORE_DATA = 234 -RmForceShutdown = 1 - -@WINFUNCTYPE(None, UINT) -def callback(percent_complete: UINT) -> None: - pass - -rstrtmgr = windll.LoadLibrary("Rstrtmgr") - -def unlock_cookies(cookies_path): - session_handle = DWORD(0) - session_flags = DWORD(0) - session_key = (WCHAR * 256)() - - result = DWORD(rstrtmgr.RmStartSession(byref(session_handle), session_flags, session_key)).value - - if result != ERROR_SUCCESS: - raise RuntimeError(f"RmStartSession returned non-zero result: {result}") - - try: - result = DWORD(rstrtmgr.RmRegisterResources(session_handle, 1, byref(pointer(create_unicode_buffer(cookies_path))), 0, None, 0, None)).value - - if result != ERROR_SUCCESS: - raise RuntimeError(f"RmRegisterResources returned non-zero result: {result}") - - proc_info_needed = DWORD(0) - proc_info = DWORD(0) - reboot_reasons = DWORD(0) - - result = DWORD(rstrtmgr.RmGetList(session_handle, byref(proc_info_needed), byref(proc_info), None, byref(reboot_reasons))).value - - if result not in (ERROR_SUCCESS, ERROR_MORE_DATA): - raise RuntimeError(f"RmGetList returned non-successful result: {result}") - - if proc_info_needed.value: - result = DWORD(rstrtmgr.RmShutdown(session_handle, RmForceShutdown, callback)).value - - if result != ERROR_SUCCESS: - raise RuntimeError(f"RmShutdown returned non-successful result: {result}") - finally: - result = DWORD(rstrtmgr.RmEndSession(session_handle)).value - - if result != ERROR_SUCCESS: - raise RuntimeError(f"RmEndSession returned non-successful result: {result}") \ No newline at end of file diff --git a/resources/po/parabolic.pot b/resources/po/parabolic.pot index 0c53fe93b..936256268 100644 --- a/resources/po/parabolic.pot +++ b/resources/po/parabolic.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-01-28 09:34-0500\n" +"POT-Creation-Date: 2025-01-28 10:18-0500\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" diff --git a/resources/yt-dlp-plugins/README.md b/resources/yt-dlp-plugins/README.md new file mode 100644 index 000000000..a3d65c1ed --- /dev/null +++ b/resources/yt-dlp-plugins/README.md @@ -0,0 +1,7 @@ +# yt-dlp-plugins + +Adapted from: + +- https://github.com/seproDev/yt-dlp-ChromeCookieUnlock +- https://github.com/coletdjnz/yt-dlp-get-pot +- https://github.com/Brainicism/bgutil-ytdlp-pot-provider diff --git a/resources/yt-dlp-plugins/yt-dlp-ChromeCookieUnlock/yt_dlp_plugins/postprocessor/chrome_cookies_unlock.py b/resources/yt-dlp-plugins/yt-dlp-ChromeCookieUnlock/yt_dlp_plugins/postprocessor/chrome_cookies_unlock.py new file mode 100644 index 000000000..5423ca130 --- /dev/null +++ b/resources/yt-dlp-plugins/yt-dlp-ChromeCookieUnlock/yt_dlp_plugins/postprocessor/chrome_cookies_unlock.py @@ -0,0 +1,68 @@ +import os +import sys +import yt_dlp.cookies + +if os.name == 'nt': + original_func = yt_dlp.cookies._open_database_copy + + def unlock_chrome(database_path, tmpdir): + try: + return original_func(database_path, tmpdir) + except PermissionError: + unlock_cookies(database_path) + return original_func(database_path, tmpdir) + + yt_dlp.cookies._open_database_copy = unlock_chrome + + + # Adapted from https://gist.github.com/csm10495/e89e660ffee0030e8ef410b793ad6a7e + # By Charles Machalow under the MIT License + + from ctypes import windll, byref, create_unicode_buffer, pointer, WINFUNCTYPE + from ctypes.wintypes import DWORD, WCHAR, UINT + + ERROR_SUCCESS = 0 + ERROR_MORE_DATA = 234 + RmForceShutdown = 1 + + @WINFUNCTYPE(None, UINT) + def callback(percent_complete: UINT) -> None: + pass + + rstrtmgr = windll.LoadLibrary("Rstrtmgr") + + def unlock_cookies(cookies_path): + session_handle = DWORD(0) + session_flags = DWORD(0) + session_key = (WCHAR * 256)() + + result = DWORD(rstrtmgr.RmStartSession(byref(session_handle), session_flags, session_key)).value + + if result != ERROR_SUCCESS: + raise RuntimeError(f"RmStartSession returned non-zero result: {result}") + + try: + result = DWORD(rstrtmgr.RmRegisterResources(session_handle, 1, byref(pointer(create_unicode_buffer(cookies_path))), 0, None, 0, None)).value + + if result != ERROR_SUCCESS: + raise RuntimeError(f"RmRegisterResources returned non-zero result: {result}") + + proc_info_needed = DWORD(0) + proc_info = DWORD(0) + reboot_reasons = DWORD(0) + + result = DWORD(rstrtmgr.RmGetList(session_handle, byref(proc_info_needed), byref(proc_info), None, byref(reboot_reasons))).value + + if result not in (ERROR_SUCCESS, ERROR_MORE_DATA): + raise RuntimeError(f"RmGetList returned non-successful result: {result}") + + if proc_info_needed.value: + result = DWORD(rstrtmgr.RmShutdown(session_handle, RmForceShutdown, callback)).value + + if result != ERROR_SUCCESS: + raise RuntimeError(f"RmShutdown returned non-successful result: {result}") + finally: + result = DWORD(rstrtmgr.RmEndSession(session_handle)).value + + if result != ERROR_SUCCESS: + raise RuntimeError(f"RmEndSession returned non-successful result: {result}")