Compare commits

...

84 Commits

Author SHA1 Message Date
c52c2d886a Merge pull request #303 from th-ch/dependabot/npm_and_yarn/ws-7.4.6
Bump ws from 7.4.3 to 7.4.6
2021-05-28 23:40:55 +02:00
e5dc1f8a58 Bump ws from 7.4.3 to 7.4.6
Bumps [ws](https://github.com/websockets/ws) from 7.4.3 to 7.4.6.
- [Release notes](https://github.com/websockets/ws/releases)
- [Commits](https://github.com/websockets/ws/compare/7.4.3...7.4.6)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-28 21:39:25 +00:00
6dbf4134de Merge pull request #301 from th-ch/dependabot/npm_and_yarn/browserslist-4.16.6
Bump browserslist from 4.16.3 to 4.16.6
2021-05-28 23:38:48 +02:00
e1cc49a74d Merge pull request #300 from th-ch/snyk-upgrade-ce2777733d9dee231391c0a822c24a84
[Snyk] Upgrade @cliqz/adblocker-electron from 1.20.4 to 1.20.5
2021-05-28 23:35:11 +02:00
TC
4489a400b7 Merge branch 'master' of github.com:th-ch/youtube-music into snyk-upgrade-ce2777733d9dee231391c0a822c24a84
# By Araxeus (5) and others
# Via GitHub (5) and TC (2)
* 'master' of github.com:th-ch/youtube-music:
  Bump electron to 12.0.8
  fix: upgrade ytdl-core from 4.5.0 to 4.7.0
  fix: upgrade @ffmpeg/core from 0.8.5 to 0.9.0
  fix notificationOnUnpause option
  fix: upgrade filenamify from 4.2.0 to 4.3.0
  switch to `registerCallback()` on song info
  fix: upgrade ytpl from 2.1.1 to 2.2.0
  lint
  refactor notifications plugin
  setup SongInfo **once**
2021-05-28 23:33:20 +02:00
28aa1c0b22 Merge pull request #299 from th-ch/snyk-upgrade-37e43892f5a34f935e8486a98b3598fb
[Snyk] Upgrade ytdl-core from 4.5.0 to 4.7.0
2021-05-28 23:32:29 +02:00
TC
c540788d20 Merge branch 'master' of github.com:th-ch/youtube-music into snyk-upgrade-37e43892f5a34f935e8486a98b3598fb
# By Araxeus (5) and others
# Via GitHub (4) and TC (1)
* 'master' of github.com:th-ch/youtube-music:
  Bump electron to 12.0.8
  fix: upgrade @ffmpeg/core from 0.8.5 to 0.9.0
  fix notificationOnUnpause option
  fix: upgrade filenamify from 4.2.0 to 4.3.0
  switch to `registerCallback()` on song info
  fix: upgrade ytpl from 2.1.1 to 2.2.0
  lint
  refactor notifications plugin
  setup SongInfo **once**
2021-05-28 23:32:05 +02:00
4ab07dc875 Merge pull request #298 from th-ch/snyk-upgrade-d305cdce94133f6db9615e7b16007c87
[Snyk] Upgrade @ffmpeg/core from 0.8.5 to 0.9.0
2021-05-28 23:28:26 +02:00
5033de13ef Merge pull request #293 from th-ch/snyk-upgrade-335ec370c7caa5a759c54a46b2e27cf5
[Snyk] Upgrade filenamify from 4.2.0 to 4.3.0
2021-05-28 23:23:49 +02:00
55a8787a16 Merge pull request #285 from th-ch/snyk-upgrade-7b9c569f5bdd092f76adf7d412b0eea1
[Snyk] Upgrade ytpl from 2.1.1 to 2.2.0
2021-05-28 23:21:51 +02:00
3515bf364d Merge pull request #269 from Araxeus/fix-XHR-duplicate-callback
fix song-info callback duplication
2021-05-28 23:18:10 +02:00
TC
d8f3246e46 Bump electron to 12.0.8 2021-05-28 23:13:07 +02:00
cd613aaba2 Bump browserslist from 4.16.3 to 4.16.6
Bumps [browserslist](https://github.com/browserslist/browserslist) from 4.16.3 to 4.16.6.
- [Release notes](https://github.com/browserslist/browserslist/releases)
- [Changelog](https://github.com/browserslist/browserslist/blob/main/CHANGELOG.md)
- [Commits](https://github.com/browserslist/browserslist/compare/4.16.3...4.16.6)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-27 02:56:37 +00:00
c5f84b568b fix: upgrade @cliqz/adblocker-electron from 1.20.4 to 1.20.5
Snyk has created this PR to upgrade @cliqz/adblocker-electron from 1.20.4 to 1.20.5.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2021-05-26 04:36:08 +00:00
14dc78984f fix: upgrade ytdl-core from 4.5.0 to 4.7.0
Snyk has created this PR to upgrade ytdl-core from 4.5.0 to 4.7.0.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2021-05-26 04:36:06 +00:00
fb61dbfa6c fix: upgrade @ffmpeg/core from 0.8.5 to 0.9.0
Snyk has created this PR to upgrade @ffmpeg/core from 0.8.5 to 0.9.0.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2021-05-26 04:36:03 +00:00
8124623142 fix notificationOnUnpause option 2021-05-22 18:38:36 +03:00
177ce5721f fix: upgrade filenamify from 4.2.0 to 4.3.0
Snyk has created this PR to upgrade filenamify from 4.2.0 to 4.3.0.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2021-05-19 05:31:34 +00:00
4fb0b1dd08 switch to registerCallback() on song info 2021-05-19 00:22:12 +03:00
bbe5a7d50b fix: upgrade ytpl from 2.1.1 to 2.2.0
Snyk has created this PR to upgrade ytpl from 2.1.1 to 2.2.0.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2021-05-17 04:44:57 +00:00
5bc8e86353 Merge pull request #270 from Araxeus/fix-normal-notification-showing-appID
fix notification showing appID instead of app name on windows
2021-05-16 22:46:54 +02:00
5b00465558 Merge pull request #273 from th-ch/upgrade-electron
Upgrade electron to v12
2021-05-16 22:31:07 +02:00
TC
0e8e78362b Upgrade electron to v12 2021-05-11 22:56:07 +02:00
cb6a5a478e lint 2021-05-11 16:47:51 +03:00
d615030222 register appID on windows reguardless of shortcut 2021-05-11 00:34:40 +03:00
cb5ef1d6e5 check that app is installed / unpacked 2021-05-11 00:15:54 +03:00
78a7dcb7e8 lint 2021-05-10 23:46:56 +03:00
8cca9f3eeb create shortcut only if needed 2021-05-10 23:23:17 +03:00
93d4d3c976 writeShortcut on windows 2021-05-10 22:13:45 +03:00
8284b56075 set appID on windows 2021-05-10 20:40:25 +03:00
b266037bb4 lint 2021-05-10 06:05:39 +03:00
cb743de7fd refactor notifications plugin 2021-05-10 05:00:58 +03:00
7cf78c6635 setup SongInfo **once** 2021-05-10 04:15:56 +03:00
7942efa202 Merge pull request #267 from Araxeus/last-fm-config-check-fix
fix last-fm overwrite config on each start
2021-05-09 21:47:07 +02:00
792c2931b0 fix config overwrite on each start 2021-05-09 22:10:20 +03:00
TC
a3778af48a Downloader: rename UrlToJPG to urlToJPG 2021-05-08 22:48:18 +02:00
TC
163dc7e1d1 Downloader: catch error when fetching playlist 2021-05-08 22:41:56 +02:00
0a59122ac2 Merge pull request #265 from Araxeus/ensure-download-from-radio-button
Downloader tweaks + taskbar progress bar
2021-05-08 22:40:24 +02:00
d2a5110f3b querySelector optimization #2 2021-05-08 23:06:18 +03:00
cf4bbf94e4 update radioButton querySelector 2021-05-08 23:02:52 +03:00
d7e42471a4 lint 2021-05-08 23:01:57 +03:00
d634c41e75 Merge pull request #262 from Araxeus/remove-open-dependency
remove `open` dependency from last-fm plugin
2021-05-08 21:58:51 +02:00
6b88397f82 lint 2021-05-08 21:21:07 +03:00
da3c709ff0 remove videoDetails?.media query from XHR
(it never exists in the XHR responce)
2021-05-08 20:46:15 +03:00
ccd320d8ff minimize getArtist() 2021-05-08 20:40:44 +03:00
3831e61d10 differentiate names of different metadata sources 2021-05-08 19:45:33 +03:00
e46e7b74e2 fix sendError() 2021-05-08 19:34:57 +03:00
b3da77a6bc small refactor 2021-05-08 19:24:25 +03:00
96a74f8955 use original metadata only if not already captured from ytpl.getInfo() 2021-05-08 19:19:11 +03:00
3ea17e6f46 refactor 2021-05-08 08:05:38 +03:00
a8ac2c3af9 download progress bar on taskbar
+ Get the best possible artwork
2021-05-08 07:11:54 +03:00
2168cbca30 use image from imageSrc if transfered 2021-05-08 04:04:35 +03:00
cceb45319a debug videoUrl from start Radio button in menu 2021-05-08 04:03:34 +03:00
e985b78241 lint 2021-05-08 01:08:24 +03:00
3522925dec remove open dependency 2021-05-08 01:00:23 +03:00
5faeddb99b Merge pull request #252 from Araxeus/fix-download-idtag-if-not-playing
Fix downloader metadata if not currently playing
2021-05-07 23:11:10 +02:00
1140c3e2e7 lint 2021-05-07 23:40:14 +03:00
TC
3fb08d27c7 Add start:debug command to enable dev with electron debug 2021-05-07 22:29:21 +02:00
250940d083 Merge pull request #259 from Araxeus/force-pause
fix playPause bugs by directly playPause video element
2021-05-07 22:24:03 +02:00
e00be8f010 lint 2021-05-07 05:43:26 +03:00
8b471c0772 create cleanupArtistName() in song-info 2021-05-07 04:47:24 +03:00
88e738c796 check if yns_pause exists 2021-05-07 04:17:17 +03:00
TC
c76d8c79d8 Bump version to 1.12.1 2021-05-06 22:29:04 +02:00
b396431a8b Merge pull request #260 from th-ch/dependabot/npm_and_yarn/ua-parser-js-0.7.28
Bump ua-parser-js from 0.7.23 to 0.7.28
2021-05-06 22:18:37 +02:00
d1795a82f7 Merge pull request #253 from Araxeus/fix-precise-volume-listener-override
Fix precise volume listener override
2021-05-06 21:45:09 +02:00
9b821a0dfe Bump ua-parser-js from 0.7.23 to 0.7.28
Bumps [ua-parser-js](https://github.com/faisalman/ua-parser-js) from 0.7.23 to 0.7.28.
- [Release notes](https://github.com/faisalman/ua-parser-js/releases)
- [Commits](https://github.com/faisalman/ua-parser-js/compare/0.7.23...0.7.28)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-06 19:41:13 +00:00
bf89842ee8 Merge pull request #255 from Araxeus/fix-css-on-reload
fix css not inserting on reload
2021-05-06 21:40:13 +02:00
d274e80f75 minify 2021-05-06 21:41:08 +03:00
a98b8945fb lint 2021-05-06 21:32:44 +03:00
6b72599f80 directly playPause video element 2021-05-06 21:20:42 +03:00
4b6fe78a1a fix css not inserting on reload 2021-05-06 18:40:56 +03:00
d000c03fca lint 2021-05-06 05:40:31 +03:00
c0a185ba68 refactor addEventListener 2021-05-06 05:18:06 +03:00
ef0813e638 fix preventDefault() being called on *all* keys 2021-05-06 04:58:05 +03:00
25e9f44260 fix listener override condition 2021-05-06 04:56:06 +03:00
2d6e858e8f lint 2021-05-06 04:43:31 +03:00
53bf7c5068 playlist download progressBar using chokidar 2021-05-06 04:41:58 +03:00
13fb686188 started playlist downlaod messageBox 2021-05-06 03:33:49 +03:00
61c5494588 custom metadata on playlist-download 2021-05-06 03:02:06 +03:00
d96fefbc24 fix error thrown when downloading playlist 2021-05-06 02:51:10 +03:00
e18b7c1013 allow unlimited playlist size 2021-05-06 02:28:35 +03:00
f190b51dcc lint 2021-05-06 02:17:48 +03:00
ca41c12f7c use media propery if exist in song-info 2021-05-06 02:05:48 +03:00
844edbe2f4 fix metadata when downloading unplayed song 2021-05-06 01:46:14 +03:00
24 changed files with 512 additions and 316 deletions

View File

@ -41,7 +41,6 @@ const defaultConfig = {
api_root: "http://ws.audioscrobbler.com/2.0/",
api_key: "04d76faaac8726e60988e14c105d421a", // api key registered by @semvis123
secret: "a5d2a36fdf64819290f6982481eaffa2",
suffixesToRemove: [' - Topic', 'VEVO'] // removes suffixes of the artist name, for better recognition
},
discord: {
enabled: false,

View File

@ -11,6 +11,7 @@ const { setApplicationMenu } = require("./menu");
const { fileExists, injectCSS } = require("./plugins/utils");
const { isTesting } = require("./utils/testing");
const { setUpTray } = require("./tray");
const { setupSongInfo } = require("./providers/song-info");
// Catch errors and log them
unhandled({
@ -157,6 +158,7 @@ function createMainWindow() {
}
app.once("browser-window-created", (event, win) => {
setupSongInfo(win);
loadPlugins(win);
win.webContents.on("did-fail-load", (
@ -255,6 +257,35 @@ app.on("ready", () => {
}, 20000);
}
// Register appID on windows
if (is.windows()) {
const appID = "com.github.th-ch.youtube-music";
app.setAppUserModelId(appID);
const appLocation = process.execPath;
const appData = app.getPath("appData");
// check shortcut validity if not in dev mode / running portable app
if (!is.dev() && !appLocation.startsWith(path.join(appData, "..", "Local", "Temp"))) {
const shortcutPath = path.join(appData, "Microsoft", "Windows", "Start Menu", "Programs", "YouTube Music.lnk");
try { // check if shortcut is registered and valid
const shortcutDetails = electron.shell.readShortcutLink(shortcutPath); // throw error if doesn't exist yet
if (shortcutDetails.target !== appLocation || shortcutDetails.appUserModelId !== appID) {
throw "needUpdate";
}
} catch (error) { // if not valid -> Register shortcut
electron.shell.writeShortcutLink(
shortcutPath,
error === "needUpdate" ? "update" : "create",
{
target: appLocation,
cwd: appLocation.slice(0, appLocation.lastIndexOf(path.sep)),
description: "YouTube Music Desktop App - including custom plugins",
appUserModelId: appID
}
);
}
}
}
mainWindow = createMainWindow();
setApplicationMenu(mainWindow);
if (config.get("options.restartOnConfigChanges")) {

View File

@ -1,7 +1,7 @@
{
"name": "youtube-music",
"productName": "YouTube Music",
"version": "1.12.0",
"version": "1.12.1",
"description": "YouTube Music Desktop App - including custom plugins",
"license": "MIT",
"repository": "th-ch/youtube-music",
@ -42,6 +42,7 @@
"scripts": {
"test": "jest",
"start": "electron .",
"start:debug": "ELECTRON_ENABLE_LOGGING=1 electron .",
"icon": "rimraf assets/generated && electron-icon-maker --input=assets/youtube-music.png --output=assets/generated",
"generate:package": "node utils/generate-package-json.js",
"postinstall": "yarn run icon && yarn run plugins",
@ -62,12 +63,13 @@
"npm": "Please use yarn and not npm"
},
"dependencies": {
"@cliqz/adblocker-electron": "^1.20.4",
"@ffmpeg/core": "^0.8.5",
"@cliqz/adblocker-electron": "^1.20.5",
"@ffmpeg/core": "^0.9.0",
"@ffmpeg/ffmpeg": "^0.9.7",
"YoutubeNonStop": "git://github.com/lawfx/YoutubeNonStop.git#v0.9.0",
"async-mutex": "^0.3.1",
"browser-id3-writer": "^4.4.0",
"chokidar": "^3.5.1",
"custom-electron-titlebar": "^3.2.6",
"discord-rpc": "^3.2.0",
"electron-debug": "^3.2.0",
@ -76,23 +78,22 @@
"electron-store": "^7.0.3",
"electron-unhandled": "^3.0.2",
"electron-updater": "^4.3.8",
"filenamify": "^4.2.0",
"filenamify": "^4.3.0",
"md5": "^2.3.0",
"node-fetch": "^2.6.1",
"node-notifier": "^9.0.1",
"open": "^8.0.3",
"ytdl-core": "^4.5.0",
"ytpl": "^2.1.1"
"ytdl-core": "^4.7.0",
"ytpl": "^2.2.0"
},
"devDependencies": {
"electron": "^11.4.4",
"electron": "^12.0.8",
"electron-builder": "^22.10.5",
"electron-devtools-installer": "^3.1.1",
"electron-icon-maker": "0.0.5",
"get-port": "^5.1.1",
"jest": "^26.6.3",
"rimraf": "^3.0.2",
"spectron": "^13.0.0",
"spectron": "^14.0.0",
"xo": "^0.38.2"
},
"resolutions": {

View File

@ -1,6 +1,6 @@
const Discord = require("discord-rpc");
const getSongInfo = require("../../providers/song-info");
const registerCallback = require("../../providers/song-info");
const rpc = new Discord.Client({
transport: "ipc",
@ -12,8 +12,6 @@ const clientId = "790655993809338398";
let clearActivity;
module.exports = (win, {activityTimoutEnabled, activityTimoutTime}) => {
const registerCallback = getSongInfo(win);
// If the page is ready, register the callback
win.once("ready-to-show", () => {
rpc.once("ready", () => {

View File

@ -2,6 +2,7 @@ const CHANNEL = "downloader";
const ACTIONS = {
ERROR: "error",
METADATA: "metadata",
PROGRESS: "progress",
};
module.exports = {

View File

@ -4,60 +4,71 @@ const { join } = require("path");
const ID3Writer = require("browser-id3-writer");
const { dialog, ipcMain } = require("electron");
const getSongInfo = require("../../providers/song-info");
const registerCallback = require("../../providers/song-info");
const { injectCSS, listenAction } = require("../utils");
const { cropMaxWidth } = require("./utils");
const { ACTIONS, CHANNEL } = require("./actions.js");
const { getImage } = require("../../providers/song-info");
const sendError = (win, err) => {
const dialogOpts = {
const sendError = (win, error) => {
win.setProgressBar(-1); // close progress bar
dialog.showMessageBox({
type: "info",
buttons: ["OK"],
title: "Error in download!",
message: "Argh! Apologies, download failed…",
detail: err.toString(),
};
dialog.showMessageBox(dialogOpts);
detail: error.toString(),
});
};
let metadata = {};
let nowPlayingMetadata = {};
function handle(win) {
injectCSS(win.webContents, join(__dirname, "style.css"));
const registerCallback = getSongInfo(win);
registerCallback((info) => {
metadata = info;
nowPlayingMetadata = info;
});
listenAction(CHANNEL, (event, action, error) => {
listenAction(CHANNEL, (event, action, arg) => {
switch (action) {
case ACTIONS.ERROR:
sendError(win, error);
case ACTIONS.ERROR: // arg = error
sendError(win, arg);
break;
case ACTIONS.METADATA:
event.returnValue = JSON.stringify(metadata);
event.returnValue = JSON.stringify(nowPlayingMetadata);
break;
case ACTIONS.PROGRESS: // arg = progress
win.setProgressBar(arg);
break;
default:
console.log("Unknown action: " + action);
}
});
ipcMain.on("add-metadata", (event, filePath, songBuffer, currentMetadata) => {
ipcMain.on("add-metadata", async (event, filePath, songBuffer, currentMetadata) => {
let fileBuffer = songBuffer;
const songMetadata = { ...metadata, ...currentMetadata };
const songMetadata = currentMetadata.imageSrcYTPL ? // This means metadata come from ytpl.getInfo();
{
...currentMetadata,
image: cropMaxWidth(await getImage(currentMetadata.imageSrcYTPL))
} :
{ ...nowPlayingMetadata, ...currentMetadata };
try {
const coverBuffer = songMetadata.image.toPNG();
const coverBuffer = songMetadata.image ? songMetadata.image.toPNG() : null;
const writer = new ID3Writer(songBuffer);
// Create the metadata tags
writer
.setFrame("TIT2", songMetadata.title)
.setFrame("TPE1", [songMetadata.artist])
.setFrame("APIC", {
.setFrame("TPE1", [songMetadata.artist]);
if (coverBuffer) {
writer.setFrame("APIC", {
type: 3,
data: coverBuffer,
description: "",
description: ""
});
}
writer.addTag();
fileBuffer = Buffer.from(writer.arrayBuffer);
} catch (error) {

View File

@ -25,6 +25,7 @@ const observer = new MutationObserver((mutations, observer) => {
});
const reinit = () => {
triggerAction(CHANNEL, ACTIONS.PROGRESS, -1); // closes progress bar
if (!progress) {
console.warn("Cannot update progress");
} else {
@ -38,22 +39,31 @@ const baseUrl = defaultConfig.url;
// contextBridge.exposeInMainWorld("downloader", {
// download: () => {
global.download = () => {
triggerAction(CHANNEL, ACTIONS.PROGRESS, 2); // starts with indefinite progress bar
let metadata;
let videoUrl = getSongMenu()
.querySelector("ytmusic-menu-navigation-item-renderer")
.querySelector("#navigation-endpoint")
.getAttribute("href");
videoUrl = !videoUrl
? global.songInfo.url || window.location.href
: baseUrl + "/" + videoUrl;
// selector of first button which is always "Start Radio"
?.querySelector('ytmusic-menu-navigation-item-renderer.iron-selected[tabindex="0"] #navigation-endpoint')
?.getAttribute("href");
if (videoUrl) {
videoUrl = baseUrl + "/" + videoUrl;
metadata = null;
} else {
metadata = global.songInfo;
videoUrl = metadata.url || window.location.href;
}
downloadVideoToMP3(
videoUrl,
(feedback) => {
(feedback, ratio = undefined) => {
if (!progress) {
console.warn("Cannot update progress");
} else {
progress.innerHTML = feedback;
}
if (ratio) {
triggerAction(CHANNEL, ACTIONS.PROGRESS, ratio);
}
},
(error) => {
triggerAction(CHANNEL, ACTIONS.ERROR, error);
@ -61,7 +71,7 @@ global.download = () => {
},
reinit,
pluginOptions,
global.songInfo
metadata
);
};
// });

View File

@ -2,12 +2,13 @@ const { existsSync, mkdirSync } = require("fs");
const { join } = require("path");
const { URL } = require("url");
const { dialog, ipcMain } = require("electron");
const { dialog } = require("electron");
const is = require("electron-is");
const ytpl = require("ytpl");
const chokidar = require('chokidar');
const { setOptions } = require("../../config/plugins");
const getSongInfo = require("../../providers/song-info");
const registerCallback = require("../../providers/song-info");
const { sendError } = require("./back");
const { defaultMenuDownloadLabel, getFolder } = require("./utils");
@ -15,9 +16,8 @@ let downloadLabel = defaultMenuDownloadLabel;
let metadataURL = undefined;
let callbackIsRegistered = false;
module.exports = (win, options, refreshMenu) => {
module.exports = (win, options) => {
if (!callbackIsRegistered) {
const registerCallback = getSongInfo(win);
registerCallback((info) => {
metadataURL = info.url;
});
@ -35,7 +35,16 @@ module.exports = (win, options, refreshMenu) => {
return;
}
const playlist = await ytpl(playlistID);
console.log(`trying to get playlist ID: '${playlistID}'`);
let playlist;
try {
playlist = await ytpl(playlistID, {
limit: options.playlistMaxItems || Infinity,
});
} catch (e) {
sendError(win, e);
return;
}
const playlistTitle = playlist.title;
const folder = getFolder(options.downloadFolder);
@ -49,24 +58,40 @@ module.exports = (win, options, refreshMenu) => {
}
mkdirSync(playlistFolder, { recursive: true });
ipcMain.on("downloader-feedback", (_, feedback) => {
downloadLabel = feedback;
refreshMenu();
dialog.showMessageBox({
type: "info",
buttons: ["OK"],
title: "Started Download",
message: `Downloading Playlist "${playlistTitle}"`,
detail: `(${playlist.items.length} songs)`,
});
downloadLabel = `Downloading "${playlistTitle}"`;
refreshMenu();
if (is.dev()) {
console.log(
`Downloading playlist "${playlistTitle}" (${playlist.items.length} songs)`
);
}
playlist.items.slice(0, options.playlistMaxItems).forEach((song) => {
const steps = 1 / playlist.items.length;
let progress = 0;
win.setProgressBar(2); // starts with indefinite bar
let dirWatcher = chokidar.watch(playlistFolder);
dirWatcher.on('add', () => {
progress += steps;
if (progress >= 0.9999) {
win.setProgressBar(-1); // close progress bar
dirWatcher.close().then(() => dirWatcher = null);
} else {
win.setProgressBar(progress);
}
});
playlist.items.forEach((song) => {
win.webContents.send(
"downloader-download-playlist",
song,
song.url,
playlistTitle,
options
);

View File

@ -3,3 +3,29 @@ const electron = require("electron");
module.exports.getFolder = (customFolder) =>
customFolder || (electron.app || electron.remote.app).getPath("downloads");
module.exports.defaultMenuDownloadLabel = "Download playlist";
const orderedQualityList = ["maxresdefault", "hqdefault", "mqdefault", "sdddefault"];
module.exports.urlToJPG = (imgUrl, videoId) => {
if (!imgUrl || imgUrl.includes(".jpg")) return imgUrl;
//it will almost never get further than hqdefault
for (const quality of orderedQualityList) {
if (imgUrl.includes(quality)) {
return `https://img.youtube.com/vi/${videoId}/${quality}.jpg`;
}
}
return `https://img.youtube.com/vi/${videoId}/default.jpg`;
}
module.exports.cropMaxWidth = (image) => {
const imageSize = image.getSize();
// standart youtube artwork width with margins from both sides is 280 + 720 + 280
if (imageSize.width === 1280 && imageSize.height === 720) {
return image.crop({
x: 280,
y: 0,
width: 720,
height: 720
});
}
return image;
}

View File

@ -14,7 +14,8 @@ const ytdl = require("ytdl-core");
const { triggerAction, triggerActionSync } = require("../utils");
const { ACTIONS, CHANNEL } = require("./actions.js");
const { defaultMenuDownloadLabel, getFolder } = require("./utils");
const { getFolder, urlToJPG } = require("./utils");
const { cleanupArtistName } = require("../../providers/song-info");
const { createFFmpeg } = FFmpeg;
const ffmpeg = createFFmpeg({
@ -24,7 +25,7 @@ const ffmpeg = createFFmpeg({
});
const ffmpegMutex = new Mutex();
const downloadVideoToMP3 = (
const downloadVideoToMP3 = async (
videoUrl,
sendFeedback,
sendError,
@ -35,6 +36,18 @@ const downloadVideoToMP3 = (
) => {
sendFeedback("Downloading…");
if (metadata === null) {
const { videoDetails } = await ytdl.getInfo(videoUrl);
const thumbnails = videoDetails?.thumbnails;
metadata = {
artist: videoDetails?.media?.artist || cleanupArtistName(videoDetails?.author?.name) || "",
title: videoDetails?.media?.song || videoDetails?.title || "",
imageSrcYTPL: thumbnails ?
urlToJPG(thumbnails[thumbnails.length - 1].url, videoDetails?.videoId)
: ""
}
}
let videoName = "YouTube Music - Unknown title";
let videoReadableStream;
try {
@ -54,9 +67,10 @@ const downloadVideoToMP3 = (
.on("data", (chunk) => {
chunks.push(chunk);
})
.on("progress", (chunkLength, downloaded, total) => {
const progress = Math.floor((downloaded / total) * 100);
sendFeedback("Download: " + progress + "%");
.on("progress", (_chunkLength, downloaded, total) => {
const ratio = downloaded / total;
const progress = Math.floor(ratio * 100);
sendFeedback("Download: " + progress + "%", ratio);
})
.on("info", (info, format) => {
videoName = info.videoDetails.title.replace("|", "").toString("ascii");
@ -101,7 +115,7 @@ const toMP3 = async (
try {
if (!ffmpeg.isLoaded()) {
sendFeedback("Loading…");
sendFeedback("Loading…", 2); // indefinite progress bar after download
await ffmpeg.load();
}
@ -135,6 +149,7 @@ const toMP3 = async (
ipcRenderer.send("add-metadata", filePath, fileBuffer, {
artist: metadata.artist,
title: metadata.title,
imageSrcYTPL: metadata.imageSrcYTPL
});
ipcRenderer.once("add-metadata-done", reinit);
} catch (e) {
@ -165,22 +180,16 @@ module.exports = {
ipcRenderer.on(
"downloader-download-playlist",
(_, songMetadata, playlistFolder, options) => {
const reinit = () =>
ipcRenderer.send("downloader-feedback", defaultMenuDownloadLabel);
(_, url, playlistFolder, options) => {
downloadVideoToMP3(
songMetadata.url,
(feedback) => {
ipcRenderer.send("downloader-feedback", feedback);
},
url,
() => {},
(error) => {
triggerAction(CHANNEL, ACTIONS.ERROR, error);
reinit();
},
reinit,
() => {},
options,
songMetadata,
null,
playlistFolder
);
}

View File

@ -1,25 +1,14 @@
const fetch = require('node-fetch');
const md5 = require('md5');
const open = require("open");
const { shell } = require('electron');
const { setOptions } = require('../../config/plugins');
const getSongInfo = require('../../providers/song-info');
const registerCallback = require('../../providers/song-info');
const defaultConfig = require('../../config/defaults');
const cleanupArtistName = (config, artist) => {
// removes the suffixes of the artist name for more recognition by last.fm
const { suffixesToRemove } = config;
if (suffixesToRemove === undefined) return artist;
for (suffix of suffixesToRemove) {
artist = artist.replace(suffix, '');
}
return artist;
}
const createFormData = params => {
// creates the body for in the post request
const formData = new URLSearchParams();
for (key in params) {
for (const key in params) {
formData.append(key, params[key]);
}
return formData;
@ -28,7 +17,7 @@ const createQueryString = (params, api_sig) => {
// creates a querystring
const queryData = [];
params.api_sig = api_sig;
for (key in params) {
for (const key in params) {
queryData.push(`${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`);
}
return '?'+queryData.join('&');
@ -37,12 +26,12 @@ const createQueryString = (params, api_sig) => {
const createApiSig = (params, secret) => {
// this function creates the api signature, see: https://www.last.fm/api/authspec
const keys = [];
for (key in params) {
for (const key in params) {
keys.push(key);
}
keys.sort();
let sig = '';
for (key of keys) {
for (const key of keys) {
if (String(key) === 'format')
continue
sig += `${key}${params[key]}`;
@ -69,7 +58,7 @@ const authenticate = async config => {
// asks the user for authentication
config.token = await createToken(config);
setOptions('last-fm', config);
open(`https://www.last.fm/api/auth/?api_key=${config.api_key}&token=${config.token}`);
shell.openExternal(`https://www.last.fm/api/auth/?api_key=${config.api_key}&token=${config.token}`);
return config;
}
@ -139,10 +128,8 @@ const setNowPlaying = (songInfo, config) => {
// this will store the timeout that will trigger addScrobble
let scrobbleTimer = undefined;
const lastfm = async (win, config) => {
const registerCallback = getSongInfo(win);
if (!config.api_root || !config.suffixesToRemove) {
const lastfm = async (_win, config) => {
if (!config.api_root) {
// settings are not present, creating them with the default values
config = defaultConfig.plugins['last-fm'];
config.enabled = true;
@ -157,8 +144,6 @@ const lastfm = async (win, config) => {
registerCallback( songInfo => {
// set remove the old scrobble timer
clearTimeout(scrobbleTimer);
// make the artist name a bit cleaner
songInfo.artist = cleanupArtistName(config, songInfo.artist);
if (!songInfo.isPaused) {
setNowPlaying(songInfo, config);
// scrobble when the song is half way through, or has passed the 4 minute mark

View File

@ -1,9 +1,9 @@
const { Notification } = require("electron");
const is = require("electron-is");
const getSongInfo = require("../../providers/song-info");
const registerCallback = require("../../providers/song-info");
const { notificationImage } = require("./utils");
const { setupInteractive, notifyInteractive } = require("./interactive")
const setupInteractive = require("./interactive")
const notify = (info, options) => {
@ -23,38 +23,24 @@ const notify = (info, options) => {
return currentNotification;
};
module.exports = (win, options) => {
const isInteractive = is.windows() && options.interactive;
//setup interactive notifications for windows
if (isInteractive) {
setupInteractive(win, options.unpauseNotification);
}
const registerCallback = getSongInfo(win);
const setup = (options) => {
let oldNotification;
let oldURL = "";
win.once("ready-to-show", () => {
// Register the callback for new song information
registerCallback(songInfo => {
// on pause - reset url? and skip notification
if (songInfo.isPaused) {
//reset oldURL if unpause notification option is on
if (options.unpauseNotification) {
oldURL = "";
}
return;
}
// If url isn't the same as last one - send notification
if (songInfo.url !== oldURL) {
oldURL = songInfo.url;
if (isInteractive) {
notifyInteractive(songInfo);
} else {
// Close the old notification
oldNotification?.close();
// This fixes a weird bug that would cause the notification to be updated instead of showing
setTimeout(() => { oldNotification = notify(songInfo, options) }, 10);
}
}
});
let currentUrl;
registerCallback(songInfo => {
if (!songInfo.isPaused && (songInfo.url !== currentUrl || options.unpauseNotification)) {
// Close the old notification
oldNotification?.close();
currentUrl = songInfo.url;
// This fixes a weird bug that would cause the notification to be updated instead of showing
setTimeout(() => { oldNotification = notify(songInfo, options) }, 10);
}
});
}
module.exports = (win, options) => {
// Register the callback for new song information
is.windows() && options.interactive ?
setupInteractive(win, options.unpauseNotification) :
setup(options);
};

View File

@ -1,17 +1,27 @@
const { notificationImage, icons } = require("./utils");
const getSongControls = require('../../providers/song-controls');
const registerCallback = require("../../providers/song-info");
const notifier = require("node-notifier");
//store song controls reference on launch
let controls;
let notificationOnPause;
let notificationOnUnpause;
//Save controls and onPause option
module.exports.setupInteractive = (win, unpauseNotification) => {
module.exports = (win, unpauseNotification) => {
//Save controls and onPause option
const { playPause, next, previous } = getSongControls(win);
controls = { playPause, next, previous };
notificationOnUnpause = unpauseNotification;
notificationOnPause = unpauseNotification;
let currentUrl;
// Register songInfoCallback
registerCallback(songInfo => {
if (!songInfo.isPaused && (songInfo.url !== currentUrl || notificationOnUnpause)) {
currentUrl = songInfo.url;
sendToaster(songInfo);
}
});
win.webContents.once("closed", () => {
deleteNotification()
@ -33,7 +43,7 @@ function deleteNotification() {
}
//New notification
module.exports.notifyInteractive = function sendToaster(songInfo) {
function sendToaster(songInfo) {
deleteNotification();
//download image and get path
let imgSrc = notificationImage(songInfo, true);
@ -71,7 +81,7 @@ module.exports.notifyInteractive = function sendToaster(songInfo) {
// dont delete notification on play/pause
toDelete = undefined;
//manually send notification if not sending automatically
if (!notificationOnPause) {
if (!notificationOnUnpause) {
songInfo.isPaused = false;
sendToaster(songInfo);
}

View File

@ -194,12 +194,13 @@ function setupLocalArrowShortcuts(options) {
}
function callback(event) {
event.preventDefault();
switch (event.code) {
case "ArrowUp":
event.preventDefault();
changeVolume(true, options);
break;
case "ArrowDown":
event.preventDefault();
changeVolume(false, options);
break;
}

View File

@ -1,28 +1,33 @@
const { ipcRenderer } = require("electron");
const is = require("electron-is");
let ignored = {
id: ["volume-slider", "expand-volume-slider"],
types: ["mousewheel", "keydown", "keyup"]
};
// Override specific listeners of volume-slider by modifying Element.prototype
function overrideAddEventListener() {
// Events to ignore
const nativeEvents = ["mousewheel", "keydown", "keyup"];
// Save native addEventListener
Element.prototype._addEventListener = Element.prototype.addEventListener;
// Override addEventListener to Ignore specific events in volume-slider
Element.prototype.addEventListener = function (type, listener, useCapture = false) {
if (this.tagName === "TP-YT-PAPER-SLIDER") { // tagName of #volume-slider
for (const eventType of nativeEvents) {
if (eventType === type) {
return;
}
}
}//else
this._addEventListener(type, listener, useCapture);
if (!(
ignored.id.includes(this.id) &&
ignored.types.includes(type)
)) {
this._addEventListener(type, listener, useCapture);
} else if (is.dev()) {
console.log(`Ignoring event: "${this.id}.${type}()"`);
}
};
}
module.exports = () => {
overrideAddEventListener();
// Restore original function after did-finish-load to avoid keeping Element.prototype altered
ipcRenderer.once("restoreAddEventListener", () => { //called from Main to make sure page is completly loaded
ipcRenderer.once("restoreAddEventListener", () => { // Called from main to make sure page is completly loaded
Element.prototype.addEventListener = Element.prototype._addEventListener;
Element.prototype._addEventListener = undefined;
ignored = undefined;
});
};

View File

@ -1,12 +1,11 @@
const getSongControls = require('../../providers/song-controls');
const getSongInfo = require('../../providers/song-info');
const registerCallback = require('../../providers/song-info');
const path = require('path');
let controls;
let currentSongInfo;
module.exports = win => {
const registerCallback = getSongInfo(win);
const { playPause, next, previous } = getSongControls(win);
controls = { playPause, next, previous };

View File

@ -7,7 +7,7 @@ const {
TouchBarScrubber,
} = TouchBar;
const getSongInfo = require("../../providers/song-info");
const registerCallback = require("../../providers/song-info");
const getSongControls = require("../../providers/song-controls");
// Songtitle label
@ -59,7 +59,6 @@ const touchBar = new TouchBar({
});
module.exports = (win) => {
const registerCallback = getSongInfo(win);
const { playPause, next, previous, like, dislike } = getSongControls(win);
// If the page is ready, register the callback

View File

@ -43,7 +43,7 @@ module.exports.fileExists = (path, callbackIfExists) => {
};
module.exports.injectCSS = (webContents, filepath, cb = undefined) => {
webContents.once("did-finish-load", async () => {
webContents.on("did-finish-load", async () => {
await webContents.insertCSS(fs.readFileSync(filepath, "utf8"));
if (cb) {
cb();

View File

@ -5,6 +5,8 @@ const { remote } = require("electron");
const config = require("./config");
const { fileExists } = require("./plugins/utils");
const setupFrontLogger = require("./providers/front-logger");
const setupSongControl = require("./providers/song-controls-front");
const setupSongInfo = require("./providers/song-info-front");
const plugins = config.plugins.getEnabled();
@ -37,8 +39,10 @@ document.addEventListener("DOMContentLoaded", () => {
});
// inject song-info provider
const songInfoProviderPath = path.join(__dirname, "providers", "song-info-front.js")
fileExists(songInfoProviderPath, require(songInfoProviderPath));
setupSongInfo();
// inject song-control provider
setupSongControl();
// inject front logger
setupFrontLogger();

View File

@ -0,0 +1,18 @@
const { ipcRenderer } = require("electron");
let videoStream = document.querySelector(".video-stream");
module.exports = () => {
ipcRenderer.on("playPause", () => {
if (!videoStream) {
videoStream = document.querySelector(".video-stream");
}
if (videoStream.paused) {
videoStream.play();
} else {
videoStream.yns_pause ?
videoStream.yns_pause() :
videoStream.pause();
}
});
};

View File

@ -12,7 +12,7 @@ module.exports = (win) => {
// Playback
previous: () => pressKey(win, "k"),
next: () => pressKey(win, "j"),
playPause: () => pressKey(win, "space"),
playPause: () => win.webContents.send("playPause"),
like: () => pressKey(win, "_"),
dislike: () => pressKey(win, "+"),
go10sBack: () => pressKey(win, "h"),

View File

@ -10,17 +10,16 @@ ipcRenderer.on("update-song-info", async (_, extractedSongInfo) => {
});
const injectListener = () => {
var oldXHR = window.XMLHttpRequest;
const oldXHR = window.XMLHttpRequest;
function newXHR() {
var realXHR = new oldXHR();
const realXHR = new oldXHR();
realXHR.addEventListener(
"readystatechange",
() => {
if (realXHR.readyState == 4 && realXHR.status == 200) {
if (realXHR.responseURL.includes("/player")) {
if (realXHR.readyState === 4 && realXHR.status === 200
&& realXHR.responseURL.includes("/player")) {
// if the request contains the song info, send the response to ipcMain
ipcRenderer.send("song-info-request", realXHR.responseText);
}
}
},
false

View File

@ -30,15 +30,10 @@ const getPausedStatus = async (win) => {
};
const getArtist = async (win) => {
return await win.webContents.executeJavaScript(
`
var bar = document.getElementsByClassName('subtitle ytmusic-player-bar')[0];
var artistName = (bar.getElementsByClassName('yt-formatted-string')[0]) || (bar.getElementsByClassName('byline ytmusic-player-bar')[0]);
if (artistName) {
artistName.textContent;
}
`
)
return await win.webContents.executeJavaScript(`
document.querySelector(".subtitle.ytmusic-player-bar .yt-formatted-string")
?.textContent
`);
}
// Fill songInfo with empty values
@ -58,7 +53,7 @@ const songInfo = {
const handleData = async (responseText, win) => {
let data = JSON.parse(responseText);
songInfo.title = data?.videoDetails?.title;
songInfo.artist = await getArtist(win) || data?.videoDetails?.author;
songInfo.artist = await getArtist(win) || cleanupArtistName(data?.videoDetails?.author);
songInfo.views = data?.videoDetails?.viewCount;
songInfo.imageSrc = data?.videoDetails?.thumbnail?.thumbnails?.pop()?.url;
songInfo.songDuration = data?.videoDetails?.lengthSeconds;
@ -69,15 +64,15 @@ const handleData = async (responseText, win) => {
win.webContents.send("update-song-info", JSON.stringify(songInfo));
};
// This variable will be filled with the callbacks once they register
const callbacks = [];
// This function will allow plugins to register callback that will be triggered when data changes
const registerCallback = (callback) => {
callbacks.push(callback);
};
const registerProvider = (win) => {
// This variable will be filled with the callbacks once they register
const callbacks = [];
// This function will allow plugins to register callback that will be triggered when data changes
const registerCallback = (callback) => {
callbacks.push(callback);
};
win.on("page-title-updated", async () => {
// Get and set the new data
songInfo.isPaused = await getPausedStatus(win);
@ -98,9 +93,23 @@ const registerProvider = (win) => {
c(songInfo);
});
});
return registerCallback;
};
module.exports = registerProvider;
const suffixesToRemove = [' - Topic', 'VEVO'];
function cleanupArtistName(artist) {
if (!artist) {
return artist;
}
for (const suffix of suffixesToRemove) {
if (artist.endsWith(suffix)) {
return artist.slice(0, -suffix.length);
}
}
return artist;
}
module.exports = registerCallback;
module.exports.setupSongInfo = registerProvider;
module.exports.getImage = getImage;
module.exports.cleanupArtistName = cleanupArtistName;

340
yarn.lock
View File

@ -439,45 +439,45 @@
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
"@cliqz/adblocker-content@^1.20.4":
version "1.20.4"
resolved "https://registry.yarnpkg.com/@cliqz/adblocker-content/-/adblocker-content-1.20.4.tgz#68c0c628acd6da49bb5a6ad9ee0cb540a8d50acd"
integrity sha512-Cp6M6MERCsLwklX6lAmrgOxom0pr4DjxmUGLcmM9MDACOIzk/m7ya1e82bXzEWAU1Jni2Bp91xUUWxg+DLWJgQ==
"@cliqz/adblocker-content@^1.20.6":
version "1.20.6"
resolved "https://registry.yarnpkg.com/@cliqz/adblocker-content/-/adblocker-content-1.20.6.tgz#1bfbdb1e5757fc610f3d5d9921bba9d166d687a7"
integrity sha512-KRo8EjIbiuAHBQHJcgs0oefJlp/lw93KQL1Rv9CeMFdKqVZV8IReGqe/V+ipoaOQFVgLZ8gWPOzEkLAQ4P2ZBQ==
dependencies:
"@cliqz/adblocker-extended-selectors" "^1.20.4"
"@cliqz/adblocker-extended-selectors" "^1.20.6"
"@cliqz/adblocker-electron-preload@^1.20.4":
version "1.20.4"
resolved "https://registry.yarnpkg.com/@cliqz/adblocker-electron-preload/-/adblocker-electron-preload-1.20.4.tgz#b7d6606dfc24e7b3f80109cc6820bd203faaf26e"
integrity sha512-tIEgFJJhEDTYrSUzAL+wbw+BBVwCtuFtckA/scka990DGlXsEmkJ7HxNXvUPwhOQiV4YUwN5bsqxCDA8VDTZNw==
"@cliqz/adblocker-electron-preload@^1.20.6":
version "1.20.6"
resolved "https://registry.yarnpkg.com/@cliqz/adblocker-electron-preload/-/adblocker-electron-preload-1.20.6.tgz#c2804edb8c4dd5ce226a2a5ef95b9e6cd3745767"
integrity sha512-2dF6aaTZftwUXswHRSIlSIop4SQGmtpzp3FHVQvB3lCCE2ssONT38nCY0b4PREooZ35tzZTZNyYcOboaear3UQ==
dependencies:
"@cliqz/adblocker-content" "^1.20.4"
"@cliqz/adblocker-content" "^1.20.6"
"@cliqz/adblocker-electron@^1.20.4":
version "1.20.4"
resolved "https://registry.yarnpkg.com/@cliqz/adblocker-electron/-/adblocker-electron-1.20.4.tgz#6d7de52cff013ef3cd0f4a7850ebfc31f6240a46"
integrity sha512-HaHexPnJL1BBvloXuqmSh8WtpPKYHyZ+o6f+9SciySN4dJAX9BIGTk9D/V6eJWLmy6+wY7/Bpcn2Q4nrYXsqBw==
"@cliqz/adblocker-electron@^1.20.5":
version "1.20.6"
resolved "https://registry.yarnpkg.com/@cliqz/adblocker-electron/-/adblocker-electron-1.20.6.tgz#870ff1ba7765f545fee70327d3c7e08adadc7764"
integrity sha512-//fdnVxuab6nfx/Eq9u6r8EbgHl/wOGGIUu/ueaYEstR+m3Re22zJDtbj8AwmN75aDynQ7jhUz81GLqH4o4pzg==
dependencies:
"@cliqz/adblocker" "^1.20.4"
"@cliqz/adblocker-electron-preload" "^1.20.4"
"@cliqz/adblocker" "^1.20.6"
"@cliqz/adblocker-electron-preload" "^1.20.6"
tldts-experimental "^5.6.21"
"@cliqz/adblocker-extended-selectors@^1.20.4":
version "1.20.4"
resolved "https://registry.yarnpkg.com/@cliqz/adblocker-extended-selectors/-/adblocker-extended-selectors-1.20.4.tgz#6f5ab8251a0d40cacf3703f5621025e0d85d6348"
integrity sha512-VBP8iv1IdYpwQ0hbbeiXCSW7ppzK05dbPM4DyeCb54mB0CjWj/pMQwEvjMZKLWTkEyPd26oMqnxNQz1UgGaZag==
"@cliqz/adblocker-extended-selectors@^1.20.6":
version "1.20.6"
resolved "https://registry.yarnpkg.com/@cliqz/adblocker-extended-selectors/-/adblocker-extended-selectors-1.20.6.tgz#964d3b96e419778c6e4c8ecf5c2b94599dfbdcd7"
integrity sha512-EuGLyv00GeRFr2PKZLaWgnRpKSFLdezqXTJFaljtvb0iieR7yNdjfEdoEJmctRmslTrlcMmpOlNhAOpJavY4bw==
"@cliqz/adblocker@^1.20.4":
version "1.20.4"
resolved "https://registry.yarnpkg.com/@cliqz/adblocker/-/adblocker-1.20.4.tgz#63f75456b6d63f66dc73b9ac2971ed073bf26722"
integrity sha512-ylwc4fScwgDjh9mKAvBQ+oCNyZWncrPakU17KbMtq+l82LkzJ0ND0wififpeq+nI9JBiQosW+eus5R08THpwCQ==
"@cliqz/adblocker@^1.20.6":
version "1.20.6"
resolved "https://registry.yarnpkg.com/@cliqz/adblocker/-/adblocker-1.20.6.tgz#3428d3c066dbaafa98644fadfd28dd206f8691e2"
integrity sha512-BhYna9gkQnqQfFJy4FOW3cER2oO0IwZzvYQaQEMP5Y/ETUzMq5WBHq5X4dOU+hiJdbkgogIS5L73uPUHDK01Hw==
dependencies:
"@cliqz/adblocker-content" "^1.20.4"
"@cliqz/adblocker-extended-selectors" "^1.20.4"
"@cliqz/adblocker-content" "^1.20.6"
"@cliqz/adblocker-extended-selectors" "^1.20.6"
"@remusao/guess-url-type" "^1.1.2"
"@remusao/small" "^1.1.2"
"@remusao/smaz" "^1.7.1"
"@types/chrome" "^0.0.133"
"@types/chrome" "^0.0.136"
"@types/firefox-webext-browser" "^82.0.0"
tldts-experimental "^5.6.21"
@ -497,7 +497,7 @@
ajv "^6.12.0"
ajv-keywords "^3.4.1"
"@electron/get@^1.0.1", "@electron/get@^1.12.2":
"@electron/get@^1.0.1", "@electron/get@^1.12.4":
version "1.12.4"
resolved "https://registry.yarnpkg.com/@electron/get/-/get-1.12.4.tgz#a5971113fc1bf8fa12a8789dc20152a7359f06ab"
integrity sha512-6nr9DbJPUR9Xujw6zD3y+rS95TyItEVM0NVjt1EehY2vUWfIgPiIPVHxCvaTS0xr2B+DRxovYVKbuOWqC35kjg==
@ -513,6 +513,11 @@
global-agent "^2.0.2"
global-tunnel-ng "^2.7.1"
"@electron/remote@^1.0.4":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@electron/remote/-/remote-1.1.0.tgz#167d119c7c03c7778b556fdc4f1f38a44b23f1c2"
integrity sha512-yr8gZTkIgJYKbFqExI4QZqMSjn1kL/us9Dl46+TH1EZdhgRtsJ6HDfdsIxu0QEc6Hv+DMAXs69rgquH+8FDk4w==
"@electron/universal@1.0.4":
version "1.0.4"
resolved "https://registry.yarnpkg.com/@electron/universal/-/universal-1.0.4.tgz#231ac246c39d45b80e159bd21c3f9027dcaa10f5"
@ -539,10 +544,10 @@
minimatch "^3.0.4"
strip-json-comments "^3.1.1"
"@ffmpeg/core@^0.8.5":
version "0.8.5"
resolved "https://registry.yarnpkg.com/@ffmpeg/core/-/core-0.8.5.tgz#2d0b7d4409a4348fa6a1888c247de706ffc0e63f"
integrity sha512-hemVFmhVLbD/VZaCG2BvCzFglKytMIMJ5aJfc12eXN4O4cG0wXnGTMVzlK1KKW/6viHhJMPkc9h4UDnJW8Uivg==
"@ffmpeg/core@^0.9.0":
version "0.9.0"
resolved "https://registry.yarnpkg.com/@ffmpeg/core/-/core-0.9.0.tgz#4a999a07671c081216fcc2714f73ec02ddc9c24b"
integrity sha512-d931yzQpb8GRgTZr+T7+BMqglPZ1R8FPH3W3UA8I21RzuasRHsMwQ4MQTlS9twjfqvUGIkD8p/8mNToUVN/Yrw==
"@ffmpeg/ffmpeg@^0.9.7":
version "0.9.7"
@ -1188,10 +1193,10 @@
"@types/node" "*"
"@types/responselike" "*"
"@types/chrome@^0.0.133":
version "0.0.133"
resolved "https://registry.yarnpkg.com/@types/chrome/-/chrome-0.0.133.tgz#9e1d55441584ba2d5274ca84db36427da9c5dc6e"
integrity sha512-G8uIUdaCTBILprQvQXBWGXZxjAWbkCkFQit17cdH3zYQEwU8f/etNl8+M7e8MRz9Xj8daHaVpysneMZMx8/ldQ==
"@types/chrome@^0.0.136":
version "0.0.136"
resolved "https://registry.yarnpkg.com/@types/chrome/-/chrome-0.0.136.tgz#7c011b9f997b0156f25a140188a0c5689d3f368f"
integrity sha512-XDEiRhLkMd+SB7Iw3ZUIj/fov3wLd4HyTdLltVszkgl1dBfc3Rb7oPMVZ2Mz2TLqnF7Ow+StbR8E7r9lqpb4DA==
dependencies:
"@types/filesystem" "*"
"@types/har-format" "*"
@ -1301,10 +1306,10 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.25.tgz#15967a7b577ff81383f9b888aa6705d43fbbae93"
integrity sha512-EPpXLOVqDvisVxtlbvzfyqSsFeQxltFbluZNRndIb8tr9KiBnYNLzrc1N3pyKUCww2RNrfHDViqDWWE1LCJQtQ==
"@types/node@^12.0.12":
version "12.19.16"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.16.tgz#15753af35cbef636182d8d8ca55b37c8583cecb3"
integrity sha512-7xHmXm/QJ7cbK2laF+YYD7gb5MggHIIQwqyjin3bpEGiSuvScMQ5JZZXPvRipi1MwckTQbJZROMns/JxdnIL1Q==
"@types/node@^14.6.2":
version "14.14.44"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.44.tgz#df7503e6002847b834371c004b372529f3f85215"
integrity sha512-+gaugz6Oce6ZInfI/tK4Pq5wIIkJMEJUu92RB3Eu93mtj4wjjjz9EB5mLp5s1pSsLXdC/CPut/xF20ZzAQJbTA==
"@types/normalize-package-data@^2.4.0":
version "2.4.0"
@ -1638,6 +1643,14 @@ anymatch@^3.0.3:
normalize-path "^3.0.0"
picomatch "^2.0.4"
anymatch@~3.1.1:
version "3.1.2"
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716"
integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==
dependencies:
normalize-path "^3.0.0"
picomatch "^2.0.4"
app-builder-bin@3.5.12:
version "3.5.12"
resolved "https://registry.yarnpkg.com/app-builder-bin/-/app-builder-bin-3.5.12.tgz#bbe174972cc1f481f73d6d92ad47a8b4c7eb4530"
@ -1991,6 +2004,11 @@ bcrypt-pbkdf@^1.0.0:
dependencies:
tweetnacl "^0.14.3"
binary-extensions@^2.0.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
binaryextensions@^4.15.0:
version "4.15.0"
resolved "https://registry.yarnpkg.com/binaryextensions/-/binaryextensions-4.15.0.tgz#c63a502e0078ff1b0e9b00a9f74d3c2b0f8bd32e"
@ -2033,9 +2051,9 @@ bn.js@^5.0.0, bn.js@^5.1.1:
integrity sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==
boolean@^3.0.1:
version "3.0.2"
resolved "https://registry.yarnpkg.com/boolean/-/boolean-3.0.2.tgz#df1baa18b6a2b0e70840475e1d93ec8fe75b2570"
integrity sha512-RwywHlpCRc3/Wh81MiCKun4ydaIFyW5Ea6JbL6sRCVx5q5irDw7pMXBUFYF/jArQ6YrG36q0kpovc9P/Kd3I4g==
version "3.0.3"
resolved "https://registry.yarnpkg.com/boolean/-/boolean-3.0.3.tgz#0fee0c9813b66bef25a8a6a904bb46736d05f024"
integrity sha512-EqrTKXQX6Z3A2nRmMEIlAIfjQOgFnVO2nqZGpbcsPnYGWBwpFqzlrozU1dy+S2iqfYDLh26ef4KrgTxu9xQrxA==
boxen@^5.0.0:
version "5.0.0"
@ -2075,7 +2093,7 @@ braces@^2.3.1:
split-string "^3.0.2"
to-regex "^3.0.1"
braces@^3.0.1:
braces@^3.0.1, braces@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
@ -2159,15 +2177,15 @@ browserify-zlib@^0.2.0:
pako "~1.0.5"
browserslist@^4.14.5:
version "4.16.3"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.3.tgz#340aa46940d7db878748567c5dea24a48ddf3717"
integrity sha512-vIyhWmIkULaq04Gt93txdh+j02yX/JzlyhLYbV3YQCn/zvES3JnY7TifHHvvr1w5hTDluNKMkV05cs4vy8Q7sw==
version "4.16.6"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.6.tgz#d7901277a5a88e554ed305b183ec9b0c08f66fa2"
integrity sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==
dependencies:
caniuse-lite "^1.0.30001181"
colorette "^1.2.1"
electron-to-chromium "^1.3.649"
caniuse-lite "^1.0.30001219"
colorette "^1.2.2"
electron-to-chromium "^1.3.723"
escalade "^3.1.1"
node-releases "^1.1.70"
node-releases "^1.1.71"
bser@2.1.1:
version "2.1.1"
@ -2349,10 +2367,10 @@ camelcase@^6.0.0, camelcase@^6.2.0:
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809"
integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==
caniuse-lite@^1.0.30001181:
version "1.0.30001208"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001208.tgz#a999014a35cebd4f98c405930a057a0d75352eb9"
integrity sha512-OE5UE4+nBOro8Dyvv0lfx+SRtfVIOM9uhKqFmJeUbGriqhhStgp1A0OyBpgy3OUF8AhYCT+PVwPC1gMl2ZcQMA==
caniuse-lite@^1.0.30001219:
version "1.0.30001230"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001230.tgz#8135c57459854b2240b57a4a6786044bdc5a9f71"
integrity sha512-5yBd5nWCBS+jWKTcHOzXwo5xzcj4ePE/yjtkZyUV1BTUmrBaA9MRGC+e7mxnqXSA90CmCA8L3eKLaSUkt099IQ==
capture-exit@^2.0.0:
version "2.0.0"
@ -2404,6 +2422,21 @@ charenc@0.0.2:
resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=
chokidar@^3.5.1:
version "3.5.1"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a"
integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==
dependencies:
anymatch "~3.1.1"
braces "~3.0.2"
glob-parent "~5.1.0"
is-binary-path "~2.1.0"
is-glob "~4.0.1"
normalize-path "~3.0.0"
readdirp "~3.5.0"
optionalDependencies:
fsevents "~2.3.1"
chownr@^1.1.1:
version "1.1.4"
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
@ -2560,7 +2593,7 @@ color-name@~1.1.4:
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
colorette@^1.2.1:
colorette@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94"
integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==
@ -2701,9 +2734,9 @@ core-assert@^0.2.0:
is-error "^2.2.0"
core-js@^3.6.5:
version "3.8.3"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.8.3.tgz#c21906e1f14f3689f93abcc6e26883550dd92dd0"
integrity sha512-KPYXeVZYemC2TkNEkX/01I+7yd+nX3KddKwZ1Ww7SKWdI2wQprSgLmrTddT8nw92AjEklTsPBoSdQBhbI1bQ6Q==
version "3.12.0"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.12.0.tgz#62bac86f7d7f087d40dba3e90a211c2c3c8559ea"
integrity sha512-SaMnchL//WwU2Ot1hhkPflE8gzo7uq1FGvUJ8GKmi3TOU7rGTHIU+eir1WGf6qOtTyxdfdcp10yPdGZ59sQ3hw==
core-util-is@1.0.2, core-util-is@~1.0.0:
version "1.0.2"
@ -2967,11 +3000,6 @@ defer-to-connect@^2.0.0:
resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.0.tgz#83d6b199db041593ac84d781b5222308ccf4c2c1"
integrity sha512-bYL2d05vOSf1JEZNx5vSAtPuBMkX8K9EUutg7zlKvTqKXHt7RhWJFbmd7qakVuf13i+IkGmp6FwSsONOf6VYIg==
define-lazy-prop@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f"
integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==
define-properties@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
@ -3032,9 +3060,9 @@ detect-newline@^3.0.0:
integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==
detect-node@^2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c"
integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==
version "2.0.5"
resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.5.tgz#9d270aa7eaa5af0b72c4c9d9b814e7f4ce738b79"
integrity sha512-qi86tE6hRcFHy8jI1m2VG+LaPUR1LhqDa5G8tVjuUXmOrpuAgqsA1pN0+ldgr3aKUH+QLI9hCY/OcRYisERejw==
dev-null@^0.1.1:
version "0.1.1"
@ -3248,12 +3276,12 @@ electron-builder@^22.10.5:
update-notifier "^5.1.0"
yargs "^16.2.0"
electron-chromedriver@^11.0.0:
version "11.0.0"
resolved "https://registry.yarnpkg.com/electron-chromedriver/-/electron-chromedriver-11.0.0.tgz#49b034ed0ad12c12e3522862c7bb46875a0d85e1"
integrity sha512-ayMJPBbB4puU0SqYbcD9XvF3/7GWIhqKE1n5lG2/GQPRnrZkNoPIilsrS0rQcD50Xhl69KowatDqLhUznZWtbA==
electron-chromedriver@^12.0.0:
version "12.0.0"
resolved "https://registry.yarnpkg.com/electron-chromedriver/-/electron-chromedriver-12.0.0.tgz#55bdc451b938b384642d613a05eadacb1fe476ee"
integrity sha512-zOs98o9+20Er8Q44z06h90VldwrJaoRCieW3Q8WkdDjA3cMRU5mlmm1kGDhPLMeYNuhq6e39aGMVH/IBFD97HQ==
dependencies:
"@electron/get" "^1.12.2"
"@electron/get" "^1.12.4"
extract-zip "^2.0.0"
electron-debug@^3.2.0:
@ -3337,10 +3365,10 @@ electron-store@^7.0.3:
conf "^9.0.0"
type-fest "^0.20.2"
electron-to-chromium@^1.3.649:
version "1.3.711"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.711.tgz#92c3caf7ffed5e18bf63f66b4b57b4db2409c450"
integrity sha512-XbklBVCDiUeho0PZQCjC25Ha6uBwqqJeyDhPLwLwfWRAo4x+FZFsmu1pPPkXT+B4MQMQoQULfyaMltDopfeiHQ==
electron-to-chromium@^1.3.723:
version "1.3.740"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.740.tgz#e38b7d2b848f632191b643e6dabca51be2162922"
integrity sha512-Mi2m55JrX2BFbNZGKYR+2ItcGnR4O5HhrvgoRRyZQlaMGQULqDhoGkLWHzJoshSzi7k1PUofxcDbNhlFrDZNhg==
electron-unhandled@^3.0.2:
version "3.0.2"
@ -3365,13 +3393,13 @@ electron-updater@^4.3.8:
lodash.isequal "^4.5.0"
semver "^7.3.4"
electron@^11.4.4:
version "11.4.4"
resolved "https://registry.yarnpkg.com/electron/-/electron-11.4.4.tgz#d6c046dedd9e22df5f6408841c3f8ae1a1d59414"
integrity sha512-m52nF85VADCmL9DpzJfgmkvc9fNiGZPYwptv/4fTYrYhAMiO+hmClGMXncCoSAzoULQjl+f+0b9CY4yd6nRFlQ==
electron@^12.0.8:
version "12.0.8"
resolved "https://registry.yarnpkg.com/electron/-/electron-12.0.8.tgz#e52583b2b4f1eaa6fbb0e3666b9907f99f1f24c7"
integrity sha512-bN2wYNnnma7ugBsiwysO1LI6oTTV1lDHOXuWip+OGjDUiz0IiJmZ+r0gAIMMeypVohZh7AA1ftnKad7tJ8sH4A==
dependencies:
"@electron/get" "^1.0.1"
"@types/node" "^12.0.12"
"@types/node" "^14.6.2"
extract-zip "^1.0.3"
elliptic@^6.5.3:
@ -3448,9 +3476,9 @@ env-editor@^0.4.1:
integrity sha512-ObFo8v4rQJAE59M69QzwloxPZtd33TpYEIjtKD1rrFDcM1Gd7IkDxEBU+HriziN6HSHQnBJi8Dmy+JWkav5HKA==
env-paths@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.0.tgz#cdca557dc009152917d6166e2febe1f039685e43"
integrity sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA==
version "2.2.1"
resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2"
integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==
errlop@^4.0.0:
version "4.1.0"
@ -4102,10 +4130,10 @@ filename-reserved-regex@^2.0.0:
resolved "https://registry.yarnpkg.com/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz#abf73dfab735d045440abfea2d91f389ebbfa229"
integrity sha1-q/c9+rc10EVECr/qLZHzieu/oik=
filenamify@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/filenamify/-/filenamify-4.2.0.tgz#c99716d676869585b3b5d328b3f06590d032e89f"
integrity sha512-pkgE+4p7N1n7QieOopmn3TqJaefjdWXwEkj2XLZJLKfOgcQKkn11ahvGNgTD8mLggexLiDFQxeTs14xVU22XPA==
filenamify@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/filenamify/-/filenamify-4.3.0.tgz#62391cb58f02b09971c9d4f9d63b3cf9aba03106"
integrity sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==
dependencies:
filename-reserved-regex "^2.0.0"
strip-outer "^1.0.1"
@ -4257,7 +4285,7 @@ fs.realpath@^1.0.0:
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
fsevents@^2.1.2:
fsevents@^2.1.2, fsevents@~2.3.1:
version "2.3.2"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
@ -4370,6 +4398,13 @@ glob-parent@^5.0.0, glob-parent@^5.1.0:
dependencies:
is-glob "^4.0.1"
glob-parent@~5.1.0:
version "5.1.2"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
dependencies:
is-glob "^4.0.1"
glob-to-regexp@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab"
@ -4388,9 +4423,9 @@ glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
path-is-absolute "^1.0.0"
global-agent@^2.0.2:
version "2.1.12"
resolved "https://registry.yarnpkg.com/global-agent/-/global-agent-2.1.12.tgz#e4ae3812b731a9e81cbf825f9377ef450a8e4195"
integrity sha512-caAljRMS/qcDo69X9BfkgrihGUgGx44Fb4QQToNQjsiWh+YlQ66uqYVAdA8Olqit+5Ng0nkz09je3ZzANMZcjg==
version "2.2.0"
resolved "https://registry.yarnpkg.com/global-agent/-/global-agent-2.2.0.tgz#566331b0646e6bf79429a16877685c4a1fbf76dc"
integrity sha512-+20KpaW6DDLqhG7JDiJpD1JvNvb8ts+TNl7BPOYcURqCrXqnN1Vf+XVOrkKJAFPqfX+oEhsdzOj1hLWkBTdNJg==
dependencies:
boolean "^3.0.1"
core-js "^3.6.5"
@ -4445,9 +4480,9 @@ globals@^13.6.0:
type-fest "^0.20.2"
globalthis@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.1.tgz#40116f5d9c071f9e8fb0037654df1ab3a83b7ef9"
integrity sha512-mJPRTc/P39NH/iNG4mXa9aIhNymaQikTrnspeCa2ZuJ+mH2QN/rXwtX3XwKrHqWgUQFbNZKtHM105aHzJalElw==
version "1.0.2"
resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.2.tgz#2a235d34f4d8036219f7e34929b5de9e18166b8b"
integrity sha512-ZQnSFO1la8P7auIOQECnm0sSuoMeaSq0EEdXMBFF2QJO4uNcwbyhSgG3MruWNbFTqCLmxVwGOl7LZ9kASvHdeQ==
dependencies:
define-properties "^1.1.3"
@ -4505,6 +4540,23 @@ got@^11.0.2:
p-cancelable "^2.0.0"
responselike "^2.0.0"
got@^11.8.0:
version "11.8.2"
resolved "https://registry.yarnpkg.com/got/-/got-11.8.2.tgz#7abb3959ea28c31f3576f1576c1effce23f33599"
integrity sha512-D0QywKgIe30ODs+fm8wMZiAcZjypcCodPNuMz5H9Mny7RJ+IjJ10BdmGW7OM7fHXP+O7r6ZwapQ/YQmMSvB0UQ==
dependencies:
"@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.1"
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"
got@^9.6.0:
version "9.6.0"
resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85"
@ -4522,11 +4574,16 @@ got@^9.6.0:
to-readable-stream "^1.0.0"
url-parse-lax "^3.0.0"
graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.4:
graceful-fs@^4.1.2, graceful-fs@^4.1.9, graceful-fs@^4.2.4:
version "4.2.5"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.5.tgz#bc18864a6c9fc7b303f2e2abdb9155ad178fbe29"
integrity sha512-kBBSQbz2K0Nyn+31j/w36fUfxkBW9/gfwRWdUY1ULReH3iokVJgddZAFcD1D0xlgTmFxJCbUkUclAlc6/IDJkw==
graceful-fs@^4.1.6, graceful-fs@^4.2.0:
version "4.2.6"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee"
integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==
"graceful-readlink@>= 1.0.0":
version "1.0.1"
resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725"
@ -4902,6 +4959,13 @@ is-arrayish@^0.2.1:
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=
is-binary-path@~2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
dependencies:
binary-extensions "^2.0.0"
is-buffer@^1.1.5, is-buffer@~1.1.6:
version "1.1.6"
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
@ -4963,7 +5027,7 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2:
is-data-descriptor "^1.0.0"
kind-of "^6.0.2"
is-docker@^2.0.0, is-docker@^2.1.1:
is-docker@^2.0.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.1.1.tgz#4125a88e44e450d384e09047ede71adc2d144156"
integrity sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw==
@ -5032,7 +5096,7 @@ is-glob@^3.1.0:
dependencies:
is-extglob "^2.1.0"
is-glob@^4.0.0, is-glob@^4.0.1:
is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc"
integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==
@ -6128,12 +6192,12 @@ lodash.zip@^4.2.0:
resolved "https://registry.yarnpkg.com/lodash.zip/-/lodash.zip-4.2.0.tgz#ec6662e4896408ed4ab6c542a3990b72cc080020"
integrity sha1-7GZi5IlkCO1KtsVCo5kLcswIACA=
lodash@^4.13.1, lodash@^4.17.10, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20:
lodash@^4.13.1, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20:
version "4.17.20"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==
lodash@^4.17.21:
lodash@^4.17.10, lodash@^4.17.21:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
@ -6549,10 +6613,10 @@ node-notifier@^9.0.1:
uuid "^8.3.0"
which "^2.0.2"
node-releases@^1.1.70:
version "1.1.71"
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.71.tgz#cb1334b179896b1c89ecfdd4b725fb7bbdfc7dbb"
integrity sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg==
node-releases@^1.1.71:
version "1.1.72"
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.72.tgz#14802ab6b1039a79a0c7d662b610a5bbd76eacbe"
integrity sha512-LLUo+PpH3dU6XizX3iVoubUNheF/owjXCZZ5yACDxNnPtgFuludV1ZL3ayK1kVep42Rmm0+R9/Y60NQbZ2bifw==
normalize-package-data@^2.3.2, normalize-package-data@^2.5.0:
version "2.5.0"
@ -6581,7 +6645,7 @@ normalize-path@^2.1.1:
dependencies:
remove-trailing-separator "^1.0.1"
normalize-path@^3.0.0:
normalize-path@^3.0.0, normalize-path@~3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
@ -6728,15 +6792,6 @@ open@^7.3.0:
is-docker "^2.0.0"
is-wsl "^2.1.1"
open@^8.0.3:
version "8.0.5"
resolved "https://registry.yarnpkg.com/open/-/open-8.0.5.tgz#92ee3faafef4ddbe78006f7881572f3e81430b8f"
integrity sha512-hkPXCz7gijWp2GoWqsQ4O/5p7F6d5pIQ/+9NyeWG1nABJ4zvLi9kJRv1a44kVf5p13wK0WMoiRA+Xey68yOytA==
dependencies:
define-lazy-prop "^2.0.0"
is-docker "^2.1.1"
is-wsl "^2.2.0"
optionator@^0.8.1:
version "0.8.3"
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495"
@ -7477,6 +7532,13 @@ readdir-glob@^1.0.0:
dependencies:
minimatch "^3.0.4"
readdirp@~3.5.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e"
integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==
dependencies:
picomatch "^2.2.1"
redent@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f"
@ -7811,13 +7873,20 @@ semver@^6.0.0, semver@^6.1.0, semver@^6.2.0, semver@^6.3.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
semver@^7.2.1, semver@^7.3.2, semver@^7.3.4:
semver@^7.2.1, semver@^7.3.4:
version "7.3.4"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97"
integrity sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==
dependencies:
lru-cache "^6.0.0"
semver@^7.3.2:
version "7.3.5"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7"
integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==
dependencies:
lru-cache "^6.0.0"
serialize-error@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-7.0.1.tgz#f1360b0447f61ffb483ec4157c737fab7d778e18"
@ -8030,14 +8099,15 @@ spdx-license-ids@^3.0.0:
resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz#e9c18a410e5ed7e12442a549fbd8afa767038d65"
integrity sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==
spectron@^13.0.0:
version "13.0.0"
resolved "https://registry.yarnpkg.com/spectron/-/spectron-13.0.0.tgz#16bdfcf9a2b26cb5ee6c3e29b4f08101e339aa4d"
integrity sha512-7RPa6Fp8gqL4V0DubobnqIRFHIijkpjg6MFHcJlxoerWyvLJd+cQvOh756XpB1Z/U3DyA9jPcS+HE2PvYRP5+A==
spectron@^14.0.0:
version "14.0.0"
resolved "https://registry.yarnpkg.com/spectron/-/spectron-14.0.0.tgz#c8160e38c30dcda39734f3e8e809162dc0805d14"
integrity sha512-88GM7D1eLiTxjByjtY7lxU7CJcQ92kX1x0WfnADaIXqqYRLbI1KlIWxXz1Xm5UxuMJh5N847K0NONG49mvZtuw==
dependencies:
"@electron/remote" "^1.0.4"
dev-null "^0.1.1"
electron-chromedriver "^11.0.0"
request "^2.88.2"
electron-chromedriver "^12.0.0"
got "^11.8.0"
split "^1.0.1"
webdriverio "^6.9.1"
@ -8671,9 +8741,9 @@ typescript@^4.1.5:
integrity sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==
ua-parser-js@^0.7.21:
version "0.7.23"
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.23.tgz#704d67f951e13195fbcd3d78818577f5bc1d547b"
integrity sha512-m4hvMLxgGHXG3O3fQVAyyAQpZzDOvwnhOTjYz5Xmr7r/+LpkNy3vJXdVRWgd1TkAb7NGROZuSy96CrlNVjA7KA==
version "0.7.28"
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.28.tgz#8ba04e653f35ce210239c64661685bf9121dec31"
integrity sha512-6Gurc1n//gjp9eQNXjD9O3M/sMwVtN5S8Lv9bvOYBfKfDNiIIhqiyi01vMBO45u4zkDE420w/e0se7Vs+sIg+g==
unbzip2-stream@^1.3.3:
version "1.4.3"
@ -9044,9 +9114,9 @@ write-file-atomic@^3.0.0:
typedarray-to-buffer "^3.1.5"
ws@^7.2.3, ws@^7.3.1:
version "7.4.3"
resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.3.tgz#1f9643de34a543b8edb124bdcbc457ae55a6e5cd"
integrity sha512-hr6vCR76GsossIRsr8OLR9acVVm1jyfEWvhbNjtgPOrfvAlKzvyeg/P6r8RuDjRyrcQoPQT7K0DGEPc7Ae6jzA==
version "7.4.6"
resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c"
integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==
xdg-basedir@^4.0.0:
version "4.0.0"
@ -9260,19 +9330,19 @@ yocto-queue@^0.1.0:
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
ytdl-core@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/ytdl-core/-/ytdl-core-4.5.0.tgz#f07733387c548e5c3a5614c93ef55bde666eeaf4"
integrity sha512-e8r6skrakWNixsVlNPBMoRM1HrdW1swE97If9nenDUjF65uogYk4DvxIuqlmqRfBWKe+6aIZwqedNxUU9XLYJA==
ytdl-core@^4.7.0:
version "4.8.0"
resolved "https://registry.yarnpkg.com/ytdl-core/-/ytdl-core-4.8.0.tgz#d9f037a370a4b984f1f937e7a11b4531e8959443"
integrity sha512-LFhhwqFojReoaME17VpsFeiamygM0W/YNG8O02mrmS2O6Em5LjCPiJYdq7Af3CmJtBEOCdptSZ3Ql+3LGWDGvg==
dependencies:
m3u8stream "^0.8.3"
miniget "^4.0.0"
sax "^1.1.3"
ytpl@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/ytpl/-/ytpl-2.1.1.tgz#c3c3e0e198e3fc7be13b52f5651e950b0aae94a0"
integrity sha512-yrU/w1k75f089zUONUm1QjlCv96QWhk/SS6jNEVJXMr8/9zEj4k2EIv81nk5wldJvpb+2rvEfm2zIwRqXRoZ9w==
ytpl@^2.2.0:
version "2.2.1"
resolved "https://registry.yarnpkg.com/ytpl/-/ytpl-2.2.1.tgz#e514eccdd46e02eeb0d16e08f8278489258ab31a"
integrity sha512-sxty58s4JTNCDkiaiTkcaXfWCOW5sfHOPwDQtWIkoU4C+Kht2qat8yaLVbWZIclUSZo+naANyaI7LGjhhrErGA==
dependencies:
miniget "^4.2.0"