From 53f0bd894b1f5be5519aeeb8e2fb0426b858f4ff Mon Sep 17 00:00:00 2001 From: "Heliomar P. Marques" Date: Thu, 14 Nov 2024 23:46:05 -0300 Subject: [PATCH] v1.13.3 --- .github/FUNDING.yml | 16 + .prettierrc | 51 +- CHANGE_LOG.md | 16 +- app/app.js | 3239 ++++++++++++++-------------- app/core/services/index.js | 14 +- app/core/services/m3u8.service.js | 319 ++- app/core/services/udemy.service.js | 744 +++---- app/helpers/auto_authenticator.js | 67 +- app/helpers/index.js | 10 +- app/helpers/settings.js | 337 ++- app/helpers/ui.js | 233 +- app/helpers/utils.js | 316 ++- app/renderer.js | 60 +- package-lock.json | 2293 +++++++++++++++++--- package.json | 13 +- sync_locales_template.py | 27 - 16 files changed, 4695 insertions(+), 3060 deletions(-) delete mode 100644 sync_locales_template.py diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index dad0ff36..4fc5d904 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -7,3 +7,19 @@ custom: [ "https://bit.ly/paypalbr-udeler", "https://www.pixme.bio/heliomarpm" ] + +# These are supported funding model platforms + +# github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +# patreon: # Replace with a single Patreon username +# open_collective: # Replace with a single Open Collective username +# ko_fi: # Replace with a single Ko-fi username +# tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +# community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +# liberapay: # Replace with a single Liberapay username +# issuehunt: # Replace with a single IssueHunt username +# lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry +# polar: # Replace with a single Polar username +# buy_me_a_coffee: # Replace with a single Buy Me a Coffee username +# thanks_dev: # Replace with a single thanks.dev username +# custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] \ No newline at end of file diff --git a/.prettierrc b/.prettierrc index 9fcd92fd..4481ed70 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,19 +1,34 @@ { - "arrowParens": "always", - "bracketSameLine": false, - "bracketSpacing": false, - "embeddedLanguageFormatting": "auto", - "htmlWhitespaceSensitivity": "css", - "insertPragma": false, - "jsxSingleQuote": false, - "printWidth": 140, - "proseWrap": "preserve", - "quoteProps": "as-needed", - "requirePragma": false, - "semi": true, - "singleAttributePerLine": false, - "singleQuote": false, - "tabWidth": 4, - "trailingComma": "es5", - "useTabs": true - } \ No newline at end of file + "singleQuote": false, + "trailingComma": "es5", + "tabWidth": 2, + "useTabs": true, + "semi": true, + "arrowParens": "always", + "bracketSpacing": true, + "bracketSameLine": false, + "importOrder": ["^@core/(.*)$", "^@shared/(.*)$", "^@server/(.*)$", "^@app/(.*)$", "^[./]"], + "importOrderSeparation": true, + "importOrderCaseInsensitive": false, + "importOrderSortAlphabetically": true, + "importOrderSortSpecifiers": true, + "singleAttributePerLine": false, + "embeddedLanguageFormatting": "auto", + "htmlWhitespaceSensitivity": "css", + "proseWrap": "preserve", + "printWidth": 140, + "overrides": [ + { + "files": "*.json", + "options": { + "printWidth": 200 + } + }, + { + "files": ["*.html", "*.css", "legacy/**/*.js"], + "options": { + "tabWidth": 4 + } + } + ] +} diff --git a/CHANGE_LOG.md b/CHANGE_LOG.md index 1724727e..c1e23957 100644 --- a/CHANGE_LOG.md +++ b/CHANGE_LOG.md @@ -1,5 +1,18 @@ # Change Log +## Version [1.13.3](https://github.com/heliomarpm/udemy-downloader-gui/compare/v1.13.2...v1.13.3) +##### Nov, 14 2024 +![](https://img.shields.io/github/downloads/heliomarpm/udemy-downloader-gui/v1.13.3/total) + + +### Issues Fixed + * Download preparer for new AssetType + - [#202](https://github.com/heliomarpm/udemy-downloader-gui/issues/202) + - [#213](https://github.com/heliomarpm/udemy-downloader-gui/issues/213) + - [#218](https://github.com/heliomarpm/udemy-downloader-gui/issues/218) + +### Update Packages + ## Version [1.13.2](https://github.com/heliomarpm/udemy-downloader-gui/compare/v1.13.1...v1.13.2) ##### Aug, 31 2024 ![](https://img.shields.io/github/downloads/heliomarpm/udemy-downloader-gui/v1.13.2/total) @@ -7,7 +20,6 @@ ### Issues Fixed * Download preparer for new AssetType - - [#198](https://github.com/heliomarpm/udemy-downloader-gui/issues/198) - [#201](https://github.com/heliomarpm/udemy-downloader-gui/issues/201) - [#206](https://github.com/heliomarpm/udemy-downloader-gui/issues/206) - [#208](https://github.com/heliomarpm/udemy-downloader-gui/issues/208) @@ -25,7 +37,7 @@ ### Issues Fixed * Download preparer - - [#198](https://github.com/heliomarpm/udemy-downloader-gui/issues/198) + - [#198](https://github.com/heliomarpm/udemy-downloader-gui/issues/198) - [#201](https://github.com/heliomarpm/udemy-downloader-gui/issues/201) - [#206](https://github.com/heliomarpm/udemy-downloader-gui/issues/206) - [#207](https://github.com/heliomarpm/udemy-downloader-gui/issues/207) diff --git a/app/app.js b/app/app.js index f40ad06b..2695f1ae 100644 --- a/app/app.js +++ b/app/app.js @@ -13,8 +13,8 @@ const Downloader = require("mt-files-downloader"); const https = require("https"); const cookie = require("cookie"); -const { Settings, ui, utils } = require('./helpers') -const { default: UdemyService } = require('./core/services'); +const { Settings, ui, utils } = require("./helpers"); +const { default: UdemyService } = require("./core/services"); const PAGE_SIZE = 25; const MSG_DRM_PROTECTED = translate("Contains DRM protection and cannot be downloaded"); @@ -29,75 +29,75 @@ ipcRenderer.on("saveDownloads", () => saveDownloads(true)); // external browser // $(document).on('click', 'a[href^="http"]', (event) => { $(document).on("click", ".how-get-token", (event) => { - event.preventDefault(); - shell.openExternal(event.target.href); + event.preventDefault(); + shell.openExternal(event.target.href); }); $(document).ajaxError(function (_event, _request) { - $(".dimmer").removeClass("active"); + $(".dimmer").removeClass("active"); }); $(".ui.dropdown").dropdown(); $(".ui.login #business").on("change", function () { - if ($(this).is(":checked")) { - ui.$subdomainField.val(Settings.subDomain); - ui.toggleSubdomainField(true); - } else { - ui.$subdomainField.val(null); - ui.toggleSubdomainField(false); - } + if ($(this).is(":checked")) { + ui.$subdomainField.val(Settings.subDomain); + ui.toggleSubdomainField(true); + } else { + ui.$subdomainField.val(null); + ui.toggleSubdomainField(false); + } }); $(".courses-sidebar").on("click", function () { - ui.navSidebar(this, "courses"); + ui.navSidebar(this, "courses"); }); $(".downloads-sidebar").on("click", async function () { - ui.navSidebar(this, "downloads"); - renderDownloads(); + ui.navSidebar(this, "downloads"); + renderDownloads(); }); $(".settings-sidebar").on("click", function () { - ui.navSidebar(this, "settings"); - loadSettings(); + ui.navSidebar(this, "settings"); + loadSettings(); }); $(".about-sidebar").on("click", function () { - ui.navSidebar(this, "about"); + ui.navSidebar(this, "about"); }); $(".logger-sidebar").on("click", function () { - ui.navSidebar(this, "logger"); - clearBagdeLoggers(); + ui.navSidebar(this, "logger"); + clearBagdeLoggers(); }); $(".logout-sidebar").on("click", function () { - dialogs.confirm(translate("Confirm Log Out?"), function (ok) { - if (ok) { - ui.busyLogout(true); - saveDownloads(false); - Settings.accessToken = null; - ui.resetToLogin(); - } - }); + dialogs.confirm(translate("Confirm Log Out?"), function (ok) { + if (ok) { + ui.busyLogout(true); + saveDownloads(false); + Settings.accessToken = null; + ui.resetToLogin(); + } + }); }); $(".ui.dashboard .content").on("click", ".load-more.button", (e) => loadMore(e.currentTarget)); $(".ui.dashboard .content").on("click", ".dismiss-download", function () { - const courseId = $(this).parents(".course.item").attr("course-id"); - removeCurseDownloads(courseId); + const courseId = $(this).parents(".course.item").attr("course-id"); + removeCurseDownloads(courseId); }); $(".ui.dashboard .content").on("click", ".open-in-browser", function () { - const link = `https://${Settings.subDomain}.udemy.com${$(this).parents(".course.item").attr("course-url")}`; - shell.openExternal(link); + const link = `https://${Settings.subDomain}.udemy.com${$(this).parents(".course.item").attr("course-url")}`; + shell.openExternal(link); }); $(".ui.dashboard .content").on("click", ".open-dir", function () { - const pathDownloaded = $(this).parents(".course.item").find('input[name="path-downloaded"]').val(); - shell.openPath(pathDownloaded); + const pathDownloaded = $(this).parents(".course.item").find('input[name="path-downloaded"]').val(); + shell.openPath(pathDownloaded); }); $(".ui.dashboard .content").on("click", ".check-updates", () => checkUpdate("heliomarpm")); @@ -105,21 +105,21 @@ $(".ui.dashboard .content").on("click", ".check-updates", () => checkUpdate("hel $(".ui.dashboard .content").on("click", ".check-updates-original", () => checkUpdate("FaisalUmair")); $(".ui.dashboard .content").on("click", ".old-version-mac", () => { - shell.openExternal("https://github.com/FaisalUmair/udemy-downloader-gui/releases/download/v1.8.2/Udeler-1.8.2-mac.dmg"); + shell.openExternal("https://github.com/FaisalUmair/udemy-downloader-gui/releases/download/v1.8.2/Udeler-1.8.2-mac.dmg"); }); $(".ui.dashboard .content").on("click", ".old-version-linux", () => { - shell.openExternal("https://github.com/FaisalUmair/udemy-downloader-gui/releases/download/v1.8.2/Udeler-1.8.2-linux-x86_x64.AppImage"); + shell.openExternal("https://github.com/FaisalUmair/udemy-downloader-gui/releases/download/v1.8.2/Udeler-1.8.2-linux-x86_x64.AppImage"); }); $(".ui.dashboard .content").on("click", ".download-success, .course-encrypted", function () { - $(this).hide(); - $(this).parents(".course").find(".download-status").show(); + $(this).hide(); + $(this).parents(".course").find(".download-status").show(); }); $(".ui.dashboard .content").on("click", ".download.button, .download-error", function (e) { - e.stopImmediatePropagation(); - prepareDownloading($(this).parents(".course")); + e.stopImmediatePropagation(); + prepareDownloading($(this).parents(".course")); }); $(".ui.dashboard .content").on("click", "#clear_logger", clearLogArea); @@ -127,296 +127,295 @@ $(".ui.dashboard .content").on("click", "#clear_logger", clearLogArea); $(".ui.dashboard .content").on("click", "#save_logger", saveLogFile); $(".ui.dashboard .content .courses.section .search.form").on("submit", function (e) { - e.preventDefault(); - const keyword = $(e.target).find("input").val(); - search(keyword); + e.preventDefault(); + const keyword = $(e.target).find("input").val(); + search(keyword); }); $(".download-update.button").on("click", () => { - shell.openExternal(`https://github.com/${repoAccount}/udemy-downloader-gui/releases/latest`); + shell.openExternal(`https://github.com/${repoAccount}/udemy-downloader-gui/releases/latest`); }); $(".content .ui.about").on("click", 'a[href^="http"]', function (e) { - e.preventDefault(); - shell.openExternal(this.href); + e.preventDefault(); + shell.openExternal(this.href); }); $(".ui.settings .form").on("submit", (e) => { - e.preventDefault(); - saveSettings(e.target); + e.preventDefault(); + saveSettings(e.target); }); const $settingsForm = $(".ui.settings .form"); $settingsForm.find('input[name="enabledownloadstartend"]').on("change", function () { - $settingsForm.find('input[name="downloadstart"], input[name="downloadend"]').prop("readonly", !this.checked); + $settingsForm.find('input[name="downloadstart"], input[name="downloadend"]').prop("readonly", !this.checked); }); function loadSettings() { - $settingsForm.find('input[name="check-new-version"]') - .prop("checked", Boolean(Settings.download.checkNewVersion)); - $settingsForm.find('input[name="auto-start-download"]') - .prop("checked", Boolean(Settings.download.autoStartDownload)); - $settingsForm.find('input[name="continue-downloading-encrypted"]') - .prop("checked", Boolean(Settings.download.continueDonwloadingEncrypted)); - - $settingsForm.find('input[name="enabledownloadstartend"]') - .prop("checked", Boolean(Settings.download.enableDownloadStartEnd)); - $settingsForm.find('input[name="downloadstart"], input[name="downloadend"]') - .prop("readonly", !Boolean(Settings.download.enableDownloadStartEnd)); - - $settingsForm.find('input:radio[name="downloadType"]') - .filter(`[value="${Settings.download.type}"]`).prop("checked", true); - $settingsForm.find('input[name="skipsubtitles"]') - .prop("checked", Boolean(Settings.download.skipSubtitles)); - $settingsForm.find('input[name="autoretry"]') - .prop("checked", Boolean(Settings.download.autoRetry)); - $settingsForm.find('input[name="seq-zero-left"]') - .prop("checked", Boolean(Settings.download.seqZeroLeft)); - - $settingsForm.find('input[name="downloadpath"]').val(Settings.downloadDirectory()); - $settingsForm.find('input[name="downloadstart"]').val(Settings.download.downloadStart); - $settingsForm.find('input[name="downloadend"]').val(Settings.download.downloadEnd); - - const videoQuality = Settings.download.videoQuality; - $settingsForm.find('input[name="videoquality"]').val(videoQuality); - $settingsForm.find('input[name="videoquality"]') - .parent(".dropdown").find(".default.text") - .html(translate(videoQuality || "Auto")); - - const language = Settings.language; - $settingsForm.find('input[name="language"]').val(language || ""); - $settingsForm.find('input[name="language"]') - .parent(".dropdown").find(".default.text") - .html(language || "English"); - - const defaultSubtitle = Settings.download.defaultSubtitle; - $settingsForm.find('input[name="defaultSubtitle"]').val(defaultSubtitle || ""); - $settingsForm.find('input[name="defaultSubtitle"]') - .parent(".dropdown").find(".defaultSubtitle.text") - .html(defaultSubtitle || ""); + $settingsForm.find('input[name="check-new-version"]').prop("checked", Boolean(Settings.download.checkNewVersion)); + $settingsForm.find('input[name="auto-start-download"]').prop("checked", Boolean(Settings.download.autoStartDownload)); + $settingsForm + .find('input[name="continue-downloading-encrypted"]') + .prop("checked", Boolean(Settings.download.continueDonwloadingEncrypted)); + + $settingsForm.find('input[name="enabledownloadstartend"]').prop("checked", Boolean(Settings.download.enableDownloadStartEnd)); + $settingsForm + .find('input[name="downloadstart"], input[name="downloadend"]') + .prop("readonly", !Boolean(Settings.download.enableDownloadStartEnd)); + + $settingsForm.find('input:radio[name="downloadType"]').filter(`[value="${Settings.download.type}"]`).prop("checked", true); + $settingsForm.find('input[name="skipsubtitles"]').prop("checked", Boolean(Settings.download.skipSubtitles)); + $settingsForm.find('input[name="autoretry"]').prop("checked", Boolean(Settings.download.autoRetry)); + $settingsForm.find('input[name="seq-zero-left"]').prop("checked", Boolean(Settings.download.seqZeroLeft)); + + $settingsForm.find('input[name="downloadpath"]').val(Settings.downloadDirectory()); + $settingsForm.find('input[name="downloadstart"]').val(Settings.download.downloadStart); + $settingsForm.find('input[name="downloadend"]').val(Settings.download.downloadEnd); + + const videoQuality = Settings.download.videoQuality; + $settingsForm.find('input[name="videoquality"]').val(videoQuality); + $settingsForm + .find('input[name="videoquality"]') + .parent(".dropdown") + .find(".default.text") + .html(translate(videoQuality || "Auto")); + + const language = Settings.language; + $settingsForm.find('input[name="language"]').val(language || ""); + $settingsForm + .find('input[name="language"]') + .parent(".dropdown") + .find(".default.text") + .html(language || "English"); + + const defaultSubtitle = Settings.download.defaultSubtitle; + $settingsForm.find('input[name="defaultSubtitle"]').val(defaultSubtitle || ""); + $settingsForm + .find('input[name="defaultSubtitle"]') + .parent(".dropdown") + .find(".defaultSubtitle.text") + .html(defaultSubtitle || ""); } function saveSettings(formElement) { - const findInput = (inputName, attr = "") => $(formElement).find(`input[name="${inputName}"]${attr}`); - - const def = Settings.DownloadDefaultOptions; - - const checkNewVersion = findInput("check-new-version")[0].checked ?? def.checkNewVersion; - const defaultSubtitle = findInput("defaultSubtitle").val() ?? def.defaultSubtitle; - const downloadPath = findInput("downloadpath").val() ?? def.path; - const autoStartDownload = findInput("auto-start-download")[0].checked ?? def.autoStartDownload; - const continueDonwloadingEncrypted = findInput("continue-downloading-encrypted")[0].checked ?? def.continueDonwloadingEncrypted; - const enableDownloadStartEnd = findInput("enabledownloadstartend")[0].checked ?? def.enableDownloadStartEnd; - const downloadStart = parseInt(findInput("downloadstart").val() ?? def.downloadStart); - const downloadEnd = parseInt(findInput("downloadend").val() ?? def.downloadEnd); - const videoQuality = findInput("videoquality").val() ?? def.videoQuality; - const downloadType = findInput("downloadType", ":checked").val() ?? def.type; - const skipSubtitles = findInput("skipsubtitles")[0].checked ?? def.skipSubtitles; - const seqZeroLeft = findInput("seq-zero-left")[0].checked ?? def.seqZeroLeft; - const autoRetry = findInput("autoretry")[0].checked ?? def.autoRetry; - const language = findInput("language").val() ?? undefined; - - Settings.download = { - checkNewVersion, - defaultSubtitle, - path: downloadPath, - autoStartDownload, - continueDonwloadingEncrypted, - enableDownloadStartEnd, - downloadStart, - downloadEnd, - videoQuality, - type: Number(downloadType), - skipSubtitles, - seqZeroLeft, - autoRetry, - }; - - Settings.language = language; - - showAlert(translate("Settings Saved")); + const findInput = (inputName, attr = "") => $(formElement).find(`input[name="${inputName}"]${attr}`); + + const def = Settings.DownloadDefaultOptions; + + const checkNewVersion = findInput("check-new-version")[0].checked ?? def.checkNewVersion; + const defaultSubtitle = findInput("defaultSubtitle").val() ?? def.defaultSubtitle; + const downloadPath = findInput("downloadpath").val() ?? def.path; + const autoStartDownload = findInput("auto-start-download")[0].checked ?? def.autoStartDownload; + const continueDonwloadingEncrypted = findInput("continue-downloading-encrypted")[0].checked ?? def.continueDonwloadingEncrypted; + const enableDownloadStartEnd = findInput("enabledownloadstartend")[0].checked ?? def.enableDownloadStartEnd; + const downloadStart = parseInt(findInput("downloadstart").val() ?? def.downloadStart); + const downloadEnd = parseInt(findInput("downloadend").val() ?? def.downloadEnd); + const videoQuality = findInput("videoquality").val() ?? def.videoQuality; + const downloadType = findInput("downloadType", ":checked").val() ?? def.type; + const skipSubtitles = findInput("skipsubtitles")[0].checked ?? def.skipSubtitles; + const seqZeroLeft = findInput("seq-zero-left")[0].checked ?? def.seqZeroLeft; + const autoRetry = findInput("autoretry")[0].checked ?? def.autoRetry; + const language = findInput("language").val() ?? undefined; + + Settings.download = { + checkNewVersion, + defaultSubtitle, + path: downloadPath, + autoStartDownload, + continueDonwloadingEncrypted, + enableDownloadStartEnd, + downloadStart, + downloadEnd, + videoQuality, + type: Number(downloadType), + skipSubtitles, + seqZeroLeft, + autoRetry, + }; + + Settings.language = language; + + showAlert(translate("Settings Saved")); } function selectDownloadPath() { - const path = dialog.showOpenDialogSync({ - properties: ["openDirectory"], - }); - - if (path && path[0]) { - fs.access(path[0], fs.constants.R_OK && fs.constants.W_OK, function (err) { - if (err) { - showAlert(translate("Cannot select this folder")); - } else { - $settingsForm.find('input[name="downloadpath"]').val(path[0]); - } - }); - } + const path = dialog.showOpenDialogSync({ + properties: ["openDirectory"], + }); + + if (path && path[0]) { + fs.access(path[0], fs.constants.R_OK && fs.constants.W_OK, function (err) { + if (err) { + showAlert(translate("Cannot select this folder")); + } else { + $settingsForm.find('input[name="downloadpath"]').val(path[0]); + } + }); + } } async function checkUpdate(account, silent = false) { - ui.busyCheckUpdate(true); - - try { - const response = await fetch(`https://api.github.com/repos/${account}/udemy-downloader-gui/releases/latest`) - - if (!response.ok) { - throw new Error(`Failed to check for updates: ${response.status}`); - } - - const data = await response.json(); - if (data.tag_name != `v${appVersion}`) { - repoAccount = account; - $(".ui.update-available.modal").modal("show"); - } else if (!silent) { - showAlert(translate("No updates available")); - } - } catch (error) { - console.error("Failed to check for updates", error); - if (!silent) { - showAlert(translate("Failed to check for updates"), translate("Check for updates")); - } - appendLog("Failed to check for updates", error); - } finally { - ui.busyCheckUpdate(false); - } + ui.busyCheckUpdate(true); + + try { + const response = await fetch(`https://api.github.com/repos/${account}/udemy-downloader-gui/releases/latest`); + + if (!response.ok) { + throw new Error(`Failed to check for updates: ${response.status}`); + } + + const data = await response.json(); + if (data.tag_name != `v${appVersion}`) { + repoAccount = account; + $(".ui.update-available.modal").modal("show"); + } else if (!silent) { + showAlert(translate("No updates available")); + } + } catch (error) { + console.error("Failed to check for updates", error); + if (!silent) { + showAlert(translate("Failed to check for updates"), translate("Check for updates")); + } + appendLog("Failed to check for updates", error); + } finally { + ui.busyCheckUpdate(false); + } } async function checkLogin(alertExpired = true) { - if (Settings.accessToken) { - try { - ui.busyLogin(true); - - udemyService = new UdemyService(Settings.subDomain, HTTP_TIMEOUT); - const userContext = await udemyService.fetchProfile(Settings.accessToken, 30000); - - if (!userContext.header.isLoggedIn) { - if (alertExpired) { - showAlert(translate("Token expired")); - } - ui.resetToLogin(); - return; - } - ui.busyLogin(false); - ui.showDashboard(); - - Settings.subscriber = utils.toBoolean(userContext.header.user.enableLabsInPersonalPlan); - fetchCourses(Settings.subscriber).then(() => { - console.log("fetchCourses done"); - }); - - if (Settings.download.checkNewVersion) { - checkUpdate("heliomarpm", true); - } - - } catch (error) { - console.error("Failed to fetch user profile", error); - if (!process.env.DEBUG_MODE) Settings.accessToken = null; - - ui.resetToLogin(); - showAlert(error.message, error.name || "Error"); - } finally { - console.log("access-token", Settings.accessToken); - } - } + if (Settings.accessToken) { + try { + ui.busyLogin(true); + + udemyService = new UdemyService(Settings.subDomain, HTTP_TIMEOUT); + const userContext = await udemyService.fetchProfile(Settings.accessToken, 30000); + + if (!userContext.header.isLoggedIn) { + if (alertExpired) { + showAlert(Settings.accessToken, translate("Token expired")); + } + ui.resetToLogin(); + return; + } + ui.busyLogin(false); + ui.showDashboard(); + + Settings.subscriber = utils.toBoolean(userContext.header.user.enableLabsInPersonalPlan); + fetchCourses(Settings.subscriber).then(() => { + console.log("fetchCourses done"); + }); + + if (Settings.download.checkNewVersion) { + checkUpdate("heliomarpm", true); + } + } catch (error) { + console.error("Failed to fetch user profile", error); + if (!process.env.DEBUG_MODE) Settings.accessToken = null; + + ui.resetToLogin(); + showAlert(error.message, error.name || "Error"); + } finally { + console.log("access-token", Settings.accessToken); + } + } } function loginWithUdemy() { - const $formLogin = $(".ui.login .form"); - - if ($formLogin.find('input[name="business"]').is(":checked")) { - if (!ui.$subdomainField.val()) { - showAlert("Type Business Name"); - return; - } - } else { - ui.$subdomainField.val(null); - } - - const parent = remote.getCurrentWindow(); - const dimensions = parent.getSize(); - const session = remote.session; - let udemyLoginWindow = new BrowserWindow({ - width: dimensions[0] - 100, - height: dimensions[1] - 100, - parent, - modal: true, - }); - - session.defaultSession.webRequest.onBeforeSendHeaders({ urls: ["*://*.udemy.com/*"] }, function (request, callback) { - const token = request.requestHeaders.Authorization - ? request.requestHeaders.Authorization.split(" ")[1] - : cookie.parse(request.requestHeaders.Cookie || "").access_token; - - if (token) { - Settings.accessToken = token; - Settings.subDomain = new URL(request.url).hostname.split(".")[0]; - - udemyLoginWindow.destroy(); - session.defaultSession.clearStorageData(); - session.defaultSession.webRequest.onBeforeSendHeaders({ urls: ["*://*.udemy.com/*"] }, function (request, callback) { - callback({ requestHeaders: request.requestHeaders }); - }); - checkLogin(); - } - callback({ requestHeaders: request.requestHeaders }); - }); - - Settings.subDomain = ui.$subdomainField.val() ?? "www"; - - if (ui.$subdomainField.val()) { - udemyLoginWindow.loadURL(`https://${Settings.subDomain}.udemy.com`); - } else { - udemyLoginWindow.loadURL("https://www.udemy.com/join/login-popup"); - } + const $formLogin = $(".ui.login .form"); + + if ($formLogin.find('input[name="business"]').is(":checked")) { + if (!ui.$subdomainField.val()) { + showAlert("Type Business Name"); + return; + } + } else { + ui.$subdomainField.val(null); + } + + const parent = remote.getCurrentWindow(); + const dimensions = parent.getSize(); + const session = remote.session; + let udemyLoginWindow = new BrowserWindow({ + width: dimensions[0] - 100, + height: dimensions[1] - 100, + parent, + modal: true, + }); + + session.defaultSession.webRequest.onBeforeSendHeaders({ urls: ["*://*.udemy.com/*"] }, function (request, callback) { + const token = request.requestHeaders.Authorization + ? request.requestHeaders.Authorization.split(" ")[1] + : cookie.parse(request.requestHeaders.Cookie || "").access_token; + + if (token) { + Settings.accessToken = token; + Settings.subDomain = new URL(request.url).hostname.split(".")[0]; + + udemyLoginWindow.destroy(); + session.defaultSession.clearStorageData(); + session.defaultSession.webRequest.onBeforeSendHeaders({ urls: ["*://*.udemy.com/*"] }, function (request, callback) { + callback({ requestHeaders: request.requestHeaders }); + }); + checkLogin(); + } + callback({ requestHeaders: request.requestHeaders }); + }); + + Settings.subDomain = ui.$subdomainField.val() ?? "www"; + + if (ui.$subdomainField.val()) { + udemyLoginWindow.loadURL(`https://${Settings.subDomain}.udemy.com`); + } else { + udemyLoginWindow.loadURL("https://www.udemy.com/join/login-popup"); + } } function loginWithAccessToken() { - const $formLogin = $(".ui.login .form"); - - if ($formLogin.find('input[name="business"]').is(":checked")) { - if (!ui.$subdomainField.val()) { - showAlert("Type Business Name"); - return; - } - } else { - ui.$subdomainField.val("www"); - } - - dialogs.prompt("Access Token", (access_token) => { - if (access_token) { - const submain = ui.$subdomainField.val(); - Settings.accessToken = access_token; - Settings.subDomain = submain.trim().length == 0 ? "www" : submain.trim(); - - checkLogin(); - } - }); + const $formLogin = $(".ui.login .form"); + + if ($formLogin.find('input[name="business"]').is(":checked")) { + if (!ui.$subdomainField.val()) { + showAlert("Type Business Name"); + return; + } + } else { + ui.$subdomainField.val("www"); + } + + dialogs.prompt("Access Token", (access_token) => { + if (access_token) { + const submain = ui.$subdomainField.val(); + Settings.accessToken = access_token; + Settings.subDomain = submain.trim().length == 0 ? "www" : submain.trim(); + + checkLogin(); + } + }); } function createCourseElement(courseCache, downloadSection = false) { - courseCache.completed = courseCache.completed || false; - courseCache.infoDownloaded = ""; - courseCache.encryptedVideos = 0; - courseCache.pathDownloaded = ""; - courseCache.name = courseCache.name || courseCache.title; - - const history = Settings.downloadHistory.find((x) => Number(x.id) === Number(courseCache.id)); - if (history) { - courseCache.infoDownloaded = translate(history.completed ? "Download finished on" : "Download started since") + " " + history.date; - courseCache.completed = history.completed ? true : courseCache.completed; - courseCache.encryptedVideos = Math.max(courseCache.encryptedVideos, history.encryptedVideos); - courseCache.selectedSubtitle = history.selectedSubtitle ?? ""; - courseCache.pathDownloaded = history.pathDownloaded ?? ""; - } - - // Se o caminho não existir, obtenha o caminho de configurações de download para o título do curso - if (!fs.existsSync(courseCache.pathDownloaded)) - courseCache.pathDownloaded = Settings.downloadDirectory(sanitize(courseCache.name)); - - const tagDismiss = `   ${translate("Dismiss")}`; - - const $course = $(` + courseCache.completed = courseCache.completed || false; + courseCache.infoDownloaded = ""; + courseCache.encryptedVideos = 0; + courseCache.pathDownloaded = ""; + courseCache.name = courseCache.name || courseCache.title; + + const history = Settings.downloadHistory.find((x) => Number(x.id) === Number(courseCache.id)); + if (history) { + courseCache.infoDownloaded = translate(history.completed ? "Download finished on" : "Download started since") + " " + history.date; + courseCache.completed = history.completed ? true : courseCache.completed; + courseCache.encryptedVideos = Math.max(courseCache.encryptedVideos, history.encryptedVideos); + courseCache.selectedSubtitle = history.selectedSubtitle ?? ""; + courseCache.pathDownloaded = history.pathDownloaded ?? ""; + } + + // Se o caminho não existir, obtenha o caminho de configurações de download para o título do curso + if (!fs.existsSync(courseCache.pathDownloaded)) courseCache.pathDownloaded = Settings.downloadDirectory(sanitize(courseCache.name)); + + const tagDismiss = `   ${translate("Dismiss")}`; + + const $course = $(`
@@ -474,1301 +473,1309 @@ function createCourseElement(courseCache, downloadSection = false) {
`); - if (!downloadSection) { - if (courseCache.completed) { - resetCourse($course, $course.find(".download-success")); - } else if (courseCache.encryptedVideos > 0) { - resetCourse($course, $course.find(".course-encrypted")); - } else { - $course.find(".info-downloaded").html(courseCache.infoDownloaded).css("color", "#6d05e8").show(); - } - } else { - if (!courseCache.completed) { - $course.find(".individual.progress").progress("set percent", courseCache.individualProgress).css("display", "block"); - $course.find(".combined.progress").progress("set percent", courseCache.combinedProgress).css("display", "block"); - $course.find(".download-status .label").html(courseCache.progressStatus); - - $course.find(".info-downloaded").hide(); - // $course.css("padding-bottom", "25px"); - } else { - $course.find(".info-downloaded").html(courseCache.infoDownloaded) - .css("color", "#48ca56").show(); - } - } - - if (Number(courseCache.encryptedVideos) === 0) { - $course.find(".icon-encrypted").hide(); - $course.find(".ui.tiny.image .tooltip").hide(); - $course.find(".ui.tiny.image").removeClass("wrapper"); - } else { - $course.find(".icon-encrypted").show(); - $course.find(".ui.tiny.image .tooltip").show(); - $course.find(".ui.tiny.image").addClass("wrapper"); - } - - if (!fs.existsSync(courseCache.pathDownloaded)) { - $course.find(".open-dir.button").hide(); - } - - return $course; + if (!downloadSection) { + if (courseCache.completed) { + resetCourse($course, $course.find(".download-success")); + } else if (courseCache.encryptedVideos > 0) { + resetCourse($course, $course.find(".course-encrypted")); + } else { + $course.find(".info-downloaded").html(courseCache.infoDownloaded).css("color", "#6d05e8").show(); + } + } else { + if (!courseCache.completed) { + $course.find(".individual.progress").progress("set percent", courseCache.individualProgress).css("display", "block"); + $course.find(".combined.progress").progress("set percent", courseCache.combinedProgress).css("display", "block"); + $course.find(".download-status .label").html(courseCache.progressStatus); + + $course.find(".info-downloaded").hide(); + // $course.css("padding-bottom", "25px"); + } else { + $course.find(".info-downloaded").html(courseCache.infoDownloaded).css("color", "#48ca56").show(); + } + } + + if (Number(courseCache.encryptedVideos) === 0) { + $course.find(".icon-encrypted").hide(); + $course.find(".ui.tiny.image .tooltip").hide(); + $course.find(".ui.tiny.image").removeClass("wrapper"); + } else { + $course.find(".icon-encrypted").show(); + $course.find(".ui.tiny.image .tooltip").show(); + $course.find(".ui.tiny.image").addClass("wrapper"); + } + + if (!fs.existsSync(courseCache.pathDownloaded)) { + $course.find(".open-dir.button").hide(); + } + + return $course; } function resetCourse($course, $elMessage, autoRetry, courseData, subtitle) { - if ($elMessage.hasClass("download-success")) { - $course.attr("course-completed", true); - } else { - $course.attr("course-completed", ""); - - if ($elMessage.hasClass("download-error") && autoRetry && courseData) { - if (courseData.errorCount++ < 5) { - $course.length = 1; - startDownload($course, courseData, subtitle); - return; - } - } - } - - $course.find(".download-quality").hide(); - $course.find(".download-speed").hide().find(".value").html(0); - $course.find(".download-status").hide().html(ui.actionCardTemplate); - // $course.css("padding", "14px 0px"); - $elMessage.css("display", "flex"); - - if (Number($course.find("input[name='encryptedvideos']").val()) > 0) { - $course.find(".icon-encrypted").show(); - $course.find(".ui.tiny.image .tooltip").show(); - $course.find(".ui.tiny.image").addClass("wrapper"); - } + if ($elMessage.hasClass("download-success")) { + $course.attr("course-completed", true); + } else { + $course.attr("course-completed", ""); + + if ($elMessage.hasClass("download-error") && autoRetry && courseData) { + if (courseData.errorCount++ < 5) { + $course.length = 1; + startDownload($course, courseData, subtitle); + return; + } + } + } + + $course.find(".download-quality").hide(); + $course.find(".download-speed").hide().find(".value").html(0); + $course.find(".download-status").hide().html(ui.actionCardTemplate); + // $course.css("padding", "14px 0px"); + $elMessage.css("display", "flex"); + + if (Number($course.find("input[name='encryptedvideos']").val()) > 0) { + $course.find(".icon-encrypted").show(); + $course.find(".ui.tiny.image .tooltip").show(); + $course.find(".ui.tiny.image").addClass("wrapper"); + } } function renderCourses(response, isResearch = false) { - const $coursesSection = $(".ui.dashboard .ui.courses.section"); - const $coursesItems = $coursesSection.find(".ui.courses.items").empty(); - - $coursesSection.find(".disposable").remove(); - - if (response.results.length) { - // response.results.forEach(course => { - // $coursesItems.append(htmlCourseCard(course)); - // }); - const courseElements = response.results.map(course => createCourseElement(course)); - $coursesItems.append(courseElements); - - if (response.next) { - // added loadMore Button - $coursesSection.append( - `` - ); - } - - } else { - let msg = ""; - if (!isResearch) { - msg = getMsgChangeSearchMode(); - appendLog(translate("No Courses Found"), msg); - } - - $coursesItems.append( - `
+ ); + } + } else { + let msg = ""; + if (!isResearch) { + msg = getMsgChangeSearchMode(); + appendLog(translate("No Courses Found"), msg); + } + + $coursesItems.append( + `
${translate("No Courses Found")}
${translate("Remember, you will only be able to see the courses you are enrolled in")} ${msg}
` - ); - } - + ); + } } async function renderDownloads() { - const $downloadsSection = $(".ui.downloads.section .ui.courses.items"); - if ($downloadsSection.find(".ui.course.item").length) { - return; - } - - const downloadedCourses = Settings.downloadedCourses || []; - if (!downloadedCourses.length) { - // if ($downloadsSection.find(".ui.yellow.message").length) { - // return; - // } - // $downloadsSection.append( - // `
- // ${translate("There are no Downloads to display")} - //
` - // ); - } - else { - ui.busyLoadDownloads(true); - // await utils.sleep(10); - // // downloadedCourses.forEach(course => { - // downloadedCourses.map(course => { - // const $courseItem = htmlCourseCard(course, true); - // $downloadsSection.append($courseItem); - - // if (!course.completed && Settings.download.autoStartDownload) { - // initializeDownload($courseItem, course.selectedSubtitle); - // // $courseItem.find(".action.buttons").find(".pause.button").removeClass("disabled"); - // } - // }); - // ui.busyLoadDownloads(false); - - function addCourseToDOM(course) { - return new Promise((resolve, _reject) => { - const $courseItem = createCourseElement(course, true); - $downloadsSection.append($courseItem); - - if (!course.completed && Settings.download.autoStartDownload) { - prepareDownloading($courseItem, course.selectedSubtitle); - } - - // Simula atraso de 200ms para demonstração - // setTimeout(() => { resolve(); }, 200); - resolve(); - }); - } - - const promises = downloadedCourses.map(course => addCourseToDOM(course)); - - // Executa todas as Promessas em paralelo - Promise.all(promises) - .then(() => ui.busyLoadDownloads(false)) - .catch(e => { - console.error("Error adding courses:", e); - ui.busyLoadDownloads(false); - }); - - } + const $downloadsSection = $(".ui.downloads.section .ui.courses.items"); + if ($downloadsSection.find(".ui.course.item").length) { + return; + } + + const downloadedCourses = Settings.downloadedCourses || []; + if (!downloadedCourses.length) { + // if ($downloadsSection.find(".ui.yellow.message").length) { + // return; + // } + // $downloadsSection.append( + // `
+ // ${translate("There are no Downloads to display")} + //
` + // ); + } else { + ui.busyLoadDownloads(true); + // await utils.sleep(10); + // // downloadedCourses.forEach(course => { + // downloadedCourses.map(course => { + // const $courseItem = htmlCourseCard(course, true); + // $downloadsSection.append($courseItem); + + // if (!course.completed && Settings.download.autoStartDownload) { + // initializeDownload($courseItem, course.selectedSubtitle); + // // $courseItem.find(".action.buttons").find(".pause.button").removeClass("disabled"); + // } + // }); + // ui.busyLoadDownloads(false); + + function addCourseToDOM(course) { + return new Promise((resolve, _reject) => { + const $courseItem = createCourseElement(course, true); + $downloadsSection.append($courseItem); + + if (!course.completed && Settings.download.autoStartDownload) { + prepareDownloading($courseItem, course.selectedSubtitle); + } + + // Simula atraso de 200ms para demonstração + // setTimeout(() => { resolve(); }, 200); + resolve(); + }); + } + + const promises = downloadedCourses.map((course) => addCourseToDOM(course)); + + // Executa todas as Promessas em paralelo + Promise.all(promises) + .then(() => ui.busyLoadDownloads(false)) + .catch((e) => { + console.trace("Error adding courses:", e); + ui.busyLoadDownloads(false); + }); + } } async function fetchCourseContent(courseId, courseName, courseUrl) { - try { - // ui.busyBuildCourseData(true); - - const response = await udemyService.fetchCourseContent(courseId, "all") - if (!response) { - // ui.busyBuildCourseData(false); - showAlert(`Id: ${courseId}`, translate("Course not found")); - return null; - } - console.log(`fetchCourseContent (${courseId})`, response); - - const downloadType = Number(Settings.download.type); - const downloadAttachments = downloadType === Settings.DownloadType.Both || downloadType === Settings.DownloadType.OnlyAttachments; - - const courseData = { - id: courseId, - name: courseName, - chapters: [], - totalLectures: 0, - encryptedVideos: 0, - errorCount: 0, - availableSubs: [], - }; - - let chapterData = null; - response.results.forEach((item) => { - const type = item._class.toLowerCase(); - if (type == "chapter") { - if (chapterData) { - courseData.chapters.push(chapterData); - } - chapterData = { id: item.id, name: item.title.trim(), lectures: [] }; - } - else if (type == "quiz" || type == "practice") { - const srcUrl = `${courseUrl}t/${item._class}/${item.id}`; - - chapterData.lectures.push({ - type: "url", - name: item.title, - src: ``, - quality: "Attachment", - }); - courseData.totalLectures++; - } - else { - const lecture = { type, name: item.title, src: "", quality: Settings.download.videoQuality, isEncrypted: false }; - const { asset, supplementary_assets } = item; - const assetType = asset.asset_type.toLowerCase(); - - if (assetType == "article") { - lecture.type = "article"; - lecture.quality = asset.asset_type; - lecture.src = asset.data?.body ?? asset.body; - } else if (assetType == "file" || assetType == "e-book") { - lecture.type = "file"; - lecture.quality = asset.asset_type; - lecture.src = asset.download_urls[asset.asset_type][0].file; - } else if (assetType == "presentation") { - lecture.type = "file"; - lecture.quality = asset.asset_type; - lecture.src = asset.url_set[asset.asset_type][0].file; - } else if(assetType.startsWith("video")) { - const streams = asset.streams; - switch (lecture.quality.toLowerCase()) { - case "auto": - case "highest": - lecture.quality = streams.maxQuality; - break; - case "lowest": - lecture.quality = streams.minQuality; - break; - default: - lecture.quality = utils.isNumber(lecture.quality) ? lecture.quality : lecture.quality.slice(0, -1); - } - - if (!streams.sources[lecture.quality]) { - if (utils.isNumber(lecture.quality) && streams.maxQuality != "auto") { - const source = utils.getClosestValue(streams.sources, lecture.quality); - lecture.quality = source?.key || streams.maxQuality; - } - else { - lecture.quality = streams.maxQuality; - } - } - lecture.src = streams.sources[lecture.quality].url; - lecture.type = streams.sources[lecture.quality].type; - if (streams.isEncrypted) { - lecture.isEncrypted = true; - courseData.encryptedVideos++; - } - } else { - appendLog("Unknown Asset Type ", `type: ${assetType}`, `Course: ${courseId}|${courseName}`); - } - - if (!Settings.download.skipSubtitles && asset.captions.length > 0) { - lecture.subtitles = {}; - - asset.captions.forEach((caption) => { - caption.video_label in courseData.availableSubs - ? (courseData.availableSubs[caption.video_label] = courseData.availableSubs[caption.video_label] + 1) - : (courseData.availableSubs[caption.video_label] = 1); - - lecture.subtitles[caption.video_label] = caption.url; - }); - } - - if (downloadAttachments && supplementary_assets.length > 0) { - const attachments = lecture.attachments = []; - - supplementary_assets.forEach((attachment) => { - const type = attachment.download_urls ? "file" : "url"; - const src = attachment.download_urls - ? attachment.download_urls[attachment.asset_type][0].file - : ``; - - attachments.push({ type, name: attachment.title, src, quality: "Attachment" }); - }); - } - - chapterData.lectures.push(lecture); - courseData.totalLectures++; - } - }); - - if (chapterData) { - courseData.chapters.push(chapterData); - } - - // ui.busyBuildingCourseData(false); - return courseData; - } catch (error) { - handleApiError(error, "EBUILDING_COURSE_DATA", courseName, true); - } + try { + // ui.busyBuildCourseData(true); + + const response = await udemyService.fetchCourseContent(courseId, "all"); + if (!response) { + // ui.busyBuildCourseData(false); + showAlert(`Id: ${courseId}`, translate("Course not found")); + return null; + } + console.log(`fetchCourseContent (${courseId})`, response); + + const downloadType = Number(Settings.download.type); + const downloadAttachments = downloadType === Settings.DownloadType.Both || downloadType === Settings.DownloadType.OnlyAttachments; + + const courseData = { + id: courseId, + name: courseName, + chapters: [], + totalLectures: 0, + encryptedVideos: 0, + errorCount: 0, + availableSubs: [], + }; + + let chapterData = null; + response.results.forEach((item) => { + const type = item._class.toLowerCase(); + if (type == "chapter") { + if (chapterData) { + courseData.chapters.push(chapterData); + } + chapterData = { id: item.id, name: item.title.trim(), lectures: [] }; + } else if (type == "quiz" || type == "practice") { + const srcUrl = `${courseUrl}t/${item._class}/${item.id}`; + + chapterData.lectures.push({ + type: "url", + name: item.title, + src: ``, + quality: "Attachment", + }); + courseData.totalLectures++; + } else { + const lecture = { type, name: item.title, src: "", quality: Settings.download.videoQuality, isEncrypted: false }; + const { asset, supplementary_assets } = item; + const assetType = asset.asset_type.toLowerCase(); + + if (assetType == "article") { + lecture.type = "article"; + lecture.quality = asset.asset_type; + lecture.src = asset.data?.body ?? asset.body; + } else if (assetType == "file" || assetType == "e-book") { + lecture.type = "file"; + lecture.quality = asset.asset_type; + lecture.src = asset.download_urls[asset.asset_type][0].file; + } else if (assetType == "presentation") { + lecture.type = "file"; + lecture.quality = asset.asset_type; + lecture.src = asset.url_set[asset.asset_type][0].file; + } else if (assetType.startsWith("video")) { + const streams = asset.streams; + + if (!streams.minQuality) { + //WARN: File not uploaded + lecture.type = "url"; + lecture.quality = "NotFound"; + lecture.src = ``; + appendLog("File not uploaded", `Course: ${courseId}|${courseName}`, `Lecture: ${item.id}|${item.title}`); + } else { + switch (lecture.quality.toLowerCase()) { + case "auto": + case "highest": + lecture.quality = streams.maxQuality; + break; + case "lowest": + lecture.quality = streams.minQuality; + break; + default: + lecture.quality = utils.isNumber(lecture.quality) ? lecture.quality : lecture.quality.slice(0, -1); + } + + if (!streams.sources[lecture.quality]) { + if (utils.isNumber(lecture.quality) && streams.maxQuality != "auto") { + const source = utils.getClosestValue(streams.sources, lecture.quality); + lecture.quality = source?.key || streams.maxQuality; + } else { + lecture.quality = streams.maxQuality; + } + } + + lecture.src = streams.sources[lecture.quality].url; + lecture.type = streams.sources[lecture.quality].type; + if (streams.isEncrypted) { + lecture.isEncrypted = true; + courseData.encryptedVideos++; + } + } + } else { + appendLog("Unknown Asset Type ", `type: ${assetType}`, `Course: ${courseId}|${courseName}`); + } + + if (!Settings.download.skipSubtitles && asset.captions.length > 0) { + lecture.subtitles = {}; + + asset.captions.forEach((caption) => { + caption.video_label in courseData.availableSubs + ? (courseData.availableSubs[caption.video_label] = courseData.availableSubs[caption.video_label] + 1) + : (courseData.availableSubs[caption.video_label] = 1); + + lecture.subtitles[caption.video_label] = caption.url; + }); + } + + if (downloadAttachments && supplementary_assets.length > 0) { + const attachments = (lecture.attachments = []); + + supplementary_assets.forEach((attachment) => { + const type = attachment.download_urls ? "file" : "url"; + const src = attachment.download_urls + ? attachment.download_urls[attachment.asset_type][0].file + : ``; + + attachments.push({ type, name: attachment.title, src, quality: "Attachment" }); + }); + } + + chapterData.lectures.push(lecture); + courseData.totalLectures++; + } + }); + + if (chapterData) { + courseData.chapters.push(chapterData); + } + + // ui.busyBuildingCourseData(false); + return courseData; + } catch (error) { + handleApiError(error, "EBUILDING_COURSE_DATA", courseName, true); + } } async function fetchCourses(isSubscriber) { - ui.busyLoadCourses(true); - - udemyService.fetchCourses(PAGE_SIZE, isSubscriber) - .then(resp => { - renderCourses(resp); - if (Settings.downloadedCourses) { - renderDownloads(); - } - }) - .catch(e => { - handleApiError(e, "EFETCHING_COURSES"); - }) - .finally(() => { - ui.busyLoadCourses(false); - }); + ui.busyLoadCourses(true); + + udemyService + .fetchCourses(PAGE_SIZE, isSubscriber) + .then((resp) => { + renderCourses(resp); + if (Settings.downloadedCourses) { + renderDownloads(); + } + }) + .catch((e) => { + handleApiError(e, "EFETCHING_COURSES"); + }) + .finally(() => { + ui.busyLoadCourses(false); + }); } function loadMore(loadMoreButton) { - const $button = $(loadMoreButton); - const $courses = $button.prev(".courses.items"); - const url = $button.data("url"); - - ui.busyLoadCourses(true); - udemyService.fetchLoadMore(url) - .then(resp => { - $courses.append(...resp.results.map(createCourseElement)); - if (!resp.next) { - $button.remove(); - } else { - $button.data("url", resp.next); - } - }).catch(e => { - const statusCode = (e.response?.status || 0).toString() + (e.code ? ` :${e.code}` : ""); - appendLog(`ELOADING_MORE: (${statusCode})`, e); - }).finally(() => { - ui.busyLoadCourses(false); - }); + const $button = $(loadMoreButton); + const $courses = $button.prev(".courses.items"); + const url = $button.data("url"); + + ui.busyLoadCourses(true); + udemyService + .fetchLoadMore(url) + .then((resp) => { + $courses.append(...resp.results.map((course) => createCourseElement(course, false))); + if (!resp.next) { + $button.remove(); + } else { + $button.data("url", resp.next); + } + }) + .catch((e) => { + const statusCode = (e.response?.status || 0).toString() + (e.code ? ` :${e.code}` : ""); + appendLog(`ELOADING_MORE: (${statusCode})`, e); + }) + .finally(() => { + ui.busyLoadCourses(false); + }); } async function search(keyword) { - ui.busyLoadCourses(true); - - try { - const courses = await udemyService.fetchSearchCourses(keyword, PAGE_SIZE, Settings.subscriber); - renderCourses(courses, !!keyword); - } catch (error) { - handleApiError(error, "ESEARCHING_COURSES", null, false); - } finally { - ui.busyLoadCourses(false); - } + ui.busyLoadCourses(true); + + try { + const courses = await udemyService.fetchSearchCourses(keyword, PAGE_SIZE, Settings.subscriber); + renderCourses(courses, !!keyword); + } catch (error) { + handleApiError(error, "ESEARCHING_COURSES", null, false); + } finally { + ui.busyLoadCourses(false); + } } function getMsgChangeSearchMode() { - const msg = Settings.subscriber - ? translate("This account has been identified with a subscription plan") - : translate("This account was identified without a subscription plan"); + const msg = Settings.subscriber + ? translate("This account has been identified with a subscription plan") + : translate("This account was identified without a subscription plan"); - const button = ` + const button = `
`; - return `

${msg}
${translate("If it's wrong, change the search mode and try again")}${button}

`; + return `

${msg}
${translate("If it's wrong, change the search mode and try again")}${button}

`; } /** * Toggles the subscriber setting and clears the search field. */ function toggleSubscriber() { - Settings.subscriber = !Settings.subscriber; - search(""); + Settings.subscriber = !Settings.subscriber; + search(""); } function addDownloadHistory(courseId, courseName, completed = false, encryptedVideos = 0, selectedSubtitle = "", pathDownloaded = "") { - courseId = Number(courseId); - courseName = String(courseName) || ""; - completed = Boolean(completed); - encryptedVideos = Number(encryptedVideos); - selectedSubtitle = String(selectedSubtitle) || ""; - pathDownloaded = String(pathDownloaded) || ""; - - const items = Settings.downloadHistory; - const index = items.findIndex((x) => Number(x.id) === courseId); - - if (index !== -1) { - const item = items[index]; - item.id = courseId; - item.name = courseName; - if (completed !== Boolean(item.completed)) { - item.completed = completed; - item.date = new Date(Date.now()).toLocaleDateString(); - } - item.encryptedVideos = encryptedVideos; - item.selectedSubtitle = selectedSubtitle; - item.pathDownloaded = pathDownloaded; - } else { - items.push({ - id: courseId, - name: courseName, - completed, - date: new Date(Date.now()).toLocaleDateString(), - encryptedVideos, - selectedSubtitle, - pathDownloaded, - }); - } - - Settings.downloadHistory = items; + courseId = Number(courseId); + courseName = String(courseName) || ""; + completed = Boolean(completed); + encryptedVideos = Number(encryptedVideos); + selectedSubtitle = String(selectedSubtitle) || ""; + pathDownloaded = String(pathDownloaded) || ""; + + const items = Settings.downloadHistory; + const index = items.findIndex((x) => Number(x.id) === courseId); + + if (index !== -1) { + const item = items[index]; + item.id = courseId; + item.name = courseName; + if (completed !== Boolean(item.completed)) { + item.completed = completed; + item.date = new Date(Date.now()).toLocaleDateString(); + } + item.encryptedVideos = encryptedVideos; + item.selectedSubtitle = selectedSubtitle; + item.pathDownloaded = pathDownloaded; + } else { + items.push({ + id: courseId, + name: courseName, + completed, + date: new Date(Date.now()).toLocaleDateString(), + encryptedVideos, + selectedSubtitle, + pathDownloaded, + }); + } + + Settings.downloadHistory = items; } function getDownloadHistory(courseId) { - return Settings.downloadHistory.find((x) => x.id === courseId) || undefined; + return Settings.downloadHistory.find((x) => x.id === courseId) || undefined; } function saveDownloads(shouldQuitApp) { - ui.busySavingHistory(true); - - function getProgress($progress) { - const dataPercent = $progress.attr("data-percent"); - return parseInt(dataPercent, 10); - } - - const downloadedCourses = []; - const downloads = $(".ui.downloads.section .ui.courses.items .ui.course.item"); - - downloads.each((_index, element) => { - const $el = $(element); - const hasProgress = $el.find(".progress.active").length > 0; - const individualProgress = hasProgress ? getProgress($el.find(".download-status .individual.progress")) : 0; - const combinedProgress = hasProgress ? getProgress($el.find(".download-status .combined.progress")) : 0; - const isCompleted = !hasProgress && $el.attr("course-completed") === "true"; - - const courseData = { - id: Number($el.attr("course-id")), - url: $el.attr("course-url"), - name: $el.find(".coursename").text(), - image: $el.find(".image img").attr("src"), - individualProgress: Math.min(100, individualProgress), - combinedProgress: Math.min(100, combinedProgress), - completed: isCompleted, - progressStatus: $el.find(".download-status .label").text(), - encryptedVideos: Number($el.find('input[name="encryptedvideos"]').val()), - selectedSubtitle: $el.find('input[name="selectedSubtitle"]').val(), - pathDownloaded: $el.find('input[name="path-downloaded"]').val(), - }; - - downloadedCourses.push(courseData); - addDownloadHistory( - courseData.id, - courseData.name, - courseData.completed, - courseData.encryptedVideos, - courseData.selectedSubtitle, - courseData.pathDownloaded - ); - }); - - Settings.downloadedCourses = downloadedCourses.sort((a, b) => { - if (a.completed === b.completed) { - return b.combinedProgress - a.combinedProgress; - } - return a.completed ? 1 : -1; - }); - - if (shouldQuitApp) { - ipcRenderer.send("quitApp"); - } else { - ui.busySavingHistory(false); - } + ui.busySavingHistory(true); + + function getProgress($progress) { + const dataPercent = $progress.attr("data-percent"); + return parseInt(dataPercent, 10); + } + + const downloadedCourses = []; + const downloads = $(".ui.downloads.section .ui.courses.items .ui.course.item"); + + downloads.each((_index, element) => { + const $el = $(element); + const hasProgress = $el.find(".progress.active").length > 0; + const individualProgress = hasProgress ? getProgress($el.find(".download-status .individual.progress")) : 0; + const combinedProgress = hasProgress ? getProgress($el.find(".download-status .combined.progress")) : 0; + const isCompleted = !hasProgress && $el.attr("course-completed") === "true"; + + const courseData = { + id: Number($el.attr("course-id")), + url: $el.attr("course-url"), + name: $el.find(".coursename").text(), + image: $el.find(".image img").attr("src"), + individualProgress: Math.min(100, individualProgress), + combinedProgress: Math.min(100, combinedProgress), + completed: isCompleted, + progressStatus: $el.find(".download-status .label").text(), + encryptedVideos: Number($el.find('input[name="encryptedvideos"]').val()), + selectedSubtitle: $el.find('input[name="selectedSubtitle"]').val(), + pathDownloaded: $el.find('input[name="path-downloaded"]').val(), + }; + + downloadedCourses.push(courseData); + addDownloadHistory( + courseData.id, + courseData.name, + courseData.completed, + courseData.encryptedVideos, + courseData.selectedSubtitle, + courseData.pathDownloaded + ); + }); + + Settings.downloadedCourses = downloadedCourses.sort((a, b) => { + if (a.completed === b.completed) { + return b.combinedProgress - a.combinedProgress; + } + return a.completed ? 1 : -1; + }); + + if (shouldQuitApp) { + ipcRenderer.send("quitApp"); + } else { + ui.busySavingHistory(false); + } } function removeCurseDownloads(courseId) { - const $downloads = $(".ui.downloads.section .ui.courses.items .ui.course.item"); //.slice(0); - - $downloads.each((_index, element) => { - const $el = $(element); - if ($el.attr("course-id") == courseId) { - $el.remove(); - } - }); + const $downloads = $(".ui.downloads.section .ui.courses.items .ui.course.item"); //.slice(0); + + $downloads.each((_index, element) => { + const $el = $(element); + if ($el.attr("course-id") == courseId) { + $el.remove(); + } + }); } async function prepareDownloading($course, subtitle) { - ui.prepareDownloading($course); - ui.showProgress($course, true); - - const courseId = $course.attr("course-id"); - const courseName = $course.find(".coursename").text(); - const courseUrl = `https://${Settings.subDomain}.udemy.com${$course.attr("course-url")}`; - - const skipSubtitles = Boolean(Settings.download.skipSubtitles); - const defaultSubtitle = skipSubtitles ? null : subtitle ?? Settings.download.defaultSubtitle; - - console.clear(); - - let courseData = null; - try { - courseData = await fetchCourseContent(courseId, courseName, courseUrl); - if (!courseData) { - ui.showProgress($course, false); - return; - } - - if (courseData.encryptedVideos > 0 && !Settings.download.continueDonwloadingEncrypted) { - resetCourse($course, $course.find(".course-encrypted")); - return; - } - - try { - console.log("Downloading", courseData); - askForSubtitle(courseData.availableSubs, courseData.totalLectures, defaultSubtitle, (subtitle) => { - startDownload($course, courseData, subtitle); - }); - } catch (error) { - throw utils.newError("EASK_FOR_SUBTITLE", error.message); - } - - } catch (error) { - const errorName = error.name === "EASK_FOR_SUBTITLE" ? error.name : "EPREPARE_DOWNLOADING"; - handleApiError(error, errorName, null, false); - ui.busyOff(); - - resetCourse($course, $course.find(".download-error"), Settings.download.autoRetry, courseData, subtitle); - } + ui.prepareDownloading($course); + // ui.showProgress($course, true); + + const courseId = $course.attr("course-id"); + const courseName = $course.find(".coursename").text(); + const courseUrl = `https://${Settings.subDomain}.udemy.com${$course.attr("course-url")}`; + + const skipSubtitles = Boolean(Settings.download.skipSubtitles); + const defaultSubtitle = skipSubtitles ? null : (subtitle ?? Settings.download.defaultSubtitle); + + console.clear(); + + let courseData = null; + try { + courseData = await fetchCourseContent(courseId, courseName, courseUrl); + if (!courseData) { + ui.showProgress($course, false); + return; + } + + if (courseData.encryptedVideos > 0 && !Settings.download.continueDonwloadingEncrypted) { + resetCourse($course, $course.find(".course-encrypted")); + return; + } + + try { + console.log("Downloading", courseData); + askForSubtitle(courseData.availableSubs, courseData.totalLectures, defaultSubtitle, (subtitle) => { + startDownload($course, courseData, subtitle); + }); + } catch (error) { + throw utils.newError("EASK_FOR_SUBTITLE", error.message); + } + } catch (error) { + const errorName = error.name === "EASK_FOR_SUBTITLE" ? error.name : "EPREPARE_DOWNLOADING"; + handleApiError(error, errorName, null, false); + ui.busyOff(); + $course.find(".prepare-downloading").hide(); + resetCourse($course, $course.find(".download-error"), Settings.download.autoRetry, courseData, subtitle); + } } function startDownload($course, courseData, subTitle = "") { - ui.showProgress($course, true); - - const subtitle = (Array.isArray(subTitle) ? subTitle[0] : subTitle).split("|"); - $course.find(".info-downloaded").hide(); - $course.find('input[name="selectedSubtitle"]').val(subtitle); - $course.find('input[name="encryptedvideos"]').val(courseData.encryptedVideos); - - const $clone = $course.clone(); - const $downloads = $(".ui.downloads.section .ui.courses.items"); - const $courses = $(".ui.courses.section .ui.courses.items"); - - if ($course.parents(".courses.section").length) { - const $downloadItem = $downloads.find("[course-id=" + $course.attr("course-id") + "]"); - if ($downloadItem.length) { - $downloadItem.replaceWith($clone); - } else { - $downloads.prepend($clone); - } - } else { - const $courseItem = $courses.find("[course-id=" + $course.attr("course-id") + "]"); - if ($courseItem.length) { - $courseItem.replaceWith($clone); - } - } - $course.push($clone[0]); - - const courseName = sanitize(courseData["name"]); //, { replacement: (s) => "? ".indexOf(s) > -1 ? "" : "-", }).trim(); - const $progressCombined = $course.find(".combined.progress"); - const $progressIndividual = $course.find(".individual.progress"); - - const $downloadSpeed = $course.find(".download-speed"); - const $downloadSpeedValue = $downloadSpeed.find(".value"); - const $downloadSpeedUnit = $downloadSpeed.find(".download-unit"); - const $downloadQuality = $course.find(".download-quality"); - - const downloadDirectory = Settings.downloadDirectory(); - $course.find('input[name="path-downloaded"]').val(`${downloadDirectory}/${courseName}`); - $course.find(".open-dir.button").show(); - // $course.css("cssText", "padding-top: 35px !important").css("padding-bottom", "25px"); - - const $actionButtons = $course.find(".action.buttons"); - const $downloadButton = $actionButtons.find(".download.button"); - const $pauseButton = $actionButtons.find(".pause.button"); - const $resumeButton = $actionButtons.find(".resume.button"); - - $downloadButton.addClass("disabled"); - $pauseButton.removeClass("disabled"); - $resumeButton.addClass("disabled"); - - $pauseButton.click(() => stopDownload()); - $resumeButton.click(() => resumeDownload()); - - let timerDownloader = null; - const downloader = new Downloader(); - - const lectureChapterMap = {}; - let sequenceMap = 0; - courseData.chapters.forEach((chapter, chapterIndex) => { - chapter.lectures.forEach((_lecture, lectureIndex) => { - sequenceMap++; - lectureChapterMap[sequenceMap] = { chapterIndex, lectureIndex }; - }); - }); - - const labelColorMap = { - 144: "brown", - 240: "purple", - 360: "yellow", - 432: "orange", - 480: "teal", - 576: "blue", - 720: "olive", - 1080: "green", - Highest: "green", - auto: "red", - Auto: "red", - Attachment: "pink", - Subtitle: "black", - }; - - let downloaded = 0; - let toDownload = courseData["totalLectures"]; - - const enableDownloadStartEnd = Settings.download.enableDownloadStartEnd; - if (enableDownloadStartEnd) { - let downloadStart = Math.max(1, Math.min(Settings.download.downloadStart, toDownload)); - let downloadEnd = Math.max(0, Settings.download.downloadEnd); - downloadEnd = Math.max(downloadStart, (downloadEnd == 0 ? toDownload : downloadEnd)); - - toDownload = downloadEnd - downloadStart + 1; - downloadChapter(lectureChapterMap[downloadStart].chapterIndex, lectureChapterMap[downloadStart].lectureIndex); - } else { - downloadChapter(0, 0); - } - - $progressCombined.progress({ - total: toDownload, - text: { - active: `${translate("Downloaded")} {value} ${translate("out of")} {total} ${translate("items")}`, - }, - }); - - $progressCombined.progress("reset"); - $downloadSpeed.show(); - $downloadQuality.show(); - - function stopDownload(isEncrypted) { - if (downloader._downloads?.length) { - downloader._downloads[downloader._downloads.length - 1].stop(); - $pauseButton.addClass("disabled"); - $resumeButton.removeClass("disabled"); - - if (isEncrypted) { - resetCourse($course, $course.find(".course-encrypted")); - } - } - } - - function resumeDownload() { - if (downloader._downloads?.length) { - downloader._downloads[downloader._downloads.length - 1].resume(); - $pauseButton.removeClass("disabled"); - $resumeButton.addClass("disabled"); - } - } - - function setLabelQuality(label) { - const lastClass = $downloadQuality.attr("class").split(" ").pop(); - $downloadQuality - .html(label.toString() + (!isNaN(parseFloat(label)) ? "p" : "")) - .removeClass(lastClass) - .addClass(labelColorMap[label] || "grey"); - } - - function downloadChapter(chapterIndex, lectureIndex) { - try { - const countLectures = courseData.chapters[chapterIndex].lectures.length; - const seqName = utils.getSequenceName( - chapterIndex + 1, - courseData.chapters.length, - sanitize(courseData.chapters[chapterIndex].name.trim()), - ". ", - downloadDirectory + "/" + courseName - ); - - fs.mkdirSync(seqName.fullPath, { recursive: true }); - downloadLecture(chapterIndex, lectureIndex, countLectures, seqName.name); - } catch (error) { - handleApiError(error, "EDOWNLOADING_CHAPTER", null, false); - resetCourse($course, $course.find(".download-error"), false, courseData); - } - } - - function downloadLecture(chapterIndex, lectureIndex, countLectures, sanitizedChapterName) { - try { - if (downloaded == toDownload) { - resetCourse($course, $course.find(".download-success")); - sendNotification( - downloadDirectory + "/" + courseName, - courseName, - $course.find(".ui.tiny.image").find(".course-image").attr("src") - ); - return; - } else if (lectureIndex == countLectures) { - downloadChapter(++chapterIndex, 0); - return; - } - - const chapterName = courseData.chapters[chapterIndex].name.trim(); - const lectureData = courseData.chapters[chapterIndex].lectures[lectureIndex]; - const lectureType = lectureData.type.toLowerCase(); - const lectureName = lectureData.name.trim(); - const sanitizedLectureName = sanitize(lectureName); - - function dlStart(dl, typeVideo, callback) { - // Change retry options to something more forgiving and threads to keep udemy from getting upset - dl.setRetryOptions({ - maxRetries: 3, // Default: 5 - retryInterval: 3000, // Default: 2000 - }); - - // Set download options - dl.setOptions({ - threadsCount: 5, // Default: 2, Set the total number of download threads - timeout: 5000, // Default: 5000, If no data is received, the download times out (milliseconds) - range: "0-100", // Default: 0-100, Control the part of file that needs to be downloaded. - }); - - dl.start(); - // To track time and restarts - let notStarted = 0; - let reStarted = 0; - - timerDownloader = setInterval(function () { - // Status: - // -3 = destroyed - // -2 = stopped - // -1 = error - // 0 = not started - // 1 = started (downloading) - // 2 = error, retrying - // 3 = finished - switch (dl.status) { - case 0: - // Wait a reasonable amount of time for the download to start and if it doesn't then start another one. - // once one of them starts the errors from the others will be ignored and we still get the file. - if (reStarted <= 5) { - notStarted++; - if (notStarted >= 15) { - dl.start(); - notStarted = 0; - reStarted++; - } - } - $downloadSpeedValue.html(0); - break; - - case 1: - case -1: - const stats = dl.getStats(); - const speedAndUnit = utils.getDownloadSpeed(stats.present.speed || 0); - $downloadSpeedValue.html(speedAndUnit.value); - $downloadSpeedUnit.html(speedAndUnit.unit); - // console.log(`dl~stats.present.speed: ${stats.present.speed}`); - // console.log(`Download speed: ${speedAndUnit.value}${speedAndUnit.unit}`); - $progressIndividual.progress("set percent", stats.total.completed); - - if (dl.status === -1 && dl.stats.total.size == 0 && fs.existsSync(dl.filePath)) { - dl.emit("end"); - clearInterval(timerDownloader); - } else if (dl.status === -1) { - appendLog("Download error, retrying... ", { url: dl.url }) - axios({ - timeout: HTTP_TIMEOUT, - type: "HEAD", - url: dl.url, - }).then(() => { - resetCourse($course, $course.find(".download-error"), Settings.download.autoRetry, courseData, subtitle); - }).catch((error) => { - handleApiError(error, "EDL_DOWNLOADING_LECTURE", courseData.name, false); - - try { - if (statusCode == 401 || statusCode == 403) { - fs.unlinkSync(dl.filePath); - } - } finally { - resetCourse($course, $course.find(".download-error"), Settings.download.autoRetry, courseData, subtitle); - } - }); - - clearInterval(timerDownloader); - } - break; - - case 2: - case -3: - break; - default: - $downloadSpeedValue.html(0); - } - }, 1000); - - dl.on("error", function (dl) { - console.error("dl.on(error)", dl.error.message); - if (hasDRMProtection(dl)) { - dl.emit("end"); - } else { - appendLog("DL_ONERROR", dl.error.message); - } - }); - - dl.on("start", function () { - // console.log("dl.on(start)", dl.filePath.split("/").slice(-2).join("/")); - $pauseButton.removeClass("disabled"); - }); - - dl.on("stop", function () { - console.warn("dl.on(stop)"); - }); - - dl.on("end", function () { - // console.log("dl.on(end)", { path: dl.filePath, typeVideo }); - if (typeVideo && hasDRMProtection(dl)) { - $course.find('input[name="encryptedvideos"]').val(++courseData.encryptedVideos); - - appendLog(`DRM Protected::${courseData.name}`, dl.filePath); - fs.unlink(dl.filePath + ".mtd", (err) => { - if (err) { - console.error("dl.on(end)__fs.unlink", err.message); - } - }); - - if (!Settings.download.continueDonwloadingEncrypted) { - dl.destroy(); - stopDownload(true); - clearInterval(timerDownloader); - return; - } - } - callback(); - }); - } - - function downloadAttachments(index, totalAttachments) { - $progressIndividual.progress("reset"); - - const attachment = lectureData.attachments[index]; - const attachmentName = attachment.name.trim(); - - setLabelQuality(attachment.quality); - - if (["article", "url"].includes(attachment.type)) { - const wfDir = downloadDirectory + "/" + courseName + "/" + sanitizedChapterName; - fs.writeFile( - utils.getSequenceName(lectureIndex + 1, countLectures, attachmentName + ".html", `.${index + 1} `, wfDir).fullPath, - attachment.src, - function () { - index++; - if (index == totalAttachments) { - $progressCombined.progress("increment"); - downloaded++; - downloadLecture(chapterIndex, ++lectureIndex, countLectures, sanitizedChapterName); - } else { - downloadAttachments(index, totalAttachments); - } - } - ); - } else { - let fileExtension = attachment.src.split("/").pop().split("?").shift().split(".").pop(); - fileExtension = attachment.name.split(".").pop() == fileExtension ? "" : "." + fileExtension; - - const lectureSeqName = utils.getSequenceName( - lectureIndex + 1, - countLectures, - sanitize(attachmentName) + fileExtension, - `.${index + 1} `, - `${downloadDirectory}/${courseName}/${sanitizedChapterName}` - ); - - // try deleting the download started without data - if (fs.existsSync(lectureSeqName.fullPath + ".mtd") && !fs.statSync(lectureSeqName.fullPath + ".mtd").size) { - fs.unlinkSync(lectureSeqName.fullPath + ".mtd"); - } - - if (fs.existsSync(lectureSeqName.fullPath + ".mtd")) { - var dl = downloader.resumeDownload(lectureSeqName.fullPath); - } else if (fs.existsSync(lectureSeqName.fullPath)) { - endDownload(); - return; - } else { - var dl = downloader.download(attachment.src, lectureSeqName.fullPath); - } - - dlStart(dl, attachment.type.includes("video"), endDownload); - - function endDownload() { - index++; - - clearInterval(timerDownloader); - if (index == totalAttachments) { - $progressCombined.progress("increment"); - downloaded++; - downloadLecture(chapterIndex, ++lectureIndex, countLectures, sanitizedChapterName); - } else { - downloadAttachments(index, totalAttachments); - } - } - } - } - - function checkAttachment() { - $progressIndividual.progress("reset"); - const attachment = lectureData.attachments; - - if (attachment) { - lectureData.attachments.sort(utils.dynamicSort("name")); - downloadAttachments(0, attachment.length); - } - else { - if (lectureData.isEncrypted) { - appendLog("Video with DRM Protection", `Chapter: ${chapterName}\nLecture: ${lectureName}`); - } - $progressCombined.progress("increment"); - downloaded++; - downloadLecture(chapterIndex, ++lectureIndex, countLectures, sanitizedChapterName); - } - - } - - function downloadSubtitle() { - $progressIndividual.progress("reset"); - - setLabelQuality("Subtitle"); - $downloadSpeedValue.html(0); - - const subtitleSeqName = utils.getSequenceName( - lectureIndex + 1, - countLectures, - sanitizedLectureName + ".srt", - ". ", - `${downloadDirectory}/${courseName}/${sanitizedChapterName}` - ); - - if (fs.existsSync(subtitleSeqName.fullPath)) { - checkAttachment(); - return; - } - - const vttFile = subtitleSeqName.fullPath.replace(".srt", ".vtt"); - const vttFileWS = fs.createWriteStream(vttFile).on("finish", function () { - const strFileWS = fs.createWriteStream(subtitleSeqName.fullPath).on("finish", function () { - fs.unlinkSync(vttFile); - checkAttachment(); - }); - - fs.createReadStream(vttFile).pipe(vtt2srt()).pipe(strFileWS); - }); - - const subtitles = lectureData.subtitles; - const availables = []; - $.map(subtitle, function (el) { - if (el in subtitles) { - availables.push(el); - } - }); - - let download_this_sub = availables[0] || Object.keys(subtitles)[0] || ""; - // Prefer non "[Auto]" subs (likely entered by the creator of the lecture.) - if (availables.length > 1) { - for (const key of availables) { - if (availables[key].indexOf("[Auto]") == -1 || availables[key].indexOf(`[${translate("Auto")}]`) == -1) { - download_this_sub = availables[key]; - break; - } - } - // availables.forEach(key=> { - // if (availables[key].indexOf("[Auto]") == -1 || availables[key].indexOf(`[${translate("Auto")}]`) == -1) { - // download_this_sub = availables[key]; - // return; - // } - // }) - } - - https.get( - subtitles[download_this_sub], - function (response) { - response.pipe(vttFileWS); - } - ); - } - - // read url as string or ArrayBuffer - async function getFile(url, binary) { - let retry = 0; - // console.log("getFile", { url, binary }); - // on error retry 3 times - while (retry < 3) { - try { - const response = await fetch(url); - const status = response.status; - - if (status >= 200 && status < 300) { - if (binary) return await response.arrayBuffer(); - - return await response.text(); - } else console.warn("getFile_Buffer", response.statusText); - } catch (error) { - appendLog("getFile_Error", error); - } - - retry++; - } - - return null; - } - - // read highest quality playlist - async function getPlaylist(url) { - const playlist = await getFile(url, false); - - if (!playlist) return []; - - const lines = playlist.trim().split("\n"); - const urlList = []; - - lines.forEach((line) => { - if (line.toLowerCase().indexOf(".ts") > -1) urlList.push(line); - }); - - if (urlList.length == 0 && playlist.indexOf("m3u8") > 0) { - let maximumQuality = 0; - let maximumQualityPlaylistUrl; - let getUrl = false; - - for (let line of lines) { - if (getUrl) { - maximumQualityPlaylistUrl = line; - getUrl = false; - } - - line = line.toUpperCase(); - - if (line.indexOf("EXT-X-STREAM-INF") > -1 && line.indexOf("RESOLUTION") > -1) { - try { - const readQuality = parseInt(line.split("RESOLUTION=")[1].split("X")[1].split(",")[0]) || 0; - - if (readQuality > maximumQuality) { - maximumQuality = readQuality; - getUrl = true; - } - } catch (error) { - appendLog("getPlaylist_Error", error); - captureException(error); - } - } - } - - if (maximumQuality > 0) { - setLabelQuality(maximumQuality); - return await getPlaylist(maximumQualityPlaylistUrl); - } - } - - return urlList; - } - - $progressIndividual.progress("reset"); - - const lectureQuality = lectureData.quality; - setLabelQuality(lectureQuality); - - if (lectureType == "article" || lectureType == "url") { - const wfDir = `${downloadDirectory}/${courseName}/${sanitizedChapterName}`; - fs.writeFile( - utils.getSequenceName(lectureIndex + 1, countLectures, sanitizedLectureName + ".html", ". ", wfDir).fullPath, - lectureData.src, - function () { - if (lectureData.attachments) { - lectureData.attachments.sort(utils.dynamicSort("name")); - const totalAttachments = lectureData.attachments.length; - let indexador = 0; - downloadAttachments(indexador, totalAttachments); - } else { - $progressCombined.progress("increment"); - downloaded++; - downloadLecture(chapterIndex, ++lectureIndex, countLectures, sanitizedChapterName); - } - } - ); - } else { - const seqName = utils.getSequenceName( - lectureIndex + 1, - countLectures, - sanitizedLectureName + (lectureType == "file" ? ".pdf" : ".mp4"), - ". ", - `${downloadDirectory}/${courseName}/${sanitizedChapterName}` - ); - - // $lecture_name.html(`${courseData["chapters"][chapterIndex].name}\\${lectureName}`); - const skipLecture = (Settings.download.type == Settings.DownloadType.OnlyAttachments); - - if (lectureType !== "application/x-mpegurl") { - - if (fs.existsSync(seqName.fullPath) || skipLecture || lectureData.isEncrypted) { - endDownloadAttachment(); - return; - } - - if (fs.existsSync(seqName.fullPath + ".mtd") && !fs.statSync(seqName.fullPath + ".mtd").size) { - fs.unlinkSync(seqName.fullPath + ".mtd"); - } - - if (fs.existsSync(seqName.fullPath + ".mtd")) { - var dl = downloader.resumeDownload(seqName.fullPath); - } else { - var dl = downloader.download(lectureData.src, seqName.fullPath); - } - - dlStart(dl, lectureType.includes("video"), endDownloadAttachment); - - } else { - - if (fs.existsSync(seqName.fullPath) || skipLecture || lectureData.isEncrypted) { - endDownloadAttachment(); - return; - } - if (fs.existsSync(seqName.fullPath + ".mtd")) { - fs.unlinkSync(seqName.fullPath + ".mtd"); - } - - getPlaylist(lectureData.src).then(async (list) => { - if (list.length > 0) { - try { - $progressIndividual.progress("reset"); - - // Define o tamanho do bloco de dados a ser processado por vez - const CHUNK_SIZE = 100; - let count = 0; - - for (let i = 0; i < list.length; i += CHUNK_SIZE) { - const chunk = list.slice(i, i + CHUNK_SIZE); - const result = []; - - for (const url of chunk) { - const startTime = performance.now(); - const response = await getFile(url, true); - const endTime = performance.now(); - const timeDiff = (endTime - startTime) / 1000.0; - - if (response) { - const chunkSize = response.byteLength; - const speedAndUnit = utils.getDownloadSpeed(chunkSize / timeDiff); - - $downloadSpeedValue.html(speedAndUnit.value); - $downloadSpeedUnit.html(speedAndUnit.unit); - - result.push(response); - count++; - } else { - console.error('Received an invalid or null response for URL:', url); - throw new Error('Invalid or null response received'); - } - - $progressIndividual.progress("set percent", parseInt((count / list.length) * 100)); - } - - const blob = new Blob(result, { type: "application/octet-binary" }); - try { - const data = Buffer.from(await blob.arrayBuffer()); - fs.appendFileSync(seqName.fullPath, data); // Use append para adicionar os dados ao arquivo existente - } catch (bufferError) { - console.error('Error creating buffer from Blob:', bufferError); - throw bufferError; - } - } - } catch (error) { - console.error('Error downloading buffer from Blob:', error); - throw error; - } - } - - endDownloadAttachment(); - return; - }); - - } - - function endDownloadAttachment() { - clearInterval(timerDownloader); - if (courseData.chapters[chapterIndex].lectures[lectureIndex].subtitles) { - downloadSubtitle(); - } else { - checkAttachment(); - } - } - } - } catch (error) { - appendLog("downloadLecture_Error:", error); - captureException(error); - - resetCourse($course, $course.find(".download-error"), false, courseData); - } - } - - function hasDRMProtection(dl) { - try { - // return !dl.meta.headers["content-type"].includes("video"); - const encrypted = dl.url.includes("encrypted-files"); - if (encrypted) console.warn("Arquivo encriptado", dl); - - return encrypted; - } catch (error) { - return false; - } - } + ui.showProgress($course, true); + + const subtitle = (Array.isArray(subTitle) ? subTitle[0] : subTitle).split("|"); + $course.find(".info-downloaded").hide(); + $course.find('input[name="selectedSubtitle"]').val(subtitle); + $course.find('input[name="encryptedvideos"]').val(courseData.encryptedVideos); + + const $clone = $course.clone(); + const $downloads = $(".ui.downloads.section .ui.courses.items"); + const $courses = $(".ui.courses.section .ui.courses.items"); + + if ($course.parents(".courses.section").length) { + const $downloadItem = $downloads.find("[course-id=" + $course.attr("course-id") + "]"); + if ($downloadItem.length) { + $downloadItem.replaceWith($clone); + } else { + $downloads.prepend($clone); + } + } else { + const $courseItem = $courses.find("[course-id=" + $course.attr("course-id") + "]"); + if ($courseItem.length) { + $courseItem.replaceWith($clone); + } + } + $course.push($clone[0]); + + const courseName = sanitize(courseData["name"]); //, { replacement: (s) => "? ".indexOf(s) > -1 ? "" : "-", }).trim(); + const $progressCombined = $course.find(".combined.progress"); + const $progressIndividual = $course.find(".individual.progress"); + + const $downloadSpeed = $course.find(".download-speed"); + const $downloadSpeedValue = $downloadSpeed.find(".value"); + const $downloadSpeedUnit = $downloadSpeed.find(".download-unit"); + const $downloadQuality = $course.find(".download-quality"); + + const downloadDirectory = Settings.downloadDirectory(); + $course.find('input[name="path-downloaded"]').val(`${downloadDirectory}/${courseName}`); + $course.find(".open-dir.button").show(); + // $course.css("cssText", "padding-top: 35px !important").css("padding-bottom", "25px"); + + const $actionButtons = $course.find(".action.buttons"); + const $downloadButton = $actionButtons.find(".download.button"); + const $pauseButton = $actionButtons.find(".pause.button"); + const $resumeButton = $actionButtons.find(".resume.button"); + + $downloadButton.addClass("disabled"); + $pauseButton.removeClass("disabled"); + $resumeButton.addClass("disabled"); + + $pauseButton.click(() => stopDownload()); + $resumeButton.click(() => resumeDownload()); + + let timerDownloader = null; + const downloader = new Downloader(); + + const lectureChapterMap = {}; + let sequenceMap = 0; + courseData.chapters.forEach((chapter, chapterIndex) => { + chapter.lectures.forEach((_lecture, lectureIndex) => { + sequenceMap++; + lectureChapterMap[sequenceMap] = { chapterIndex, lectureIndex }; + }); + }); + + const labelColorMap = { + 144: "brown", + 240: "purple", + 360: "yellow", + 432: "orange", + 480: "teal", + 576: "blue", + 720: "olive", + 1080: "green", + Highest: "green", + auto: "red", + Auto: "red", + Attachment: "pink", + Subtitle: "black", + }; + + let downloaded = 0; + let toDownload = courseData["totalLectures"]; + + const enableDownloadStartEnd = Settings.download.enableDownloadStartEnd; + if (enableDownloadStartEnd) { + let downloadStart = Math.max(1, Math.min(Settings.download.downloadStart, toDownload)); + let downloadEnd = Math.max(0, Settings.download.downloadEnd); + downloadEnd = Math.max(downloadStart, downloadEnd == 0 ? toDownload : downloadEnd); + + toDownload = downloadEnd - downloadStart + 1; + } + + $progressCombined.progress({ + total: toDownload, + text: { + active: `${translate("Downloaded")} {value} ${translate("out of")} {total} ${translate("items")}`, + }, + }); + + $progressCombined.progress("reset"); + $downloadSpeed.show(); + $downloadQuality.show(); + + if (enableDownloadStartEnd) { + downloadChapter(lectureChapterMap[downloadStart].chapterIndex, lectureChapterMap[downloadStart].lectureIndex); + } else { + downloadChapter(0, 0); + } + + function stopDownload(isEncrypted) { + if (downloader._downloads?.length) { + downloader._downloads[downloader._downloads.length - 1].stop(); + $pauseButton.addClass("disabled"); + $resumeButton.removeClass("disabled"); + + if (isEncrypted) { + resetCourse($course, $course.find(".course-encrypted")); + } + } + } + + function resumeDownload() { + if (downloader._downloads?.length) { + downloader._downloads[downloader._downloads.length - 1].resume(); + $pauseButton.removeClass("disabled"); + $resumeButton.addClass("disabled"); + } + } + + function setLabelQuality(label) { + const lastClass = $downloadQuality.attr("class").split(" ").pop(); + $downloadQuality + .html(label.toString() + (!isNaN(parseFloat(label)) ? "p" : "")) + .removeClass(lastClass) + .addClass(labelColorMap[label] || "grey"); + } + + function downloadChapter(chapterIndex, lectureIndex) { + try { + const countLectures = courseData.chapters[chapterIndex].lectures.length; + const seqName = utils.getSequenceName( + chapterIndex + 1, + courseData.chapters.length, + sanitize(courseData.chapters[chapterIndex].name.trim()), + ". ", + downloadDirectory + "/" + courseName + ); + + fs.mkdirSync(seqName.fullPath, { recursive: true }); + downloadLecture(chapterIndex, lectureIndex, countLectures, seqName.name); + } catch (error) { + handleApiError(error, "EDOWNLOADING_CHAPTER", null, false); + resetCourse($course, $course.find(".download-error"), false, courseData); + } + } + + function downloadLecture(chapterIndex, lectureIndex, countLectures, sanitizedChapterName) { + try { + if (downloaded == toDownload) { + resetCourse($course, $course.find(".download-success")); + sendNotification( + downloadDirectory + "/" + courseName, + courseName, + $course.find(".ui.tiny.image").find(".course-image").attr("src") + ); + return; + } else if (lectureIndex == countLectures) { + downloadChapter(++chapterIndex, 0); + return; + } + + const chapterName = courseData.chapters[chapterIndex].name.trim(); + const lectureData = courseData.chapters[chapterIndex].lectures[lectureIndex]; + const lectureType = lectureData.type.toLowerCase(); + const lectureName = lectureData.name.trim(); + const sanitizedLectureName = sanitize(lectureName); + + function dlStart(dl, typeVideo, callback) { + // Change retry options to something more forgiving and threads to keep udemy from getting upset + dl.setRetryOptions({ + maxRetries: 3, // Default: 5 + retryInterval: 3000, // Default: 2000 + }); + + // Set download options + dl.setOptions({ + threadsCount: 5, // Default: 2, Set the total number of download threads + timeout: 5000, // Default: 5000, If no data is received, the download times out (milliseconds) + range: "0-100", // Default: 0-100, Control the part of file that needs to be downloaded. + }); + + dl.start(); + // To track time and restarts + let notStarted = 0; + let reStarted = 0; + + timerDownloader = setInterval(function () { + // Status: + // -3 = destroyed + // -2 = stopped + // -1 = error + // 0 = not started + // 1 = started (downloading) + // 2 = error, retrying + // 3 = finished + switch (dl.status) { + case 0: + // Wait a reasonable amount of time for the download to start and if it doesn't then start another one. + // once one of them starts the errors from the others will be ignored and we still get the file. + if (reStarted <= 5) { + notStarted++; + if (notStarted >= 15) { + dl.start(); + notStarted = 0; + reStarted++; + } + } + $downloadSpeedValue.html(0); + break; + + case 1: + case -1: + const stats = dl.getStats(); + const speedAndUnit = utils.getDownloadSpeed(stats.present.speed || 0); + $downloadSpeedValue.html(speedAndUnit.value); + $downloadSpeedUnit.html(speedAndUnit.unit); + // console.log(`dl~stats.present.speed: ${stats.present.speed}`); + // console.log(`Download speed: ${speedAndUnit.value}${speedAndUnit.unit}`); + $progressIndividual.progress("set percent", stats.total.completed); + + if (dl.status === -1 && dl.stats.total.size == 0 && fs.existsSync(dl.filePath)) { + dl.emit("end"); + clearInterval(timerDownloader); + } else if (dl.status === -1) { + appendLog("Download error, retrying... ", { url: dl.url }); + axios({ + timeout: HTTP_TIMEOUT, + type: "HEAD", + url: dl.url, + }) + .then(() => { + resetCourse($course, $course.find(".download-error"), Settings.download.autoRetry, courseData, subtitle); + }) + .catch((error) => { + handleApiError(error, "EDL_DOWNLOADING_LECTURE", courseData.name, false); + const statusCode = error.response?.status || 0; + const unlinkFile = statusCode == 401 || statusCode == 403; + try { + if (unlinkFile) { + fs.unlinkSync(dl.filePath); + } + } finally { + resetCourse( + $course, + $course.find(".download-error"), + Settings.download.autoRetry && !unlinkFile, + courseData, + subtitle + ); + } + }); + + clearInterval(timerDownloader); + } + break; + + case 2: + case -3: + break; + default: + $downloadSpeedValue.html(0); + } + }, 1000); + + dl.on("error", function (dl) { + console.error("dl.on(error)", dl.error.message); + if (hasDRMProtection(dl)) { + dl.emit("end"); + } else { + appendLog("DL_ONERROR", dl.error.message); + } + }); + + dl.on("start", function () { + // console.log("dl.on(start)", dl.filePath.split("/").slice(-2).join("/")); + $pauseButton.removeClass("disabled"); + }); + + dl.on("stop", function () { + console.warn("dl.on(stop)"); + }); + + dl.on("end", function () { + // console.log("dl.on(end)", { path: dl.filePath, typeVideo }); + if (typeVideo && hasDRMProtection(dl)) { + $course.find('input[name="encryptedvideos"]').val(++courseData.encryptedVideos); + + appendLog(`DRM Protected::${courseData.name}`, dl.filePath); + fs.unlink(dl.filePath + ".mtd", (err) => { + if (err) { + console.error("dl.on(end)__fs.unlink", err.message); + } + }); + + if (!Settings.download.continueDonwloadingEncrypted) { + dl.destroy(); + stopDownload(true); + clearInterval(timerDownloader); + return; + } + } + callback(); + }); + } + + function downloadAttachments(index, totalAttachments) { + $progressIndividual.progress("reset"); + + const attachment = lectureData.attachments[index]; + const attachmentName = attachment.name.trim(); + + setLabelQuality(attachment.quality); + + if (["article", "url"].includes(attachment.type)) { + const wfDir = downloadDirectory + "/" + courseName + "/" + sanitizedChapterName; + fs.writeFile( + utils.getSequenceName(lectureIndex + 1, countLectures, attachmentName + ".html", `.${index + 1} `, wfDir).fullPath, + attachment.src, + function () { + index++; + if (index == totalAttachments) { + $progressCombined.progress("increment"); + downloaded++; + downloadLecture(chapterIndex, ++lectureIndex, countLectures, sanitizedChapterName); + } else { + downloadAttachments(index, totalAttachments); + } + } + ); + } else { + let fileExtension = attachment.src.split("/").pop().split("?").shift().split(".").pop(); + fileExtension = attachment.name.split(".").pop() == fileExtension ? "" : "." + fileExtension; + + const lectureSeqName = utils.getSequenceName( + lectureIndex + 1, + countLectures, + sanitize(attachmentName) + fileExtension, + `.${index + 1} `, + `${downloadDirectory}/${courseName}/${sanitizedChapterName}` + ); + + // try deleting the download started without data + if (fs.existsSync(lectureSeqName.fullPath + ".mtd") && !fs.statSync(lectureSeqName.fullPath + ".mtd").size) { + fs.unlinkSync(lectureSeqName.fullPath + ".mtd"); + } + + if (fs.existsSync(lectureSeqName.fullPath + ".mtd")) { + var dl = downloader.resumeDownload(lectureSeqName.fullPath); + } else if (fs.existsSync(lectureSeqName.fullPath)) { + endDownload(); + return; + } else { + var dl = downloader.download(attachment.src, lectureSeqName.fullPath); + } + + dlStart(dl, attachment.type.includes("video"), endDownload); + + function endDownload() { + index++; + + clearInterval(timerDownloader); + if (index == totalAttachments) { + $progressCombined.progress("increment"); + downloaded++; + downloadLecture(chapterIndex, ++lectureIndex, countLectures, sanitizedChapterName); + } else { + downloadAttachments(index, totalAttachments); + } + } + } + } + + function checkAttachment() { + $progressIndividual.progress("reset"); + const attachment = lectureData.attachments; + + if (attachment) { + lectureData.attachments.sort(utils.dynamicSort("name")); + downloadAttachments(0, attachment.length); + } else { + if (lectureData.isEncrypted) { + appendLog("Video with DRM Protection", `Chapter: ${chapterName}\nLecture: ${lectureName}`); + } + $progressCombined.progress("increment"); + downloaded++; + downloadLecture(chapterIndex, ++lectureIndex, countLectures, sanitizedChapterName); + } + } + + function downloadSubtitle() { + $progressIndividual.progress("reset"); + + setLabelQuality("Subtitle"); + $downloadSpeedValue.html(0); + + const subtitleSeqName = utils.getSequenceName( + lectureIndex + 1, + countLectures, + sanitizedLectureName + ".srt", + ". ", + `${downloadDirectory}/${courseName}/${sanitizedChapterName}` + ); + + if (fs.existsSync(subtitleSeqName.fullPath)) { + checkAttachment(); + return; + } + + const vttFile = subtitleSeqName.fullPath.replace(".srt", ".vtt"); + const vttFileWS = fs.createWriteStream(vttFile).on("finish", function () { + const strFileWS = fs.createWriteStream(subtitleSeqName.fullPath).on("finish", function () { + fs.unlinkSync(vttFile); + checkAttachment(); + }); + + fs.createReadStream(vttFile).pipe(vtt2srt()).pipe(strFileWS); + }); + + const subtitles = lectureData.subtitles; + const availables = []; + $.map(subtitle, function (el) { + if (el in subtitles) { + availables.push(el); + } + }); + + let download_this_sub = availables[0] || Object.keys(subtitles)[0] || ""; + // Prefer non "[Auto]" subs (likely entered by the creator of the lecture.) + if (availables.length > 1) { + for (const key of availables) { + if (availables[key].indexOf("[Auto]") == -1 || availables[key].indexOf(`[${translate("Auto")}]`) == -1) { + download_this_sub = availables[key]; + break; + } + } + // availables.forEach(key=> { + // if (availables[key].indexOf("[Auto]") == -1 || availables[key].indexOf(`[${translate("Auto")}]`) == -1) { + // download_this_sub = availables[key]; + // return; + // } + // }) + } + + https.get(subtitles[download_this_sub], function (response) { + response.pipe(vttFileWS); + }); + } + + // read url as string or ArrayBuffer + async function getFile(url, binary) { + let retry = 0; + // console.log("getFile", { url, binary }); + // on error retry 3 times + while (retry < 3) { + try { + const response = await fetch(url); + const status = response.status; + + if (status >= 200 && status < 300) { + if (binary) return await response.arrayBuffer(); + + return await response.text(); + } else console.warn("getFile_Buffer", response.statusText); + } catch (error) { + appendLog("getFile_Error", error); + } + + retry++; + } + + return null; + } + + // read highest quality playlist + async function getPlaylist(url) { + const playlist = await getFile(url, false); + + if (!playlist) return []; + + const lines = playlist.trim().split("\n"); + const urlList = []; + + lines.forEach((line) => { + if (line.toLowerCase().indexOf(".ts") > -1) urlList.push(line); + }); + + if (urlList.length == 0 && playlist.indexOf("m3u8") > 0) { + let maximumQuality = 0; + let maximumQualityPlaylistUrl; + let getUrl = false; + + for (let line of lines) { + if (getUrl) { + maximumQualityPlaylistUrl = line; + getUrl = false; + } + + line = line.toUpperCase(); + + if (line.indexOf("EXT-X-STREAM-INF") > -1 && line.indexOf("RESOLUTION") > -1) { + try { + const readQuality = parseInt(line.split("RESOLUTION=")[1].split("X")[1].split(",")[0]) || 0; + + if (readQuality > maximumQuality) { + maximumQuality = readQuality; + getUrl = true; + } + } catch (error) { + appendLog("getPlaylist_Error", error); + captureException(error); + } + } + } + + if (maximumQuality > 0) { + setLabelQuality(maximumQuality); + return await getPlaylist(maximumQualityPlaylistUrl); + } + } + + return urlList; + } + + $progressIndividual.progress("reset"); + + const lectureQuality = lectureData.quality; + setLabelQuality(lectureQuality); + + if (lectureType == "article" || lectureType == "url") { + const wfDir = `${downloadDirectory}/${courseName}/${sanitizedChapterName}`; + fs.writeFile( + utils.getSequenceName(lectureIndex + 1, countLectures, sanitizedLectureName + ".html", ". ", wfDir).fullPath, + lectureData.src, + function () { + if (lectureData.attachments) { + lectureData.attachments.sort(utils.dynamicSort("name")); + const totalAttachments = lectureData.attachments.length; + let indexador = 0; + downloadAttachments(indexador, totalAttachments); + } else { + $progressCombined.progress("increment"); + downloaded++; + downloadLecture(chapterIndex, ++lectureIndex, countLectures, sanitizedChapterName); + } + } + ); + } else { + const seqName = utils.getSequenceName( + lectureIndex + 1, + countLectures, + sanitizedLectureName + (lectureType == "file" ? ".pdf" : ".mp4"), + ". ", + `${downloadDirectory}/${courseName}/${sanitizedChapterName}` + ); + + // $lecture_name.html(`${courseData["chapters"][chapterIndex].name}\\${lectureName}`); + const skipLecture = Settings.download.type == Settings.DownloadType.OnlyAttachments; + + if (lectureType !== "application/x-mpegurl") { + if (fs.existsSync(seqName.fullPath) || skipLecture || lectureData.isEncrypted) { + endDownloadAttachment(); + return; + } + + if (fs.existsSync(seqName.fullPath + ".mtd") && !fs.statSync(seqName.fullPath + ".mtd").size) { + fs.unlinkSync(seqName.fullPath + ".mtd"); + } + + if (fs.existsSync(seqName.fullPath + ".mtd")) { + var dl = downloader.resumeDownload(seqName.fullPath); + } else { + var dl = downloader.download(lectureData.src, seqName.fullPath); + } + + dlStart(dl, lectureType.includes("video"), endDownloadAttachment); + } else { + if (fs.existsSync(seqName.fullPath) || skipLecture || lectureData.isEncrypted) { + endDownloadAttachment(); + return; + } + if (fs.existsSync(seqName.fullPath + ".mtd")) { + fs.unlinkSync(seqName.fullPath + ".mtd"); + } + + getPlaylist(lectureData.src).then(async (list) => { + if (list.length > 0) { + try { + $progressIndividual.progress("reset"); + + // Define o tamanho do bloco de dados a ser processado por vez + const CHUNK_SIZE = 100; + let count = 0; + + for (let i = 0; i < list.length; i += CHUNK_SIZE) { + const chunk = list.slice(i, i + CHUNK_SIZE); + const result = []; + + for (const url of chunk) { + const startTime = performance.now(); + const response = await getFile(url, true); + const endTime = performance.now(); + const timeDiff = (endTime - startTime) / 1000.0; + + if (response) { + const chunkSize = response.byteLength; + const speedAndUnit = utils.getDownloadSpeed(chunkSize / timeDiff); + + $downloadSpeedValue.html(speedAndUnit.value); + $downloadSpeedUnit.html(speedAndUnit.unit); + + result.push(response); + count++; + } else { + console.error("Received an invalid or null response for URL:", url); + throw new Error("Invalid or null response received"); + } + + $progressIndividual.progress("set percent", parseInt((count / list.length) * 100)); + } + + const blob = new Blob(result, { type: "application/octet-binary" }); + try { + const data = Buffer.from(await blob.arrayBuffer()); + fs.appendFileSync(seqName.fullPath, data); // Use append para adicionar os dados ao arquivo existente + } catch (bufferError) { + console.error("Error creating buffer from Blob:", bufferError); + throw bufferError; + } + } + } catch (error) { + console.error("Error downloading buffer from Blob:", error); + throw error; + } + } + + endDownloadAttachment(); + return; + }); + } + + function endDownloadAttachment() { + clearInterval(timerDownloader); + if (courseData.chapters[chapterIndex].lectures[lectureIndex].subtitles) { + downloadSubtitle(); + } else { + checkAttachment(); + } + } + } + } catch (error) { + appendLog("downloadLecture_Error:", error); + captureException(error); + + resetCourse($course, $course.find(".download-error"), false, courseData); + } + } + + function hasDRMProtection(dl) { + try { + // return !dl.meta.headers["content-type"].includes("video"); + const encrypted = dl.url.includes("encrypted-files"); + if (encrypted) console.warn("Arquivo encriptado", dl); + + return encrypted; + } catch (error) { + return false; + } + } } function askForSubtitle(subtitlesAvailable, totalLectures, defaultSubtitle = "", callback) { - const subtitleLanguages = []; - const languages = []; - const totals = {}; - const languageKeys = {}; - - if (Object.keys(subtitlesAvailable).length === 0) { - callback(""); - return; - } - - defaultSubtitle = defaultSubtitle.replace(/\s*\[.*?\]/g, '').trim(); - for (const key in subtitlesAvailable) { - const subtitle = key.replace(/\s*\[.*?\]/g, '').trim(); - - // default subtitle exists - if (subtitle === defaultSubtitle) { - callback(key); - return; - } - - if (!(subtitle in totals)) { - languages.push(subtitle); - totals[subtitle] = 0; - languageKeys[subtitle] = []; - } - - totals[subtitle] += subtitlesAvailable[key]; - languageKeys[subtitle].push(key); - }; - - if (languages.length === 1) { - callback(languageKeys[0]); - return; - } else if (languages.length === 0) { - return; - } - - languages.forEach(language => { - totals[language] = Math.min(totalLectures, totals[language]); - }); - - languages.sort(); - languages.forEach(language => { - subtitleLanguages.push({ - name: `${language} ${totals[language]} ${translate("Lectures")}`, - value: languageKeys[language].join("|"), - }); - }); - subtitleLanguages.unshift({ name: "", value: "" }); - - const $subtitleModal = $(".ui.subtitle.modal"); - const $subtitleDropdown = $subtitleModal.find(".ui.dropdown"); - - $subtitleModal.modal({ closable: false }).modal("show"); - $subtitleDropdown.dropdown({ - values: subtitleLanguages, - onChange: (subtitle) => { - $subtitleModal.modal("hide"); - $subtitleDropdown.dropdown({ values: [] }); - callback(subtitle); - }, - }); + const subtitleLanguages = []; + const languages = []; + const totals = {}; + const languageKeys = {}; + + if (Object.keys(subtitlesAvailable).length === 0) { + callback(""); + return; + } + + defaultSubtitle = defaultSubtitle.replace(/\s*\[.*?\]/g, "").trim(); + for (const key in subtitlesAvailable) { + const subtitle = key.replace(/\s*\[.*?\]/g, "").trim(); + + // default subtitle exists + if (subtitle === defaultSubtitle) { + callback(key); + return; + } + + if (!(subtitle in totals)) { + languages.push(subtitle); + totals[subtitle] = 0; + languageKeys[subtitle] = []; + } + + totals[subtitle] += subtitlesAvailable[key]; + languageKeys[subtitle].push(key); + } + + if (languages.length === 1) { + callback(languageKeys[0]); + return; + } else if (languages.length === 0) { + return; + } + + languages.forEach((language) => { + totals[language] = Math.min(totalLectures, totals[language]); + }); + + languages.sort(); + languages.forEach((language) => { + subtitleLanguages.push({ + name: `${language} ${totals[language]} ${translate("Lectures")}`, + value: languageKeys[language].join("|"), + }); + }); + subtitleLanguages.unshift({ name: "", value: "" }); + + const $subtitleModal = $(".ui.subtitle.modal"); + const $subtitleDropdown = $subtitleModal.find(".ui.dropdown"); + + $subtitleModal.modal({ closable: false }).modal("show"); + $subtitleDropdown.dropdown({ + values: subtitleLanguages, + onChange: (subtitle) => { + $subtitleModal.modal("hide"); + $subtitleDropdown.dropdown({ values: [] }); + callback(subtitle); + }, + }); } function sendNotification(pathCourse, courseName, urlImage = null) { - try { - new Notification(courseName, { - body: translate("Download Finished"), - icon: urlImage ?? __dirname + "/assets/images/build/icon.png", - }).onclick = () => { - shell.openPath(pathCourse); - }; - } catch (error) { - appendLog("sendNotification", error); - } + try { + new Notification(courseName, { + body: translate("Download Finished"), + icon: urlImage ?? __dirname + "/assets/images/build/icon.png", + }).onclick = () => { + shell.openPath(pathCourse); + }; + } catch (error) { + appendLog("sendNotification", error); + } } function clearLogArea() { - loggers.length = 0; - $(".ui.logger.section .ui.list").html(""); - clearBagdeLoggers(); + loggers.length = 0; + $(".ui.logger.section .ui.list").html(""); + clearBagdeLoggers(); } function clearBagdeLoggers() { - $("#badge-logger").text("0"); - $("#badge-logger").hide(); + $("#badge-logger").text("0"); + $("#badge-logger").hide(); } /** @@ -1778,131 +1785,133 @@ function clearBagdeLoggers() { * @param {string|Error|object} error - The error message or Error object. */ function appendLog(title, error, additionalDescription = "") { - let description = error instanceof Error - ? error.message //`${error.message}\n ${error.stack}` - : (typeof error == "object" ? JSON.stringify(error) : error); - - description += additionalDescription !== "" ? "\n\n" + additionalDescription : ""; - - // item added to list to display - $(".ui.logger.section .ui.list").prepend( - `
+ let description = + error instanceof Error + ? error.message //`${error.message}\n ${error.stack}` + : typeof error == "object" + ? JSON.stringify(error) + : error; + + description += additionalDescription !== "" ? "\n\n" + additionalDescription : ""; + + // item added to list to display + $(".ui.logger.section .ui.list").prepend( + `
${title}
${description.replace("\n", "
").replace("\r", "
")}
` - ); - - // item added to array to save txt file - loggers.unshift({ - datetime: new Date().toLocaleString(), - title, - description, - }); - - // increment badge - const $badge = $("#badge-logger"); - const qtd = (parseInt($badge.text(), 0) || 0) + 1; - - $badge.text(qtd > 99 ? "99+" : qtd); - $badge.show(); - - if (error instanceof Error) { - console.error(`[${title}] ${error.message}\n ${error.stack}`); - captureException(error); - } else { - console.warn(`[${title}] ${description}`); - } + ); + + // item added to array to save txt file + loggers.unshift({ + datetime: new Date().toLocaleString(), + title, + description, + }); + + // increment badge + const $badge = $("#badge-logger"); + const qtd = (parseInt($badge.text(), 0) || 0) + 1; + + $badge.text(qtd > 99 ? "99+" : qtd); + $badge.show(); + + if (error instanceof Error) { + console.trace(`[${title}] ${error.message}\n ${error.stack}`); + captureException(error); + } else { + console.warn(`[${title}] ${description}`); + } } function saveLogFile() { - if (loggers.length == 0) return; - - dialog - .showSaveDialog({ - title: "Udeler Log", - defaultPath: "udeler_logger.txt", - filters: [{ name: "Text File (*.txt)", fileExtension: ["txt"] }], - }) - .then((result) => { - if (!result.canceled) { - let filePath = result.filePath; - if (!filePath.endsWith(".txt")) filePath += ".txt"; - - let content = ""; - - loggers.forEach((item) => { - content += `${item.datetime} - ${item.title}: ${item.description}\n`; - }); - - fs.writeFile(filePath, content, (error) => { - if (error) { - appendLog("saveLogFile_Error", error); - return; - } - console.log("File successfully create!"); - }); - } - }); + if (loggers.length == 0) return; + + dialog + .showSaveDialog({ + title: "Udeler Log", + defaultPath: "udeler_logger.txt", + filters: [{ name: "Text File (*.txt)", fileExtension: ["txt"] }], + }) + .then((result) => { + if (!result.canceled) { + let filePath = result.filePath; + if (!filePath.endsWith(".txt")) filePath += ".txt"; + + let content = ""; + + loggers.forEach((item) => { + content += `${item.datetime} - ${item.title}: ${item.description}\n`; + }); + + fs.writeFile(filePath, content, (error) => { + if (error) { + appendLog("saveLogFile_Error", error); + return; + } + console.log("File successfully create!"); + }); + } + }); } function handleApiError(error, errorName, courseName = null, triggerThrow = true) { - error.name = errorName; - error.code = error.code || ""; - - const statusCode = error.response?.status || 0; - switch (statusCode) { - case 403: - error.message = translate("You do not have permission to access this course"); - // prompt.alert(msgError); - showAlertError(error.message, errorName); - break; - case 503: - error.message = translate("Service is temporarily unavailable. Please wait a few minutes and try again."); - showAlertError(error.message, errorName); - break; - case 504: - error.message = "Gateway timeout"; - showAlertError(error.message, errorName); - break; - default: - break; - } - - if (courseName) - error.message += `\n\n course: ${courseName}`; - - appendLog(`${errorName}: ${error.code}(${statusCode})`, error); - - if (triggerThrow) { - // throw utils.newError(errorName, error.message); - throw error; - } + error.name = errorName; + error.code = error.code || ""; + + const statusCode = error.response?.status || 0; + switch (statusCode) { + case 403: + error.message = translate("You do not have permission to access this course"); + // prompt.alert(msgError); + showAlertError(error.message, errorName); + break; + case 503: + error.message = translate("Service is temporarily unavailable. Please wait a few minutes and try again."); + showAlertError(error.message, errorName); + break; + case 504: + error.message = "Gateway timeout"; + showAlertError(error.message, errorName); + break; + default: + break; + } + + if (courseName) error.message += `\n\n course: ${courseName}`; + + appendLog(`${errorName}: ${error.code}(${statusCode})`, error); + + if (triggerThrow) { + // throw utils.newError(errorName, error.message); + throw error; + } } function showAlertError(message, title = "") { - title = title ? `.:: ${title} ::.` : ".:: Error ::."; - dialog.showErrorBox(title, message); + title = title ? `.:: ${title} ::.` : ".:: Error ::."; + dialog.showErrorBox(title, message); } function showAlert(message, title = "") { - if (title) title = `.:: ${title} ::.\n\r`; - dialogs.alert(`${title}${message}`); + if (title) title = `.:: ${title} ::.\n\r`; + dialogs.alert(`${title}${message}`); } function captureException(exception) { - if (Sentry) Sentry.captureException(exception); + if (Sentry) Sentry.captureException(exception); } process.on("uncaughtException", (error) => { - appendLog("EPROCESS_UNCAUGHT_EXCEPTION", error); - captureException(error); + appendLog("EPROCESS_UNCAUGHT_EXCEPTION", error); + captureException(error); }); process.on("unhandledRejection", (error) => { - appendLog("EPROCESS_UNHANDLED_REJECTION", error); - captureException(error); + appendLog("EPROCESS_UNHANDLED_REJECTION", error); + captureException(error); }); // console.table(getAllDownloadsHistory()); diff --git a/app/core/services/index.js b/app/core/services/index.js index eeb35987..2330ab87 100644 --- a/app/core/services/index.js +++ b/app/core/services/index.js @@ -1,7 +1,7 @@ -const UdemyService = require("./udemy.service"); -const M3U8Service = require("./m3u8.service"); - -module.exports = { - default: UdemyService, - M3U8Service, -} \ No newline at end of file +const UdemyService = require("./udemy.service"); +const M3U8Service = require("./m3u8.service"); + +module.exports = { + default: UdemyService, + M3U8Service, +}; diff --git a/app/core/services/m3u8.service.js b/app/core/services/m3u8.service.js index d593b5f5..ba6e32b0 100644 --- a/app/core/services/m3u8.service.js +++ b/app/core/services/m3u8.service.js @@ -1,165 +1,164 @@ -"use strict" +"use strict"; class M3U8Service { - - /** - * Creates a new instance of M3U8Playlist. - * @param {string} m3u8Url - The URL of the M3U8 playlist. - * @returns {M3U8Service} - The newly created M3U8Playlist instance. - */ - constructor(m3u8Url) { - if (!this._isValidUrl(m3u8Url)) { - throw new Error('Invalid URL'); - } - this._m3u8Url = m3u8Url; - /** @type {Array<{quality: number, resolution: string, url: string}>} */ - this._playlist = []; - } - - /** - * Validates the URL. - * @param {string} url - The URL to validate. - * @returns {boolean} - True if the URL is valid, false otherwise. - */ - _isValidUrl(url) { - try { - new URL(url); - return true; - } catch (_) { - return false; - } - } - - /** - * Checks if the content is a valid M3U8 playlist. - * @param {string} content - The content to check. - * @returns {boolean} - True if the content is a valid M3U8 playlist, false otherwise. - */ - _isValidM3U8Content(content) { - return content.startsWith('#EXTM3U'); - } - - /** - * Extracts URLs and qualities from an M3U8 playlist content. - * @param {string} m3u8Content - The content of the M3U8 playlist. - * @returns {Array<{quality: number, resolution: string, url: string}>} - An array of objects containing the quality, - * resolution, and URL of each playlist. - */ - _extractUrlsAndQualities(m3u8Content) { - const lines = m3u8Content.split('\n'); - const urlsAndQualities = []; - - let currentResolution = null; - let currentQuality = null; - - lines.forEach(line => { - if (line.startsWith('#EXT-X-STREAM-INF')) { - const match = line.match(/RESOLUTION=(\d+x\d+)/); - if (match) { - currentResolution = match[1]; - currentQuality = parseInt(match[1].split('x')[1], 10); - } - } else if (line.startsWith('http')) { - if (currentResolution) { - urlsAndQualities.push({ - quality: currentQuality, - resolution: currentResolution, - url: line - }); - currentResolution = null; - currentQuality = null; - } - } - }); - - return urlsAndQualities; - } - - /** - * Fetches a file from the given URL. - * - * @param {string} url - The URL of the file to fetch. - * @param {boolean} [isBinary=false] - Whether the file is binary or text. - * @param {number} [maxRetries=3] - The maximum number of retries to fetch the file. - * @returns {Promise} - A promise that resolves with the file content. - * @throws {Error} - If the file fails to load after multiple attempts. - */ - static async getFile(url, isBinary = false, maxRetries = 3) { - let retries = 0; - - while (retries < maxRetries) { - try { - const response = await fetch(url); - - if (!response.ok) { - throw new Error(`Failed to fetch ${isBinary ? 'binary' : 'text'} file: ${response.statusText}`); - } - - return isBinary ? await response.arrayBuffer() : await response.text(); - } catch (error) { - retries++; - } - } - - throw new Error('Failed to load file after multiple attempts'); - } - - /** - * Loads the M3U8 playlist. - * - * @param {number} [maxRetries=3] - The maximum number of retries to fetch the playlist. - * @returns {Promise} - A promise that resolves when the playlist is loaded successfully. - * @throws {Error} - If the playlist fails to load after multiple attempts. - */ - async loadPlaylist(maxRetries = 3) { - const playlistContent = await M3U8Service.getFile(this._m3u8Url, false, maxRetries); - if (!this._isValidM3U8Content(playlistContent)) { - throw new Error('Invalid M3U8 playlist content'); - } - this._playlist = this._extractUrlsAndQualities(playlistContent); - return this._playlist; - } - - /** - * Retrieves the playlist. - * - * @return {Array<{quality: number, resolution: string, url: string}>} The playlist. - */ - getPlaylist() { - return this._playlist; - } - - _sortPlaylistByQuality(ascending = true) { - return [...this._playlist].sort((a, b) => { - const heightA = parseInt(a.resolution.split('x')[1], 10); - const heightB = parseInt(b.resolution.split('x')[1], 10); - return ascending ? heightA - heightB : heightB - heightA; - }); - } - - /** - * Retrieves the highest quality item from the playlist. - * - * @return {Object|null} The highest quality item from the playlist, or null if the playlist is empty. - */ - getHighestQuality() { - if (this._playlist.length === 0) { - return null; - } - return this._sortPlaylistByQuality(false)[0]; // Retornar o item de maior qualidade - } - - /** - * Retrieves the lowest quality item from the playlist. - * - * @return {Object|null} The lowest quality item from the playlist, or null if the playlist is empty. - */ - getLowestQuality() { - if (this._playlist.length === 0) { - return null; - } - return this._sortPlaylistByQuality(true)[0]; // Retornar o item de menor qualidade - } + /** + * Creates a new instance of M3U8Playlist. + * @param {string} m3u8Url - The URL of the M3U8 playlist. + * @returns {M3U8Service} - The newly created M3U8Playlist instance. + */ + constructor(m3u8Url) { + if (!this._isValidUrl(m3u8Url)) { + throw new Error("Invalid URL"); + } + this._m3u8Url = m3u8Url; + /** @type {Array<{quality: number, resolution: string, url: string}>} */ + this._playlist = []; + } + + /** + * Validates the URL. + * @param {string} url - The URL to validate. + * @returns {boolean} - True if the URL is valid, false otherwise. + */ + _isValidUrl(url) { + try { + new URL(url); + return true; + } catch (_) { + return false; + } + } + + /** + * Checks if the content is a valid M3U8 playlist. + * @param {string} content - The content to check. + * @returns {boolean} - True if the content is a valid M3U8 playlist, false otherwise. + */ + _isValidM3U8Content(content) { + return content.startsWith("#EXTM3U"); + } + + /** + * Extracts URLs and qualities from an M3U8 playlist content. + * @param {string} m3u8Content - The content of the M3U8 playlist. + * @returns {Array<{quality: number, resolution: string, url: string}>} - An array of objects containing the quality, + * resolution, and URL of each playlist. + */ + _extractUrlsAndQualities(m3u8Content) { + const lines = m3u8Content.split("\n"); + const urlsAndQualities = []; + + let currentResolution = null; + let currentQuality = null; + + lines.forEach((line) => { + if (line.startsWith("#EXT-X-STREAM-INF")) { + const match = line.match(/RESOLUTION=(\d+x\d+)/); + if (match) { + currentResolution = match[1]; + currentQuality = parseInt(match[1].split("x")[1], 10); + } + } else if (line.startsWith("http")) { + if (currentResolution) { + urlsAndQualities.push({ + quality: currentQuality, + resolution: currentResolution, + url: line, + }); + currentResolution = null; + currentQuality = null; + } + } + }); + + return urlsAndQualities; + } + + /** + * Fetches a file from the given URL. + * + * @param {string} url - The URL of the file to fetch. + * @param {boolean} [isBinary=false] - Whether the file is binary or text. + * @param {number} [maxRetries=3] - The maximum number of retries to fetch the file. + * @returns {Promise} - A promise that resolves with the file content. + * @throws {Error} - If the file fails to load after multiple attempts. + */ + static async getFile(url, isBinary = false, maxRetries = 3) { + let retries = 0; + + while (retries < maxRetries) { + try { + const response = await fetch(url); + + if (!response.ok) { + throw new Error(`Failed to fetch ${isBinary ? "binary" : "text"} file: ${response.statusText}`); + } + + return isBinary ? await response.arrayBuffer() : await response.text(); + } catch (error) { + retries++; + } + } + + throw new Error("Failed to load file after multiple attempts"); + } + + /** + * Loads the M3U8 playlist. + * + * @param {number} [maxRetries=3] - The maximum number of retries to fetch the playlist. + * @returns {Promise} - A promise that resolves when the playlist is loaded successfully. + * @throws {Error} - If the playlist fails to load after multiple attempts. + */ + async loadPlaylist(maxRetries = 3) { + const playlistContent = await M3U8Service.getFile(this._m3u8Url, false, maxRetries); + if (!this._isValidM3U8Content(playlistContent)) { + throw new Error("Invalid M3U8 playlist content"); + } + this._playlist = this._extractUrlsAndQualities(playlistContent); + return this._playlist; + } + + /** + * Retrieves the playlist. + * + * @return {Array<{quality: number, resolution: string, url: string}>} The playlist. + */ + getPlaylist() { + return this._playlist; + } + + _sortPlaylistByQuality(ascending = true) { + return [...this._playlist].sort((a, b) => { + const heightA = parseInt(a.resolution.split("x")[1], 10); + const heightB = parseInt(b.resolution.split("x")[1], 10); + return ascending ? heightA - heightB : heightB - heightA; + }); + } + + /** + * Retrieves the highest quality item from the playlist. + * + * @return {Object|null} The highest quality item from the playlist, or null if the playlist is empty. + */ + getHighestQuality() { + if (this._playlist.length === 0) { + return null; + } + return this._sortPlaylistByQuality(false)[0]; // Retornar o item de maior qualidade + } + + /** + * Retrieves the lowest quality item from the playlist. + * + * @return {Object|null} The lowest quality item from the playlist, or null if the playlist is empty. + */ + getLowestQuality() { + if (this._playlist.length === 0) { + return null; + } + return this._sortPlaylistByQuality(true)[0]; // Retornar o item de menor qualidade + } } module.exports = M3U8Service; diff --git a/app/core/services/udemy.service.js b/app/core/services/udemy.service.js index bd850d0c..2c99b857 100644 --- a/app/core/services/udemy.service.js +++ b/app/core/services/udemy.service.js @@ -1,372 +1,388 @@ "use strict"; -const axios = require('axios'); -const NodeCache = require('node-cache'); +const axios = require("axios"); +const NodeCache = require("node-cache"); const M3U8Service = require("./m3u8.service"); class UdemyService { - #timeout = 40000; - #headerAuth = null; - - #urlBase; - #urlLogin; - #URL_COURSES = "/users/me/subscribed-courses"; - #URL_COURSES_ENROLL = "/users/me/subscription-course-enrollments"; - #ASSETS_FIELDS = "&fields[asset]=asset_type,title,filename,body,captions,media_sources,stream_urls,download_urls,external_url,media_license_token"; - - #cache = new NodeCache({ stdTTL: 3600 }); // TTL padrão de 1 hora - - constructor(subDomain = "www", httpTimeout = 40000) { - subDomain = (subDomain.trim().length === 0 ? "www" : subDomain.trim()).toLowerCase(); - - this.#urlBase = `https://${subDomain}.udemy.com`; - this.#timeout = httpTimeout; - this.#headerAuth = null; - this.#urlLogin = `${this.#urlBase}/join/login-popup`; - } - - /** - * Creates and returns a new Error object with the specified name and message. - * - * @param {string} name - The name of the error. - * @param {string} [message=""] - The optional error message. Default is an empty string. - * @returns {Error} The newly created Error object. - */ - _error(name, message = "") { - const error = new Error(); - error.name = name; - error.message = message; - return error; - } - - async _prepareStreamSource(courseId, el) { - try { - if (el._class === "lecture") { - const assetType = el.asset?.asset_type.toLowerCase(); - if (assetType === "video" || assetType === "videomashup") { - const asset = el.asset; - const stream_urls = asset.stream_urls?.Video || asset.media_sources; - const isEncrypted = Boolean(asset.media_license_token); - if (stream_urls) { - // console.log(`Preparing streams for asset id: ${asset.id}`); - const streams = await this._convertToStreams(stream_urls, isEncrypted, asset.title); - - delete el.asset.stream_urls; - delete el.asset.media_sources; - el.asset.streams = streams; - } - } else if (assetType === "presentation") { - const lecture = await this.fetchLecture(courseId, el.id, true, true); - el.asset = lecture.asset; - el.supplementary_assets = lecture.supplementary_assets; - } - } - } catch (error) { - throw this._error("EPREPARE_STREAM_SOURCE", error.message); - } - } - - async _prepareStreamsSource(courseId, items) { - // console.log("Preparing stream urls...", items); - try { - const promises = items.map(el => this._prepareStreamSource(courseId, el)); - await Promise.all(promises); - // console.log("All streams prepared"); - } catch (error) { - throw this._error("EPREPARE_STREAMS_SOURCE", error.message); - } - } - - /** - * Transforms media sources into a standardized format. - * - * @param {Array} streamUrls - The array of stream URLs. - * @param {boolean} isEncrypted - Indicates if the media is encrypted. - * @returns {Promise<{ - * minQuality: string, - * maxQuality: string, - * isEncrypted: boolean - * sources: { [key: string]: { type: string, url: string } } - * }>} - The transformed media sources. - */ - async _convertToStreams(streamUrls, isEncrypted, title = "") { - try { - if (!streamUrls) { - throw this._error("ENO_STREAMS", "No streams found to convert"); - } - const sources = {}; - let minQuality = Number.MAX_SAFE_INTEGER; - let maxQuality = Number.MIN_SAFE_INTEGER; - - let streams = !isEncrypted ? streamUrls : streamUrls.filter(v => !(v.file || v.src).includes("/encrypted-files")); - isEncrypted = isEncrypted ? (streams.length === 0) : isEncrypted; - - streams = streams.length > 0 ? streams : streamUrls; - - const promises = streams.map(async video => { - const type = video.type; - if (type !== "application/dash+xml") { - - const quality = video.label.toLowerCase(); - const url = video.file || video.src; - - sources[quality] = { type, url }; - - if (quality !== "auto") { - const numericQuality = parseInt(quality, 10); - if (!isNaN(numericQuality)) { - if (numericQuality < minQuality) { - minQuality = numericQuality; - } - if (numericQuality > maxQuality) { - maxQuality = numericQuality; - } - } - } else { - // auto - if (!isEncrypted) { - const m3u8 = new M3U8Service(url); - // console.log('Before loading playlist'); - const playlist = await m3u8.loadPlaylist(); - // console.log('After loading playlist', playlist); - - for (const item of playlist) { - // console.log(`for of playlist ${title}`, item); - const numericQuality = item.quality; - - if (numericQuality < minQuality) { - minQuality = numericQuality; - } - if (numericQuality > maxQuality) { - maxQuality = numericQuality; - } - if (!sources[numericQuality.toString()]) { - sources[numericQuality.toString()] = { type, url: item.url } - } - } - - // playlist.forEach(item => { - // const numericQuality = item.quality; - - // if (numericQuality < minQuality) { - // minQuality = numericQuality; - // } - // if (numericQuality > maxQuality) { - // maxQuality = numericQuality; - // } - // if (!sources[numericQuality.toString()]) { - // sources[numericQuality.toString()] = { type, url: item.url } - // } - // }); - } - } - } - }); - - await Promise.all(promises); - // console.log(`All stream urls converted for assetName: ${title}`); - - return { - minQuality: minQuality === Number.MAX_SAFE_INTEGER ? "auto" : minQuality.toString(), - maxQuality: maxQuality === Number.MIN_SAFE_INTEGER ? "auto" : maxQuality.toString(), - isEncrypted, - sources - }; - } catch (error) { - throw this._error("ECONVERT_TO_STREAMS", error.message); - } - } - - async #fetchUrl(url, method = "GET", httpTimeout = this.#timeout) { - url = `${this.#urlBase}/api-2.0${url}`; - - // Verifique o cache antes de fazer a requisição - const cachedData = this.#cache.get(url); - if (cachedData) { - // console.log(`Cache hit: ${url}`); - return cachedData; - } - - // console.log(`Fetching URL: ${url}`); - try { - const response = await axios({ - url, - method, - headers: this.#headerAuth, - timeout: this.#timeout, - }); - - // Armazene o resultado no cache - this.#cache.set(url, response.data); - return response.data; - } catch (e) { - console.error(`Error fetching URL: ${url}`, e); - throw e; - } - } - - async fetchLoadMore(url, httpTimeout = this.#timeout) { - // Verifique o cache antes de fazer a requisição - const cachedData = this.#cache.get(url); - if (cachedData) { - // console.log(`Cache hit: ${url}`); - return cachedData; - } - - // console.log(`Fetching URL: ${url}`); - try { - const response = await axios({ - url, - method: "GET", - headers: this.#headerAuth, - timeout: this.#timeout, - }); - - // Armazene o resultado no cache - this.#cache.set(url, response.data); - return response.data; - } catch (e) { - console.error(`Error fetching URL: ${url}`, e); - throw e; - } - } - - async fetchProfile(accessToken, httpTimeout = this.#timeout) { - this.#headerAuth = { Authorization: `Bearer ${accessToken}` }; - // return await this._fetchUrl("https://www.udemy.com/api-2.0/users/me"); - return await this.#fetchUrl("/contexts/me/?header=True"); - } - - async fetchSearchCourses(keyword, pageSize, isSubscriber, httpTimeout = this.#timeout) { - if (!keyword) { - return await this.fetchCourses(pageSize, isSubscriber, httpTimeout); - } - - pageSize = Math.max(pageSize, 10); - - const param = `page=1&ordering=title&fields[user]=job_title&page_size=${pageSize}&search=${keyword}`; - const url = !isSubscriber - ? `${this.#URL_COURSES}?${param}` - : `${this.#URL_COURSES_ENROLL}?${param}`; - - return await this.#fetchUrl(url, "GET", httpTimeout); - } - - async fetchCourses(pageSize = 30, isSubscriber = false, httpTimeout = this.#timeout) { - pageSize = Math.max(pageSize, 10); - - const param = `page_size=${pageSize}&ordering=-last_accessed`; - const url = !isSubscriber - ? `${this.#URL_COURSES}?${param}` - : `${this.#URL_COURSES_ENROLL}?${param}`; - - return await this.#fetchUrl(url, "GET", httpTimeout); - } - - async fetchCourse(courseId, httpTimeout = this.#timeout) { - const url = `/courses/${courseId}/cached-subscriber-curriculum-items?page_size=10000`; - return await this.#fetchUrl(url, "GET", httpTimeout); - } - - /** - * Fetches the lecture data for a given course and lecture ID. - * - * @param {number} courseId - The ID of the course. - * @param {number} lectureId - The ID of the lecture. - * @param {boolean} getAttachments - Whether to get supplementary assets. Defaults to false. - * @return {Promise} - The lecture data. - */ - async fetchLecture(courseId, lectureId, getAttachments, allAssets = false, httpTimeout = this.#timeout) { - let url = `/users/me/subscribed-courses/${courseId}/lectures/${lectureId}?fields[lecture]=id,title,asset${getAttachments ? ",supplementary_assets" : ""}` - url += allAssets ? "&fields[asset]=@all" : this.#ASSETS_FIELDS; - - const lectureData = await this.#fetchUrl(`${url}`, "GET", httpTimeout); - // console.log("fetchLecture", lectureData); - // await this._prepareStreamSource(lectureData); - - return lectureData; - } - - async fetchLectureAttachments(lectureId, httpTimeout = this.#timeout) { - const url = `/lectures/${lectureId}/supplementary-assets`; - return await this.#fetchUrl(url); - } - - /** - * Fetches the course content for a given course ID and content type. - * - * @param {number} courseId - The ID of the course. - * @param {'less' | 'all' | 'lectures' | 'attachments'} [contentType='all'] - The type of content to fetch. - * @return {Promise} - The course content data. - */ - async fetchCourseContent(courseId, contentType, httpTimeout = this.#timeout) { - let url = `/courses/${courseId}/cached-subscriber-curriculum-items?page_size=10000` - - contentType = (contentType || "less").toLowerCase(); - if (contentType !== "less") url += "&fields[lecture]=id,title"; - if (contentType === "all") url += ",asset,supplementary_assets"; - if (contentType === "lectures") url += ",asset"; - if (contentType === "attachments") url += ",supplementary_assets"; - if (contentType !== "less") url += this.#ASSETS_FIELDS; - - let contentData = null; - let loadContent = false; - - try { - contentData = await this.#fetchUrl(url); - } - catch (error) { - if (error?.response?.status === 503) { - contentData = await this.fetchCourse(courseId, httpTimeout); - loadContent = contentType !== "less"; - } else { - throw error; - } - } - - if (!contentData || contentData.count == 0) { - return null; - } - - if (contentData.results[0]._class !== "chapter") { - contentData.results.unshift({ - id: 0, - _class: "chapter", - title: "Chapter 1", - }); - contentData.count++; - } - - if (loadContent) { - const promises = contentData.results.map(async (el) => { - if (el._class === "lecture") { - const lecture = await this.fetchLecture(courseId, el.id, true, false, httpTimeout); - el.asset = lecture.asset; - el.supplementary_assets = lecture.supplementary_assets; - } - return el; - }); - await Promise.all(promises); - } - - await this._prepareStreamsSource(courseId, contentData.results); - // console.log("fetchCourseContent", contentData); - return contentData; - } - - get urlBase() { - return this.#urlBase; - } - get urlLogin() { - return this.#urlLogin; - } - - get timeout() { - return this.#timeout; - } - set timeout(value) { - this.#timeout = value; - } + #timeout = 40000; + #headerAuth = null; + + #urlBase; + #urlLogin; + #URL_COURSES = "/users/me/subscribed-courses"; + #URL_COURSES_ENROLL = "/users/me/subscription-course-enrollments"; + #ASSETS_FIELDS = "&fields[asset]=asset_type,title,filename,body,captions,media_sources,stream_urls,download_urls,external_url,media_license_token"; + + #cache = new NodeCache({ stdTTL: 3600 }); // TTL padrão de 1 hora + + constructor(subDomain = "www", httpTimeout = 40000) { + subDomain = (subDomain.trim().length === 0 ? "www" : subDomain.trim()).toLowerCase(); + + this.#urlBase = `https://${subDomain}.udemy.com`; + this.#timeout = httpTimeout; + this.#headerAuth = null; + this.#urlLogin = `${this.#urlBase}/join/login-popup`; + } + + /** + * Creates and returns a new Error object with the specified name and message. + * + * @param {string} name - The name of the error. + * @param {string} [message=""] - The optional error message. Default is an empty string. + * @returns {Error} The newly created Error object. + */ + _error(name, message = "") { + const error = new Error(); + error.name = name; + error.message = message; + return error; + } + + async _prepareStreamSource(courseId, el) { + try { + if (el._class === "lecture") { + const assetType = el.asset?.asset_type.toLowerCase(); + if (assetType === "video" || assetType === "videomashup") { + const asset = el.asset; + const stream_urls = asset.stream_urls?.Video || asset.media_sources; + const isEncrypted = Boolean(asset.media_license_token); + if (stream_urls) { + // console.log(`Preparing streams for asset id: ${asset.id}`); + const streams = await this._convertToStreams(stream_urls, isEncrypted, asset.title); + + delete el.asset.stream_urls; + delete el.asset.media_sources; + el.asset.streams = streams; + } + } else if (assetType === "presentation") { + const lecture = await this.fetchLecture(courseId, el.id, true, true); + el.asset = lecture.asset; + el.supplementary_assets = lecture.supplementary_assets; + } + } + } catch (error) { + throw this._error("EPREPARE_STREAM_SOURCE", error.message); + } + } + + async _prepareStreamsSource(courseId, items) { + // console.log("Preparing stream urls...", items); + try { + const promises = items.map((el) => this._prepareStreamSource(courseId, el)); + await Promise.all(promises); + // console.log("All streams prepared"); + } catch (error) { + throw this._error("EPREPARE_STREAMS_SOURCE", error.message); + } + } + + /** + * Transforms media sources into a standardized format. + * + * @param {Array} streamUrls - The array of stream URLs. + * @param {boolean} isEncrypted - Indicates if the media is encrypted. + * @returns {Promise<{ + * minQuality: string|null, + * maxQuality: string|null, + * isEncrypted: boolean + * sources: { [key: string]: { type: string, url: string } } + * }>} - The transformed media sources. + */ + async _convertToStreams(streamUrls, isEncrypted, title = "") { + try { + if (!streamUrls) { + throw this._error("ENO_STREAMS", "No streams found to convert"); + } + const sources = {}; + let minQuality = Number.MAX_SAFE_INTEGER; + let maxQuality = Number.MIN_SAFE_INTEGER; + + let streams = !isEncrypted ? streamUrls : streamUrls.filter((v) => !(v.file || v.src).includes("/encrypted-files")); + isEncrypted = isEncrypted ? streams.length === 0 : isEncrypted; + + streams = streams.length > 0 ? streams : streamUrls; + + const promises = streams.map(async (video) => { + const type = video.type; + if (type !== "application/dash+xml") { + const quality = video.label.toLowerCase(); + const url = video.file || video.src; + + sources[quality] = { type, url }; + + if (quality !== "auto") { + const numericQuality = parseInt(quality, 10); + if (!isNaN(numericQuality)) { + if (numericQuality < minQuality) { + minQuality = numericQuality; + } + if (numericQuality > maxQuality) { + maxQuality = numericQuality; + } + } + } else { + // auto + if (!isEncrypted) { + const m3u8 = new M3U8Service(url); + // console.log('Before loading playlist'); + const playlist = await m3u8.loadPlaylist(); + // console.log('After loading playlist', playlist); + + for (const item of playlist) { + // console.log(`for of playlist ${title}`, item); + const numericQuality = item.quality; + + if (numericQuality < minQuality) { + minQuality = numericQuality; + } + if (numericQuality > maxQuality) { + maxQuality = numericQuality; + } + if (!sources[numericQuality.toString()]) { + sources[numericQuality.toString()] = { type, url: item.url }; + } + } + + // playlist.forEach(item => { + // const numericQuality = item.quality; + + // if (numericQuality < minQuality) { + // minQuality = numericQuality; + // } + // if (numericQuality > maxQuality) { + // maxQuality = numericQuality; + // } + // if (!sources[numericQuality.toString()]) { + // sources[numericQuality.toString()] = { type, url: item.url } + // } + // }); + } + } + } + }); + + await Promise.all(promises); + // console.log(`All stream urls converted for assetName: ${title}`); + + return { + minQuality: minQuality === Number.MAX_SAFE_INTEGER ? (sources["auto"] ? "auto" : null) : minQuality.toString(), + maxQuality: maxQuality === Number.MIN_SAFE_INTEGER ? (sources["auto"] ? "auto" : null) : maxQuality.toString(), + isEncrypted, + sources, + }; + } catch (error) { + throw this._error("ECONVERT_TO_STREAMS", error.message); + } + } + + async #fetchUrl(url, method = "GET", httpTimeout = this.#timeout) { + // Verifique o cache antes de fazer a requisição + const cachedData = this.#cache.get(url); + if (cachedData) { + // console.log(`Cache hit: ${url}`); + return cachedData; + } + + console.log(`Fetching URL: ${url}`); + try { + const response = await axios({ + url, + method, + headers: this.#headerAuth, + timeout: this.#timeout, + }); + + // Armazene o resultado no cache + this.#cache.set(url, response.data); + return response.data; + } catch (e) { + console.error(`Error fetching URL: ${url}`, e); + throw e; + } + } + + async #fetchEndpoint(endpoint, method = "GET", httpTimeout = this.#timeout) { + endpoint = `${this.#urlBase}/api-2.0${endpoint}`; + return await this.#fetchUrl(endpoint, method, httpTimeout); + } + + async fetchLoadMore(url, httpTimeout = this.#timeout) { + // Verifique o cache antes de fazer a requisição + const cachedData = this.#cache.get(url); + if (cachedData) { + // console.log(`Cache hit: ${url}`); + return cachedData; + } + + // console.log(`Fetching URL: ${url}`); + try { + const response = await axios({ + url, + method: "GET", + headers: this.#headerAuth, + timeout: this.#timeout, + }); + + // Armazene o resultado no cache + this.#cache.set(url, response.data); + return response.data; + } catch (e) { + console.error(`Error fetching URL: ${url}`, e); + throw e; + } + } + + async fetchProfile(accessToken, httpTimeout = this.#timeout) { + this.#headerAuth = { Authorization: `Bearer ${accessToken}` }; + // return await this._fetchUrl("https://www.udemy.com/api-2.0/users/me"); + return await this.#fetchEndpoint("/contexts/me/?header=True"); + } + + async fetchSearchCourses(keyword, pageSize, isSubscriber, httpTimeout = this.#timeout) { + if (!keyword) { + return await this.fetchCourses(pageSize, isSubscriber, httpTimeout); + } + + pageSize = Math.max(pageSize, 10); + + const param = `page=1&ordering=title&fields[user]=job_title&page_size=${pageSize}&search=${keyword}`; + const url = !isSubscriber ? `${this.#URL_COURSES}?${param}` : `${this.#URL_COURSES_ENROLL}?${param}`; + + return await this.#fetchEndpoint(url, "GET", httpTimeout); + } + + async fetchCourses(pageSize = 30, isSubscriber = false, httpTimeout = this.#timeout) { + pageSize = Math.max(pageSize, 10); + + const param = `page_size=${pageSize}&ordering=-last_accessed`; + const url = !isSubscriber ? `${this.#URL_COURSES}?${param}` : `${this.#URL_COURSES_ENROLL}?${param}`; + + return await this.#fetchEndpoint(url, "GET", httpTimeout); + } + + async fetchCourse(courseId, httpTimeout = this.#timeout) { + const url = `/courses/${courseId}/cached-subscriber-curriculum-items?page_size=10000&fields[lecture]=id,title,asset`; + return await this.#fetchEndpoint(url, "GET", httpTimeout); + } + + /** + * Fetches the lecture data for a given course and lecture ID. + * + * @param {number} courseId - The ID of the course. + * @param {number} lectureId - The ID of the lecture. + * @param {boolean} getAttachments - Whether to get supplementary assets. Defaults to false. + * @return {Promise} - The lecture data. + */ + async fetchLecture(courseId, lectureId, getAttachments, allAssets = false, httpTimeout = this.#timeout) { + let url = `/users/me/subscribed-courses/${courseId}/lectures/${lectureId}?fields[lecture]=id,title,asset${getAttachments ? ",supplementary_assets" : ""}`; + url += allAssets ? "&fields[asset]=@all" : this.#ASSETS_FIELDS; + + const lectureData = await this.#fetchEndpoint(`${url}`, "GET", httpTimeout); + // console.log("fetchLecture", lectureData); + // await this._prepareStreamSource(lectureData); + + return lectureData; + } + + async fetchLectureAttachments(lectureId, httpTimeout = this.#timeout) { + const url = `/lectures/${lectureId}/supplementary-assets`; + return await this.#fetchEndpoint(url); + } + + /** + * Fetches the course content for a given course ID and content type. + * + * @param {number} courseId - The ID of the course. + * @param {'less' | 'all' | 'lectures' | 'attachments'} [contentType='all'] - The type of content to fetch. + * @return {Promise} - The course content data. + */ + async fetchCourseContent(courseId, contentType, httpTimeout = this.#timeout) { + let url = `${this.#urlBase}/api-2.0/courses/${courseId}/cached-subscriber-curriculum-items?page_size=200`; + + contentType = (contentType || "less").toLowerCase(); + if (contentType !== "less") url += "&fields[lecture]=id,title"; + if (contentType === "all") url += ",asset,supplementary_assets"; + if (contentType === "lectures") url += ",asset"; + if (contentType === "attachments") url += ",supplementary_assets"; + if (contentType !== "less") url += this.#ASSETS_FIELDS; + + let contentData = null; + let loadContent = false; + + try { + // contentData = await this.#fetchEndpoint(url); + do { + const resp = await this.#fetchUrl(url); + if (!contentData) { + contentData = resp; + } else { + contentData.results.push(...resp.results); + } + + if (resp.next) { + url = decodeURI(resp.next); + url = url.replace(/%5B/g, "[").replace(/%5D/g, "]").replace(/%2C/g, ","); + } + + loadContent = resp.next != null; + } while (loadContent); + + loadContent = false; + } catch (error) { + if (error?.response?.status === 503) { + contentData = await this.fetchCourse(courseId, httpTimeout); + loadContent = contentType !== "less"; + } else { + throw error; + } + } + + if (!contentData || contentData.count == 0) { + return null; + } + + if (contentData.results[0]._class !== "chapter") { + contentData.results.unshift({ + id: 0, + _class: "chapter", + title: "Chapter 1", + }); + contentData.count++; + } + + if (loadContent) { + const promises = contentData.results.map(async (el) => { + if (el._class === "lecture") { + const lecture = await this.fetchLecture(courseId, el.id, true, false, httpTimeout); + el.asset = lecture.asset; + el.supplementary_assets = lecture.supplementary_assets; + } + return el; + }); + await Promise.all(promises); + } + + contentData.count = contentData.results.length; + + await this._prepareStreamsSource(courseId, contentData.results); + // console.log("fetchCourseContent", contentData); + return contentData; + } + + get urlBase() { + return this.#urlBase; + } + get urlLogin() { + return this.#urlLogin; + } + + get timeout() { + return this.#timeout; + } + set timeout(value) { + this.#timeout = value; + } } module.exports = UdemyService; diff --git a/app/helpers/auto_authenticator.js b/app/helpers/auto_authenticator.js index e8e70511..98d7063c 100644 --- a/app/helpers/auto_authenticator.js +++ b/app/helpers/auto_authenticator.js @@ -1,34 +1,33 @@ - -// var awaitingLogin = false; -// const server = require("http").createServer(); -// const socketIO = require("socket.io")(server); - -// const $loginAuthenticator = $(".ui.login.authenticator"); - -// server.listen(50490); -// socketIO.on("connect", function (socket) { -// console.log('io.onConnect'); -// $loginAuthenticator.removeClass("disabled"); - -// socket.on("disconnect", function () { -// console.log('socket.onDisconnect'); -// $loginAuthenticator.addClass("disabled"); -// $(".ui.authenticator.dimmer").removeClass("active"); -// awaitingLogin = false; -// }); - -// $loginAuthenticator.click(function () { -// $(".ui.authenticator.dimmer").addClass("active"); -// awaitingLogin = true; -// socket.emit("awaitingLogin"); -// }); - -// socket.on("newLogin", function (data) { -// console.log('socket.onNewLogin'); -// if (awaitingLogin) { -// settings.set("access_token", data.access_token); -// settings.set("subdomain", data.subdomain); -// checkLogin(); -// } -// }); -// }); \ No newline at end of file +// var awaitingLogin = false; +// const server = require("http").createServer(); +// const socketIO = require("socket.io")(server); + +// const $loginAuthenticator = $(".ui.login.authenticator"); + +// server.listen(50490); +// socketIO.on("connect", function (socket) { +// console.log('io.onConnect'); +// $loginAuthenticator.removeClass("disabled"); + +// socket.on("disconnect", function () { +// console.log('socket.onDisconnect'); +// $loginAuthenticator.addClass("disabled"); +// $(".ui.authenticator.dimmer").removeClass("active"); +// awaitingLogin = false; +// }); + +// $loginAuthenticator.click(function () { +// $(".ui.authenticator.dimmer").addClass("active"); +// awaitingLogin = true; +// socket.emit("awaitingLogin"); +// }); + +// socket.on("newLogin", function (data) { +// console.log('socket.onNewLogin'); +// if (awaitingLogin) { +// settings.set("access_token", data.access_token); +// settings.set("subdomain", data.subdomain); +// checkLogin(); +// } +// }); +// }); diff --git a/app/helpers/index.js b/app/helpers/index.js index 76d4bd9a..928abfe5 100644 --- a/app/helpers/index.js +++ b/app/helpers/index.js @@ -1,5 +1,5 @@ -const Settings = require("./settings"); -const ui = require("./ui"); -const utils = require("./utils"); - -module.exports = { Settings, ui, utils, } \ No newline at end of file +const Settings = require("./settings"); +const ui = require("./ui"); +const utils = require("./utils"); + +module.exports = { Settings, ui, utils }; diff --git a/app/helpers/settings.js b/app/helpers/settings.js index d0e91342..9efdcdbc 100644 --- a/app/helpers/settings.js +++ b/app/helpers/settings.js @@ -3,7 +3,7 @@ * @property {number} Both * @property {number} OnlyLectures * @property {number} OnlyAttachments -*/ + */ /** * @typedef {Object} DownloadSetting @@ -48,174 +48,173 @@ */ const Settings = (() => { - "use strict" - - const settings = require("electron-settings"); - const path = require("path"); - const { homedir } = require("os"); - - /** @type {DownloadTypeSetting} */ - const DownloadType = Object.freeze({ - Both: 0, - OnlyLectures: 1, - OnlyAttachments: 2 - }); - - /** @type {DownloadSetting} */ - const DownloadDefaultOptions = Object.freeze({ - checkNewVersion: true, - defaultSubtitle: undefined, - path: path.join(homedir(), "Downloads", "Udeler"), - autoStartDownload: false, - continueDonwloadingEncrypted: false, - enableDownloadStartEnd: false, - downloadStart: 0, - downloadEnd: 0, - type: DownloadType.Both, - skipSubtitles: false, - autoRetry: false, - videoQuality: "Auto", - seqZeroLeft: false, - }); - - let _language = null; - let _prettify = false; - - /** - * Ensures all default keys are set in the settings - * @internal - * @returns {void} - */ - function ensureDefaultKeys() { - if (!settings.get("language")) { - settings.set("language", getLanguage()); - } - - if (!settings.get("download")) { - settings.set("download", DownloadDefaultOptions); - } else { - // certifica que exista todas as propriedades - Object.keys(DownloadDefaultOptions).forEach(key => { - settings.get(`download.${key}`, DownloadDefaultOptions[key]); - }); - } - } - - /** - * Get navigator default language and set in settings "language" - * - * @returns defined language - */ - function getLanguage() { - try { - let language = settings.get("language"); - - if (!language) { - const navigatorLang = navigator.language.substring(0, 2); - const meta = require("../locale/meta.json"); - - language = Object.keys(meta).find(key => meta[key] === (navigatorLang === 'pt' ? 'pt_BR.json' : `${navigatorLang}.json`)); - - if (language) { - settings.set("language", language, { prettify: _prettify }); - } - } - - return language || "English"; - - } catch (error) { - console.error("Error_Settings getLanguage(): " + error); - return "English"; - } - } - - /** - * Get the download directory for a given course - * @param {string} courseName - The name of the course - * @returns {string} - The download directory path - */ - function downloadDirectory(courseName = "") { - const download_dir = settings.get("download.path") || DownloadDefaultOptions.path; - return path.join(download_dir, courseName); - } - - // Initialize settings - (function init() { - console.log('Initialize settings'); - _prettify = process.env.PRETTIFY_SETTINGS || false; - ensureDefaultKeys(); - })(); - - return { - DownloadType, - DownloadDefaultOptions, - /** @param {String, Object} */ - get: (keyPath, defaultValue = undefined) => settings.get(keyPath, defaultValue), - /** @param {String, Object} */ - set: (keyPath, value) => settings.set(keyPath, value, { prettify: _prettify }), - /** @type {string} */ - get language() { - if (!_language) { - _language = getLanguage(); - } - return _language; - }, - /** @type {string} */ - set language(value) { - this.set("language", value || null); - _language = value; - }, - /** @type {string} */ - get subDomain() { - return this.get("subdomain", "www"); - }, - /** @type {string} */ - set subDomain(value) { - this.set("subdomain", value); - }, - /** @type {string} */ - get accessToken() { - return this.get("access_token"); - }, - /** @type {string} */ - set accessToken(value) { - this.set("access_token", value || null); - }, - /** @type {boolean} */ - get subscriber() { - return Boolean(this.get("subscriber")); - }, - /** @type {boolean} */ - set subscriber(value) { - this.set("subscriber", value); - }, - /** @type {DownloadSetting} */ - get download() { - return this.get("download"); - }, - /** @type {DownloadSetting} */ - set download(value) { - this.set("download", value); - }, - /** @type {Array} */ - get downloadHistory() { - return this.get("downloadedHistory", []); - }, - /** @type {Array} */ - set downloadHistory(value) { - this.set("downloadedHistory", value); - }, - /** @type {Array} */ - get downloadedCourses() { - return this.get("downloadedCourses"); - }, - /** @type {Array} */ - set downloadedCourses(value) { - this.set("downloadedCourses", value); - }, - /** @param {String} */ - downloadDirectory: (courseName) => downloadDirectory(courseName), - }; + "use strict"; + + const settings = require("electron-settings"); + const path = require("path"); + const { homedir } = require("os"); + + /** @type {DownloadTypeSetting} */ + const DownloadType = Object.freeze({ + Both: 0, + OnlyLectures: 1, + OnlyAttachments: 2, + }); + + /** @type {DownloadSetting} */ + const DownloadDefaultOptions = Object.freeze({ + checkNewVersion: true, + defaultSubtitle: undefined, + path: path.join(homedir(), "Downloads", "Udeler"), + autoStartDownload: false, + continueDonwloadingEncrypted: false, + enableDownloadStartEnd: false, + downloadStart: 0, + downloadEnd: 0, + type: DownloadType.Both, + skipSubtitles: false, + autoRetry: false, + videoQuality: "Auto", + seqZeroLeft: false, + }); + + let _language = null; + let _prettify = false; + + /** + * Ensures all default keys are set in the settings + * @internal + * @returns {void} + */ + function ensureDefaultKeys() { + if (!settings.get("language")) { + settings.set("language", getLanguage()); + } + + if (!settings.get("download")) { + settings.set("download", DownloadDefaultOptions); + } else { + // certifica que exista todas as propriedades + Object.keys(DownloadDefaultOptions).forEach((key) => { + settings.get(`download.${key}`, DownloadDefaultOptions[key]); + }); + } + } + + /** + * Get navigator default language and set in settings "language" + * + * @returns defined language + */ + function getLanguage() { + try { + let language = settings.get("language"); + + if (!language) { + const navigatorLang = navigator.language.substring(0, 2); + const meta = require("../locale/meta.json"); + + language = Object.keys(meta).find((key) => meta[key] === (navigatorLang === "pt" ? "pt_BR.json" : `${navigatorLang}.json`)); + + if (language) { + settings.set("language", language, { prettify: _prettify }); + } + } + + return language || "English"; + } catch (error) { + console.error("Error_Settings getLanguage(): " + error); + return "English"; + } + } + + /** + * Get the download directory for a given course + * @param {string} courseName - The name of the course + * @returns {string} - The download directory path + */ + function downloadDirectory(courseName = "") { + const download_dir = settings.get("download.path") || DownloadDefaultOptions.path; + return path.join(download_dir, courseName); + } + + // Initialize settings + (function init() { + console.log("Initialize settings"); + _prettify = process.env.PRETTIFY_SETTINGS || false; + ensureDefaultKeys(); + })(); + + return { + DownloadType, + DownloadDefaultOptions, + /** @param {String, Object} */ + get: (keyPath, defaultValue = undefined) => settings.get(keyPath, defaultValue), + /** @param {String, Object} */ + set: (keyPath, value) => settings.set(keyPath, value, { prettify: _prettify }), + /** @type {string} */ + get language() { + if (!_language) { + _language = getLanguage(); + } + return _language; + }, + /** @type {string} */ + set language(value) { + this.set("language", value || null); + _language = value; + }, + /** @type {string} */ + get subDomain() { + return this.get("subdomain", "www"); + }, + /** @type {string} */ + set subDomain(value) { + this.set("subdomain", value); + }, + /** @type {string} */ + get accessToken() { + return this.get("access_token"); + }, + /** @type {string} */ + set accessToken(value) { + this.set("access_token", value || null); + }, + /** @type {boolean} */ + get subscriber() { + return Boolean(this.get("subscriber")); + }, + /** @type {boolean} */ + set subscriber(value) { + this.set("subscriber", value); + }, + /** @type {DownloadSetting} */ + get download() { + return this.get("download"); + }, + /** @type {DownloadSetting} */ + set download(value) { + this.set("download", value); + }, + /** @type {Array} */ + get downloadHistory() { + return this.get("downloadedHistory", []); + }, + /** @type {Array} */ + set downloadHistory(value) { + this.set("downloadedHistory", value); + }, + /** @type {Array} */ + get downloadedCourses() { + return this.get("downloadedCourses"); + }, + /** @type {Array} */ + set downloadedCourses(value) { + this.set("downloadedCourses", value); + }, + /** @param {String} */ + downloadDirectory: (courseName) => downloadDirectory(courseName), + }; })(); module.exports = Settings; diff --git a/app/helpers/ui.js b/app/helpers/ui.js index 252e0dbd..d710a2e3 100644 --- a/app/helpers/ui.js +++ b/app/helpers/ui.js @@ -1,133 +1,136 @@ -"use strict" +"use strict"; const ui = { - navSidebar: (tab, tabName) => { - $(".content .ui.section").hide(); - $(`.content .ui.${tabName}.section`).show(); - $(tab).parent(".sidebar").find(".active").removeClass("active purple"); - $(tab).addClass("active purple"); - }, - busyOff: () => { - $(".ui .dimmer").removeClass("active"); - }, - busy: (isActive, text) => { - const $busyDimmer = $(".ui.dashboard .dimmer"); - $busyDimmer.find(".ui.big.text.loader").text(text); - if (isActive) { - $busyDimmer.addClass("active"); - } else { - $busyDimmer.removeClass("active"); - } - }, - busyLogin: (isActive) => { - const $busyDimmer = $(".ui.login.dimmer"); - if (isActive) { - $busyDimmer.addClass("active"); - } else { - $busyDimmer.removeClass("active"); - } - }, - busyLogout: (isActive) => { - ui.busy(isActive, translate("Logging Out")); - }, - busyCheckUpdate: (isActive) => { - ui.busy(isActive, translate("Checking for Updates")); - }, - busyLoadCourses: (isActive) => { - ui.busy(isActive, translate("Loading Courses")); - }, - busyBuildingCourseData: (isActive) => { - ui.busy(isActive, translate("Getting Info")); - }, - busyLoadDownloads: (isActive) => { - ui.busy(isActive, translate("Loading Downloads")); - }, - busySavingHistory: (isActive) => { - ui.busy(isActive, translate("Saving download history")); - }, - showModalUpdate: () => { - $(".ui.update-available.modal").modal("show"); - }, - showDashboard: () => { - $(".ui.login.grid").slideUp("fast"); - $(".ui.dashboard").fadeIn("fast").css("display", "flex"); - }, - resetToLogin: () => { - $(".ui.dimmer").removeClass("active"); - $(".ui.dashboard .courses.items").empty(); - $(".content .ui.section").hide(); - $(".content .ui.courses.section").show(); - $(".sidebar").find(".active").removeClass("active purple"); - $(".sidebar").find(".courses-sidebar").addClass("active purple"); - $(".ui.login.grid").slideDown("fast"); - $(".ui.dashboard").fadeOut("fast"); - }, - toggleSubdomainField: (isVisible) => { - const $subdomainField = $(".ui.login #divsubdomain"); - isVisible ? $subdomainField.show() : $subdomainField.hide(); - }, - get $subdomainField() { - return $(".ui.login #subdomain"); - }, - get actionCardTemplate() { - return ` + navSidebar: (tab, tabName) => { + $(".content .ui.section").hide(); + $(`.content .ui.${tabName}.section`).show(); + $(tab).parent(".sidebar").find(".active").removeClass("active purple"); + $(tab).addClass("active purple"); + }, + busyOff: () => { + $(".ui .dimmer").removeClass("active"); + }, + busy: (isActive, text) => { + const $busyDimmer = $(".ui.dashboard .dimmer"); + $busyDimmer.find(".ui.big.text.loader").text(text); + if (isActive) { + $busyDimmer.addClass("active"); + } else { + $busyDimmer.removeClass("active"); + } + }, + busyLogin: (isActive) => { + const $busyDimmer = $(".ui.login.dimmer"); + if (isActive) { + $busyDimmer.addClass("active"); + } else { + $busyDimmer.removeClass("active"); + } + }, + busyLogout: (isActive) => { + ui.busy(isActive, translate("Logging Out")); + }, + busyCheckUpdate: (isActive) => { + ui.busy(isActive, translate("Checking for Updates")); + }, + busyLoadCourses: (isActive) => { + ui.busy(isActive, translate("Loading Courses")); + }, + busyBuildingCourseData: (isActive) => { + ui.busy(isActive, translate("Getting Info")); + }, + busyLoadDownloads: (isActive) => { + ui.busy(isActive, translate("Loading Downloads")); + }, + busySavingHistory: (isActive) => { + ui.busy(isActive, translate("Saving download history")); + }, + showModalUpdate: () => { + $(".ui.update-available.modal").modal("show"); + }, + showDashboard: () => { + $(".ui.login.grid").slideUp("fast"); + $(".ui.dashboard").fadeIn("fast").css("display", "flex"); + }, + resetToLogin: () => { + $(".ui.dimmer").removeClass("active"); + $(".ui.dashboard .courses.items").empty(); + $(".content .ui.section").hide(); + $(".content .ui.courses.section").show(); + $(".sidebar").find(".active").removeClass("active purple"); + $(".sidebar").find(".courses-sidebar").addClass("active purple"); + $(".ui.login.grid").slideDown("fast"); + $(".ui.dashboard").fadeOut("fast"); + }, + toggleSubdomainField: (isVisible) => { + const $subdomainField = $(".ui.login #divsubdomain"); + isVisible ? $subdomainField.show() : $subdomainField.hide(); + }, + get $subdomainField() { + return $(".ui.login #subdomain"); + }, + get actionCardTemplate() { + return `
- - - + + + -
- - - +
+ +
+
-
+
-
-
-
-
${translate("Building Course Data")}
+
+
+
+
${translate("Building Course Data")}
`; - }, - prepareDownloading: ($courseCard) => { - $courseCard.find(".download-quality").html("").hide(); - $courseCard.find(".download-speed").hide(); - $courseCard.find(".combined.progress").progress("reset"); - $courseCard.find(".individual.progress").progress("reset"); + }, + prepareDownloading: ($courseCard) => { + $courseCard.find(".prepare-downloading").show(); + $courseCard.find(".ui.progress").hide(); - $courseCard.find(".download-error").hide(); - $courseCard.find(".course-encrypted").hide(); - $courseCard.find(".download-status").show(); - $courseCard.find(".info-downloaded").hide(); - $courseCard.find(".icon-encrypted").hide(); - $courseCard.find(".ui.tiny.image .tooltip").hide(); - $courseCard.find(".ui.tiny.image").removeClass("wrapper"); - // $courseCard.find('input[name="encryptedvideos"]').val(0); - // $courseCard.css("padding-bottom", "25px") - }, - showProgress: ($courseCard, shouldShow) => { - const $progressElement = $courseCard.find(".ui.progress"); - shouldShow ? $progressElement.show() : $progressElement.hide(); - }, - configureEncryptedIcon($courseCard) { - if (Number($courseCard.find("input[name='encryptedvideos']").val()) === 0) { - $courseCard.find(".icon-encrypted").hide(); - $courseCard.find(".ui.tiny.image .tooltip").hide(); - $courseCard.find(".ui.tiny.image").removeClass("wrapper"); - } else { - $courseCard.find(".icon-encrypted").show(); - $courseCard.find(".ui.tiny.image .tooltip").show(); - $courseCard.find(".ui.tiny.image").addClass("wrapper"); - } - } + $courseCard.find(".individual.progress").progress("reset"); + $courseCard.find(".combined.progress").progress("reset"); + $courseCard.find(".download-quality").html("").hide(); + $courseCard.find(".download-speed").hide(); + $courseCard.find(".download-error").hide(); + $courseCard.find(".course-encrypted").hide(); + $courseCard.find(".download-status").show(); + $courseCard.find(".info-downloaded").hide(); + $courseCard.find(".icon-encrypted").hide(); + $courseCard.find(".ui.tiny.image .tooltip").hide(); + $courseCard.find(".ui.tiny.image").removeClass("wrapper"); + // $courseCard.find('input[name="encryptedvideos"]').val(0); + // $courseCard.css("padding-bottom", "25px") + }, + showProgress: ($courseCard, shouldShow) => { + $courseCard.find(".prepare-downloading").hide(); + const $progressElement = $courseCard.find(".ui.progress"); + shouldShow ? $progressElement.show() : $progressElement.hide(); + }, + configureEncryptedIcon($courseCard) { + if (Number($courseCard.find("input[name='encryptedvideos']").val()) === 0) { + $courseCard.find(".icon-encrypted").hide(); + $courseCard.find(".ui.tiny.image .tooltip").hide(); + $courseCard.find(".ui.tiny.image").removeClass("wrapper"); + } else { + $courseCard.find(".icon-encrypted").show(); + $courseCard.find(".ui.tiny.image .tooltip").show(); + $courseCard.find(".ui.tiny.image").addClass("wrapper"); + } + }, }; -module.exports = ui; \ No newline at end of file +module.exports = ui; diff --git a/app/helpers/utils.js b/app/helpers/utils.js index 1990c522..bcacdfb8 100644 --- a/app/helpers/utils.js +++ b/app/helpers/utils.js @@ -1,163 +1,161 @@ -"use strict" +"use strict"; const utils = { - isNumber: (n) => { - return !isNaN(parseFloat(n)) && isFinite(n); - }, - - toBoolean: (value) => { - return utils.isNumber(value) ? !/^0$/i.test(value) : /^true$/i.test(value); - }, - - /** - * This function takes a string parameter property that represents the property by which the array of objects will be sorted. - * The function returns another function that will be used to sort the array of objects. - * - * If the property starts with a hyphen (-), the function will sort the array in descending order. - * Otherwise, it will sort in ascending order. - * - * @param property The name of the property to sort by. Use a minus sign prefix to sort in descending order. - * @returns `Function` A function that can be passed to the sort() method of an array to sort it by the specified property. - * @example - * - * ```javascript - * myArray = [ - * {name: 'A', age: 18, univerty: 'lorem ipsum dolor sit amet'} - * {name: 'C', age: 22, univerty: 'lorem ipsum dolor sit amet'} - * {name: 'B', age: 16, univerty: 'lorem ipsum dolor sit amet'} - * ] - * myArray.sort(utils.dynamicSort('age')); // Sorts ascending by age - * myArray.sort(utils.dynamicSort('-age')); // Sorts descending by age - * ``` - */ - dynamicSort: (property) => { - var sortOrder = 1; - - if (property[0] === "-") { - sortOrder = -1; - property = property.substr(1); - } - - return function (a, b) { - if (sortOrder == -1) { - return b[property].localeCompare(a[property]); - } else { - return a[property].localeCompare(b[property]); - } - }; - }, - - /** - * Pads a number with leading zeros to match the number of digits in a given maximum value. - * - * @param num The number to be padded with leading zeros. - * @param max The maximum value for which the number of digits will be used to determine the padding length - * - * @returns `string` the input number padded with leading zeros to match the number of digits in the maximum value. - * - * @example - * ```js - * console.log(zeroPad(2, 9)); // "2" - * console.log(zeroPad(2, 10)); // "02" - * ``` - */ - zeroPad: (num, max) => { - return num.toString().padStart(Math.floor(Math.log10(max) + 1), "0"); - }, - - /** - * Generates a string name based on the given index with or without leading zero, count, name, separatorIndex and optional path. - * - * @param {number} index The index of the sequence. - * @param {number} count The total count of the sequence. - * @param {string} name The name of the string. - * @param {string} [separatorIndex='. '] - The separator index used between the index and the name. - * @param {string|null} [path=null] The optional path to the sequence. - * @return {object} An object containing the generated name and full path of the sequence. - */ - getSequenceName: (index, count, name, separatorIndex = ". ", path = null) => { - // const sanitize = require("sanitize-filename"); - // const sanitizeName = sanitize(name, { replacement: (s) => "? ".indexOf(s) > -1 ? "" : "-", }).trim(); - - const indexName = sanitize(`${index}${separatorIndex}${name}`); - const indexPath = path ? `${path}/${indexName}` : indexName; - - const sequence = utils.zeroPad(index, count); - const sequenceName = `${sequence}${separatorIndex}${name}`; - const sequencePath = path ? `${path}/${sequenceName}` : sequenceName; - - if (indexPath === sequencePath) { - return { name: indexName, fullPath: indexPath }; - } else { - if (Boolean(Settings.download.seqZeroLeft)) { - // if it exists then rename it with leading zero - if (fs.existsSync(indexPath)) { - fs.renameSync(indexPath, sequencePath); - } - - return { name: sequenceName, fullPath: sequencePath }; - } else { - // if it exists then rename it without leading zero - if (fs.existsSync(sequencePath)) { - fs.renameSync(sequencePath, indexPath); - } - - return { name: indexName, fullPath: indexPath }; - } - } - }, - - /** - * Calculates the download speed given the input speed in kilobytes per second. - * - * @param {number} bytes - The download speed in kilobytes per second. - * @return {Object} The download speed value and unit. - */ - getDownloadSpeed: (bytes) => { - const BYTES_PER_KB = 1024; - const UNITS = ["B/s", "KB/s", "MB/s", "GB/s"]; - - let speed = bytes; - let unitIndex = 0; - - if (speed >= BYTES_PER_KB) { - unitIndex = speed >= BYTES_PER_KB ** 3 ? 3 : speed >= BYTES_PER_KB ** 2 ? 2 : 1; - speed /= BYTES_PER_KB ** unitIndex; - } - - return { - value: Number(speed.toFixed(2)), - unit: UNITS[unitIndex], - }; - }, - - paginate: (array, page_size, page_number) => { - // human-readable page numbers usually start with 1, so we reduce 1 in the first argument - return array.slice((page_number - 1) * page_size, page_number * page_size); - }, - sleep: (ms) => { - return new Promise((resolve) => setTimeout(resolve, ms)); - }, - newError(name, message = "") { - const error = new Error(); - error.name = name; - error.message = message; - return error; - }, - /** - * Returns the value in the given object that is closest to the target value. - * - * @param {Object} obj - The object containing the values to compare. - * @param {number} target - The target value to find the closest match for. - * @return {*} The value in the object that is closest to the target value. - */ - getClosestValue(obj, target) { - const keys = Object.keys(obj).map(Number); // Converte as chaves para números - const closestKey = keys.reduce((prev, curr) => - Math.abs(curr - target) < Math.abs(prev - target) ? curr : prev - ); - return {key: closestKey, value: obj[closestKey]}; - } -} + isNumber: (n) => { + return !isNaN(parseFloat(n)) && isFinite(n); + }, + + toBoolean: (value) => { + return utils.isNumber(value) ? !/^0$/i.test(value) : /^true$/i.test(value); + }, + + /** + * This function takes a string parameter property that represents the property by which the array of objects will be sorted. + * The function returns another function that will be used to sort the array of objects. + * + * If the property starts with a hyphen (-), the function will sort the array in descending order. + * Otherwise, it will sort in ascending order. + * + * @param property The name of the property to sort by. Use a minus sign prefix to sort in descending order. + * @returns `Function` A function that can be passed to the sort() method of an array to sort it by the specified property. + * @example + * + * ```javascript + * myArray = [ + * {name: 'A', age: 18, univerty: 'lorem ipsum dolor sit amet'} + * {name: 'C', age: 22, univerty: 'lorem ipsum dolor sit amet'} + * {name: 'B', age: 16, univerty: 'lorem ipsum dolor sit amet'} + * ] + * myArray.sort(utils.dynamicSort('age')); // Sorts ascending by age + * myArray.sort(utils.dynamicSort('-age')); // Sorts descending by age + * ``` + */ + dynamicSort: (property) => { + var sortOrder = 1; + + if (property[0] === "-") { + sortOrder = -1; + property = property.substr(1); + } + + return function (a, b) { + if (sortOrder == -1) { + return b[property].localeCompare(a[property]); + } else { + return a[property].localeCompare(b[property]); + } + }; + }, + + /** + * Pads a number with leading zeros to match the number of digits in a given maximum value. + * + * @param num The number to be padded with leading zeros. + * @param max The maximum value for which the number of digits will be used to determine the padding length + * + * @returns `string` the input number padded with leading zeros to match the number of digits in the maximum value. + * + * @example + * ```js + * console.log(zeroPad(2, 9)); // "2" + * console.log(zeroPad(2, 10)); // "02" + * ``` + */ + zeroPad: (num, max) => { + return num.toString().padStart(Math.floor(Math.log10(max) + 1), "0"); + }, + + /** + * Generates a string name based on the given index with or without leading zero, count, name, separatorIndex and optional path. + * + * @param {number} index The index of the sequence. + * @param {number} count The total count of the sequence. + * @param {string} name The name of the string. + * @param {string} [separatorIndex='. '] - The separator index used between the index and the name. + * @param {string|null} [path=null] The optional path to the sequence. + * @return {object} An object containing the generated name and full path of the sequence. + */ + getSequenceName: (index, count, name, separatorIndex = ". ", path = null) => { + // const sanitize = require("sanitize-filename"); + // const sanitizeName = sanitize(name, { replacement: (s) => "? ".indexOf(s) > -1 ? "" : "-", }).trim(); + + const indexName = sanitize(`${index}${separatorIndex}${name}`); + const indexPath = path ? `${path}/${indexName}` : indexName; + + const sequence = utils.zeroPad(index, count); + const sequenceName = `${sequence}${separatorIndex}${name}`; + const sequencePath = path ? `${path}/${sequenceName}` : sequenceName; + + if (indexPath === sequencePath) { + return { name: indexName, fullPath: indexPath }; + } else { + if (Boolean(Settings.download.seqZeroLeft)) { + // if it exists then rename it with leading zero + if (fs.existsSync(indexPath)) { + fs.renameSync(indexPath, sequencePath); + } + + return { name: sequenceName, fullPath: sequencePath }; + } else { + // if it exists then rename it without leading zero + if (fs.existsSync(sequencePath)) { + fs.renameSync(sequencePath, indexPath); + } + + return { name: indexName, fullPath: indexPath }; + } + } + }, + + /** + * Calculates the download speed given the input speed in kilobytes per second. + * + * @param {number} bytes - The download speed in kilobytes per second. + * @return {Object} The download speed value and unit. + */ + getDownloadSpeed: (bytes) => { + const BYTES_PER_KB = 1024; + const UNITS = ["B/s", "KB/s", "MB/s", "GB/s"]; + + let speed = bytes; + let unitIndex = 0; + + if (speed >= BYTES_PER_KB) { + unitIndex = speed >= BYTES_PER_KB ** 3 ? 3 : speed >= BYTES_PER_KB ** 2 ? 2 : 1; + speed /= BYTES_PER_KB ** unitIndex; + } + + return { + value: Number(speed.toFixed(2)), + unit: UNITS[unitIndex], + }; + }, + + paginate: (array, page_size, page_number) => { + // human-readable page numbers usually start with 1, so we reduce 1 in the first argument + return array.slice((page_number - 1) * page_size, page_number * page_size); + }, + sleep: (ms) => { + return new Promise((resolve) => setTimeout(resolve, ms)); + }, + newError(name, message = "") { + const error = new Error(); + error.name = name; + error.message = message; + return error; + }, + /** + * Returns the value in the given object that is closest to the target value. + * + * @param {Object} obj - The object containing the values to compare. + * @param {number} target - The target value to find the closest match for. + * @return {*} The value in the object that is closest to the target value. + */ + getClosestValue(obj, target) { + const keys = Object.keys(obj).map(Number); // Converte as chaves para números + const closestKey = keys.reduce((prev, curr) => (Math.abs(curr - target) < Math.abs(prev - target) ? curr : prev)); + return { key: closestKey, value: obj[closestKey] }; + }, +}; module.exports = utils; diff --git a/app/renderer.js b/app/renderer.js index 88809bee..c2612e81 100644 --- a/app/renderer.js +++ b/app/renderer.js @@ -1,49 +1,47 @@ -"use strict" +"use strict"; -const Sentry = require('@sentry/electron'); -const Gettings = require('./helpers/settings.js') -const { version: appVersion, vars: pkgVars } = require('../package.json'); +const Sentry = require("@sentry/electron"); +const Gettings = require("./helpers/settings.js"); +const { version: appVersion, vars: pkgVars } = require("../package.json"); let featToggle = {}; if (!process.env.DEBUG_MODE) { - fetch(pkgVars.urlToggles).then(resp => resp.json()) - .then(json => { - featToggle = json; - Sentry.init({ dsn: featToggle.enableSentry ? process.env.SENTRY_DSN : "" }); - console.log(featToggle.enableSentry ? "Sentry is enabled" : "Sentry is disabled"); - }); + fetch(pkgVars.urlToggles) + .then((resp) => resp.json()) + .then((json) => { + featToggle = json; + Sentry.init({ dsn: featToggle.enableSentry ? process.env.SENTRY_DSN : "" }); + console.log(featToggle.enableSentry ? "Sentry is enabled" : "Sentry is disabled"); + }); } const localeMeta = require("./locale/meta.json"); let localeJson; function translate(text) { - const language = Gettings.language; - - if (language == "English") { - return text; - } - else { - try { - if (!localeJson) { - localeJson = require(`./locale/${localeMeta[language]}`); - } - - return localeJson[text] || text; - } - catch (e) { - console.error(e); - return text; - } - } + const language = Gettings.language; + + if (language == "English") { + return text; + } else { + try { + if (!localeJson) { + localeJson = require(`./locale/${localeMeta[language]}`); + } + + return localeJson[text] || text; + } catch (e) { + console.error(e); + return text; + } + } } function translateWrite(text) { - document.write(translate(text)); + document.write(translate(text)); } - function urlDonate() { - return `${pkgVars.urlDonate}&item_name=${translate("Udeler is free and without any ads. If you appreciate that, please consider donating to the Developer.").replace(" ", "+")}` + return `${pkgVars.urlDonate}&item_name=${translate("Udeler is free and without any ads. If you appreciate that, please consider donating to the Developer.").replace(" ", "+")}`; } diff --git a/package-lock.json b/package-lock.json index 91118a51..1dd52ed7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,9 +10,9 @@ "hasInstallScript": true, "license": "ISC", "dependencies": { - "@sentry/electron": "4.24.0", - "axios": "^1.7.5", - "cookie": "^0.6.0", + "@sentry/electron": "^4.24.0", + "axios": "^1.7.7", + "cookie": "^1.0.1", "dialogs": "^2.0.1", "electron-settings": "3.2.0", "jquery": "^3.7.1", @@ -22,8 +22,8 @@ "sanitize-filename": "^1.6.3" }, "devDependencies": { - "electron": "11.5.0", - "electron-builder": "^24.1.1", + "electron": "^11.5.0", + "electron-builder": "^25.1.8", "electron-reload": "^2.0.0-alpha.1", "gh_deploy": "github:heliomarpm/gh_deploy" } @@ -33,6 +33,7 @@ "resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz", "integrity": "sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^6.12.0", "ajv-keywords": "^3.4.1" @@ -46,10 +47,11 @@ } }, "node_modules/@electron/asar": { - "version": "3.2.10", - "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.2.10.tgz", - "integrity": "sha512-mvBSwIBUeiRscrCeJE1LwctAriBj65eUDm0Pc11iE5gRwzkmsdbS7FnZ1XUWjpSeQWL1L5g12Fc/SchPM9DUOw==", + "version": "3.2.17", + "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.2.17.tgz", + "integrity": "sha512-OcWImUI686w8LkghQj9R2ynZ2ME693Ek6L1SiaAgqGKzBaTIZw3fHDqN82Rcl+EU1Gm9EgkJ5KLIY/q5DCRbbA==", "dev": true, + "license": "MIT", "dependencies": { "commander": "^5.0.0", "glob": "^7.1.6", @@ -67,6 +69,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -77,6 +80,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -89,6 +93,7 @@ "resolved": "https://registry.npmjs.org/@electron/get/-/get-1.14.1.tgz", "integrity": "sha512-BrZYyL/6m0ZXz/lDxy/nlVhQz+WF+iPS6qXolEU8atw7h6v1aYkjwJZ63m+bJMBTxDE66X+r2tPS4a/8C82sZw==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^4.1.1", "env-paths": "^2.2.0", @@ -106,20 +111,187 @@ "global-tunnel-ng": "^2.7.1" } }, + "node_modules/@electron/get/node_modules/@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@electron/get/node_modules/@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "defer-to-connect": "^1.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@electron/get/node_modules/cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@electron/get/node_modules/decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-response": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@electron/get/node_modules/defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@electron/get/node_modules/got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/@electron/get/node_modules/got/node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@electron/get/node_modules/got/node_modules/lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@electron/get/node_modules/json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@electron/get/node_modules/keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.0" + } + }, + "node_modules/@electron/get/node_modules/normalize-url": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@electron/get/node_modules/p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@electron/get/node_modules/responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "lowercase-keys": "^1.0.0" + } + }, + "node_modules/@electron/get/node_modules/responselike/node_modules/lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/@electron/get/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/@electron/notarize": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-2.2.1.tgz", - "integrity": "sha512-aL+bFMIkpR0cmmj5Zgy0LMKEpgy43/hw5zadEArgmAMWWlKc5buwFvFT9G/o/YJkvXAJm5q3iuTuLaiaXW39sg==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-2.5.0.tgz", + "integrity": "sha512-jNT8nwH1f9X5GEITXaQ8IF/KdskvIkOFfB2CvwumsveVidzpSc+mvhhTMdAGSYF3O+Nq49lJ7y+ssODRXu06+A==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^4.1.1", "fs-extra": "^9.0.1", @@ -134,6 +306,7 @@ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", "dev": true, + "license": "MIT", "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", @@ -149,6 +322,7 @@ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, + "license": "MIT", "dependencies": { "universalify": "^2.0.0" }, @@ -161,15 +335,17 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10.0.0" } }, "node_modules/@electron/osx-sign": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.0.5.tgz", - "integrity": "sha512-k9ZzUQtamSoweGQDV2jILiRIHUu7lYlJ3c6IEmjv1hC17rclE+eb9U+f6UFlOOETo0JzY1HNlXy4YOlCvl+Lww==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.3.1.tgz", + "integrity": "sha512-BAfviURMHpmb1Yb50YbCxnOY0wfwaLXH5KJ4+80zS0gUkzDX3ec23naTlEqKsN+PwYn+a1cCzM7BJ4Wcd3sGzw==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "compare-version": "^0.1.2", "debug": "^4.3.4", @@ -191,6 +367,7 @@ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -205,6 +382,7 @@ "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8.0.0" }, @@ -217,6 +395,7 @@ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, + "license": "MIT", "dependencies": { "universalify": "^2.0.0" }, @@ -229,51 +408,110 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10.0.0" } }, - "node_modules/@electron/universal": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.5.1.tgz", - "integrity": "sha512-kbgXxyEauPJiQQUNG2VgUeyfQNFk6hBF11ISN2PNI6agUgPl55pv4eQmaqHzTAzchBvqZ2tQuRVaPStGf0mxGw==", + "node_modules/@electron/rebuild": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@electron/rebuild/-/rebuild-3.6.1.tgz", + "integrity": "sha512-f6596ZHpEq/YskUd8emYvOUne89ij8mQgjYFA5ru25QwbrRO+t1SImofdDv7kKOuWCmVOuU5tvfkbgGxIl3E/w==", "dev": true, + "license": "MIT", "dependencies": { - "@electron/asar": "^3.2.1", - "@malept/cross-spawn-promise": "^1.1.0", - "debug": "^4.3.1", - "dir-compare": "^3.0.0", - "fs-extra": "^9.0.1", - "minimatch": "^3.0.4", - "plist": "^3.0.4" + "@malept/cross-spawn-promise": "^2.0.0", + "chalk": "^4.0.0", + "debug": "^4.1.1", + "detect-libc": "^2.0.1", + "fs-extra": "^10.0.0", + "got": "^11.7.0", + "node-abi": "^3.45.0", + "node-api-version": "^0.2.0", + "node-gyp": "^9.0.0", + "ora": "^5.1.0", + "read-binary-file-arch": "^1.0.6", + "semver": "^7.3.5", + "tar": "^6.0.5", + "yargs": "^17.0.1" + }, + "bin": { + "electron-rebuild": "lib/cli.js" }, "engines": { - "node": ">=8.6" + "node": ">=12.13.0" } }, - "node_modules/@electron/universal/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/@electron/rebuild/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, + "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@electron/rebuild/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@electron/rebuild/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@electron/universal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-2.0.1.tgz", + "integrity": "sha512-fKpv9kg4SPmt+hY7SVBnIYULE9QJl8L3sCfcBsnqbJwwBwAeTLokJ9TRt9y7bK0JAzIW2y78TVVjvnQEms/yyA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@electron/asar": "^3.2.7", + "@malept/cross-spawn-promise": "^2.0.0", + "debug": "^4.3.1", + "dir-compare": "^4.2.0", + "fs-extra": "^11.1.1", + "minimatch": "^9.0.3", + "plist": "^3.1.0" + }, + "engines": { + "node": ">=16.4" } }, "node_modules/@electron/universal/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", "dev": true, + "license": "MIT", "dependencies": { - "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" }, "engines": { - "node": ">=10" + "node": ">=14.14" } }, "node_modules/@electron/universal/node_modules/jsonfile": { @@ -281,6 +519,7 @@ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, + "license": "MIT", "dependencies": { "universalify": "^2.0.0" }, @@ -289,15 +528,19 @@ } }, "node_modules/@electron/universal/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, + "license": "ISC", "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "*" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/@electron/universal/node_modules/universalify": { @@ -305,15 +548,24 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10.0.0" } }, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "dev": true, + "license": "MIT" + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, + "license": "ISC", "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", @@ -327,10 +579,11 @@ } }, "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -343,6 +596,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -354,13 +608,15 @@ "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@isaacs/cliui/node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, + "license": "MIT", "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -378,6 +634,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -393,6 +650,7 @@ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", @@ -406,9 +664,9 @@ } }, "node_modules/@malept/cross-spawn-promise": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz", - "integrity": "sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-2.0.0.tgz", + "integrity": "sha512-1DpKU0Z5ThltBwjNySMC14g0CkbyhCaz9FkhxqNsZI6uAPJXFS8cMXlBKo26FJ8ZuW6S9GCMcR9IO5k2X5/9Fg==", "dev": true, "funding": [ { @@ -420,11 +678,12 @@ "url": "https://tidelift.com/subscription/pkg/npm-.malept-cross-spawn-promise?utm_medium=referral&utm_source=npm_fund" } ], + "license": "Apache-2.0", "dependencies": { "cross-spawn": "^7.0.1" }, "engines": { - "node": ">= 10" + "node": ">= 12.13.0" } }, "node_modules/@malept/flatpak-bundler": { @@ -432,6 +691,7 @@ "resolved": "https://registry.npmjs.org/@malept/flatpak-bundler/-/flatpak-bundler-0.4.0.tgz", "integrity": "sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^4.1.1", "fs-extra": "^9.0.0", @@ -447,6 +707,7 @@ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", "dev": true, + "license": "MIT", "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", @@ -462,6 +723,7 @@ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, + "license": "MIT", "dependencies": { "universalify": "^2.0.0" }, @@ -474,15 +736,59 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10.0.0" } }, + "node_modules/@npmcli/fs": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", + "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "@gar/promisify": "^1.1.3", + "semver": "^7.3.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/move-file": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", + "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", + "deprecated": "This functionality has been moved to @npmcli/fs", + "dev": true, + "license": "MIT", + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/move-file/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "dev": true, + "license": "MIT", "optional": true, "engines": { "node": ">=14" @@ -492,6 +798,7 @@ "version": "7.112.0", "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-7.112.0.tgz", "integrity": "sha512-aqndxnTvZnqo/uUhuWLNWY/0W3zOxNs9FofLYi1SK5+QzMqDIyFY1dc9+ZqQH3/9GIlEGao+zveGAHeUEtpE8g==", + "license": "MIT", "dependencies": { "@sentry/core": "7.112.0", "@sentry/types": "7.112.0", @@ -505,6 +812,7 @@ "version": "7.112.0", "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-7.112.0.tgz", "integrity": "sha512-DwpGY5oZf0ab4Jm9HtM8fB3xqnpAcxBKORqiVHZizz7eo0arrb1n9HCXcxsRNNOAuMRBS8aEHKberfdL6rYpyw==", + "license": "MIT", "dependencies": { "@sentry/core": "7.112.0", "@sentry/replay": "7.112.0", @@ -519,6 +827,7 @@ "version": "7.112.0", "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.112.0.tgz", "integrity": "sha512-PkA3NaSg4nTWp9pwVsV9x0EBiY0pEAnIboIpMuLGE5MJ/FL10NC5Fn1GPebcxNnOou62dM7P/z7Wtcm8czAn6A==", + "license": "MIT", "dependencies": { "@sentry/core": "7.112.0", "@sentry/types": "7.112.0", @@ -532,6 +841,7 @@ "version": "7.112.0", "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.112.0.tgz", "integrity": "sha512-xqxtlQ/GMHxYcJYAhWR0ELO4kCnQV9GuIcBUEHlU/mYbPBDPxNYFzXkoz3514DBKxRVTHDkVle6vLuG0yKvXsg==", + "license": "MIT", "dependencies": { "@sentry-internal/feedback": "7.112.0", "@sentry-internal/replay-canvas": "7.112.0", @@ -550,6 +860,7 @@ "version": "7.112.0", "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.112.0.tgz", "integrity": "sha512-q4K0fTULXMf9vb0Je6qFwQyVjfMvuPiKRRvRHcpWvWudV7oTcfPixlbbIQaj3OiY3nrjk5q86hktqboI/Z6ISw==", + "license": "MIT", "dependencies": { "@sentry/types": "7.112.0", "@sentry/utils": "7.112.0" @@ -562,6 +873,7 @@ "version": "4.24.0", "resolved": "https://registry.npmjs.org/@sentry/electron/-/electron-4.24.0.tgz", "integrity": "sha512-UF+9v5jhVCryEMwQ54/4t8Hec1SfamkdswqlDezwJQkoWVpZ4hhPMziULYTBqSFdXCQGShuNuKjcdowhdTVI3Q==", + "license": "MIT", "dependencies": { "@sentry/browser": "7.112.0", "@sentry/core": "7.112.0", @@ -576,6 +888,7 @@ "version": "7.112.0", "resolved": "https://registry.npmjs.org/@sentry/integrations/-/integrations-7.112.0.tgz", "integrity": "sha512-brN6eZkXuz1e/OKhMGJsAZjc0cUU+5G+LQWet+gGXWVGM2v7uY7mKDHr5Yl/c8WxeJBurjJzJn7YmtmR9++ZKQ==", + "license": "MIT", "dependencies": { "@sentry/core": "7.112.0", "@sentry/types": "7.112.0", @@ -590,6 +903,7 @@ "version": "7.112.0", "resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.112.0.tgz", "integrity": "sha512-Me0Um3PbPQADHhm5zJ1EM4/me+i1OMT3w+1ZUgkPGX+2Wtqfp0djHF/SzCOL45X1IR+YLVrcCTpyAWRhPZAdVw==", + "license": "MIT", "dependencies": { "@sentry-internal/tracing": "7.112.0", "@sentry/core": "7.112.0", @@ -605,6 +919,7 @@ "version": "7.112.0", "resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.112.0.tgz", "integrity": "sha512-uP38yQpYKdU9onJEl77nSJslajXMbTLp3j+8EK4tNnXDMv+yDnSouODEdHQyX9fajKHsFi/FjjOIrVujR0Qd7w==", + "license": "MIT", "dependencies": { "@sentry-internal/tracing": "7.112.0", "@sentry/core": "7.112.0", @@ -619,6 +934,7 @@ "version": "7.112.0", "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.112.0.tgz", "integrity": "sha512-ASonavVCSrgDjMyWjuNMSytKMGYJq7d/1+IoBJsQFLgLe1gLIXuDNbhfUAM4A+muQUGZepV9iRX4ZYhiROMHVQ==", + "license": "MIT", "engines": { "node": ">=8" } @@ -627,6 +943,7 @@ "version": "7.112.0", "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.112.0.tgz", "integrity": "sha512-dNGcNWKoJE9VwIAZxQsqC6/7BC+8wn1rT7Km9S8xltcjhRvaK4n3QZwXoNLHjNWT0mS2lZaFyRx2hsHjblQqLg==", + "license": "MIT", "dependencies": { "@sentry/types": "7.112.0" }, @@ -635,24 +952,29 @@ } }, "node_modules/@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", "dev": true, + "license": "MIT", "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" } }, "node_modules/@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", "dev": true, + "license": "MIT", "dependencies": { - "defer-to-connect": "^1.0.1" + "defer-to-connect": "^2.0.0" }, "engines": { - "node": ">=6" + "node": ">=10" } }, "node_modules/@tootallnate/once": { @@ -660,15 +982,30 @@ "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10" } }, + "node_modules/@types/cacheable-request": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "^3.1.4", + "@types/node": "*", + "@types/responselike": "^1.0.0" + } + }, "node_modules/@types/debug": { "version": "4.1.12", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/ms": "*" } @@ -678,6 +1015,24 @@ "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", + "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -686,30 +1041,47 @@ "version": "0.7.34", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/node": { - "version": "12.20.55", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", - "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", - "dev": true + "version": "20.17.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.6.tgz", + "integrity": "sha512-VEI7OdvK2wP7XHnsuXbAJnEpEkF6NjSN45QJlL4VGqZSXsnicpesdTWsg9RISeSdYd3yeRj/y3k5KGjUXYnFwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.2" + } }, "node_modules/@types/plist": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@types/plist/-/plist-3.0.5.tgz", "integrity": "sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { "@types/node": "*", "xmlbuilder": ">=11.0.1" } }, + "node_modules/@types/responselike": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", + "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/verror": { "version": "1.10.10", "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.10.tgz", "integrity": "sha512-l4MM0Jppn18hb9xmM6wwD1uTdShpf9Pn80aXTStnK1C94gtPvJcV2FrDmbOQUAQfJ1cKZHktkQUDwEqaAKXMMg==", "dev": true, + "license": "MIT", "optional": true }, "node_modules/@xmldom/xmldom": { @@ -717,6 +1089,7 @@ "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==", "dev": true, + "license": "MIT", "engines": { "node": ">=10.0.0" } @@ -725,7 +1098,15 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-5.2.0.tgz", "integrity": "sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true, + "license": "ISC" }, "node_modules/acorn": { "version": "7.4.1", @@ -765,15 +1146,43 @@ } }, "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", "dev": true, + "license": "MIT", "dependencies": { - "debug": "4" + "debug": "^4.3.4" }, "engines": { - "node": ">= 6.0.0" + "node": ">= 14" + } + }, + "node_modules/agentkeepalive": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", + "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", + "dev": true, + "license": "MIT", + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, "node_modules/ajv": { @@ -781,6 +1190,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -797,6 +1207,7 @@ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", "dev": true, + "license": "MIT", "peerDependencies": { "ajv": "^6.9.1" } @@ -839,40 +1250,47 @@ } }, "node_modules/app-builder-bin": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-4.0.0.tgz", - "integrity": "sha512-xwdG0FJPQMe0M0UA4Tz0zEB8rBJTRA5a476ZawAqiBkMv16GRK5xpXThOjMaEOFnZ6zabejjG4J3da0SXG63KA==", - "dev": true + "version": "5.0.0-alpha.10", + "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-5.0.0-alpha.10.tgz", + "integrity": "sha512-Ev4jj3D7Bo+O0GPD2NMvJl+PGiBAfS7pUGawntBNpCbxtpncfUixqFj9z9Jme7V7s3LBGqsWZZP54fxBX3JKJw==", + "dev": true, + "license": "MIT" }, "node_modules/app-builder-lib": { - "version": "24.13.3", - "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-24.13.3.tgz", - "integrity": "sha512-FAzX6IBit2POXYGnTCT8YHFO/lr5AapAII6zzhQO3Rw4cEDOgK+t1xhLc5tNcKlicTHlo9zxIwnYCX9X2DLkig==", + "version": "25.1.8", + "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-25.1.8.tgz", + "integrity": "sha512-pCqe7dfsQFBABC1jeKZXQWhGcCPF3rPCXDdfqVKjIeWBcXzyC1iOWZdfFhGl+S9MyE/k//DFmC6FzuGAUudNDg==", "dev": true, + "license": "MIT", "dependencies": { "@develar/schema-utils": "~2.6.5", - "@electron/notarize": "2.2.1", - "@electron/osx-sign": "1.0.5", - "@electron/universal": "1.5.1", + "@electron/notarize": "2.5.0", + "@electron/osx-sign": "1.3.1", + "@electron/rebuild": "3.6.1", + "@electron/universal": "2.0.1", "@malept/flatpak-bundler": "^0.4.0", "@types/fs-extra": "9.0.13", "async-exit-hook": "^2.0.1", "bluebird-lst": "^1.0.9", - "builder-util": "24.13.1", - "builder-util-runtime": "9.2.4", + "builder-util": "25.1.7", + "builder-util-runtime": "9.2.10", "chromium-pickle-js": "^0.2.0", + "config-file-ts": "0.2.8-rc1", "debug": "^4.3.4", + "dotenv": "^16.4.5", + "dotenv-expand": "^11.0.6", "ejs": "^3.1.8", - "electron-publish": "24.13.1", + "electron-publish": "25.1.7", "form-data": "^4.0.0", "fs-extra": "^10.1.0", "hosted-git-info": "^4.1.0", "is-ci": "^3.0.0", "isbinaryfile": "^5.0.0", "js-yaml": "^4.1.0", + "json5": "^2.2.3", "lazy-val": "^1.0.5", - "minimatch": "^5.1.1", - "read-config-file": "6.3.2", + "minimatch": "^10.0.0", + "resedit": "^1.7.0", "sanitize-filename": "^1.6.3", "semver": "^7.3.8", "tar": "^6.1.12", @@ -882,8 +1300,8 @@ "node": ">=14.0.0" }, "peerDependencies": { - "dmg-builder": "24.13.3", - "electron-builder-squirrel-windows": "24.13.3" + "dmg-builder": "25.1.8", + "electron-builder-squirrel-windows": "25.1.8" } }, "node_modules/app-builder-lib/node_modules/fs-extra": { @@ -891,6 +1309,7 @@ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -905,6 +1324,7 @@ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, + "license": "MIT", "dependencies": { "universalify": "^2.0.0" }, @@ -917,15 +1337,24 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10.0.0" } }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "dev": true, + "license": "ISC" + }, "node_modules/archiver": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.2.tgz", "integrity": "sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "archiver-utils": "^2.1.0", @@ -945,6 +1374,7 @@ "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "glob": "^7.1.4", @@ -967,6 +1397,7 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "core-util-is": "~1.0.0", @@ -983,6 +1414,7 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/archiver-utils/node_modules/string_decoder": { @@ -990,16 +1422,33 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "safe-buffer": "~5.1.0" } }, + "node_modules/are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "deprecated": "This package is no longer supported.", + "dev": true, + "license": "ISC", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "dev": true, + "license": "Python-2.0" }, "node_modules/array-from": { "version": "2.1.1", @@ -1011,6 +1460,7 @@ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", "dev": true, + "license": "MIT", "optional": true, "engines": { "node": ">=0.8" @@ -1021,22 +1471,25 @@ "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", "dev": true, + "license": "MIT", "optional": true, "engines": { "node": ">=8" } }, "node_modules/async": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", - "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", - "dev": true + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true, + "license": "MIT" }, "node_modules/async-exit-hook": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz", "integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -1051,14 +1504,15 @@ "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", "dev": true, + "license": "ISC", "engines": { "node": ">= 4.0.0" } }, "node_modules/axios": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.5.tgz", - "integrity": "sha512-fZu86yCo+svH3uqJ/yTdQ0QHpQu5oL+/QE+QPSv6BZSkDAoky9vytxp7u5qk83OJFS3kEBcesWni9WTZAv3tSw==", + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", @@ -1070,7 +1524,8 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/base64-js": { "version": "1.5.1", @@ -1090,7 +1545,8 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/binary-extensions": { "version": "2.3.0", @@ -1109,7 +1565,7 @@ "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", @@ -1120,13 +1576,15 @@ "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/bluebird-lst": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/bluebird-lst/-/bluebird-lst-1.0.9.tgz", "integrity": "sha512-7B1Rtx82hjnSD4PGLAjVWeYH3tHAcVUmChh85a3lltKQm6FresXh9ErQo6oAv6CqxttczC3/kEg8SY5NluPuUw==", "dev": true, + "license": "MIT", "dependencies": { "bluebird": "^3.5.5" } @@ -1135,7 +1593,9 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", "dev": true, + "license": "MIT", "optional": true }, "node_modules/brace-expansion": { @@ -1143,6 +1603,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -1192,6 +1653,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" @@ -1206,40 +1668,29 @@ "node": "*" } }, - "node_modules/buffer-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.1.tgz", - "integrity": "sha512-QoV3ptgEaQpvVwbXdSO39iqPQTCxSF7A5U99AxbHYqUdCizL/lH2Z0A2y6nbZucxMEOtNyZfG2s6gsVugGpKkg==", - "dev": true, - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, "node_modules/builder-util": { - "version": "24.13.1", - "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-24.13.1.tgz", - "integrity": "sha512-NhbCSIntruNDTOVI9fdXz0dihaqX2YuE1D6zZMrwiErzH4ELZHE6mdiB40wEgZNprDia+FghRFgKoAqMZRRjSA==", + "version": "25.1.7", + "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-25.1.7.tgz", + "integrity": "sha512-7jPjzBwEGRbwNcep0gGNpLXG9P94VA3CPAZQCzxkFXiV2GMQKlziMbY//rXPI7WKfhsvGgFXjTcXdBEwgXw9ww==", "dev": true, + "license": "MIT", "dependencies": { "@types/debug": "^4.1.6", "7zip-bin": "~5.2.0", - "app-builder-bin": "4.0.0", + "app-builder-bin": "5.0.0-alpha.10", "bluebird-lst": "^1.0.9", - "builder-util-runtime": "9.2.4", + "builder-util-runtime": "9.2.10", "chalk": "^4.1.2", "cross-spawn": "^7.0.3", "debug": "^4.3.4", "fs-extra": "^10.1.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.1", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.0", "is-ci": "^3.0.0", "js-yaml": "^4.1.0", "source-map-support": "^0.5.19", @@ -1248,10 +1699,11 @@ } }, "node_modules/builder-util-runtime": { - "version": "9.2.4", - "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.2.4.tgz", - "integrity": "sha512-upp+biKpN/XZMLim7aguUyW8s0FUpDvOtK6sbanMFDAMBzpHDqdhgVYm6zc9HJ6nWo7u2Lxk60i2M6Jd3aiNrA==", + "version": "9.2.10", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.2.10.tgz", + "integrity": "sha512-6p/gfG1RJSQeIbz8TK5aPNkoztgY1q5TgmGFMAXcY8itsGW6Y2ld1ALsZ5UJn8rog7hKF3zHx5iQbNQ8uLcRlw==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^4.3.4", "sax": "^1.2.4" @@ -1265,6 +1717,7 @@ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -1279,6 +1732,7 @@ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, + "license": "MIT", "dependencies": { "universalify": "^2.0.0" }, @@ -1291,48 +1745,123 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10.0.0" } }, - "node_modules/cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "node_modules/cacache": { + "version": "16.1.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", + "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", "dev": true, + "license": "ISC", "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" + "@npmcli/fs": "^2.1.0", + "@npmcli/move-file": "^2.0.0", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "glob": "^8.0.1", + "infer-owner": "^1.0.4", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "mkdirp": "^1.0.4", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^9.0.0", + "tar": "^6.1.11", + "unique-filename": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/cacache/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/cacheable-request/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "node_modules/cacache/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/cacache/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, + "license": "ISC", "dependencies": { - "pump": "^3.0.0" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=8" + "node": ">=10" + } + }, + "node_modules/cacache/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=10" } }, - "node_modules/cacheable-request/node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/cacheable-request": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", + "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", "dev": true, + "license": "MIT", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, "engines": { "node": ">=8" } @@ -1342,6 +1871,7 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -1382,6 +1912,7 @@ "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", "dev": true, + "license": "ISC", "engines": { "node": ">=10" } @@ -1390,7 +1921,8 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz", "integrity": "sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/ci-info": { "version": "3.9.0", @@ -1403,15 +1935,53 @@ "url": "https://github.com/sponsors/sibiraj-s" } ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^3.1.0" + }, "engines": { "node": ">=8" } }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/cli-truncate": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { "slice-ansi": "^3.0.0", @@ -1451,6 +2021,7 @@ "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", "dev": true, + "license": "MIT", "dependencies": { "mimic-response": "^1.0.0" }, @@ -1476,6 +2047,16 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true, + "license": "ISC", + "bin": { + "color-support": "bin.js" + } + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -1492,6 +2073,7 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 6" } @@ -1501,6 +2083,7 @@ "resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz", "integrity": "sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -1510,6 +2093,7 @@ "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.2.tgz", "integrity": "sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "buffer-crc32": "^0.2.13", @@ -1525,7 +2109,8 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/concat-stream": { "version": "1.6.2", @@ -1573,6 +2158,7 @@ "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { "ini": "^1.3.4", @@ -1580,13 +2166,14 @@ } }, "node_modules/config-file-ts": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/config-file-ts/-/config-file-ts-0.2.6.tgz", - "integrity": "sha512-6boGVaglwblBgJqGyxm4+xCmEGcWgnWHSWHY5jad58awQhB6gftq0G8HbzU39YqCIYHMLAiL1yjwiZ36m/CL8w==", + "version": "0.2.8-rc1", + "resolved": "https://registry.npmjs.org/config-file-ts/-/config-file-ts-0.2.8-rc1.tgz", + "integrity": "sha512-GtNECbVI82bT4RiDIzBSVuTKoSHufnU7Ce7/42bkWZJZFLjmDF2WBpVsvRkhKCfKBnTBb3qZrBwPpFBU/Myvhg==", "dev": true, + "license": "MIT", "dependencies": { - "glob": "^10.3.10", - "typescript": "^5.3.3" + "glob": "^10.3.12", + "typescript": "^5.4.3" } }, "node_modules/config-file-ts/node_modules/glob": { @@ -1594,6 +2181,7 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, + "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", @@ -1614,6 +2202,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -1629,21 +2218,30 @@ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, + "license": "ISC", "engines": { "node": ">=16 || 14 >=14.17" } }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "dev": true, + "license": "ISC" + }, "node_modules/convert-source-map": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" }, "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.1.tgz", + "integrity": "sha512-Xd8lFX4LM9QEEwxQpF9J9NTUh8pmdJO0cyRJhFiDoLTk2eH8FXlRv2IFGYVadZpqI3j8fhNrSdKCeYPxiAhLXw==", + "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=18" } }, "node_modules/core-util-is": { @@ -1656,6 +2254,7 @@ "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { "buffer": "^5.1.0" @@ -1666,6 +2265,7 @@ "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", "dev": true, + "license": "Apache-2.0", "peer": true, "bin": { "crc32": "bin/crc32.njs" @@ -1679,6 +2279,7 @@ "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.3.tgz", "integrity": "sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "crc-32": "^1.2.0", @@ -1689,10 +2290,11 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.5.tgz", + "integrity": "sha512-ZVJrKKYunU38/76t0RMOulHOnUcbU9GbpWKAOZ0mhjr7CX6FVrH+4FrAapSOekrgFQ3f/8gwMEuIft0aKq6Hug==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -1737,15 +2339,32 @@ } }, "node_modules/decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", "dev": true, + "license": "MIT", "dependencies": { - "mimic-response": "^1.0.0" + "mimic-response": "^3.1.0" }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/deep-is": { @@ -1757,21 +2376,50 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.0.tgz", "integrity": "sha512-z2wJZXrmeHdvYJp/Ux55wIjqo81G5Bp4c+oELTW+7ar6SogWHajt5a9gO3s3IDaGSAXjDk0vlQKN3rms8ab3og==", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defaults/node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, "node_modules/defer-to-connect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", - "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", - "dev": true + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } }, "node_modules/define-data-property": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { "es-define-property": "^1.0.0", @@ -1800,6 +2448,7 @@ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { "define-data-property": "^1.0.1", @@ -1821,11 +2470,29 @@ "node": ">=0.4.0" } }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, "node_modules/detect-node": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", "dev": true, + "license": "MIT", "optional": true }, "node_modules/dialogs": { @@ -1840,13 +2507,14 @@ } }, "node_modules/dir-compare": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-3.3.0.tgz", - "integrity": "sha512-J7/et3WlGUCxjdnD3HAAzQ6nsnc0WL6DD7WcwJb7c39iH1+AWfg+9OqzJNaI6PkBwBvm1mhZNL9iY/nRiZXlPg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-4.2.0.tgz", + "integrity": "sha512-2xMCmOoMrdQIPHdsTawECdNPwlVFB9zGcz3kuhmBO6U3oU+UQjsue0i8ayLKpgBcm+hcXPMVSGUN9d+pvJ6+VQ==", "dev": true, + "license": "MIT", "dependencies": { - "buffer-equal": "^1.0.0", - "minimatch": "^3.0.4" + "minimatch": "^3.0.5", + "p-limit": "^3.1.0 " } }, "node_modules/dir-compare/node_modules/brace-expansion": { @@ -1854,6 +2522,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1864,6 +2533,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -1872,14 +2542,15 @@ } }, "node_modules/dmg-builder": { - "version": "24.13.3", - "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-24.13.3.tgz", - "integrity": "sha512-rcJUkMfnJpfCboZoOOPf4L29TRtEieHNOeAbYPWPxlaBw/Z1RKrRA86dOI9rwaI4tQSc/RD82zTNHprfUHXsoQ==", + "version": "25.1.8", + "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-25.1.8.tgz", + "integrity": "sha512-NoXo6Liy2heSklTI5OIZbCgXC1RzrDQsZkeEwXhdOro3FT1VBOvbubvscdPnjVuQ4AMwwv61oaH96AbiYg9EnQ==", "dev": true, + "license": "MIT", "dependencies": { - "app-builder-lib": "24.13.3", - "builder-util": "24.13.1", - "builder-util-runtime": "9.2.4", + "app-builder-lib": "25.1.8", + "builder-util": "25.1.7", + "builder-util-runtime": "9.2.10", "fs-extra": "^10.1.0", "iconv-lite": "^0.6.2", "js-yaml": "^4.1.0" @@ -1893,6 +2564,7 @@ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -1907,6 +2579,7 @@ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, + "license": "MIT", "dependencies": { "universalify": "^2.0.0" }, @@ -1919,6 +2592,7 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10.0.0" } @@ -1928,6 +2602,7 @@ "resolved": "https://registry.npmjs.org/dmg-license/-/dmg-license-1.0.11.tgz", "integrity": "sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q==", "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -1955,19 +2630,33 @@ "integrity": "sha512-j9Vu1yONejh9I6gFxRI/AppmHpbtk6tyinLTEEKMEau+tGPfVd9M5+ZrYZPlXcBv0oAQGLSwYnsZqSqjxQPAcA==" }, "node_modules/dotenv": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-9.0.2.tgz", - "integrity": "sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg==", + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", "dev": true, + "license": "BSD-2-Clause", "engines": { - "node": ">=10" + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" } }, "node_modules/dotenv-expand": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", - "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", - "dev": true + "version": "11.0.7", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.7.tgz", + "integrity": "sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "dotenv": "^16.4.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } }, "node_modules/duplexer2": { "version": "0.1.4", @@ -2008,7 +2697,8 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz", "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/duplexify": { "version": "3.7.1", @@ -2052,13 +2742,15 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/ejs": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "jake": "^10.8.5" }, @@ -2075,6 +2767,7 @@ "integrity": "sha512-WjNDd6lGpxyiNjE3LhnFCAk/D9GIj1rU3GSDealVShhkkkPR3Vh4q8ErXGDl1OAO/faomVa10KoFPUN/pLbNxg==", "dev": true, "hasInstallScript": true, + "license": "MIT", "dependencies": { "@electron/get": "^1.0.1", "@types/node": "^12.0.12", @@ -2088,20 +2781,20 @@ } }, "node_modules/electron-builder": { - "version": "24.13.3", - "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-24.13.3.tgz", - "integrity": "sha512-yZSgVHft5dNVlo31qmJAe4BVKQfFdwpRw7sFp1iQglDRCDD6r22zfRJuZlhtB5gp9FHUxCMEoWGq10SkCnMAIg==", + "version": "25.1.8", + "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-25.1.8.tgz", + "integrity": "sha512-poRgAtUHHOnlzZnc9PK4nzG53xh74wj2Jy7jkTrqZ0MWPoHGh1M2+C//hGeYdA+4K8w4yiVCNYoLXF7ySj2Wig==", "dev": true, + "license": "MIT", "dependencies": { - "app-builder-lib": "24.13.3", - "builder-util": "24.13.1", - "builder-util-runtime": "9.2.4", + "app-builder-lib": "25.1.8", + "builder-util": "25.1.7", + "builder-util-runtime": "9.2.10", "chalk": "^4.1.2", - "dmg-builder": "24.13.3", + "dmg-builder": "25.1.8", "fs-extra": "^10.1.0", "is-ci": "^3.0.0", "lazy-val": "^1.0.5", - "read-config-file": "6.3.2", "simple-update-notifier": "2.0.0", "yargs": "^17.6.2" }, @@ -2114,15 +2807,16 @@ } }, "node_modules/electron-builder-squirrel-windows": { - "version": "24.13.3", - "resolved": "https://registry.npmjs.org/electron-builder-squirrel-windows/-/electron-builder-squirrel-windows-24.13.3.tgz", - "integrity": "sha512-oHkV0iogWfyK+ah9ZIvMDpei1m9ZRpdXcvde1wTpra2U8AFDNNpqJdnin5z+PM1GbQ5BoaKCWas2HSjtR0HwMg==", + "version": "25.1.8", + "resolved": "https://registry.npmjs.org/electron-builder-squirrel-windows/-/electron-builder-squirrel-windows-25.1.8.tgz", + "integrity": "sha512-2ntkJ+9+0GFP6nAISiMabKt6eqBB0kX1QqHNWFWAXgi0VULKGisM46luRFpIBiU3u/TDmhZMM8tzvo2Abn3ayg==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { - "app-builder-lib": "24.13.3", + "app-builder-lib": "25.1.8", "archiver": "^5.3.1", - "builder-util": "24.13.1", + "builder-util": "25.1.7", "fs-extra": "^10.1.0" } }, @@ -2131,6 +2825,7 @@ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "graceful-fs": "^4.2.0", @@ -2146,6 +2841,7 @@ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "universalify": "^2.0.0" @@ -2159,6 +2855,7 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">= 10.0.0" @@ -2200,14 +2897,15 @@ } }, "node_modules/electron-publish": { - "version": "24.13.1", - "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-24.13.1.tgz", - "integrity": "sha512-2ZgdEqJ8e9D17Hwp5LEq5mLQPjqU3lv/IALvgp+4W8VeNhryfGhYEQC/PgDPMrnWUp+l60Ou5SJLsu+k4mhQ8A==", + "version": "25.1.7", + "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-25.1.7.tgz", + "integrity": "sha512-+jbTkR9m39eDBMP4gfbqglDd6UvBC7RLh5Y0MhFSsc6UkGHj9Vj9TWobxevHYMMqmoujL11ZLjfPpMX+Pt6YEg==", "dev": true, + "license": "MIT", "dependencies": { "@types/fs-extra": "^9.0.11", - "builder-util": "24.13.1", - "builder-util-runtime": "9.2.4", + "builder-util": "25.1.7", + "builder-util-runtime": "9.2.10", "chalk": "^4.1.2", "fs-extra": "^10.1.0", "lazy-val": "^1.0.5", @@ -2219,6 +2917,7 @@ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -2233,6 +2932,7 @@ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, + "license": "MIT", "dependencies": { "universalify": "^2.0.0" }, @@ -2245,6 +2945,7 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10.0.0" } @@ -2267,6 +2968,13 @@ "jsonfile": "^4.0.0" } }, + "node_modules/electron/node_modules/@types/node": { + "version": "12.20.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", + "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", + "dev": true, + "license": "MIT" + }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -2278,11 +2986,23 @@ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "dev": true, + "license": "MIT", "optional": true, "engines": { "node": ">= 0.8" } }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, "node_modules/end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -2304,13 +3024,15 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/es-define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { "get-intrinsic": "^1.2.4" @@ -2324,6 +3046,7 @@ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "dev": true, + "license": "MIT", "optional": true, "engines": { "node": ">= 0.4" @@ -2349,6 +3072,7 @@ "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", "dev": true, + "license": "MIT", "optional": true }, "node_modules/es6-iterator": { @@ -2416,6 +3140,7 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, + "license": "MIT", "optional": true, "engines": { "node": ">=10" @@ -2501,6 +3226,13 @@ "es5-ext": "~0.10.14" } }, + "node_modules/exponential-backoff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", + "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/ext": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", @@ -2514,6 +3246,7 @@ "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "concat-stream": "^1.6.2", "debug": "^2.6.9", @@ -2529,6 +3262,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -2537,7 +3271,8 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/extsprintf": { "version": "1.4.1", @@ -2547,19 +3282,22 @@ "engines": [ "node >=0.6.0" ], + "license": "MIT", "optional": true }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", @@ -2571,6 +3309,7 @@ "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", "dev": true, + "license": "MIT", "dependencies": { "pend": "~1.2.0" } @@ -2580,10 +3319,24 @@ "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", "dev": true, + "license": "Apache-2.0", "dependencies": { "minimatch": "^5.0.1" } }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -2620,6 +3373,7 @@ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", "dev": true, + "license": "ISC", "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^4.0.1" @@ -2631,6 +3385,19 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", @@ -2649,6 +3416,7 @@ "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/fs-extra": { @@ -2656,6 +3424,7 @@ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", @@ -2670,6 +3439,7 @@ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", "dev": true, + "license": "ISC", "dependencies": { "minipass": "^3.0.0" }, @@ -2677,23 +3447,12 @@ "node": ">= 8" } }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/fsevents": { "version": "2.3.3", @@ -2717,6 +3476,27 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "deprecated": "This package is no longer supported.", + "dev": true, + "license": "ISC", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, "node_modules/get-assigned-identifiers": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", @@ -2736,6 +3516,7 @@ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { "es-errors": "^1.3.0", @@ -2752,15 +3533,19 @@ } }, "node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "dev": true, + "license": "MIT", "dependencies": { "pump": "^3.0.0" }, "engines": { - "node": ">=6" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/gh_deploy": { @@ -2778,6 +3563,7 @@ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -2810,6 +3596,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2820,6 +3607,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -2832,6 +3620,7 @@ "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", "dev": true, + "license": "BSD-3-Clause", "optional": true, "dependencies": { "boolean": "^3.0.1", @@ -2850,6 +3639,7 @@ "resolved": "https://registry.npmjs.org/global-tunnel-ng/-/global-tunnel-ng-2.7.1.tgz", "integrity": "sha512-4s+DyciWBV0eK148wqXxcmVAbFVPqtc3sEtUE/GTQfuU80rySLcMhUmHKSHI7/LDj8q0gDYI1lIhRRB7ieRAqg==", "dev": true, + "license": "BSD-3-Clause", "optional": true, "dependencies": { "encodeurl": "^1.0.2", @@ -2866,6 +3656,7 @@ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { "define-properties": "^1.2.1", @@ -2883,6 +3674,7 @@ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { "get-intrinsic": "^1.1.3" @@ -2892,25 +3684,29 @@ } }, "node_modules/got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "version": "11.8.6", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", "dev": true, + "license": "MIT", "dependencies": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" }, "engines": { - "node": ">=8.6" + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" } }, "node_modules/graceful-fs": { @@ -2932,6 +3728,7 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -2941,6 +3738,7 @@ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { "es-define-property": "^1.0.0" @@ -2954,6 +3752,7 @@ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "dev": true, + "license": "MIT", "optional": true, "engines": { "node": ">= 0.4" @@ -2967,6 +3766,7 @@ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", "dev": true, + "license": "MIT", "optional": true, "engines": { "node": ">= 0.4" @@ -2975,6 +3775,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "dev": true, + "license": "ISC" + }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -2991,6 +3798,7 @@ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -3005,30 +3813,55 @@ "dev": true }, "node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", "dev": true, + "license": "MIT", "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" + "agent-base": "^7.1.0", + "debug": "^4.3.4" }, "engines": { - "node": ">= 6" + "node": ">= 14" + } + }, + "node_modules/http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" } }, "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", "dev": true, + "license": "MIT", "dependencies": { - "agent-base": "6", + "agent-base": "^7.0.2", "debug": "4" }, "engines": { - "node": ">= 6" + "node": ">= 14" + } + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.0.0" } }, "node_modules/hyperglue": { @@ -3044,6 +3877,7 @@ "resolved": "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz", "integrity": "sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ==", "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -3061,6 +3895,7 @@ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, @@ -3086,12 +3921,41 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "BSD-3-Clause" }, "node_modules/immediate": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==" + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "license": "MIT" + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true, + "license": "ISC" }, "node_modules/inflight": { "version": "1.0.6", @@ -3099,6 +3963,7 @@ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, + "license": "ISC", "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -3114,6 +3979,7 @@ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true, + "license": "ISC", "optional": true }, "node_modules/insert-css": { @@ -3121,6 +3987,20 @@ "resolved": "https://registry.npmjs.org/insert-css/-/insert-css-2.0.0.tgz", "integrity": "sha512-xGq5ISgcUP5cvGkS2MMFLtPDBtrtQPSFfC6gA6U8wHKqfjTIMZLZNxOItQnoSjdOzlXOLU/yD32RKC4SvjNbtA==" }, + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -3138,6 +4018,7 @@ "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", "dev": true, + "license": "MIT", "dependencies": { "ci-info": "^3.2.0" }, @@ -3205,6 +4086,23 @@ "node": ">=0.10.0" } }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "dev": true, + "license": "MIT" + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -3214,6 +4112,19 @@ "node": ">=0.12.0" } }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-wsl": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", @@ -3233,10 +4144,11 @@ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" }, "node_modules/isbinaryfile": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.2.tgz", - "integrity": "sha512-GvcjojwonMjWbTkfMpnVHVqXW/wKMYDfEpY94/8zy8HFMOqb/VL6oeONq9v87q4ttVlaTLnGXnJD4B5B1OTGIg==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.4.tgz", + "integrity": "sha512-YKBKVkKhty7s8rxddb40oOkuP0NbaeXrQvLin6QMHL7Ypiy2RW9LwOVrVgZRyOrhQlayMd9t+D8yDy8MKFTSDQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 18.0.0" }, @@ -3248,13 +4160,15 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/jackspeak": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/cliui": "^8.0.2" }, @@ -3270,6 +4184,7 @@ "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "async": "^3.2.3", "chalk": "^4.0.2", @@ -3288,6 +4203,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3298,6 +4214,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -3315,6 +4232,7 @@ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -3322,23 +4240,33 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "dev": true, + "license": "MIT" + }, "node_modules/json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==", - "dev": true + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", "dev": true, + "license": "ISC", "optional": true }, "node_modules/json5": { @@ -3346,6 +4274,7 @@ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, + "license": "MIT", "bin": { "json5": "lib/cli.js" }, @@ -3362,25 +4291,28 @@ } }, "node_modules/keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, + "license": "MIT", "dependencies": { - "json-buffer": "3.0.0" + "json-buffer": "3.0.1" } }, "node_modules/lazy-val": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz", "integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lazystream": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "readable-stream": "^2.0.5" @@ -3394,6 +4326,7 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "core-util-is": "~1.0.0", @@ -3410,6 +4343,7 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/lazystream/node_modules/string_decoder": { @@ -3417,6 +4351,7 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "safe-buffer": "~5.1.0" @@ -3438,6 +4373,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", "integrity": "sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==", + "license": "MIT", "dependencies": { "immediate": "~3.0.5" } @@ -3446,6 +4382,7 @@ "version": "1.10.0", "resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz", "integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==", + "license": "Apache-2.0", "dependencies": { "lie": "3.1.1" } @@ -3461,6 +4398,7 @@ "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/lodash.difference": { @@ -3468,6 +4406,7 @@ "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/lodash.flatten": { @@ -3475,6 +4414,7 @@ "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/lodash.isplainobject": { @@ -3482,6 +4422,7 @@ "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/lodash.union": { @@ -3489,15 +4430,34 @@ "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==", "dev": true, + "license": "MIT", "peer": true }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, "node_modules/lru-cache": { @@ -3505,6 +4465,7 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -3520,11 +4481,92 @@ "sourcemap-codec": "^1.4.1" } }, + "node_modules/make-fetch-happen": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", + "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", + "dev": true, + "license": "ISC", + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^16.1.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^2.0.3", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^9.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/make-fetch-happen/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/make-fetch-happen/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/matcher": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { "escape-string-regexp": "^4.0.0" @@ -3554,6 +4596,7 @@ "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", "dev": true, + "license": "MIT", "bin": { "mime": "cli.js" }, @@ -3580,25 +4623,40 @@ "node": ">= 0.6" } }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/mimic-response": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", + "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=10" + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/minimist": { @@ -3610,44 +4668,108 @@ } }, "node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, "engines": { "node": ">=8" } }, - "node_modules/minizlib": { + "node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-fetch": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", + "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", "dev": true, + "license": "MIT", "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" + "minipass": "^3.1.6", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" }, "engines": { "node": ">= 8" } }, - "node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", "dev": true, + "license": "ISC", "dependencies": { - "yallist": "^4.0.0" + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" }, "engines": { "node": ">=8" } }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "dev": true, + "license": "MIT", "dependencies": { "minimist": "^1.2.6" }, @@ -3677,18 +4799,52 @@ "zeltice-mt-downloader": "https://github.com/FaisalUmair/mt-files-downloader" } }, + "node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/next-tick": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" }, + "node_modules/node-abi": { + "version": "3.71.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.71.0.tgz", + "integrity": "sha512-SZ40vRiy/+wRTf21hxkkEjPJZpARzUMVcJoQse2EF8qkUWbbO2z7vd5oA/H6bVH6SZQ5STGcu0KRDS7biNRfxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/node-addon-api": { "version": "1.7.2", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==", "dev": true, + "license": "MIT", "optional": true }, + "node_modules/node-api-version": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/node-api-version/-/node-api-version-0.2.0.tgz", + "integrity": "sha512-fthTTsi8CxaBXMaBAD7ST2uylwvsnYxh2PfaScwpMhos6KlSFajXQPcM4ogNE1q2s3Lbz9GCGqeIHC+C6OZnKg==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + } + }, "node_modules/node-cache": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/node-cache/-/node-cache-5.1.2.tgz", @@ -3700,6 +4856,32 @@ "node": ">= 8.0.0" } }, + "node_modules/node-gyp": { + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.1.tgz", + "integrity": "sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^10.0.3", + "nopt": "^6.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^12.13 || ^14.13 || >=16" + } + }, "node_modules/node-vtt-to-srt": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/node-vtt-to-srt/-/node-vtt-to-srt-1.0.1.tgz", @@ -3743,6 +4925,22 @@ "xtend": ">=4.0.0 <4.1.0-0" } }, + "node_modules/nopt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", + "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", + "dev": true, + "license": "ISC", + "dependencies": { + "abbrev": "^1.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -3753,12 +4951,16 @@ } }, "node_modules/normalize-url": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", - "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/npm-conf": { @@ -3766,6 +4968,7 @@ "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz", "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { "config-chain": "^1.1.11", @@ -3775,6 +4978,23 @@ "node": ">=4" } }, + "node_modules/npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "deprecated": "This package is no longer supported.", + "dev": true, + "license": "ISC", + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, "node_modules/object-inspect": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", @@ -3791,6 +5011,7 @@ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true, + "license": "MIT", "optional": true, "engines": { "node": ">= 0.4" @@ -3804,6 +5025,22 @@ "wrappy": "1" } }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/open": { "version": "8.4.2", "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", @@ -3838,26 +5075,85 @@ "node": ">= 0.8.0" } }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", "dev": true, + "license": "MIT", + "dependencies": { + "aggregate-error": "^3.0.0" + }, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/package-json-from-dist": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", - "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", - "dev": true + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -3867,6 +5163,7 @@ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -3881,6 +5178,7 @@ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" @@ -3896,13 +5194,40 @@ "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true + "dev": true, + "license": "ISC" + }, + "node_modules/path-scurry/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/pe-library": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/pe-library/-/pe-library-0.4.1.tgz", + "integrity": "sha512-eRWB5LBz7PpDu4PUlwT0PhnQfTQJlDDdPa35urV4Osrm0t0AqQFGn+UIkU3klZvwJ8KPO3VbBFsXquA6p6kqZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jet2jet" + } }, "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/picomatch": { "version": "2.3.1", @@ -3921,6 +5246,7 @@ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", "dev": true, + "license": "MIT", "optional": true, "engines": { "node": ">=4" @@ -3931,6 +5257,7 @@ "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", "integrity": "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==", "dev": true, + "license": "MIT", "dependencies": { "@xmldom/xmldom": "^0.8.8", "base64-js": "^1.5.1", @@ -3953,6 +5280,7 @@ "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -3967,15 +5295,24 @@ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.4.0" } }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "dev": true, + "license": "ISC" + }, "node_modules/promise-retry": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", "dev": true, + "license": "MIT", "dependencies": { "err-code": "^2.0.2", "retry": "^0.12.0" @@ -3989,6 +5326,7 @@ "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", "dev": true, + "license": "ISC", "optional": true }, "node_modules/proxy-from-env": { @@ -3997,10 +5335,11 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", "dev": true, + "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -4030,10 +5369,24 @@ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/quote-stream": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/quote-stream/-/quote-stream-1.0.2.tgz", @@ -4055,21 +5408,17 @@ "node": ">=0.4.0" } }, - "node_modules/read-config-file": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-6.3.2.tgz", - "integrity": "sha512-M80lpCjnE6Wt6zb98DoW8WHR09nzMSpu8XHtPkiTHrJ5Az9CybfeQhTJ8D7saeBHpGhLPIVyA8lcL6ZmdKwY6Q==", + "node_modules/read-binary-file-arch": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/read-binary-file-arch/-/read-binary-file-arch-1.0.6.tgz", + "integrity": "sha512-BNg9EN3DD3GsDXX7Aa8O4p92sryjkmzYYgmgTAc6CA4uGLEDzFfxOxugu21akOxpcXHiEgsYkC6nPsQvLLLmEg==", "dev": true, + "license": "MIT", "dependencies": { - "config-file-ts": "^0.2.4", - "dotenv": "^9.0.2", - "dotenv-expand": "^5.1.0", - "js-yaml": "^4.1.0", - "json5": "^2.2.0", - "lazy-val": "^1.0.4" + "debug": "^4.3.4" }, - "engines": { - "node": ">=12.0.0" + "bin": { + "read-binary-file-arch": "cli.js" } }, "node_modules/readable-stream": { @@ -4077,7 +5426,7 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -4092,11 +5441,26 @@ "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", "dev": true, + "license": "Apache-2.0", "peer": true, "dependencies": { "minimatch": "^5.1.0" } }, + "node_modules/readdir-glob/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -4118,6 +5482,24 @@ "node": ">=0.10.0" } }, + "node_modules/resedit": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/resedit/-/resedit-1.7.2.tgz", + "integrity": "sha512-vHjcY2MlAITJhC0eRD/Vv8Vlgmu9Sd3LX9zZvtGzU5ZImdTN3+d6e/4mnTyV8vEbyf1sgNIrWxhWlrys52OkEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pe-library": "^0.4.1" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jet2jet" + } + }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -4134,13 +5516,38 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true, + "license": "MIT" + }, "node_modules/responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", "dev": true, + "license": "MIT", "dependencies": { - "lowercase-keys": "^1.0.0" + "lowercase-keys": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" } }, "node_modules/retry": { @@ -4148,15 +5555,34 @@ "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/roarr": { "version": "2.15.4", "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", "dev": true, + "license": "BSD-3-Clause", "optional": true, "dependencies": { "boolean": "^3.0.1", @@ -4189,13 +5615,14 @@ "url": "https://feross.org/support" } ], - "peer": true + "license": "MIT" }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/sanitize-filename": { "version": "1.6.3", @@ -4209,7 +5636,8 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/scope-analyzer": { "version": "2.1.2", @@ -4242,6 +5670,7 @@ "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", "dev": true, + "license": "MIT", "optional": true }, "node_modules/serialize-error": { @@ -4249,6 +5678,7 @@ "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { "type-fest": "^0.13.1" @@ -4260,6 +5690,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true, + "license": "ISC" + }, "node_modules/shallow-copy": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz", @@ -4270,6 +5707,7 @@ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, + "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -4282,21 +5720,17 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } + "license": "ISC" }, "node_modules/simple-update-notifier": { "version": "2.0.0", @@ -4315,6 +5749,7 @@ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { "ansi-styles": "^4.0.0", @@ -4330,12 +5765,55 @@ "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", "dev": true, - "optional": true, + "license": "MIT", "engines": { "node": ">= 6.0.0", "npm": ">= 3.0.0" } }, + "node_modules/socks": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", + "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", + "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/socks-proxy-agent/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -4350,6 +5828,7 @@ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, + "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -4403,14 +5882,27 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "dev": true + }, + "node_modules/ssri": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", + "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", "dev": true, - "optional": true + "license": "ISC", + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } }, "node_modules/stat-mode": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-1.0.0.tgz", "integrity": "sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 6" } @@ -4509,7 +6001,7 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { "safe-buffer": "~5.2.0" } @@ -4534,6 +6026,7 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -4561,6 +6054,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -4573,6 +6067,7 @@ "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", "dev": true, + "license": "Apache-2.0", "dependencies": { "debug": "^4.1.0" }, @@ -4585,6 +6080,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -4608,6 +6104,7 @@ "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", "dev": true, + "license": "ISC", "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -4625,6 +6122,7 @@ "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "bl": "^4.0.3", @@ -4637,11 +6135,22 @@ "node": ">=6" } }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=8" + } + }, "node_modules/tar/node_modules/mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true, + "license": "MIT", "bin": { "mkdirp": "bin/cmd.js" }, @@ -4654,6 +6163,7 @@ "resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.4.0.tgz", "integrity": "sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==", "dev": true, + "license": "MIT", "dependencies": { "async-exit-hook": "^2.0.1", "fs-extra": "^10.0.0" @@ -4664,6 +6174,7 @@ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -4678,6 +6189,7 @@ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, + "license": "MIT", "dependencies": { "universalify": "^2.0.0" }, @@ -4690,6 +6202,7 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10.0.0" } @@ -4735,6 +6248,7 @@ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", "dev": true, + "license": "MIT", "engines": { "node": ">=14.14" } @@ -4744,6 +6258,7 @@ "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz", "integrity": "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==", "dev": true, + "license": "MIT", "dependencies": { "tmp": "^0.2.0" } @@ -4753,6 +6268,7 @@ "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -4778,15 +6294,17 @@ } }, "node_modules/tslib": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", - "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" }, "node_modules/tunnel": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", "dev": true, + "license": "MIT", "optional": true, "engines": { "node": ">=0.6.11 <=0.7.0 || >=0.7.3" @@ -4813,6 +6331,7 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", "dev": true, + "license": "(MIT OR CC0-1.0)", "optional": true, "engines": { "node": ">=10" @@ -4827,10 +6346,11 @@ "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" }, "node_modules/typescript": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", - "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -4844,11 +6364,45 @@ "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.5.2.tgz", "integrity": "sha512-yejOFsRnTJs0N9CK5Apzf6maDO2djxGoLLrlZlvGs2o9ZQuhIhDL18rtFyy4FBIbOkzA6+4hDgXbgz5EvDQCXQ==" }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true, + "license": "MIT" + }, + "node_modules/unique-filename": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", + "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", + "dev": true, + "license": "ISC", + "dependencies": { + "unique-slug": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/unique-slug": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", + "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, "node_modules/universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4.0.0" } @@ -4858,6 +6412,7 @@ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } @@ -4867,6 +6422,7 @@ "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==", "dev": true, + "license": "MIT", "dependencies": { "prepend-http": "^2.0.0" }, @@ -4889,6 +6445,7 @@ "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz", "integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { "assert-plus": "^1.0.0", @@ -4899,11 +6456,22 @@ "node": ">=0.6.0" } }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "license": "MIT", + "dependencies": { + "defaults": "^1.0.3" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -4914,6 +6482,16 @@ "node": ">= 8" } }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", @@ -4945,6 +6523,7 @@ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -4967,6 +6546,7 @@ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.0" } @@ -4992,7 +6572,8 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/yargs": { "version": "17.7.2", @@ -5026,11 +6607,25 @@ "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", "dev": true, + "license": "MIT", "dependencies": { "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" } }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/zeltice-mt-downloader": { "version": "1.1.3", "resolved": "git+ssh://git@github.com/FaisalUmair/mt-files-downloader.git#436713c73fa9653c8585c075731aea06abad07d6", @@ -5049,6 +6644,7 @@ "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.1.tgz", "integrity": "sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "archiver-utils": "^3.0.4", @@ -5064,6 +6660,7 @@ "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-3.0.4.tgz", "integrity": "sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "glob": "^7.2.3", diff --git a/package.json b/package.json index 6ccf1c02..68ea625d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "udeler", "productName": "Udeler", - "version": "1.13.2", + "version": "1.13.3", "description": "A cross platform (Windows, Mac, Linux) desktop application for downloading Udemy Courses.", "main": "main.js", "type": "commonjs", @@ -23,6 +23,7 @@ "scripts": { "dev": "electron . --developer", "start": "electron .", + "format": "prettier --write \"app/**/*.js\"", "postinstall": "electron-builder install-app-deps", "build": "electron-builder", "build:w32": "electron-builder -w \"--ia32\"", @@ -31,9 +32,9 @@ "sync:locales": "node ./sync-locales.js" }, "dependencies": { - "@sentry/electron": "4.24.0", - "axios": "^1.7.5", - "cookie": "^0.6.0", + "@sentry/electron": "^4.24.0", + "axios": "^1.7.7", + "cookie": "^1.0.1", "dialogs": "^2.0.1", "electron-settings": "3.2.0", "jquery": "^3.7.1", @@ -43,8 +44,8 @@ "sanitize-filename": "^1.6.3" }, "devDependencies": { - "electron": "11.5.0", - "electron-builder": "^24.1.1", + "electron": "^11.5.0", + "electron-builder": "^25.1.8", "electron-reload": "^2.0.0-alpha.1", "gh_deploy": "github:heliomarpm/gh_deploy" }, diff --git a/sync_locales_template.py b/sync_locales_template.py deleted file mode 100644 index 68d8f304..00000000 --- a/sync_locales_template.py +++ /dev/null @@ -1,27 +0,0 @@ -# Sync locales with template.json -# by @mirusu400 -import json -import os - -def update(filename): - with open('template.json', 'r', encoding="utf-8") as f: - template_data = json.load(f) - - with open(filename, 'r', encoding="utf-8") as f: - ko_data = json.load(f) - - out_dict = {} - for key in template_data.keys(): - if key in ko_data.keys(): - out_dict[key] = ko_data[key] - else: - out_dict[key] = template_data[key] - - with open(filename, 'w', encoding="utf-8") as f: - json.dump(out_dict, f, ensure_ascii=False, indent=2) - - -if __name__ == "__main__": - for filename in os.listdir("./"): - if filename.endswith(".json") and filename != "template.json" and filename != "meta.json": - update(filename) \ No newline at end of file