mirror of
https://github.com/th-ch/youtube-music.git
synced 2026-01-14 03:41:46 +00:00
additional cleanup/refactoring
This commit is contained in:
@ -66,7 +66,6 @@
|
|||||||
"@ffmpeg/core": "^0.8.5",
|
"@ffmpeg/core": "^0.8.5",
|
||||||
"@ffmpeg/ffmpeg": "^0.9.7",
|
"@ffmpeg/ffmpeg": "^0.9.7",
|
||||||
"YoutubeNonStop": "git://github.com/lawfx/YoutubeNonStop.git#v0.8.1",
|
"YoutubeNonStop": "git://github.com/lawfx/YoutubeNonStop.git#v0.8.1",
|
||||||
"axios": "^0.21.1",
|
|
||||||
"async-mutex": "^0.3.1",
|
"async-mutex": "^0.3.1",
|
||||||
"browser-id3-writer": "^4.4.0",
|
"browser-id3-writer": "^4.4.0",
|
||||||
"discord-rpc": "^3.2.0",
|
"discord-rpc": "^3.2.0",
|
||||||
|
|||||||
@ -1,35 +1,24 @@
|
|||||||
const fetch = require('node-fetch');
|
const fetch = require('node-fetch');
|
||||||
const md5 = require('md5');
|
const md5 = require('md5');
|
||||||
const open = require("open");
|
const open = require("open");
|
||||||
const axios = require('axios');
|
|
||||||
const { setOptions } = require('../../config/plugins');
|
const { setOptions } = require('../../config/plugins');
|
||||||
const getSongInfo = require('../../providers/song-info');
|
const getSongInfo = require('../../providers/song-info');
|
||||||
|
const defaultConfig = require('../../config/defaults');
|
||||||
const defaultSettings = {
|
|
||||||
enabled: true,
|
|
||||||
api_root: "http://ws.audioscrobbler.com/2.0/",
|
|
||||||
api_key: "04d76faaac8726e60988e14c105d421a", // api key registered by @semvis123
|
|
||||||
secret: "a5d2a36fdf64819290f6982481eaffa2",
|
|
||||||
suffixesToRemove: [' - Topic', 'VEVO']
|
|
||||||
}
|
|
||||||
|
|
||||||
const cleanupArtistName = (config, artist) => {
|
const cleanupArtistName = (config, artist) => {
|
||||||
// removes the suffixes of the artist name for more recognition by last.fm
|
// removes the suffixes of the artist name for more recognition by last.fm
|
||||||
let { suffixesToRemove } = config;
|
const { suffixesToRemove } = config;
|
||||||
if (suffixesToRemove === undefined) {
|
if (suffixesToRemove === undefined) return artist;
|
||||||
suffixesToRemove = defaultSettings.suffixesToRemove;
|
|
||||||
config.suffixesToRemove = suffixesToRemove;
|
|
||||||
setOptions('last-fm', config);
|
|
||||||
}
|
|
||||||
for (suffix of suffixesToRemove) {
|
for (suffix of suffixesToRemove) {
|
||||||
artist = artist.replace(suffix, '');
|
artist = artist.replace(suffix, '');
|
||||||
}
|
}
|
||||||
return artist
|
return artist;
|
||||||
}
|
}
|
||||||
|
|
||||||
const createFormData = params => {
|
const createFormData = params => {
|
||||||
// creates the body for in the post request
|
// creates the body for in the post request
|
||||||
let formData = new URLSearchParams();
|
const formData = new URLSearchParams();
|
||||||
for (key in params) {
|
for (key in params) {
|
||||||
formData.append(key, params[key]);
|
formData.append(key, params[key]);
|
||||||
}
|
}
|
||||||
@ -40,14 +29,14 @@ const createQueryString = (params, api_sig) => {
|
|||||||
const queryData = [];
|
const queryData = [];
|
||||||
params.api_sig = api_sig;
|
params.api_sig = api_sig;
|
||||||
for (key in params) {
|
for (key in params) {
|
||||||
queryData.push(`${key}=${params[key]}`);
|
queryData.push(`${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`);
|
||||||
}
|
}
|
||||||
return '?'+queryData.join('&');
|
return '?'+queryData.join('&');
|
||||||
}
|
}
|
||||||
|
|
||||||
const createApiSig = (params, secret) => {
|
const createApiSig = (params, secret) => {
|
||||||
// this function creates the api signature, see: https://www.last.fm/api/authspec
|
// this function creates the api signature, see: https://www.last.fm/api/authspec
|
||||||
let keys = [];
|
const keys = [];
|
||||||
for (key in params) {
|
for (key in params) {
|
||||||
keys.push(key);
|
keys.push(key);
|
||||||
}
|
}
|
||||||
@ -65,12 +54,12 @@ const createApiSig = (params, secret) => {
|
|||||||
|
|
||||||
const createToken = async ({ api_key, api_root, secret }) => {
|
const createToken = async ({ api_key, api_root, secret }) => {
|
||||||
// creates and stores the auth token
|
// creates and stores the auth token
|
||||||
data = {
|
const data = {
|
||||||
method: 'auth.gettoken',
|
method: 'auth.gettoken',
|
||||||
api_key: api_key,
|
api_key: api_key,
|
||||||
format: 'json'
|
format: 'json'
|
||||||
};
|
};
|
||||||
let api_sig = createApiSig(data, secret);
|
const api_sig = createApiSig(data, secret);
|
||||||
let response = await fetch(`${api_root}${createQueryString(data, api_sig)}`);
|
let response = await fetch(`${api_root}${createQueryString(data, api_sig)}`);
|
||||||
response = await response.json();
|
response = await response.json();
|
||||||
return response?.token;
|
return response?.token;
|
||||||
@ -86,14 +75,14 @@ const authenticate = async config => {
|
|||||||
|
|
||||||
const getAndSetSessionKey = async config => {
|
const getAndSetSessionKey = async config => {
|
||||||
// get and store the session key
|
// get and store the session key
|
||||||
data = {
|
const data = {
|
||||||
api_key: config.api_key,
|
api_key: config.api_key,
|
||||||
format: 'json',
|
format: 'json',
|
||||||
method: 'auth.getsession',
|
method: 'auth.getsession',
|
||||||
token: config.token,
|
token: config.token,
|
||||||
};
|
};
|
||||||
api_sig = createApiSig(data, config.secret);
|
const api_sig = createApiSig(data, config.secret);
|
||||||
res = await fetch(`${config.api_root}${createQueryString(data, api_sig)}`);
|
let res = await fetch(`${config.api_root}${createQueryString(data, api_sig)}`);
|
||||||
res = await res.json();
|
res = await res.json();
|
||||||
if (res.error)
|
if (res.error)
|
||||||
await authenticate(config);
|
await authenticate(config);
|
||||||
@ -102,23 +91,23 @@ const getAndSetSessionKey = async config => {
|
|||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const postSongDataToAPI = async (songInfo, config, data) => {
|
||||||
const addScrobble = async (songInfo, config) => {
|
// this sends a post request to the api, and adds the common data
|
||||||
// this adds one scrobbled song to last.fm
|
|
||||||
if (!config.session_key)
|
if (!config.session_key)
|
||||||
await getAndSetSessionKey(config);
|
await getAndSetSessionKey(config);
|
||||||
data = {
|
|
||||||
|
const postData = {
|
||||||
track: songInfo.title,
|
track: songInfo.title,
|
||||||
|
duration: songInfo.songDuration,
|
||||||
artist: songInfo.artist,
|
artist: songInfo.artist,
|
||||||
api_key: config.api_key,
|
api_key: config.api_key,
|
||||||
sk: config.session_key,
|
sk: config.session_key,
|
||||||
format: 'json',
|
format: 'json',
|
||||||
method: 'track.scrobble',
|
...data,
|
||||||
timestamp: ~~((Date.now() - songInfo.elapsedSeconds) / 1000),
|
|
||||||
duration: songInfo.songDuration,
|
|
||||||
};
|
};
|
||||||
data.api_sig = createApiSig(data, config.secret);
|
|
||||||
axios.post('https://ws.audioscrobbler.com/2.0/', createFormData(data))
|
postData.api_sig = createApiSig(postData, config.secret);
|
||||||
|
fetch('https://ws.audioscrobbler.com/2.0/', {method: 'POST', body: createFormData(postData)})
|
||||||
.catch(res => {
|
.catch(res => {
|
||||||
if (res.response.data.error == 9) {
|
if (res.response.data.error == 9) {
|
||||||
// session key is invalid, so remove it from the config and reauthenticate
|
// session key is invalid, so remove it from the config and reauthenticate
|
||||||
@ -129,29 +118,21 @@ const addScrobble = async (songInfo, config) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const setNowPlaying = async (songInfo, config) => {
|
const addScrobble = (songInfo, config) => {
|
||||||
// this sets the now playing status in last.fm
|
// this adds one scrobbled song to last.fm
|
||||||
if (!config.session_key)
|
const data = {
|
||||||
await getAndSetSessionKey(config);
|
method: 'track.scrobble',
|
||||||
data = {
|
timestamp: ~~((Date.now() - songInfo.elapsedSeconds) / 1000),
|
||||||
track: songInfo.title,
|
|
||||||
artist: songInfo.artist,
|
|
||||||
api_key: config.api_key,
|
|
||||||
sk: config.session_key,
|
|
||||||
format: 'json',
|
|
||||||
method: 'track.updateNowPlaying',
|
|
||||||
duration: songInfo.songDuration,
|
|
||||||
};
|
};
|
||||||
data.api_sig = createApiSig(data, config.secret);
|
postSongDataToAPI(songInfo, config, data);
|
||||||
axios.post('https://ws.audioscrobbler.com/2.0/', createFormData(data))
|
}
|
||||||
.catch(res => {
|
|
||||||
if (res.response.data.error == 9) {
|
const setNowPlaying = (songInfo, config) => {
|
||||||
// session key is invalid, so remove it from the config and reauthenticate
|
// this sets the now playing status in last.fm
|
||||||
config.session_key = undefined;
|
const data = {
|
||||||
setOptions('last-fm', config);
|
method: 'track.updateNowPlaying',
|
||||||
authenticate(config);
|
};
|
||||||
}
|
postSongDataToAPI(songInfo, config, data);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -161,9 +142,10 @@ let scrobbleTimer = undefined;
|
|||||||
const lastfm = async (win, config) => {
|
const lastfm = async (win, config) => {
|
||||||
const registerCallback = getSongInfo(win);
|
const registerCallback = getSongInfo(win);
|
||||||
|
|
||||||
if (!config.api_root) {
|
if (!config.api_root || !config.suffixesToRemove) {
|
||||||
// settings are not present, creating them with the default values
|
// settings are not present, creating them with the default values
|
||||||
config = defaultSettings;
|
config = defaultConfig.plugins['last-fm'];
|
||||||
|
config.enabled = true;
|
||||||
setOptions('last-fm', config);
|
setOptions('last-fm', config);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,10 +161,11 @@ const lastfm = async (win, config) => {
|
|||||||
songInfo.artist = cleanupArtistName(config, songInfo.artist);
|
songInfo.artist = cleanupArtistName(config, songInfo.artist);
|
||||||
if (!songInfo.isPaused) {
|
if (!songInfo.isPaused) {
|
||||||
setNowPlaying(songInfo, config);
|
setNowPlaying(songInfo, config);
|
||||||
let scrobbleTime = Math.min(Math.ceil(songInfo.songDuration / 2), 4 * 60);
|
// scrobble when the song is half way through, or has passed the 4 minute mark
|
||||||
|
const scrobbleTime = Math.min(Math.ceil(songInfo.songDuration / 2), 4 * 60);
|
||||||
if (scrobbleTime > songInfo.elapsedSeconds) {
|
if (scrobbleTime > songInfo.elapsedSeconds) {
|
||||||
// scrobble still needs to happen
|
// scrobble still needs to happen
|
||||||
timeToWait = (scrobbleTime - songInfo.elapsedSeconds) * 1000;
|
const timeToWait = (scrobbleTime - songInfo.elapsedSeconds) * 1000;
|
||||||
scrobbleTimer = setTimeout(addScrobble, timeToWait, songInfo, config);
|
scrobbleTimer = setTimeout(addScrobble, timeToWait, songInfo, config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
49
yarn.lock
49
yarn.lock
@ -1708,6 +1708,13 @@ aws4@^1.8.0:
|
|||||||
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59"
|
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59"
|
||||||
integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==
|
integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==
|
||||||
|
|
||||||
|
axios@^0.21.1:
|
||||||
|
version "0.21.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8"
|
||||||
|
integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==
|
||||||
|
dependencies:
|
||||||
|
follow-redirects "^1.10.0"
|
||||||
|
|
||||||
babel-eslint@^10.1.0:
|
babel-eslint@^10.1.0:
|
||||||
version "10.1.0"
|
version "10.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232"
|
resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232"
|
||||||
@ -2223,6 +2230,11 @@ char-regex@^1.0.2:
|
|||||||
resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf"
|
resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf"
|
||||||
integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==
|
integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==
|
||||||
|
|
||||||
|
charenc@0.0.2:
|
||||||
|
version "0.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
|
||||||
|
integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=
|
||||||
|
|
||||||
chownr@^1.1.1:
|
chownr@^1.1.1:
|
||||||
version "1.1.4"
|
version "1.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
|
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
|
||||||
@ -2587,6 +2599,11 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
|
|||||||
shebang-command "^2.0.0"
|
shebang-command "^2.0.0"
|
||||||
which "^2.0.1"
|
which "^2.0.1"
|
||||||
|
|
||||||
|
crypt@0.0.2:
|
||||||
|
version "0.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
|
||||||
|
integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=
|
||||||
|
|
||||||
crypto-browserify@^3.11.0:
|
crypto-browserify@^3.11.0:
|
||||||
version "3.12.0"
|
version "3.12.0"
|
||||||
resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec"
|
resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec"
|
||||||
@ -2756,6 +2773,11 @@ defer-to-connect@^2.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.0.tgz#83d6b199db041593ac84d781b5222308ccf4c2c1"
|
resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.0.tgz#83d6b199db041593ac84d781b5222308ccf4c2c1"
|
||||||
integrity sha512-bYL2d05vOSf1JEZNx5vSAtPuBMkX8K9EUutg7zlKvTqKXHt7RhWJFbmd7qakVuf13i+IkGmp6FwSsONOf6VYIg==
|
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:
|
define-properties@^1.1.3:
|
||||||
version "1.1.3"
|
version "1.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
|
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
|
||||||
@ -3961,6 +3983,11 @@ flatted@^3.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469"
|
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469"
|
||||||
integrity sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==
|
integrity sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==
|
||||||
|
|
||||||
|
follow-redirects@^1.10.0:
|
||||||
|
version "1.13.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.3.tgz#e5598ad50174c1bc4e872301e82ac2cd97f90267"
|
||||||
|
integrity sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA==
|
||||||
|
|
||||||
for-in@^1.0.2:
|
for-in@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
|
resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
|
||||||
@ -4686,7 +4713,7 @@ is-arrayish@^0.2.1:
|
|||||||
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
|
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
|
||||||
integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=
|
integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=
|
||||||
|
|
||||||
is-buffer@^1.1.5:
|
is-buffer@^1.1.5, is-buffer@~1.1.6:
|
||||||
version "1.1.6"
|
version "1.1.6"
|
||||||
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
|
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
|
||||||
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
|
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
|
||||||
@ -4747,7 +4774,7 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2:
|
|||||||
is-data-descriptor "^1.0.0"
|
is-data-descriptor "^1.0.0"
|
||||||
kind-of "^6.0.2"
|
kind-of "^6.0.2"
|
||||||
|
|
||||||
is-docker@^2.0.0:
|
is-docker@^2.0.0, is-docker@^2.1.1:
|
||||||
version "2.1.1"
|
version "2.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.1.1.tgz#4125a88e44e450d384e09047ede71adc2d144156"
|
resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.1.1.tgz#4125a88e44e450d384e09047ede71adc2d144156"
|
||||||
integrity sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw==
|
integrity sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw==
|
||||||
@ -6023,6 +6050,15 @@ md5.js@^1.3.4:
|
|||||||
inherits "^2.0.1"
|
inherits "^2.0.1"
|
||||||
safe-buffer "^5.1.2"
|
safe-buffer "^5.1.2"
|
||||||
|
|
||||||
|
md5@^2.3.0:
|
||||||
|
version "2.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/md5/-/md5-2.3.0.tgz#c3da9a6aae3a30b46b7b0c349b87b110dc3bda4f"
|
||||||
|
integrity sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==
|
||||||
|
dependencies:
|
||||||
|
charenc "0.0.2"
|
||||||
|
crypt "0.0.2"
|
||||||
|
is-buffer "~1.1.6"
|
||||||
|
|
||||||
memory-fs@^0.2.0:
|
memory-fs@^0.2.0:
|
||||||
version "0.2.0"
|
version "0.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.2.0.tgz#f2bb25368bc121e391c2520de92969caee0a0290"
|
resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.2.0.tgz#f2bb25368bc121e391c2520de92969caee0a0290"
|
||||||
@ -6519,6 +6555,15 @@ open@^7.3.0:
|
|||||||
is-docker "^2.0.0"
|
is-docker "^2.0.0"
|
||||||
is-wsl "^2.1.1"
|
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:
|
optionator@^0.8.1:
|
||||||
version "0.8.3"
|
version "0.8.3"
|
||||||
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495"
|
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495"
|
||||||
|
|||||||
Reference in New Issue
Block a user