diff --git a/package.json b/package.json index 390b470..26da961 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "@types/mongoose": "^5.7.19", "@types/node": "^14.0.1", "@types/nodemailer": "^6.4.0", + "@types/puppeteer": "^5.4.2", "@types/signale": "^1.4.1", "@types/uuid": "^7.0.3", "@typescript-eslint/eslint-plugin": "^2.33.0", @@ -51,6 +52,7 @@ "mongoose": "^5.9.13", "nodemailer": "^6.4.8", "pluris": "^0.2.5", + "puppeteer": "^5.5.0", "sd-notify": "^2.8.0", "signale": "^1.4.0", "stripe": "^8.120.0", diff --git a/src/class/Util.ts b/src/class/Util.ts index dab5ff3..25c0d3f 100644 --- a/src/class/Util.ts +++ b/src/class/Util.ts @@ -63,6 +63,16 @@ export default class Util { } */ + public dataConversion(bytes: number): string { + const i = Math.floor(Math.log(bytes) / Math.log(1024)); + const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; + if (bytes === 0) { + return '0 KB'; + } + return `${(bytes / 1024 ** i).toFixed(2)} ${sizes[i]}`; + } + + public async exec(command: string, _options: childProcess.ExecOptions = {}): Promise { const ex = promisify(childProcess.exec); try { diff --git a/src/commands/index.ts b/src/commands/index.ts index cf37a6e..8916297 100644 --- a/src/commands/index.ts +++ b/src/commands/index.ts @@ -32,10 +32,10 @@ export { default as pulldata } from './pulldata'; export { default as rank } from './rank'; export { default as roleinfo } from './roleinfo'; export { default as score } from './score'; +export { default as site } from './site'; export { default as stats } from './stats'; export { default as storemessages } from './storemessages'; export { default as sysinfo } from './sysinfo'; -export { default as tls } from './tls'; export { default as train } from './train'; export { default as tts } from './tts'; export { default as unban } from './unban'; diff --git a/src/commands/site.ts b/src/commands/site.ts new file mode 100644 index 0000000..620aeed --- /dev/null +++ b/src/commands/site.ts @@ -0,0 +1,287 @@ +/* eslint-disable dot-notation */ +/* eslint-disable no-plusplus */ +import cheerio from 'cheerio'; +import https from 'https'; +import dns from 'dns'; +import puppeteer from 'puppeteer'; +import { createPaginationEmbed } from 'eris-pagination'; +import { promisify } from 'util'; +import axios, { AxiosError, AxiosResponse } from 'axios'; +import { Message } from 'eris'; +import { Client, Command, RichEmbed } from '../class'; + +interface TLSResponse { + status: boolean, + message?: string, + subject: { + commonName: string, + organization: string[], + organizationalUnit: string[], + locality: string[], + country: string[], + }, + issuer: { + commonName: string, + organization: string[], + organizationalUnit: string[], + locality: string[], + country: string[], + }, + root: { + commonName: string, + organization: string[], + organizationalUnit: string[], + locality: string[], + country: string[], + }, + notBefore: Date, + notAfter: Date, + validationType: 'DV' | 'OV' | 'EV', + signatureAlgorithm: string, + publicKeyAlgorithm: string, + serialNumber: string, + keyUsage: number[], + keyUsageAsText: ['CRL Signing'?, 'Certificate Signing'?, 'Content Commitment'?, 'Data Encipherment'?, 'Decipher Only'?, 'Digital Signature'?, 'Encipher Only'?, 'Key Agreement'?, 'Key Encipherment'?], + extendedKeyUsage: number[], + extendedKeyUsageAsText: ['All/Any Usages'?, 'TLS Web Server Authentication'?, 'TLS Web Client Authentication'?, 'Code Signing'?, 'E-mail Protection (S/MIME)'?], + san: string[], + fingerprint: string, + connection: { + cipherSuite: string, + tlsVersion: 'SSLv3' | 'TLSv1' | 'TLSv1.1' | 'TLSv1.2' | 'TLSv1.3', + }, +} + + +export default class SiteInfo extends Command { + constructor(client: Client) { + super(client); + this.name = 'site'; + this.description = 'Retrieves various information about a site. Includes web, host, and TLS information.'; + this.usage = `${this.client.config.prefix}tls \n*Only raw domain, no protocols or URLs.*`; + this.aliases = ['ssl', 'cert', 'certinfo', 'ci', 'tls', 'si', 'siteinfo']; + this.permissions = 0; + this.guildOnly = true; + this.enabled = true; + } + + public async run(message: Message, args: string[]) { + try { + if (!args[0]) return this.client.commands.get('help').run(message, [this.name]); + + const loading = await this.loading(message.channel, 'Loading...'); + + let author: { name?: string, icon?: string, url?: string } = {}; + let s: AxiosResponse; + try { + s = await axios.get(`https://${args[0]}`, { + httpsAgent: new https.Agent({ + rejectUnauthorized: false, + }), + }); + } catch (err) { + loading.delete().catch(() => {}); + return this.error(message.channel, `Unable to retrieve information from site. | ${err}`); + } + try { + const site = cheerio.load(s.data); + + let iconURI: string; + + try { + await axios.get(`https://${args[0]}/favicon.ico`, { + httpsAgent: new https.Agent({ + rejectUnauthorized: false, + }), + }); + iconURI = `https://${args[0]}/favicon.ico`; + } catch { + const att = site('link').toArray().filter((a) => a.attribs.rel === 'icon'); + if (att?.length > 0) { + if (att[0].attribs.href.startsWith('/') || !att[0].attribs.href.startsWith('http')) { + iconURI = `https://${args[0]}${att[0].attribs.href}`; + } else { + iconURI = att[0].attribs.href; + } + } + } + author = { + name: site('title').text(), + icon: iconURI, + url: `https://${args[0]}`, + }; + } catch { + author = { + name: `https://${args[0]}`, + icon: `https://${args[0]}/favicon.ico`, + url: `https://${args[0]}`, + }; + } + + const embeds: RichEmbed[] = []; + try { + const server = await this.getServerInformation(args[0]); + if (server) { + const em = new RichEmbed(); + em.setTitle('Web Information'); + server.forEach((f) => em.addField(f.name, f.value, f.inline)); + embeds.push(em); + } + const host = await this.getHostInformation(args[0]); + if (host) { + const em = new RichEmbed(); + em.setTitle('Host Information'); + host.forEach((f) => em.addField(f.name, f.value, f.inline)); + embeds.push(em); + } + const tls = await this.getTLSInformation(args[0]); + if (tls) { + const em = new RichEmbed(); + em.setTitle('TLS Information'); + tls.forEach((f) => em.addField(f.name, f.value, f.inline)); + embeds.push(em); + } + } catch { + loading.delete().catch(() => {}); + return this.error(message.channel, 'Unable to receive information.'); + } + + const browser = await puppeteer.launch(); + const page = await browser.newPage(); + await page.goto(`https://${args[0]}`); + const screenshotData = await page.screenshot(); + embeds.forEach((embed) => { + embed.setAuthor(author.name, author.icon, author.url); + embed.setColor('#4870fe'); + embed.setFooter(this.client.user.username, this.client.user.avatarURL); + embed.setTimestamp(); + }); + + if (embeds.length === 1) return message.channel.createMessage({ embed: embeds[0] }, { name: 'img.png', file: screenshotData }); + await message.channel.createMessage('', { name: 'img.png', file: screenshotData }); + loading.delete().catch(() => {}); + return await createPaginationEmbed(message, embeds, { + cycling: true, + extendedButtons: true, + }); + } catch (err) { + return this.client.util.handleError(err, message, this); + } + } + + public async getHostInformation(domain: string) { + const getDNS = promisify(dns.resolve4); + + try { + const dnsd = await getDNS(domain); + if (dnsd?.length < 1) return null; + + const r = await axios.get(`http://ip-api.com/json/${dnsd[0]}`); + + const embed = new RichEmbed(); + embed.addField('IPv4 Address', dnsd[0], true); + embed.addBlankField(); + embed.addField('Organization/Customer', r.data.org, true); + embed.addField('Internet Service Provider', r.data.isp, true); + embed.addField('Location', `${r.data.city}, ${r.data.regionName}, ${r.data.country}`, true); + return embed.fields; + } catch (err) { + this.client.util.signale.error(err); + return null; + } + } + + public async getServerInformation(domain: string) { + let r: AxiosResponse; + try { + r = await axios.get(domain, { + httpsAgent: new https.Agent({ + rejectUnauthorized: false, + }), + }); + } catch (err) { + return null; + } + + const embed = new RichEmbed(); + embed.addField('Web Software', r.headers['server'] ?? 'N/A', true); + embed.addField('Content Type', r.headers['content-type'] ? r.headers['content-type'].split(';')[0] : 'N/A', true); + embed.addField('Content Length', r.headers['content-length'] ? this.client.util.dataConversion(r.headers['content-length']) : 'N/A', true); + return embed.fields; + } + + public async getTLSInformation(domain: string) { + https.globalAgent.options.rejectUnauthorized = false; + + let r: AxiosResponse; + try { + r = await axios.get(`https://certapi.libraryofcode.org?q=${domain}`, { + httpsAgent: new https.Agent({ + rejectUnauthorized: false, + }), + }); + } catch (err) { + const error = err; + return null; + } + const resp: TLSResponse = r.data; + + const embed = new RichEmbed(); + + let subjectString = `**Common Name:** ${resp.subject.commonName}\n`; + if (resp.subject.organization?.length > 0) subjectString += `**Organization:** ${resp.subject.organization[0]}\n`; + if (resp.subject.organizationalUnit?.length > 0) subjectString += `**Organizational Unit:** ${resp.subject.organizationalUnit[0]}\n`; + if (resp.subject.locality?.length > 0) subjectString += `**Locality:** ${resp.subject.locality[0]}\n`; + if (resp.subject.country?.length > 0) subjectString += `**Country:** ${resp.subject.country[0]}`; + embed.addField('Subject', subjectString, true); + + let issuerString = `**Common Name:** ${resp.subject.commonName}\n`; + if (resp.issuer.organization?.length > 0) issuerString += `**Organization:** ${resp.issuer.organization[0]}\n`; + if (resp.issuer.organizationalUnit?.length > 0) issuerString += `**Organizational Unit:** ${resp.issuer.organizationalUnit[0]}\n`; + if (resp.issuer.locality?.length > 0) issuerString += `**Locality:** ${resp.issuer.locality[0]}\n`; + if (resp.issuer.country?.length > 0) issuerString += `**Country:** ${resp.issuer.country[0]}`; + const rootString = `**Root Certificate:** ${resp.root.organization?.length > 0 ? resp.root.organization[0] : ''} (${resp.root.commonName ?? ''} : ${resp.root.organizationalUnit?.length > 0 ? resp.root.organizationalUnit[0] : ''})`; + if (rootString?.length > 0) issuerString += `\n\n${rootString}`; + embed.addField('Issuer', issuerString, true); + + embed.addBlankField(); + + embed.addField('Issued On', new Date(resp.notBefore).toLocaleString('en-us'), true); + embed.addField('Expiry', new Date(resp.notAfter).toLocaleString('en-us'), true); + + embed.addBlankField(); + + let sanString = ''; + + for (let i = 0; i < resp.san.length; i++) { + if (i >= 10) { + sanString += '...'; + break; + } + sanString += `${resp.san[i]}\n`; + } + + embed.addField('Subject Alternative Names', sanString, true); + + embed.addBlankField(); + + embed.addField('Key Usage', resp.keyUsageAsText.join(', '), true); + embed.addField('Extended Key Usage', resp.extendedKeyUsageAsText.join(', '), true); + embed.addField('Validation Type', resp.validationType, true); + + embed.addBlankField(); + + embed.addField('Serial Number', String(resp.serialNumber), true); + embed.addField('Fingerprint (SHA1)', resp.fingerprint, true); + embed.addField('Signature Algorithm', resp.signatureAlgorithm, true); + embed.addField('Public Key Algorithm', resp.publicKeyAlgorithm, true); + + embed.addBlankField(); + + embed.addField('TLS Cipher Suite', resp.connection.cipherSuite, true); + embed.addField('TLS Version', resp.connection.tlsVersion, true); + + https.globalAgent.options.rejectUnauthorized = true; + return embed.fields; + } +} diff --git a/src/commands/tls.ts b/src/commands/tls.ts deleted file mode 100644 index 9dd3789..0000000 --- a/src/commands/tls.ts +++ /dev/null @@ -1,171 +0,0 @@ -/* eslint-disable no-plusplus */ -import cheerio from 'cheerio'; -import https from 'https'; -import axios, { AxiosError, AxiosResponse } from 'axios'; -import { Message } from 'eris'; -import { Client, Command, RichEmbed } from '../class'; - -interface TLSResponse { - status: boolean, - message?: string, - subject: { - commonName: string, - organization: string[], - organizationalUnit: string[], - locality: string[], - country: string[], - }, - issuer: { - commonName: string, - organization: string[], - organizationalUnit: string[], - locality: string[], - country: string[], - }, - root: { - commonName: string, - organization: string[], - organizationalUnit: string[], - locality: string[], - country: string[], - }, - notBefore: Date, - notAfter: Date, - validationType: 'DV' | 'OV' | 'EV', - signatureAlgorithm: string, - publicKeyAlgorithm: string, - serialNumber: string, - keyUsage: number[], - keyUsageAsText: ['CRL Signing'?, 'Certificate Signing'?, 'Content Commitment'?, 'Data Encipherment'?, 'Decipher Only'?, 'Digital Signature'?, 'Encipher Only'?, 'Key Agreement'?, 'Key Encipherment'?], - extendedKeyUsage: number[], - extendedKeyUsageAsText: ['All/Any Usages'?, 'TLS Web Server Authentication'?, 'TLS Web Client Authentication'?, 'Code Signing'?, 'E-mail Protection (S/MIME)'?], - san: string[], - fingerprint: string, - connection: { - cipherSuite: string, - tlsVersion: 'SSLv3' | 'TLSv1' | 'TLSv1.1' | 'TLSv1.2' | 'TLSv1.3', - }, -} - - -export default class TLS extends Command { - constructor(client: Client) { - super(client); - this.name = 'tls'; - this.description = 'Retrieves information about TLS and x509 configuration used by a site.'; - this.usage = `${this.client.config.prefix}tls `; - this.aliases = ['ssl', 'cert', 'certinfo', 'ci']; - this.permissions = 0; - this.guildOnly = true; - this.enabled = true; - } - - public async run(message: Message, args: string[]) { - try { - if (!args[0]) return this.client.commands.get('help').run(message, [this.name]); - https.globalAgent.options.rejectUnauthorized = false; - - let r: AxiosResponse; - let s: AxiosResponse; - try { - r = await axios.get(`https://certapi.libraryofcode.org?q=${args[0]}`); - s = await axios.get(`https://${args[0]}`); - } catch (err) { - const error = err; - return this.error(message.channel, `Unable to receive TLS information for this site. | ${error?.response?.data?.message ?? ''}`); - } - const resp: TLSResponse = r.data; - - const embed = new RichEmbed(); - embed.setTitle('TLS Information'); - embed.setColor('#4870fe'); - - - try { - const site = cheerio.load(s.data); - - let iconURI: string; - - try { - await axios.get(`https://${args[0]}/favicon.ico`); - iconURI = `https://${args[0]}/favicon.ico`; - } catch { - const att = site('link').toArray().filter((a) => a.attribs.rel === 'icon'); - if (att?.length > 0) { - if (att[0].attribs.href.startsWith('/') || !att[0].attribs.href.startsWith('http')) { - iconURI = `https://${args[0]}${att[0].attribs.href}`; - } else { - iconURI = att[0].attribs.href; - } - } - } - - embed.setAuthor(site('title').text(), iconURI, `https://${args[0]}`); - } catch { - embed.setAuthor(`https://${args[0]}`, `https://${args[0]}/favicon.ico`, `https://${args[0]}`); - } - - let subjectString = `**Common Name:** ${resp.subject.commonName}\n`; - if (resp.subject.organization?.length > 0) subjectString += `**Organization:** ${resp.subject.organization[0]}\n`; - if (resp.subject.organizationalUnit?.length > 0) subjectString += `**Organizational Unit:** ${resp.subject.organizationalUnit[0]}\n`; - if (resp.subject.locality?.length > 0) subjectString += `**Locality:** ${resp.subject.locality[0]}\n`; - if (resp.subject.country?.length > 0) subjectString += `**Country:** ${resp.subject.country[0]}`; - embed.addField('Subject', subjectString, true); - - let issuerString = `**Common Name:** ${resp.subject.commonName}\n`; - if (resp.issuer.organization?.length > 0) issuerString += `**Organization:** ${resp.issuer.organization[0]}\n`; - if (resp.issuer.organizationalUnit?.length > 0) issuerString += `**Organizational Unit:** ${resp.issuer.organizationalUnit[0]}\n`; - if (resp.issuer.locality?.length > 0) issuerString += `**Locality:** ${resp.issuer.locality[0]}\n`; - if (resp.issuer.country?.length > 0) issuerString += `**Country:** ${resp.issuer.country[0]}`; - const rootString = `**Root Certificate:** ${resp.root.organization?.length > 0 ? resp.root.organization[0] : ''} (${resp.root.commonName ?? ''} : ${resp.root.organizationalUnit?.length > 0 ? resp.root.organizationalUnit[0] : ''})`; - if (rootString?.length > 0) issuerString += `\n\n${rootString}`; - embed.addField('Issuer', issuerString, true); - - embed.addBlankField(); - - embed.addField('Issued On', new Date(resp.notBefore).toLocaleString('en-us'), true); - embed.addField('Expiry', new Date(resp.notAfter).toLocaleString('en-us'), true); - - embed.addBlankField(); - - let sanString = ''; - - for (let i = 0; i < resp.san.length; i++) { - if (i >= 10) { - sanString += '...'; - break; - } - sanString += `${resp.san[i]}\n`; - } - - embed.addField('Subject Alternative Names', sanString, true); - - embed.addBlankField(); - - embed.addField('Key Usage', resp.keyUsageAsText.join(', '), true); - embed.addField('Extended Key Usage', resp.extendedKeyUsageAsText.join(', '), true); - embed.addField('Validation Type', resp.validationType, true); - - embed.addBlankField(); - - embed.addField('Serial Number', String(resp.serialNumber), true); - embed.addField('Fingerprint (SHA1)', resp.fingerprint, true); - embed.addField('Signature Algorithm', resp.signatureAlgorithm, true); - embed.addField('Public Key Algorithm', resp.publicKeyAlgorithm, true); - - embed.addBlankField(); - - embed.addField('TLS Cipher Suite', resp.connection.cipherSuite, true); - embed.addField('TLS Version', resp.connection.tlsVersion, true); - - embed.setFooter(this.client.user.username, this.client.user.avatarURL); - embed.setTimestamp(); - - https.globalAgent.options.rejectUnauthorized = true; - return message.channel.createMessage({ embed }); - } catch (err) { - https.globalAgent.options.rejectUnauthorized = true; - return this.client.util.handleError(err, message, this, false); - } - } -} diff --git a/yarn.lock b/yarn.lock index 1fdfd4d..2a09a46 100644 --- a/yarn.lock +++ b/yarn.lock @@ -278,6 +278,13 @@ dependencies: "@types/node" "*" +"@types/puppeteer@^5.4.2": + version "5.4.2" + resolved "https://registry.yarnpkg.com/@types/puppeteer/-/puppeteer-5.4.2.tgz#80f3a1f54dedbbf750779716de81401549062072" + integrity sha512-yjbHoKjZFOGqA6bIEI2dfBE5UPqU0YGWzP+ipDVP1iGzmlhksVKTBVZfT3Aj3wnvmcJ2PQ9zcncwOwyavmafBw== + dependencies: + "@types/node" "*" + "@types/qs@*": version "6.9.2" resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.2.tgz#faab98ec4f96ee72c829b7ec0983af4f4d343113" @@ -308,6 +315,13 @@ resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-7.0.3.tgz#45cd03e98e758f8581c79c535afbd4fc27ba7ac8" integrity sha512-PUdqTZVrNYTNcIhLHkiaYzoOIaUi5LFg/XLerAdgvwQrUCx+oSbtoBze1AMyvYbcwzUSNC+Isl58SM4Sm/6COw== +"@types/yauzl@^2.9.1": + version "2.9.1" + resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.9.1.tgz#d10f69f9f522eef3cf98e30afb684a1e1ec923af" + integrity sha512-A1b8SU4D10uoPjwb0lnHmmu8wZhR9d+9o2PKBQT2jU5YPTKsxac6M2qGAdY7VcL+dHHhARVUDmeg0rOrcd9EjA== + dependencies: + "@types/node" "*" + "@typescript-eslint/eslint-plugin@^2.33.0": version "2.33.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.33.0.tgz#d6c8319d5011b4783bb3d2dadf105d8bdd499bd5" @@ -381,6 +395,11 @@ acorn@^7.1.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.2.0.tgz#17ea7e40d7c8640ff54a694c889c26f31704effe" integrity sha512-apwXVmYVpQ34m/i71vrApRrRKCWQnZZF1+npOD0WV5xZFfwWOmKGQ2RWlfdy9vWITsenisM8M0Qeq8agcFHNiQ== +agent-base@5: + version "5.1.1" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-5.1.1.tgz#e8fb3f242959db44d63be665db7a8e739537a32c" + integrity sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g== + agent-base@6: version "6.0.2" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" @@ -599,7 +618,7 @@ base64-js@^1.0.2: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g== -base64-js@^1.3.0: +base64-js@^1.3.0, base64-js@^1.3.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== @@ -707,11 +726,24 @@ btoa@1.1.1: resolved "https://registry.yarnpkg.com/btoa/-/btoa-1.1.1.tgz#27c8106263108e9dd41ff2faaad2a17045e35eba" integrity sha1-J8gQYmMQjp3UH/L6qtKhcEXjXro= +buffer-crc32@~0.2.3: + version "0.2.13" + resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" + integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= + buffer-equal-constant-time@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk= +buffer@^5.2.1: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + buffer@^5.5.0: version "5.6.0" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.6.0.tgz#a31749dc7d81d84db08abf937b6b8c4033f62786" @@ -1020,7 +1052,7 @@ debug@3.1.0, debug@=3.1.0: dependencies: ms "2.0.0" -debug@4: +debug@4, debug@^4.1.0: version "4.3.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== @@ -1108,6 +1140,11 @@ detect-libc@^1.0.3: resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= +devtools-protocol@0.0.818844: + version "0.0.818844" + resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.818844.tgz#d1947278ec85b53e4c8ca598f607a28fa785ba9e" + integrity sha512-AD1hi7iVJ8OD0aMLQU5VK0XH9LDlA1+BcPIgrAxPfaibx2DbWucuyOhc4oyQCbnvDDO68nN6/LcKfqTP343Jjg== + dns-prefetch-control@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/dns-prefetch-control/-/dns-prefetch-control-0.2.0.tgz#73988161841f3dcc81f47686d539a2c702c88624" @@ -1547,6 +1584,17 @@ external-editor@^3.0.3: iconv-lite "^0.4.24" tmp "^0.0.33" +extract-zip@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a" + integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg== + dependencies: + debug "^4.1.1" + get-stream "^5.1.0" + yauzl "^2.10.0" + optionalDependencies: + "@types/yauzl" "^2.9.1" + extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" @@ -1577,6 +1625,13 @@ fast-text-encoding@^1.0.0: resolved "https://registry.yarnpkg.com/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz#ec02ac8e01ab8a319af182dae2681213cfe9ce53" integrity sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig== +fd-slicer@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" + integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4= + dependencies: + pend "~1.2.0" + feature-policy@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/feature-policy/-/feature-policy-0.3.0.tgz#7430e8e54a40da01156ca30aaec1a381ce536069" @@ -1628,7 +1683,7 @@ find-up@^2.0.0, find-up@^2.1.0: dependencies: locate-path "^2.0.0" -find-up@^4.1.0: +find-up@^4.0.0, find-up@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== @@ -1761,6 +1816,13 @@ get-port@^5.1.1: resolved "https://registry.yarnpkg.com/get-port/-/get-port-5.1.1.tgz#0469ed07563479de6efb986baf053dcd7d4e3193" integrity sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ== +get-stream@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== + dependencies: + pump "^3.0.0" + getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" @@ -2031,6 +2093,14 @@ http-signature@~1.2.0: jsprim "^1.2.2" sshpk "^1.7.0" +https-proxy-agent@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz#702b71fb5520a132a66de1f67541d9e62154d82b" + integrity sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg== + dependencies: + agent-base "5" + debug "4" + https-proxy-agent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" @@ -2053,6 +2123,11 @@ iconv-lite@0.4.24, iconv-lite@^0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3.0.0" +ieee754@^1.1.13: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + ieee754@^1.1.4: version "1.1.13" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" @@ -3074,6 +3149,11 @@ path-type@^2.0.0: dependencies: pify "^2.0.0" +pend@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" + integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= + performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" @@ -3104,6 +3184,13 @@ pkg-dir@^2.0.0: dependencies: find-up "^2.1.0" +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + pluris@^0.2.5: version "0.2.5" resolved "https://registry.yarnpkg.com/pluris/-/pluris-0.2.5.tgz#e98d8e0e7a49432b8bfe168b46e919e55405259e" @@ -3144,7 +3231,7 @@ process-nextick-args@~2.0.0: resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== -progress@^2.0.0: +progress@^2.0.0, progress@^2.0.1: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== @@ -3185,6 +3272,11 @@ proxy-addr@~2.0.5: forwarded "~0.1.2" ipaddr.js "1.9.1" +proxy-from-env@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + psl@^1.1.28: version "1.8.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" @@ -3203,6 +3295,24 @@ punycode@^2.1.0, punycode@^2.1.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== +puppeteer@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-5.5.0.tgz#331a7edd212ca06b4a556156435f58cbae08af00" + integrity sha512-OM8ZvTXAhfgFA7wBIIGlPQzvyEETzDjeRa4mZRCRHxYL+GNH5WAuYUQdja3rpWZvkX/JKqmuVgbsxDNsDFjMEg== + dependencies: + debug "^4.1.0" + devtools-protocol "0.0.818844" + extract-zip "^2.0.0" + https-proxy-agent "^4.0.0" + node-fetch "^2.6.1" + pkg-dir "^4.2.0" + progress "^2.0.1" + proxy-from-env "^1.0.0" + rimraf "^3.0.2" + tar-fs "^2.0.0" + unbzip2-stream "^1.3.3" + ws "^7.2.3" + qs@6.7.0: version "6.7.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" @@ -3419,6 +3529,13 @@ rimraf@^2.6.3: dependencies: glob "^7.1.3" +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + run-async@^2.4.0: version "2.4.1" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" @@ -3899,7 +4016,7 @@ through2@^0.6.3: readable-stream ">=1.0.33-1 <1.1.0-0" xtend ">=4.0.0 <4.1.0-0" -through@^2.3.6: +through@^2.3.6, through@^2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= @@ -3993,6 +4110,14 @@ typescript@^3.9.2: resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.2.tgz#64e9c8e9be6ea583c54607677dd4680a1cf35db9" integrity sha512-q2ktq4n/uLuNNShyayit+DTobV2ApPEo/6so68JaD5ojvc/6GClBipedB9zNWYxRSAlZXAe405Rlijzl6qDiSw== +unbzip2-stream@^1.3.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz#b0da04c4371311df771cdc215e87f2130991ace7" + integrity sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg== + dependencies: + buffer "^5.2.1" + through "^2.3.8" + unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" @@ -4129,6 +4254,11 @@ ws@^7.2.1: resolved "https://registry.yarnpkg.com/ws/-/ws-7.3.0.tgz#4b2f7f219b3d3737bc1a2fbf145d825b94d38ffd" integrity sha512-iFtXzngZVXPGgpTlP1rBqsUK82p9tKqsWRPg5L56egiljujJT3vGAYnHANvFxBieXrTFavhzhxW52jnaWV+w2w== +ws@^7.2.3: + version "7.4.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.1.tgz#a333be02696bd0e54cea0434e21dcc8a9ac294bb" + integrity sha512-pTsP8UAfhy3sk1lSk/O/s4tjD0CRwvMnzvwr4OKGX7ZvqZtUyx4KIJB5JWbkykPoc55tixMGgTNoh3k4FkNGFQ== + x-xss-protection@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/x-xss-protection/-/x-xss-protection-1.3.0.tgz#3e3a8dd638da80421b0e9fff11a2dbe168f6d52c" @@ -4180,3 +4310,11 @@ yargs@^15.3.1: which-module "^2.0.0" y18n "^4.0.0" yargs-parser "^18.1.2" + +yauzl@^2.10.0: + version "2.10.0" + resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" + integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= + dependencies: + buffer-crc32 "~0.2.3" + fd-slicer "~1.1.0"