diff --git a/.gitignore b/.gitignore index 90bb524..43bea89 100644 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,9 @@ ext *.webm yarn.lock out -*.data \ No newline at end of file +*.data +ext.js +core.js +fag +rollup.config.js +.vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json index 55712c1..272276a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,23 @@ { - "typescript.tsdk": "node_modules/typescript/lib" + "typescript.tsdk": "node_modules/typescript/lib", + "files.exclude": { + "**/dist": true, + "**/node_modules": true, + "**/*.png": true, + "**/*.html": true, + "**/*.c": true, + "**/*~": true, + "**/*.jpg": true, + "**/*.gif": true, + "**/*.exe": true, + "**/*.cs": true, + "**/*.out": true, + "**/*.zip": true, + "**/ext": true, + "**/*.mp4": true, + "**/*.webm": true, + "**/yarn.lock": true, + "**/out": true, + "**/*.data": true + } } \ No newline at end of file diff --git a/main.d.ts b/main.d.ts index 4eea2dc..fc3bd97 100644 --- a/main.d.ts +++ b/main.d.ts @@ -6,4 +6,14 @@ declare module '*.png' { export default new Uint8Array; } +declare module 'blockhash' { + export const hammingDistance: (a: string, b: string) => number; + export const blockhash: () => void; + export const blockhashData: (imgData: { + width: number, + height: number, + data: Uint8Array + }, bits: number, method: number) => string; +} + declare const QR: any; \ No newline at end of file diff --git a/main.meta.js b/main.meta.js index 82a12c7..0507d03 100644 --- a/main.meta.js +++ b/main.meta.js @@ -1,7 +1,7 @@ // ==UserScript== // @name PNGExtraEmbed // @namespace https://coom.tech/ -// @version 0.156 +// @version 0.157 // @description uhh // @author You // @match https://boards.4channel.org/* diff --git a/main.user.js b/main.user.js index 4383de0..9912dce 100644 --- a/main.user.js +++ b/main.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @name PNGExtraEmbed // @namespace https://coom.tech/ -// @version 0.156 +// @version 0.157 // @description uhh // @author You // @match https://boards.4channel.org/* @@ -7302,6 +7302,2118 @@ } }); + // node_modules/jpeg-js/lib/encoder.js + var require_encoder = __commonJS({ + "node_modules/jpeg-js/lib/encoder.js"(exports, module) { + init_esbuild_inject(); + var btoa = btoa || function(buf2) { + return Buffer2.from(buf2).toString("base64"); + }; + function JPEGEncoder(quality) { + var self = this; + var fround = Math.round; + var ffloor = Math.floor; + var YTable = new Array(64); + var UVTable = new Array(64); + var fdtbl_Y = new Array(64); + var fdtbl_UV = new Array(64); + var YDC_HT; + var UVDC_HT; + var YAC_HT; + var UVAC_HT; + var bitcode = new Array(65535); + var category = new Array(65535); + var outputfDCTQuant = new Array(64); + var DU = new Array(64); + var byteout = []; + var bytenew = 0; + var bytepos = 7; + var YDU = new Array(64); + var UDU = new Array(64); + var VDU = new Array(64); + var clt = new Array(256); + var RGB_YUV_TABLE = new Array(2048); + var currentQuality; + var ZigZag = [ + 0, + 1, + 5, + 6, + 14, + 15, + 27, + 28, + 2, + 4, + 7, + 13, + 16, + 26, + 29, + 42, + 3, + 8, + 12, + 17, + 25, + 30, + 41, + 43, + 9, + 11, + 18, + 24, + 31, + 40, + 44, + 53, + 10, + 19, + 23, + 32, + 39, + 45, + 52, + 54, + 20, + 22, + 33, + 38, + 46, + 51, + 55, + 60, + 21, + 34, + 37, + 47, + 50, + 56, + 59, + 61, + 35, + 36, + 48, + 49, + 57, + 58, + 62, + 63 + ]; + var std_dc_luminance_nrcodes = [0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0]; + var std_dc_luminance_values = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; + var std_ac_luminance_nrcodes = [0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 125]; + var std_ac_luminance_values = [ + 1, + 2, + 3, + 0, + 4, + 17, + 5, + 18, + 33, + 49, + 65, + 6, + 19, + 81, + 97, + 7, + 34, + 113, + 20, + 50, + 129, + 145, + 161, + 8, + 35, + 66, + 177, + 193, + 21, + 82, + 209, + 240, + 36, + 51, + 98, + 114, + 130, + 9, + 10, + 22, + 23, + 24, + 25, + 26, + 37, + 38, + 39, + 40, + 41, + 42, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 131, + 132, + 133, + 134, + 135, + 136, + 137, + 138, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 178, + 179, + 180, + 181, + 182, + 183, + 184, + 185, + 186, + 194, + 195, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 210, + 211, + 212, + 213, + 214, + 215, + 216, + 217, + 218, + 225, + 226, + 227, + 228, + 229, + 230, + 231, + 232, + 233, + 234, + 241, + 242, + 243, + 244, + 245, + 246, + 247, + 248, + 249, + 250 + ]; + var std_dc_chrominance_nrcodes = [0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0]; + var std_dc_chrominance_values = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; + var std_ac_chrominance_nrcodes = [0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 119]; + var std_ac_chrominance_values = [ + 0, + 1, + 2, + 3, + 17, + 4, + 5, + 33, + 49, + 6, + 18, + 65, + 81, + 7, + 97, + 113, + 19, + 34, + 50, + 129, + 8, + 20, + 66, + 145, + 161, + 177, + 193, + 9, + 35, + 51, + 82, + 240, + 21, + 98, + 114, + 209, + 10, + 22, + 36, + 52, + 225, + 37, + 241, + 23, + 24, + 25, + 26, + 38, + 39, + 40, + 41, + 42, + 53, + 54, + 55, + 56, + 57, + 58, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 130, + 131, + 132, + 133, + 134, + 135, + 136, + 137, + 138, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 178, + 179, + 180, + 181, + 182, + 183, + 184, + 185, + 186, + 194, + 195, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 210, + 211, + 212, + 213, + 214, + 215, + 216, + 217, + 218, + 226, + 227, + 228, + 229, + 230, + 231, + 232, + 233, + 234, + 242, + 243, + 244, + 245, + 246, + 247, + 248, + 249, + 250 + ]; + function initQuantTables(sf) { + var YQT = [ + 16, + 11, + 10, + 16, + 24, + 40, + 51, + 61, + 12, + 12, + 14, + 19, + 26, + 58, + 60, + 55, + 14, + 13, + 16, + 24, + 40, + 57, + 69, + 56, + 14, + 17, + 22, + 29, + 51, + 87, + 80, + 62, + 18, + 22, + 37, + 56, + 68, + 109, + 103, + 77, + 24, + 35, + 55, + 64, + 81, + 104, + 113, + 92, + 49, + 64, + 78, + 87, + 103, + 121, + 120, + 101, + 72, + 92, + 95, + 98, + 112, + 100, + 103, + 99 + ]; + for (var i = 0; i < 64; i++) { + var t = ffloor((YQT[i] * sf + 50) / 100); + if (t < 1) { + t = 1; + } else if (t > 255) { + t = 255; + } + YTable[ZigZag[i]] = t; + } + var UVQT = [ + 17, + 18, + 24, + 47, + 99, + 99, + 99, + 99, + 18, + 21, + 26, + 66, + 99, + 99, + 99, + 99, + 24, + 26, + 56, + 99, + 99, + 99, + 99, + 99, + 47, + 66, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99 + ]; + for (var j = 0; j < 64; j++) { + var u = ffloor((UVQT[j] * sf + 50) / 100); + if (u < 1) { + u = 1; + } else if (u > 255) { + u = 255; + } + UVTable[ZigZag[j]] = u; + } + var aasf = [ + 1, + 1.387039845, + 1.306562965, + 1.175875602, + 1, + 0.785694958, + 0.5411961, + 0.275899379 + ]; + var k = 0; + for (var row = 0; row < 8; row++) { + for (var col = 0; col < 8; col++) { + fdtbl_Y[k] = 1 / (YTable[ZigZag[k]] * aasf[row] * aasf[col] * 8); + fdtbl_UV[k] = 1 / (UVTable[ZigZag[k]] * aasf[row] * aasf[col] * 8); + k++; + } + } + } + function computeHuffmanTbl(nrcodes, std_table) { + var codevalue = 0; + var pos_in_table = 0; + var HT = new Array(); + for (var k = 1; k <= 16; k++) { + for (var j = 1; j <= nrcodes[k]; j++) { + HT[std_table[pos_in_table]] = []; + HT[std_table[pos_in_table]][0] = codevalue; + HT[std_table[pos_in_table]][1] = k; + pos_in_table++; + codevalue++; + } + codevalue *= 2; + } + return HT; + } + function initHuffmanTbl() { + YDC_HT = computeHuffmanTbl(std_dc_luminance_nrcodes, std_dc_luminance_values); + UVDC_HT = computeHuffmanTbl(std_dc_chrominance_nrcodes, std_dc_chrominance_values); + YAC_HT = computeHuffmanTbl(std_ac_luminance_nrcodes, std_ac_luminance_values); + UVAC_HT = computeHuffmanTbl(std_ac_chrominance_nrcodes, std_ac_chrominance_values); + } + function initCategoryNumber() { + var nrlower = 1; + var nrupper = 2; + for (var cat = 1; cat <= 15; cat++) { + for (var nr = nrlower; nr < nrupper; nr++) { + category[32767 + nr] = cat; + bitcode[32767 + nr] = []; + bitcode[32767 + nr][1] = cat; + bitcode[32767 + nr][0] = nr; + } + for (var nrneg = -(nrupper - 1); nrneg <= -nrlower; nrneg++) { + category[32767 + nrneg] = cat; + bitcode[32767 + nrneg] = []; + bitcode[32767 + nrneg][1] = cat; + bitcode[32767 + nrneg][0] = nrupper - 1 + nrneg; + } + nrlower <<= 1; + nrupper <<= 1; + } + } + function initRGBYUVTable() { + for (var i = 0; i < 256; i++) { + RGB_YUV_TABLE[i] = 19595 * i; + RGB_YUV_TABLE[i + 256 >> 0] = 38470 * i; + RGB_YUV_TABLE[i + 512 >> 0] = 7471 * i + 32768; + RGB_YUV_TABLE[i + 768 >> 0] = -11059 * i; + RGB_YUV_TABLE[i + 1024 >> 0] = -21709 * i; + RGB_YUV_TABLE[i + 1280 >> 0] = 32768 * i + 8421375; + RGB_YUV_TABLE[i + 1536 >> 0] = -27439 * i; + RGB_YUV_TABLE[i + 1792 >> 0] = -5329 * i; + } + } + function writeBits(bs) { + var value = bs[0]; + var posval = bs[1] - 1; + while (posval >= 0) { + if (value & 1 << posval) { + bytenew |= 1 << bytepos; + } + posval--; + bytepos--; + if (bytepos < 0) { + if (bytenew == 255) { + writeByte(255); + writeByte(0); + } else { + writeByte(bytenew); + } + bytepos = 7; + bytenew = 0; + } + } + } + function writeByte(value) { + byteout.push(value); + } + function writeWord(value) { + writeByte(value >> 8 & 255); + writeByte(value & 255); + } + function fDCTQuant(data, fdtbl) { + var d0, d1, d2, d3, d4, d5, d6, d7; + var dataOff = 0; + var i; + var I8 = 8; + var I64 = 64; + for (i = 0; i < I8; ++i) { + d0 = data[dataOff]; + d1 = data[dataOff + 1]; + d2 = data[dataOff + 2]; + d3 = data[dataOff + 3]; + d4 = data[dataOff + 4]; + d5 = data[dataOff + 5]; + d6 = data[dataOff + 6]; + d7 = data[dataOff + 7]; + var tmp0 = d0 + d7; + var tmp7 = d0 - d7; + var tmp1 = d1 + d6; + var tmp6 = d1 - d6; + var tmp2 = d2 + d5; + var tmp5 = d2 - d5; + var tmp3 = d3 + d4; + var tmp4 = d3 - d4; + var tmp10 = tmp0 + tmp3; + var tmp13 = tmp0 - tmp3; + var tmp11 = tmp1 + tmp2; + var tmp12 = tmp1 - tmp2; + data[dataOff] = tmp10 + tmp11; + data[dataOff + 4] = tmp10 - tmp11; + var z1 = (tmp12 + tmp13) * 0.707106781; + data[dataOff + 2] = tmp13 + z1; + data[dataOff + 6] = tmp13 - z1; + tmp10 = tmp4 + tmp5; + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + var z5 = (tmp10 - tmp12) * 0.382683433; + var z2 = 0.5411961 * tmp10 + z5; + var z4 = 1.306562965 * tmp12 + z5; + var z3 = tmp11 * 0.707106781; + var z11 = tmp7 + z3; + var z13 = tmp7 - z3; + data[dataOff + 5] = z13 + z2; + data[dataOff + 3] = z13 - z2; + data[dataOff + 1] = z11 + z4; + data[dataOff + 7] = z11 - z4; + dataOff += 8; + } + dataOff = 0; + for (i = 0; i < I8; ++i) { + d0 = data[dataOff]; + d1 = data[dataOff + 8]; + d2 = data[dataOff + 16]; + d3 = data[dataOff + 24]; + d4 = data[dataOff + 32]; + d5 = data[dataOff + 40]; + d6 = data[dataOff + 48]; + d7 = data[dataOff + 56]; + var tmp0p2 = d0 + d7; + var tmp7p2 = d0 - d7; + var tmp1p2 = d1 + d6; + var tmp6p2 = d1 - d6; + var tmp2p2 = d2 + d5; + var tmp5p2 = d2 - d5; + var tmp3p2 = d3 + d4; + var tmp4p2 = d3 - d4; + var tmp10p2 = tmp0p2 + tmp3p2; + var tmp13p2 = tmp0p2 - tmp3p2; + var tmp11p2 = tmp1p2 + tmp2p2; + var tmp12p2 = tmp1p2 - tmp2p2; + data[dataOff] = tmp10p2 + tmp11p2; + data[dataOff + 32] = tmp10p2 - tmp11p2; + var z1p2 = (tmp12p2 + tmp13p2) * 0.707106781; + data[dataOff + 16] = tmp13p2 + z1p2; + data[dataOff + 48] = tmp13p2 - z1p2; + tmp10p2 = tmp4p2 + tmp5p2; + tmp11p2 = tmp5p2 + tmp6p2; + tmp12p2 = tmp6p2 + tmp7p2; + var z5p2 = (tmp10p2 - tmp12p2) * 0.382683433; + var z2p2 = 0.5411961 * tmp10p2 + z5p2; + var z4p2 = 1.306562965 * tmp12p2 + z5p2; + var z3p2 = tmp11p2 * 0.707106781; + var z11p2 = tmp7p2 + z3p2; + var z13p2 = tmp7p2 - z3p2; + data[dataOff + 40] = z13p2 + z2p2; + data[dataOff + 24] = z13p2 - z2p2; + data[dataOff + 8] = z11p2 + z4p2; + data[dataOff + 56] = z11p2 - z4p2; + dataOff++; + } + var fDCTQuant2; + for (i = 0; i < I64; ++i) { + fDCTQuant2 = data[i] * fdtbl[i]; + outputfDCTQuant[i] = fDCTQuant2 > 0 ? fDCTQuant2 + 0.5 | 0 : fDCTQuant2 - 0.5 | 0; + } + return outputfDCTQuant; + } + function writeAPP0() { + writeWord(65504); + writeWord(16); + writeByte(74); + writeByte(70); + writeByte(73); + writeByte(70); + writeByte(0); + writeByte(1); + writeByte(1); + writeByte(0); + writeWord(1); + writeWord(1); + writeByte(0); + writeByte(0); + } + function writeAPP1(exifBuffer) { + if (!exifBuffer) + return; + writeWord(65505); + if (exifBuffer[0] === 69 && exifBuffer[1] === 120 && exifBuffer[2] === 105 && exifBuffer[3] === 102) { + writeWord(exifBuffer.length + 2); + } else { + writeWord(exifBuffer.length + 5 + 2); + writeByte(69); + writeByte(120); + writeByte(105); + writeByte(102); + writeByte(0); + } + for (var i = 0; i < exifBuffer.length; i++) { + writeByte(exifBuffer[i]); + } + } + function writeSOF0(width, height) { + writeWord(65472); + writeWord(17); + writeByte(8); + writeWord(height); + writeWord(width); + writeByte(3); + writeByte(1); + writeByte(17); + writeByte(0); + writeByte(2); + writeByte(17); + writeByte(1); + writeByte(3); + writeByte(17); + writeByte(1); + } + function writeDQT() { + writeWord(65499); + writeWord(132); + writeByte(0); + for (var i = 0; i < 64; i++) { + writeByte(YTable[i]); + } + writeByte(1); + for (var j = 0; j < 64; j++) { + writeByte(UVTable[j]); + } + } + function writeDHT() { + writeWord(65476); + writeWord(418); + writeByte(0); + for (var i = 0; i < 16; i++) { + writeByte(std_dc_luminance_nrcodes[i + 1]); + } + for (var j = 0; j <= 11; j++) { + writeByte(std_dc_luminance_values[j]); + } + writeByte(16); + for (var k = 0; k < 16; k++) { + writeByte(std_ac_luminance_nrcodes[k + 1]); + } + for (var l = 0; l <= 161; l++) { + writeByte(std_ac_luminance_values[l]); + } + writeByte(1); + for (var m = 0; m < 16; m++) { + writeByte(std_dc_chrominance_nrcodes[m + 1]); + } + for (var n = 0; n <= 11; n++) { + writeByte(std_dc_chrominance_values[n]); + } + writeByte(17); + for (var o = 0; o < 16; o++) { + writeByte(std_ac_chrominance_nrcodes[o + 1]); + } + for (var p = 0; p <= 161; p++) { + writeByte(std_ac_chrominance_values[p]); + } + } + function writeSOS() { + writeWord(65498); + writeWord(12); + writeByte(3); + writeByte(1); + writeByte(0); + writeByte(2); + writeByte(17); + writeByte(3); + writeByte(17); + writeByte(0); + writeByte(63); + writeByte(0); + } + function processDU(CDU, fdtbl, DC, HTDC, HTAC) { + var EOB = HTAC[0]; + var M16zeroes = HTAC[240]; + var pos; + var I16 = 16; + var I63 = 63; + var I64 = 64; + var DU_DCT = fDCTQuant(CDU, fdtbl); + for (var j = 0; j < I64; ++j) { + DU[ZigZag[j]] = DU_DCT[j]; + } + var Diff = DU[0] - DC; + DC = DU[0]; + if (Diff == 0) { + writeBits(HTDC[0]); + } else { + pos = 32767 + Diff; + writeBits(HTDC[category[pos]]); + writeBits(bitcode[pos]); + } + var end0pos = 63; + for (; end0pos > 0 && DU[end0pos] == 0; end0pos--) { + } + ; + if (end0pos == 0) { + writeBits(EOB); + return DC; + } + var i = 1; + var lng; + while (i <= end0pos) { + var startpos = i; + for (; DU[i] == 0 && i <= end0pos; ++i) { + } + var nrzeroes = i - startpos; + if (nrzeroes >= I16) { + lng = nrzeroes >> 4; + for (var nrmarker = 1; nrmarker <= lng; ++nrmarker) + writeBits(M16zeroes); + nrzeroes = nrzeroes & 15; + } + pos = 32767 + DU[i]; + writeBits(HTAC[(nrzeroes << 4) + category[pos]]); + writeBits(bitcode[pos]); + i++; + } + if (end0pos != I63) { + writeBits(EOB); + } + return DC; + } + function initCharLookupTable() { + var sfcc = String.fromCharCode; + for (var i = 0; i < 256; i++) { + clt[i] = sfcc(i); + } + } + this.encode = function(image, quality2) { + var time_start = new Date().getTime(); + if (quality2) + setQuality(quality2); + byteout = new Array(); + bytenew = 0; + bytepos = 7; + writeWord(65496); + writeAPP0(); + writeAPP1(image.exifBuffer); + writeDQT(); + writeSOF0(image.width, image.height); + writeDHT(); + writeSOS(); + var DCY = 0; + var DCU = 0; + var DCV = 0; + bytenew = 0; + bytepos = 7; + this.encode.displayName = "_encode_"; + var imageData = image.data; + var width = image.width; + var height = image.height; + var quadWidth = width * 4; + var tripleWidth = width * 3; + var x, y = 0; + var r, g, b; + var start, p, col, row, pos; + while (y < height) { + x = 0; + while (x < quadWidth) { + start = quadWidth * y + x; + p = start; + col = -1; + row = 0; + for (pos = 0; pos < 64; pos++) { + row = pos >> 3; + col = (pos & 7) * 4; + p = start + row * quadWidth + col; + if (y + row >= height) { + p -= quadWidth * (y + 1 + row - height); + } + if (x + col >= quadWidth) { + p -= x + col - quadWidth + 4; + } + r = imageData[p++]; + g = imageData[p++]; + b = imageData[p++]; + YDU[pos] = (RGB_YUV_TABLE[r] + RGB_YUV_TABLE[g + 256 >> 0] + RGB_YUV_TABLE[b + 512 >> 0] >> 16) - 128; + UDU[pos] = (RGB_YUV_TABLE[r + 768 >> 0] + RGB_YUV_TABLE[g + 1024 >> 0] + RGB_YUV_TABLE[b + 1280 >> 0] >> 16) - 128; + VDU[pos] = (RGB_YUV_TABLE[r + 1280 >> 0] + RGB_YUV_TABLE[g + 1536 >> 0] + RGB_YUV_TABLE[b + 1792 >> 0] >> 16) - 128; + } + DCY = processDU(YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT); + DCU = processDU(UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT); + DCV = processDU(VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT); + x += 32; + } + y += 8; + } + if (bytepos >= 0) { + var fillbits = []; + fillbits[1] = bytepos + 1; + fillbits[0] = (1 << bytepos + 1) - 1; + writeBits(fillbits); + } + writeWord(65497); + if (typeof module === "undefined") + return new Uint8Array(byteout); + return Buffer2.from(byteout); + var jpegDataUri = "data:image/jpeg;base64," + btoa(byteout.join("")); + byteout = []; + var duration = new Date().getTime() - time_start; + return jpegDataUri; + }; + function setQuality(quality2) { + if (quality2 <= 0) { + quality2 = 1; + } + if (quality2 > 100) { + quality2 = 100; + } + if (currentQuality == quality2) + return; + var sf = 0; + if (quality2 < 50) { + sf = Math.floor(5e3 / quality2); + } else { + sf = Math.floor(200 - quality2 * 2); + } + initQuantTables(sf); + currentQuality = quality2; + } + function init2() { + var time_start = new Date().getTime(); + if (!quality) + quality = 50; + initCharLookupTable(); + initHuffmanTbl(); + initCategoryNumber(); + initRGBYUVTable(); + setQuality(quality); + var duration = new Date().getTime() - time_start; + } + init2(); + } + if (typeof module !== "undefined") { + module.exports = encode; + } else if (typeof window !== "undefined") { + window["jpeg-js"] = window["jpeg-js"] || {}; + window["jpeg-js"].encode = encode; + } + function encode(imgData, qu) { + if (typeof qu === "undefined") + qu = 50; + var encoder = new JPEGEncoder(qu); + var data = encoder.encode(imgData, qu); + return { + data, + width: imgData.width, + height: imgData.height + }; + } + } + }); + + // node_modules/jpeg-js/lib/decoder.js + var require_decoder = __commonJS({ + "node_modules/jpeg-js/lib/decoder.js"(exports, module) { + init_esbuild_inject(); + var JpegImage = function jpegImage() { + "use strict"; + var dctZigZag = new Int32Array([ + 0, + 1, + 8, + 16, + 9, + 2, + 3, + 10, + 17, + 24, + 32, + 25, + 18, + 11, + 4, + 5, + 12, + 19, + 26, + 33, + 40, + 48, + 41, + 34, + 27, + 20, + 13, + 6, + 7, + 14, + 21, + 28, + 35, + 42, + 49, + 56, + 57, + 50, + 43, + 36, + 29, + 22, + 15, + 23, + 30, + 37, + 44, + 51, + 58, + 59, + 52, + 45, + 38, + 31, + 39, + 46, + 53, + 60, + 61, + 54, + 47, + 55, + 62, + 63 + ]); + var dctCos1 = 4017; + var dctSin1 = 799; + var dctCos3 = 3406; + var dctSin3 = 2276; + var dctCos6 = 1567; + var dctSin6 = 3784; + var dctSqrt2 = 5793; + var dctSqrt1d2 = 2896; + function constructor() { + } + function buildHuffmanTable(codeLengths, values) { + var k = 0, code = [], i, j, length = 16; + while (length > 0 && !codeLengths[length - 1]) + length--; + code.push({ children: [], index: 0 }); + var p = code[0], q; + for (i = 0; i < length; i++) { + for (j = 0; j < codeLengths[i]; j++) { + p = code.pop(); + p.children[p.index] = values[k]; + while (p.index > 0) { + if (code.length === 0) + throw new Error("Could not recreate Huffman Table"); + p = code.pop(); + } + p.index++; + code.push(p); + while (code.length <= i) { + code.push(q = { children: [], index: 0 }); + p.children[p.index] = q.children; + p = q; + } + k++; + } + if (i + 1 < length) { + code.push(q = { children: [], index: 0 }); + p.children[p.index] = q.children; + p = q; + } + } + return code[0].children; + } + function decodeScan(data, offset, frame, components, resetInterval, spectralStart, spectralEnd, successivePrev, successive, opts) { + var precision = frame.precision; + var samplesPerLine = frame.samplesPerLine; + var scanLines = frame.scanLines; + var mcusPerLine = frame.mcusPerLine; + var progressive = frame.progressive; + var maxH = frame.maxH, maxV = frame.maxV; + var startOffset = offset, bitsData = 0, bitsCount = 0; + function readBit() { + if (bitsCount > 0) { + bitsCount--; + return bitsData >> bitsCount & 1; + } + bitsData = data[offset++]; + if (bitsData == 255) { + var nextByte = data[offset++]; + if (nextByte) { + throw new Error("unexpected marker: " + (bitsData << 8 | nextByte).toString(16)); + } + } + bitsCount = 7; + return bitsData >>> 7; + } + function decodeHuffman(tree) { + var node = tree, bit; + while ((bit = readBit()) !== null) { + node = node[bit]; + if (typeof node === "number") + return node; + if (typeof node !== "object") + throw new Error("invalid huffman sequence"); + } + return null; + } + function receive(length) { + var n2 = 0; + while (length > 0) { + var bit = readBit(); + if (bit === null) + return; + n2 = n2 << 1 | bit; + length--; + } + return n2; + } + function receiveAndExtend(length) { + var n2 = receive(length); + if (n2 >= 1 << length - 1) + return n2; + return n2 + (-1 << length) + 1; + } + function decodeBaseline(component2, zz) { + var t = decodeHuffman(component2.huffmanTableDC); + var diff = t === 0 ? 0 : receiveAndExtend(t); + zz[0] = component2.pred += diff; + var k2 = 1; + while (k2 < 64) { + var rs = decodeHuffman(component2.huffmanTableAC); + var s = rs & 15, r = rs >> 4; + if (s === 0) { + if (r < 15) + break; + k2 += 16; + continue; + } + k2 += r; + var z = dctZigZag[k2]; + zz[z] = receiveAndExtend(s); + k2++; + } + } + function decodeDCFirst(component2, zz) { + var t = decodeHuffman(component2.huffmanTableDC); + var diff = t === 0 ? 0 : receiveAndExtend(t) << successive; + zz[0] = component2.pred += diff; + } + function decodeDCSuccessive(component2, zz) { + zz[0] |= readBit() << successive; + } + var eobrun = 0; + function decodeACFirst(component2, zz) { + if (eobrun > 0) { + eobrun--; + return; + } + var k2 = spectralStart, e = spectralEnd; + while (k2 <= e) { + var rs = decodeHuffman(component2.huffmanTableAC); + var s = rs & 15, r = rs >> 4; + if (s === 0) { + if (r < 15) { + eobrun = receive(r) + (1 << r) - 1; + break; + } + k2 += 16; + continue; + } + k2 += r; + var z = dctZigZag[k2]; + zz[z] = receiveAndExtend(s) * (1 << successive); + k2++; + } + } + var successiveACState = 0, successiveACNextValue; + function decodeACSuccessive(component2, zz) { + var k2 = spectralStart, e = spectralEnd, r = 0; + while (k2 <= e) { + var z = dctZigZag[k2]; + var direction = zz[z] < 0 ? -1 : 1; + switch (successiveACState) { + case 0: + var rs = decodeHuffman(component2.huffmanTableAC); + var s = rs & 15, r = rs >> 4; + if (s === 0) { + if (r < 15) { + eobrun = receive(r) + (1 << r); + successiveACState = 4; + } else { + r = 16; + successiveACState = 1; + } + } else { + if (s !== 1) + throw new Error("invalid ACn encoding"); + successiveACNextValue = receiveAndExtend(s); + successiveACState = r ? 2 : 3; + } + continue; + case 1: + case 2: + if (zz[z]) + zz[z] += (readBit() << successive) * direction; + else { + r--; + if (r === 0) + successiveACState = successiveACState == 2 ? 3 : 0; + } + break; + case 3: + if (zz[z]) + zz[z] += (readBit() << successive) * direction; + else { + zz[z] = successiveACNextValue << successive; + successiveACState = 0; + } + break; + case 4: + if (zz[z]) + zz[z] += (readBit() << successive) * direction; + break; + } + k2++; + } + if (successiveACState === 4) { + eobrun--; + if (eobrun === 0) + successiveACState = 0; + } + } + function decodeMcu(component2, decode2, mcu2, row, col) { + var mcuRow = mcu2 / mcusPerLine | 0; + var mcuCol = mcu2 % mcusPerLine; + var blockRow = mcuRow * component2.v + row; + var blockCol = mcuCol * component2.h + col; + if (component2.blocks[blockRow] === void 0 && opts.tolerantDecoding) + return; + decode2(component2, component2.blocks[blockRow][blockCol]); + } + function decodeBlock(component2, decode2, mcu2) { + var blockRow = mcu2 / component2.blocksPerLine | 0; + var blockCol = mcu2 % component2.blocksPerLine; + if (component2.blocks[blockRow] === void 0 && opts.tolerantDecoding) + return; + decode2(component2, component2.blocks[blockRow][blockCol]); + } + var componentsLength = components.length; + var component, i, j, k, n; + var decodeFn; + if (progressive) { + if (spectralStart === 0) + decodeFn = successivePrev === 0 ? decodeDCFirst : decodeDCSuccessive; + else + decodeFn = successivePrev === 0 ? decodeACFirst : decodeACSuccessive; + } else { + decodeFn = decodeBaseline; + } + var mcu = 0, marker; + var mcuExpected; + if (componentsLength == 1) { + mcuExpected = components[0].blocksPerLine * components[0].blocksPerColumn; + } else { + mcuExpected = mcusPerLine * frame.mcusPerColumn; + } + if (!resetInterval) + resetInterval = mcuExpected; + var h, v; + while (mcu < mcuExpected) { + for (i = 0; i < componentsLength; i++) + components[i].pred = 0; + eobrun = 0; + if (componentsLength == 1) { + component = components[0]; + for (n = 0; n < resetInterval; n++) { + decodeBlock(component, decodeFn, mcu); + mcu++; + } + } else { + for (n = 0; n < resetInterval; n++) { + for (i = 0; i < componentsLength; i++) { + component = components[i]; + h = component.h; + v = component.v; + for (j = 0; j < v; j++) { + for (k = 0; k < h; k++) { + decodeMcu(component, decodeFn, mcu, j, k); + } + } + } + mcu++; + if (mcu === mcuExpected) + break; + } + } + if (mcu === mcuExpected) { + do { + if (data[offset] === 255) { + if (data[offset + 1] !== 0) { + break; + } + } + offset += 1; + } while (offset < data.length - 2); + } + bitsCount = 0; + marker = data[offset] << 8 | data[offset + 1]; + if (marker < 65280) { + throw new Error("marker was not found"); + } + if (marker >= 65488 && marker <= 65495) { + offset += 2; + } else + break; + } + return offset - startOffset; + } + function buildComponentData(frame, component) { + var lines = []; + var blocksPerLine = component.blocksPerLine; + var blocksPerColumn = component.blocksPerColumn; + var samplesPerLine = blocksPerLine << 3; + var R = new Int32Array(64), r = new Uint8Array(64); + function quantizeAndInverse(zz, dataOut, dataIn) { + var qt = component.quantizationTable; + var v0, v1, v2, v3, v4, v5, v6, v7, t; + var p = dataIn; + var i2; + for (i2 = 0; i2 < 64; i2++) + p[i2] = zz[i2] * qt[i2]; + for (i2 = 0; i2 < 8; ++i2) { + var row = 8 * i2; + if (p[1 + row] == 0 && p[2 + row] == 0 && p[3 + row] == 0 && p[4 + row] == 0 && p[5 + row] == 0 && p[6 + row] == 0 && p[7 + row] == 0) { + t = dctSqrt2 * p[0 + row] + 512 >> 10; + p[0 + row] = t; + p[1 + row] = t; + p[2 + row] = t; + p[3 + row] = t; + p[4 + row] = t; + p[5 + row] = t; + p[6 + row] = t; + p[7 + row] = t; + continue; + } + v0 = dctSqrt2 * p[0 + row] + 128 >> 8; + v1 = dctSqrt2 * p[4 + row] + 128 >> 8; + v2 = p[2 + row]; + v3 = p[6 + row]; + v4 = dctSqrt1d2 * (p[1 + row] - p[7 + row]) + 128 >> 8; + v7 = dctSqrt1d2 * (p[1 + row] + p[7 + row]) + 128 >> 8; + v5 = p[3 + row] << 4; + v6 = p[5 + row] << 4; + t = v0 - v1 + 1 >> 1; + v0 = v0 + v1 + 1 >> 1; + v1 = t; + t = v2 * dctSin6 + v3 * dctCos6 + 128 >> 8; + v2 = v2 * dctCos6 - v3 * dctSin6 + 128 >> 8; + v3 = t; + t = v4 - v6 + 1 >> 1; + v4 = v4 + v6 + 1 >> 1; + v6 = t; + t = v7 + v5 + 1 >> 1; + v5 = v7 - v5 + 1 >> 1; + v7 = t; + t = v0 - v3 + 1 >> 1; + v0 = v0 + v3 + 1 >> 1; + v3 = t; + t = v1 - v2 + 1 >> 1; + v1 = v1 + v2 + 1 >> 1; + v2 = t; + t = v4 * dctSin3 + v7 * dctCos3 + 2048 >> 12; + v4 = v4 * dctCos3 - v7 * dctSin3 + 2048 >> 12; + v7 = t; + t = v5 * dctSin1 + v6 * dctCos1 + 2048 >> 12; + v5 = v5 * dctCos1 - v6 * dctSin1 + 2048 >> 12; + v6 = t; + p[0 + row] = v0 + v7; + p[7 + row] = v0 - v7; + p[1 + row] = v1 + v6; + p[6 + row] = v1 - v6; + p[2 + row] = v2 + v5; + p[5 + row] = v2 - v5; + p[3 + row] = v3 + v4; + p[4 + row] = v3 - v4; + } + for (i2 = 0; i2 < 8; ++i2) { + var col = i2; + if (p[1 * 8 + col] == 0 && p[2 * 8 + col] == 0 && p[3 * 8 + col] == 0 && p[4 * 8 + col] == 0 && p[5 * 8 + col] == 0 && p[6 * 8 + col] == 0 && p[7 * 8 + col] == 0) { + t = dctSqrt2 * dataIn[i2 + 0] + 8192 >> 14; + p[0 * 8 + col] = t; + p[1 * 8 + col] = t; + p[2 * 8 + col] = t; + p[3 * 8 + col] = t; + p[4 * 8 + col] = t; + p[5 * 8 + col] = t; + p[6 * 8 + col] = t; + p[7 * 8 + col] = t; + continue; + } + v0 = dctSqrt2 * p[0 * 8 + col] + 2048 >> 12; + v1 = dctSqrt2 * p[4 * 8 + col] + 2048 >> 12; + v2 = p[2 * 8 + col]; + v3 = p[6 * 8 + col]; + v4 = dctSqrt1d2 * (p[1 * 8 + col] - p[7 * 8 + col]) + 2048 >> 12; + v7 = dctSqrt1d2 * (p[1 * 8 + col] + p[7 * 8 + col]) + 2048 >> 12; + v5 = p[3 * 8 + col]; + v6 = p[5 * 8 + col]; + t = v0 - v1 + 1 >> 1; + v0 = v0 + v1 + 1 >> 1; + v1 = t; + t = v2 * dctSin6 + v3 * dctCos6 + 2048 >> 12; + v2 = v2 * dctCos6 - v3 * dctSin6 + 2048 >> 12; + v3 = t; + t = v4 - v6 + 1 >> 1; + v4 = v4 + v6 + 1 >> 1; + v6 = t; + t = v7 + v5 + 1 >> 1; + v5 = v7 - v5 + 1 >> 1; + v7 = t; + t = v0 - v3 + 1 >> 1; + v0 = v0 + v3 + 1 >> 1; + v3 = t; + t = v1 - v2 + 1 >> 1; + v1 = v1 + v2 + 1 >> 1; + v2 = t; + t = v4 * dctSin3 + v7 * dctCos3 + 2048 >> 12; + v4 = v4 * dctCos3 - v7 * dctSin3 + 2048 >> 12; + v7 = t; + t = v5 * dctSin1 + v6 * dctCos1 + 2048 >> 12; + v5 = v5 * dctCos1 - v6 * dctSin1 + 2048 >> 12; + v6 = t; + p[0 * 8 + col] = v0 + v7; + p[7 * 8 + col] = v0 - v7; + p[1 * 8 + col] = v1 + v6; + p[6 * 8 + col] = v1 - v6; + p[2 * 8 + col] = v2 + v5; + p[5 * 8 + col] = v2 - v5; + p[3 * 8 + col] = v3 + v4; + p[4 * 8 + col] = v3 - v4; + } + for (i2 = 0; i2 < 64; ++i2) { + var sample2 = 128 + (p[i2] + 8 >> 4); + dataOut[i2] = sample2 < 0 ? 0 : sample2 > 255 ? 255 : sample2; + } + } + requestMemoryAllocation(samplesPerLine * blocksPerColumn * 8); + var i, j; + for (var blockRow = 0; blockRow < blocksPerColumn; blockRow++) { + var scanLine = blockRow << 3; + for (i = 0; i < 8; i++) + lines.push(new Uint8Array(samplesPerLine)); + for (var blockCol = 0; blockCol < blocksPerLine; blockCol++) { + quantizeAndInverse(component.blocks[blockRow][blockCol], r, R); + var offset = 0, sample = blockCol << 3; + for (j = 0; j < 8; j++) { + var line = lines[scanLine + j]; + for (i = 0; i < 8; i++) + line[sample + i] = r[offset++]; + } + } + } + return lines; + } + function clampTo8bit(a) { + return a < 0 ? 0 : a > 255 ? 255 : a; + } + constructor.prototype = { + load: function load(path) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", path, true); + xhr.responseType = "arraybuffer"; + xhr.onload = function() { + var data = new Uint8Array(xhr.response || xhr.mozResponseArrayBuffer); + this.parse(data); + if (this.onload) + this.onload(); + }.bind(this); + xhr.send(null); + }, + parse: function parse(data) { + var maxResolutionInPixels = this.opts.maxResolutionInMP * 1e3 * 1e3; + var offset = 0, length = data.length; + function readUint16() { + var value = data[offset] << 8 | data[offset + 1]; + offset += 2; + return value; + } + function readDataBlock() { + var length2 = readUint16(); + var array = data.subarray(offset, offset + length2 - 2); + offset += array.length; + return array; + } + function prepareComponents(frame2) { + var maxH2 = 0, maxV2 = 0; + var component2, componentId2; + for (componentId2 in frame2.components) { + if (frame2.components.hasOwnProperty(componentId2)) { + component2 = frame2.components[componentId2]; + if (maxH2 < component2.h) + maxH2 = component2.h; + if (maxV2 < component2.v) + maxV2 = component2.v; + } + } + var mcusPerLine = Math.ceil(frame2.samplesPerLine / 8 / maxH2); + var mcusPerColumn = Math.ceil(frame2.scanLines / 8 / maxV2); + for (componentId2 in frame2.components) { + if (frame2.components.hasOwnProperty(componentId2)) { + component2 = frame2.components[componentId2]; + var blocksPerLine = Math.ceil(Math.ceil(frame2.samplesPerLine / 8) * component2.h / maxH2); + var blocksPerColumn = Math.ceil(Math.ceil(frame2.scanLines / 8) * component2.v / maxV2); + var blocksPerLineForMcu = mcusPerLine * component2.h; + var blocksPerColumnForMcu = mcusPerColumn * component2.v; + var blocksToAllocate = blocksPerColumnForMcu * blocksPerLineForMcu; + var blocks = []; + requestMemoryAllocation(blocksToAllocate * 256); + for (var i2 = 0; i2 < blocksPerColumnForMcu; i2++) { + var row = []; + for (var j2 = 0; j2 < blocksPerLineForMcu; j2++) + row.push(new Int32Array(64)); + blocks.push(row); + } + component2.blocksPerLine = blocksPerLine; + component2.blocksPerColumn = blocksPerColumn; + component2.blocks = blocks; + } + } + frame2.maxH = maxH2; + frame2.maxV = maxV2; + frame2.mcusPerLine = mcusPerLine; + frame2.mcusPerColumn = mcusPerColumn; + } + var jfif = null; + var adobe = null; + var pixels = null; + var frame, resetInterval; + var quantizationTables = [], frames = []; + var huffmanTablesAC = [], huffmanTablesDC = []; + var fileMarker = readUint16(); + var malformedDataOffset = -1; + this.comments = []; + if (fileMarker != 65496) { + throw new Error("SOI not found"); + } + fileMarker = readUint16(); + while (fileMarker != 65497) { + var i, j, l; + switch (fileMarker) { + case 65280: + break; + case 65504: + case 65505: + case 65506: + case 65507: + case 65508: + case 65509: + case 65510: + case 65511: + case 65512: + case 65513: + case 65514: + case 65515: + case 65516: + case 65517: + case 65518: + case 65519: + case 65534: + var appData = readDataBlock(); + if (fileMarker === 65534) { + var comment = String.fromCharCode.apply(null, appData); + this.comments.push(comment); + } + if (fileMarker === 65504) { + if (appData[0] === 74 && appData[1] === 70 && appData[2] === 73 && appData[3] === 70 && appData[4] === 0) { + jfif = { + version: { major: appData[5], minor: appData[6] }, + densityUnits: appData[7], + xDensity: appData[8] << 8 | appData[9], + yDensity: appData[10] << 8 | appData[11], + thumbWidth: appData[12], + thumbHeight: appData[13], + thumbData: appData.subarray(14, 14 + 3 * appData[12] * appData[13]) + }; + } + } + if (fileMarker === 65505) { + if (appData[0] === 69 && appData[1] === 120 && appData[2] === 105 && appData[3] === 102 && appData[4] === 0) { + this.exifBuffer = appData.subarray(5, appData.length); + } + } + if (fileMarker === 65518) { + if (appData[0] === 65 && appData[1] === 100 && appData[2] === 111 && appData[3] === 98 && appData[4] === 101 && appData[5] === 0) { + adobe = { + version: appData[6], + flags0: appData[7] << 8 | appData[8], + flags1: appData[9] << 8 | appData[10], + transformCode: appData[11] + }; + } + } + break; + case 65499: + var quantizationTablesLength = readUint16(); + var quantizationTablesEnd = quantizationTablesLength + offset - 2; + while (offset < quantizationTablesEnd) { + var quantizationTableSpec = data[offset++]; + requestMemoryAllocation(64 * 4); + var tableData = new Int32Array(64); + if (quantizationTableSpec >> 4 === 0) { + for (j = 0; j < 64; j++) { + var z = dctZigZag[j]; + tableData[z] = data[offset++]; + } + } else if (quantizationTableSpec >> 4 === 1) { + for (j = 0; j < 64; j++) { + var z = dctZigZag[j]; + tableData[z] = readUint16(); + } + } else + throw new Error("DQT: invalid table spec"); + quantizationTables[quantizationTableSpec & 15] = tableData; + } + break; + case 65472: + case 65473: + case 65474: + readUint16(); + frame = {}; + frame.extended = fileMarker === 65473; + frame.progressive = fileMarker === 65474; + frame.precision = data[offset++]; + frame.scanLines = readUint16(); + frame.samplesPerLine = readUint16(); + frame.components = {}; + frame.componentsOrder = []; + var pixelsInFrame = frame.scanLines * frame.samplesPerLine; + if (pixelsInFrame > maxResolutionInPixels) { + var exceededAmount = Math.ceil((pixelsInFrame - maxResolutionInPixels) / 1e6); + throw new Error(`maxResolutionInMP limit exceeded by ${exceededAmount}MP`); + } + var componentsCount = data[offset++], componentId; + var maxH = 0, maxV = 0; + for (i = 0; i < componentsCount; i++) { + componentId = data[offset]; + var h = data[offset + 1] >> 4; + var v = data[offset + 1] & 15; + var qId = data[offset + 2]; + frame.componentsOrder.push(componentId); + frame.components[componentId] = { + h, + v, + quantizationIdx: qId + }; + offset += 3; + } + prepareComponents(frame); + frames.push(frame); + break; + case 65476: + var huffmanLength = readUint16(); + for (i = 2; i < huffmanLength; ) { + var huffmanTableSpec = data[offset++]; + var codeLengths = new Uint8Array(16); + var codeLengthSum = 0; + for (j = 0; j < 16; j++, offset++) { + codeLengthSum += codeLengths[j] = data[offset]; + } + requestMemoryAllocation(16 + codeLengthSum); + var huffmanValues = new Uint8Array(codeLengthSum); + for (j = 0; j < codeLengthSum; j++, offset++) + huffmanValues[j] = data[offset]; + i += 17 + codeLengthSum; + (huffmanTableSpec >> 4 === 0 ? huffmanTablesDC : huffmanTablesAC)[huffmanTableSpec & 15] = buildHuffmanTable(codeLengths, huffmanValues); + } + break; + case 65501: + readUint16(); + resetInterval = readUint16(); + break; + case 65500: + readUint16(); + readUint16(); + break; + case 65498: + var scanLength = readUint16(); + var selectorsCount = data[offset++]; + var components = [], component; + for (i = 0; i < selectorsCount; i++) { + component = frame.components[data[offset++]]; + var tableSpec = data[offset++]; + component.huffmanTableDC = huffmanTablesDC[tableSpec >> 4]; + component.huffmanTableAC = huffmanTablesAC[tableSpec & 15]; + components.push(component); + } + var spectralStart = data[offset++]; + var spectralEnd = data[offset++]; + var successiveApproximation = data[offset++]; + var processed = decodeScan(data, offset, frame, components, resetInterval, spectralStart, spectralEnd, successiveApproximation >> 4, successiveApproximation & 15, this.opts); + offset += processed; + break; + case 65535: + if (data[offset] !== 255) { + offset--; + } + break; + default: + if (data[offset - 3] == 255 && data[offset - 2] >= 192 && data[offset - 2] <= 254) { + offset -= 3; + break; + } else if (fileMarker === 224 || fileMarker == 225) { + if (malformedDataOffset !== -1) { + throw new Error(`first unknown JPEG marker at offset ${malformedDataOffset.toString(16)}, second unknown JPEG marker ${fileMarker.toString(16)} at offset ${(offset - 1).toString(16)}`); + } + malformedDataOffset = offset - 1; + const nextOffset = readUint16(); + if (data[offset + nextOffset - 2] === 255) { + offset += nextOffset - 2; + break; + } + } + throw new Error("unknown JPEG marker " + fileMarker.toString(16)); + } + fileMarker = readUint16(); + } + if (frames.length != 1) + throw new Error("only single frame JPEGs supported"); + for (var i = 0; i < frames.length; i++) { + var cp = frames[i].components; + for (var j in cp) { + cp[j].quantizationTable = quantizationTables[cp[j].quantizationIdx]; + delete cp[j].quantizationIdx; + } + } + this.width = frame.samplesPerLine; + this.height = frame.scanLines; + this.jfif = jfif; + this.adobe = adobe; + this.components = []; + for (var i = 0; i < frame.componentsOrder.length; i++) { + var component = frame.components[frame.componentsOrder[i]]; + this.components.push({ + lines: buildComponentData(frame, component), + scaleX: component.h / frame.maxH, + scaleY: component.v / frame.maxV + }); + } + }, + getData: function getData(width, height) { + var scaleX = this.width / width, scaleY = this.height / height; + var component1, component2, component3, component4; + var component1Line, component2Line, component3Line, component4Line; + var x, y; + var offset = 0; + var Y, Cb, Cr, K, C, M, Ye, R, G, B; + var colorTransform; + var dataLength = width * height * this.components.length; + requestMemoryAllocation(dataLength); + var data = new Uint8Array(dataLength); + switch (this.components.length) { + case 1: + component1 = this.components[0]; + for (y = 0; y < height; y++) { + component1Line = component1.lines[0 | y * component1.scaleY * scaleY]; + for (x = 0; x < width; x++) { + Y = component1Line[0 | x * component1.scaleX * scaleX]; + data[offset++] = Y; + } + } + break; + case 2: + component1 = this.components[0]; + component2 = this.components[1]; + for (y = 0; y < height; y++) { + component1Line = component1.lines[0 | y * component1.scaleY * scaleY]; + component2Line = component2.lines[0 | y * component2.scaleY * scaleY]; + for (x = 0; x < width; x++) { + Y = component1Line[0 | x * component1.scaleX * scaleX]; + data[offset++] = Y; + Y = component2Line[0 | x * component2.scaleX * scaleX]; + data[offset++] = Y; + } + } + break; + case 3: + colorTransform = true; + if (this.adobe && this.adobe.transformCode) + colorTransform = true; + else if (typeof this.opts.colorTransform !== "undefined") + colorTransform = !!this.opts.colorTransform; + component1 = this.components[0]; + component2 = this.components[1]; + component3 = this.components[2]; + for (y = 0; y < height; y++) { + component1Line = component1.lines[0 | y * component1.scaleY * scaleY]; + component2Line = component2.lines[0 | y * component2.scaleY * scaleY]; + component3Line = component3.lines[0 | y * component3.scaleY * scaleY]; + for (x = 0; x < width; x++) { + if (!colorTransform) { + R = component1Line[0 | x * component1.scaleX * scaleX]; + G = component2Line[0 | x * component2.scaleX * scaleX]; + B = component3Line[0 | x * component3.scaleX * scaleX]; + } else { + Y = component1Line[0 | x * component1.scaleX * scaleX]; + Cb = component2Line[0 | x * component2.scaleX * scaleX]; + Cr = component3Line[0 | x * component3.scaleX * scaleX]; + R = clampTo8bit(Y + 1.402 * (Cr - 128)); + G = clampTo8bit(Y - 0.3441363 * (Cb - 128) - 0.71413636 * (Cr - 128)); + B = clampTo8bit(Y + 1.772 * (Cb - 128)); + } + data[offset++] = R; + data[offset++] = G; + data[offset++] = B; + } + } + break; + case 4: + if (!this.adobe) + throw new Error("Unsupported color mode (4 components)"); + colorTransform = false; + if (this.adobe && this.adobe.transformCode) + colorTransform = true; + else if (typeof this.opts.colorTransform !== "undefined") + colorTransform = !!this.opts.colorTransform; + component1 = this.components[0]; + component2 = this.components[1]; + component3 = this.components[2]; + component4 = this.components[3]; + for (y = 0; y < height; y++) { + component1Line = component1.lines[0 | y * component1.scaleY * scaleY]; + component2Line = component2.lines[0 | y * component2.scaleY * scaleY]; + component3Line = component3.lines[0 | y * component3.scaleY * scaleY]; + component4Line = component4.lines[0 | y * component4.scaleY * scaleY]; + for (x = 0; x < width; x++) { + if (!colorTransform) { + C = component1Line[0 | x * component1.scaleX * scaleX]; + M = component2Line[0 | x * component2.scaleX * scaleX]; + Ye = component3Line[0 | x * component3.scaleX * scaleX]; + K = component4Line[0 | x * component4.scaleX * scaleX]; + } else { + Y = component1Line[0 | x * component1.scaleX * scaleX]; + Cb = component2Line[0 | x * component2.scaleX * scaleX]; + Cr = component3Line[0 | x * component3.scaleX * scaleX]; + K = component4Line[0 | x * component4.scaleX * scaleX]; + C = 255 - clampTo8bit(Y + 1.402 * (Cr - 128)); + M = 255 - clampTo8bit(Y - 0.3441363 * (Cb - 128) - 0.71413636 * (Cr - 128)); + Ye = 255 - clampTo8bit(Y + 1.772 * (Cb - 128)); + } + data[offset++] = 255 - C; + data[offset++] = 255 - M; + data[offset++] = 255 - Ye; + data[offset++] = 255 - K; + } + } + break; + default: + throw new Error("Unsupported color mode"); + } + return data; + }, + copyToImageData: function copyToImageData(imageData, formatAsRGBA) { + var width = imageData.width, height = imageData.height; + var imageDataArray = imageData.data; + var data = this.getData(width, height); + var i = 0, j = 0, x, y; + var Y, K, C, M, R, G, B; + switch (this.components.length) { + case 1: + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + Y = data[i++]; + imageDataArray[j++] = Y; + imageDataArray[j++] = Y; + imageDataArray[j++] = Y; + if (formatAsRGBA) { + imageDataArray[j++] = 255; + } + } + } + break; + case 3: + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + R = data[i++]; + G = data[i++]; + B = data[i++]; + imageDataArray[j++] = R; + imageDataArray[j++] = G; + imageDataArray[j++] = B; + if (formatAsRGBA) { + imageDataArray[j++] = 255; + } + } + } + break; + case 4: + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + C = data[i++]; + M = data[i++]; + Y = data[i++]; + K = data[i++]; + R = 255 - clampTo8bit(C * (1 - K / 255) + K); + G = 255 - clampTo8bit(M * (1 - K / 255) + K); + B = 255 - clampTo8bit(Y * (1 - K / 255) + K); + imageDataArray[j++] = R; + imageDataArray[j++] = G; + imageDataArray[j++] = B; + if (formatAsRGBA) { + imageDataArray[j++] = 255; + } + } + } + break; + default: + throw new Error("Unsupported color mode"); + } + } + }; + var totalBytesAllocated = 0; + var maxMemoryUsageBytes = 0; + function requestMemoryAllocation(increaseAmount = 0) { + var totalMemoryImpactBytes = totalBytesAllocated + increaseAmount; + if (totalMemoryImpactBytes > maxMemoryUsageBytes) { + var exceededAmount = Math.ceil((totalMemoryImpactBytes - maxMemoryUsageBytes) / 1024 / 1024); + throw new Error(`maxMemoryUsageInMB limit exceeded by at least ${exceededAmount}MB`); + } + totalBytesAllocated = totalMemoryImpactBytes; + } + constructor.resetMaxMemoryUsage = function(maxMemoryUsageBytes_) { + totalBytesAllocated = 0; + maxMemoryUsageBytes = maxMemoryUsageBytes_; + }; + constructor.getBytesAllocated = function() { + return totalBytesAllocated; + }; + constructor.requestMemoryAllocation = requestMemoryAllocation; + return constructor; + }(); + if (typeof module !== "undefined") { + module.exports = decode; + } else if (typeof window !== "undefined") { + window["jpeg-js"] = window["jpeg-js"] || {}; + window["jpeg-js"].decode = decode; + } + function decode(jpegData, userOpts = {}) { + var defaultOpts = { + colorTransform: void 0, + useTArray: false, + formatAsRGBA: true, + tolerantDecoding: true, + maxResolutionInMP: 100, + maxMemoryUsageInMB: 512 + }; + var opts = { ...defaultOpts, ...userOpts }; + var arr = new Uint8Array(jpegData); + var decoder = new JpegImage(); + decoder.opts = opts; + JpegImage.resetMaxMemoryUsage(opts.maxMemoryUsageInMB * 1024 * 1024); + decoder.parse(arr); + var channels = opts.formatAsRGBA ? 4 : 3; + var bytesNeeded = decoder.width * decoder.height * channels; + try { + JpegImage.requestMemoryAllocation(bytesNeeded); + var image = { + width: decoder.width, + height: decoder.height, + exifBuffer: decoder.exifBuffer, + data: opts.useTArray ? new Uint8Array(bytesNeeded) : Buffer2.alloc(bytesNeeded) + }; + if (decoder.comments.length > 0) { + image["comments"] = decoder.comments; + } + } catch (err) { + if (err instanceof RangeError) { + throw new Error("Could not allocate enough memory for the image. Required: " + bytesNeeded); + } else { + throw err; + } + } + decoder.copyToImageData(image, opts.formatAsRGBA); + return image; + } + } + }); + + // node_modules/jpeg-js/index.js + var require_jpeg_js = __commonJS({ + "node_modules/jpeg-js/index.js"(exports, module) { + init_esbuild_inject(); + var encode = require_encoder(); + var decode = require_decoder(); + module.exports = { + encode, + decode + }; + } + }); + // node_modules/events/events.js var require_events2 = __commonJS({ "node_modules/events/events.js"(exports, module) { @@ -11207,6 +13319,8 @@ sh: false, ep: false, expte: false, + mdist: -1, + phash: false, hotlink: false, vercheck: false, fhost: 0, @@ -12071,6 +14185,64 @@ // src/thirdeye.ts init_esbuild_inject(); var import_buffer7 = __toESM(require_buffer(), 1); + var import_jpeg_js = __toESM(require_jpeg_js(), 1); + + // src/phash.ts + init_esbuild_inject(); + var median = (data) => { + const mdarr = data.slice(0); + mdarr.sort((a, b) => a - b); + if (mdarr.length % 2 === 0) + return (mdarr[mdarr.length / 2 - 1] + mdarr[mdarr.length / 2]) / 2; + return mdarr[Math.floor(mdarr.length / 2)]; + }; + var translate_blocks_to_bits = function(blocks, pixels_per_block) { + const half_block_value = pixels_per_block * 256 * 3 / 2; + const bandsize = blocks.length / 4; + for (let i = 0; i < 4; i++) { + const m = median(blocks.slice(i * bandsize, (i + 1) * bandsize)); + for (let j = i * bandsize; j < (i + 1) * bandsize; j++) { + const v = blocks[j]; + blocks[j] = Number(v > m || Math.abs(v - m) < 1 && m > half_block_value); + } + } + }; + var bits_to_hexhash = (bitsArray) => { + const hex = []; + for (let i = 0; i < bitsArray.length; i += 4) { + const nibble = bitsArray.slice(i, i + 4); + hex.push(parseInt(nibble.join(""), 2).toString(16)); + } + return hex.join(""); + }; + var bmvbhash_even = (data, bits) => { + const blocksize_x = Math.floor(data.width / bits); + const blocksize_y = Math.floor(data.height / bits); + const result = []; + for (let y = 0; y < bits; y++) { + for (let x = 0; x < bits; x++) { + let total = 0; + for (let iy = 0; iy < blocksize_y; iy++) { + for (let ix = 0; ix < blocksize_x; ix++) { + const cx = x * blocksize_x + ix; + const cy = y * blocksize_y + iy; + const ii = (cy * data.width + cx) * 4; + const alpha = data.data[ii + 3]; + if (alpha === 0) { + total += 765; + } else { + total += data.data[ii] + data.data[ii + 1] + data.data[ii + 2]; + } + } + } + result.push(total); + } + } + translate_blocks_to_bits(result, blocksize_x * blocksize_y); + return bits_to_hexhash(result); + }; + + // src/thirdeye.ts var csettings3; settings.subscribe((b) => { csettings3 = b; @@ -12084,21 +14256,23 @@ tags: (e.tag_string || (e.tags && (Array.isArray(e.tags) && (typeof e.tags[0] == "string" ? e.tags.join(" ") : e.tags.map((e2) => e2.name_en).join(" "))) || e.tags) || "").split(" ") })) || []; var experimentalApi = false; + var black = /* @__PURE__ */ new Set(); + var phashEn = false; + var mindist = 5; settings.subscribe((s) => { experimentalApi = s.expte; boorus = s.rsources.map((e) => ({ ...e, quirks: gelquirk(e.view) })); + black = new Set(s.blacklist); + mindist = s.mdist || 5; + phashEn = s.phash; }); var boorus = localLoad("settingsv2", { rsources: [] }).rsources.map((e) => ({ ...e, quirks: gelquirk(e.view) })); - var black = /* @__PURE__ */ new Set(); - settings.subscribe((s) => { - black = new Set(s.blacklist); - }); var unlockQueue = Promise.resolve(); var cache = {}; var findFileFrom = async (b, hex, abort) => { @@ -12133,7 +14307,10 @@ const full = result[0].full_url; return [{ source: result[0].source, - page: { title: booru, url: result[0].page }, + page: { + title: booru, + url: result[0].page + }, filename: fn.substring(0, 33) + result[0].ext, thumbnail: await (await GM_fetch(prev || full)).arrayBuffer(), data: csettings3.hotlink ? full || prev : async (lsn) => { @@ -12143,7 +14320,20 @@ } }]; }; - var has_embed4 = async (b, fn) => { + var phash = (b) => { + const res = import_jpeg_js.default.decode(b); + return bmvbhash_even(res, 8); + }; + var hammingDist = (a, b) => { + let res = BigInt("0x" + a) ^ BigInt("0x" + b); + let acc = 0; + while (res != 0n) { + acc += Number(res & 1n); + res >>= 1n; + } + return acc; + }; + var has_embed4 = async (b, fn, prevlink) => { if (import_buffer7.Buffer.from(fn, "hex").equals(b)) return false; let result = void 0; @@ -12155,6 +14345,20 @@ if (result.length) break; } + if (result && result.length != 0 && phashEn && prevlink) { + const getHash = async (l) => { + const ogreq = await GM_fetch(l); + const origPreview = await ogreq.arrayBuffer(); + return await phash(import_buffer7.Buffer.from(origPreview)); + }; + const [orighash, tehash] = await Promise.all([ + getHash(prevlink), + getHash(result[0].preview_url) + ]); + const d = hammingDist(orighash, tehash); + console.log(d, prevlink); + return d > mindist; + } return result && result.length != 0; }; var thirdeye_default = { @@ -12911,20 +15115,20 @@ } function get_each_context(ctx, list, i) { const child_ctx = ctx.slice(); - child_ctx[36] = list[i]; - child_ctx[38] = i; + child_ctx[38] = list[i]; + child_ctx[40] = i; return child_ctx; } function get_each_context_1(ctx, list, i) { const child_ctx = ctx.slice(); - child_ctx[39] = list[i]; - child_ctx[38] = i; + child_ctx[41] = list[i]; + child_ctx[40] = i; return child_ctx; } function get_each_context_2(ctx, list, i) { const child_ctx = ctx.slice(); - child_ctx[41] = list[i]; - child_ctx[38] = i; + child_ctx[43] = list[i]; + child_ctx[40] = i; return child_ctx; } function create_default_slot_8(ctx) { @@ -13015,17 +15219,17 @@ }, p(ctx2, dirty) { const tab0_changes = {}; - if (dirty[1] & 4096) { + if (dirty[1] & 16384) { tab0_changes.$$scope = { dirty, ctx: ctx2 }; } tab0.$set(tab0_changes); const tab1_changes = {}; - if (dirty[1] & 4096) { + if (dirty[1] & 16384) { tab1_changes.$$scope = { dirty, ctx: ctx2 }; } tab1.$set(tab1_changes); const tab2_changes = {}; - if (dirty[1] & 4096) { + if (dirty[1] & 16384) { tab2_changes.$$scope = { dirty, ctx: ctx2 }; } tab2.$set(tab2_changes); @@ -13055,7 +15259,7 @@ } }; } - function create_if_block_1(ctx) { + function create_if_block_2(ctx) { let label; let input; let t; @@ -13143,7 +15347,7 @@ let a; let mounted; let dispose; - let if_block = ctx[3].eye && create_if_block_1(ctx); + let if_block = ctx[3].eye && create_if_block_2(ctx); return { c() { label0 = element("label"); @@ -13317,7 +15521,7 @@ if (if_block) { if_block.p(ctx2, dirty); } else { - if_block = create_if_block_1(ctx2); + if_block = create_if_block_2(ctx2); if_block.c(); if_block.m(t12.parentNode, t12); } @@ -13401,24 +15605,30 @@ }; } function create_if_block4(ctx) { - let h30; + let label; + let input0; + let t0; let t1; - let div0; let t2; - let button; + let h30; let t4; - let dialog; + let div0; let t5; + let button; + let t7; + let dialog; + let t8; let hr; - let t6; + let t9; let h31; - let t8; + let t11; let div1; - let t9; - let input; + let t12; + let input1; let current; let mounted; let dispose; + let if_block = ctx[3].phash && create_if_block_1(ctx); let each_value_2 = ctx[3].rsources; let each_blocks_1 = []; for (let i = 0; i < each_value_2.length; i += 1) { @@ -13432,7 +15642,7 @@ $$scope: { ctx } }; dialog = new Dialog_default({ props: dialog_props }); - ctx[30](dialog); + ctx[32](dialog); let each_value_1 = ctx[3].blacklist; let each_blocks = []; for (let i = 0; i < each_value_1.length; i += 1) { @@ -13443,67 +15653,99 @@ }); return { c() { + label = element("label"); + input0 = element("input"); + t0 = text("\n Enable perceptual hash-based filtering"); + t1 = space(); + if (if_block) + if_block.c(); + t2 = space(); h30 = element("h3"); h30.textContent = "Booru sources"; - t1 = space(); + t4 = space(); div0 = element("div"); for (let i = 0; i < each_blocks_1.length; i += 1) { each_blocks_1[i].c(); } - t2 = space(); + t5 = space(); button = element("button"); button.textContent = "Add a source"; - t4 = space(); + t7 = space(); create_component(dialog.$$.fragment); - t5 = space(); + t8 = space(); hr = element("hr"); - t6 = space(); + t9 = space(); h31 = element("h3"); h31.textContent = "Blacklisted tags"; - t8 = space(); + t11 = space(); div1 = element("div"); for (let i = 0; i < each_blocks.length; i += 1) { each_blocks[i].c(); } - t9 = space(); - input = element("input"); + t12 = space(); + input1 = element("input"); + attr(input0, "type", "checkbox"); attr(div0, "class", "tagcont svelte-14cwalg"); attr(hr, "class", "svelte-14cwalg"); attr(div1, "class", "tagcont svelte-14cwalg"); - attr(input, "placeholder", "Press enter after typing your tag"); + attr(input1, "placeholder", "Press enter after typing your tag"); }, m(target, anchor) { - insert(target, h30, anchor); + insert(target, label, anchor); + append(label, input0); + input0.checked = ctx[3].phash; + append(label, t0); insert(target, t1, anchor); + if (if_block) + if_block.m(target, anchor); + insert(target, t2, anchor); + insert(target, h30, anchor); + insert(target, t4, anchor); insert(target, div0, anchor); for (let i = 0; i < each_blocks_1.length; i += 1) { each_blocks_1[i].m(div0, null); } - insert(target, t2, anchor); + insert(target, t5, anchor); insert(target, button, anchor); - insert(target, t4, anchor); + insert(target, t7, anchor); mount_component(dialog, target, anchor); - insert(target, t5, anchor); + insert(target, t8, anchor); insert(target, hr, anchor); - insert(target, t6, anchor); + insert(target, t9, anchor); insert(target, h31, anchor); - insert(target, t8, anchor); + insert(target, t11, anchor); insert(target, div1, anchor); for (let i = 0; i < each_blocks.length; i += 1) { each_blocks[i].m(div1, null); } - insert(target, t9, anchor); - insert(target, input, anchor); + insert(target, t12, anchor); + insert(target, input1, anchor); current = true; if (!mounted) { dispose = [ - listen(button, "click", ctx[25]), - listen(input, "keydown", ctx[32]) + listen(input0, "change", ctx[22]), + listen(button, "click", ctx[27]), + listen(input1, "keydown", ctx[34]) ]; mounted = true; } }, p(ctx2, dirty) { + if (dirty[0] & 8) { + input0.checked = ctx2[3].phash; + } + if (ctx2[3].phash) { + if (if_block) { + if_block.p(ctx2, dirty); + } else { + if_block = create_if_block_1(ctx2); + if_block.c(); + if_block.m(t2.parentNode, t2); + } + } else if (if_block) { + if_block.d(1); + if_block = null; + } if (dirty[0] & 200) { each_value_2 = ctx2[3].rsources; let i; @@ -13526,7 +15768,7 @@ check_outros(); } const dialog_changes = {}; - if (dirty[0] & 1 | dirty[1] & 4096) { + if (dirty[0] & 1 | dirty[1] & 16384) { dialog_changes.$$scope = { dirty, ctx: ctx2 }; } dialog.$set(dialog_changes); @@ -13578,57 +15820,106 @@ }, d(detaching) { if (detaching) - detach(h30); + detach(label); if (detaching) detach(t1); + if (if_block) + if_block.d(detaching); + if (detaching) + detach(t2); + if (detaching) + detach(h30); + if (detaching) + detach(t4); if (detaching) detach(div0); destroy_each(each_blocks_1, detaching); if (detaching) - detach(t2); + detach(t5); if (detaching) detach(button); if (detaching) - detach(t4); - ctx[30](null); + detach(t7); + ctx[32](null); destroy_component(dialog, detaching); if (detaching) - detach(t5); + detach(t8); if (detaching) detach(hr); if (detaching) - detach(t6); + detach(t9); if (detaching) detach(h31); if (detaching) - detach(t8); + detach(t11); if (detaching) detach(div1); destroy_each(each_blocks, detaching); if (detaching) - detach(t9); + detach(t12); if (detaching) - detach(input); + detach(input1); mounted = false; run_all(dispose); } }; } + function create_if_block_1(ctx) { + let label; + let input; + let t0; + let a; + let mounted; + let dispose; + return { + c() { + label = element("label"); + input = element("input"); + t0 = text("\n Minimum distance required (5 recommended)\n \n "); + a = element("a"); + a.textContent = "?"; + attr(input, "type", "number"); + attr(a, "title", "Higher will filter more potentially different images, lower will let more identical images through"); + }, + m(target, anchor) { + insert(target, label, anchor); + append(label, input); + set_input_value(input, ctx[3].mdist); + append(label, t0); + append(label, a); + if (!mounted) { + dispose = listen(input, "input", ctx[23]); + mounted = true; + } + }, + p(ctx2, dirty) { + if (dirty[0] & 8 && to_number(input.value) !== ctx2[3].mdist) { + set_input_value(input, ctx2[3].mdist); + } + }, + d(detaching) { + if (detaching) + detach(label); + mounted = false; + dispose(); + } + }; + } function create_each_block_2(ctx) { let tag; let current; function func(...args) { - return ctx[22](ctx[41], ...args); + return ctx[24](ctx[43], ...args); } function remove_handler() { - return ctx[23](ctx[41]); + return ctx[25](ctx[43]); } function toggle_handler() { - return ctx[24](ctx[41]); + return ctx[26](ctx[43]); } tag = new Tag_default({ props: { - tag: ctx[41].name, + tag: ctx[43].name, toggleable: true, toggled: !ctx[3].rsources.find(func)?.disabled } @@ -13647,7 +15938,7 @@ ctx = new_ctx; const tag_changes = {}; if (dirty[0] & 8) - tag_changes.tag = ctx[41].name; + tag_changes.tag = ctx[43].name; if (dirty[0] & 8) tag_changes.toggled = !ctx[3].rsources.find(func)?.disabled; tag.$set(tag_changes); @@ -13748,10 +16039,10 @@ append(div, button); if (!mounted) { dispose = [ - listen(input0, "input", ctx[26]), - listen(input1, "input", ctx[27]), - listen(input2, "input", ctx[28]), - listen(input3, "input", ctx[29]), + listen(input0, "input", ctx[28]), + listen(input1, "input", ctx[29]), + listen(input2, "input", ctx[30]), + listen(input3, "input", ctx[31]), listen(button, "click", ctx[4]) ]; mounted = true; @@ -13783,9 +16074,9 @@ let tag; let current; function toggle_handler_1() { - return ctx[31](ctx[39]); + return ctx[33](ctx[41]); } - tag = new Tag_default({ props: { tag: ctx[39] } }); + tag = new Tag_default({ props: { tag: ctx[41] } }); tag.$on("toggle", toggle_handler_1); return { c() { @@ -13799,7 +16090,7 @@ ctx = new_ctx; const tag_changes = {}; if (dirty[0] & 8) - tag_changes.tag = ctx[39]; + tag_changes.tag = ctx[41]; tag.$set(tag_changes); }, i(local) { @@ -13903,14 +16194,14 @@ } function create_each_block(ctx) { let option; - let t_value = ctx[36].domain + ""; + let t_value = ctx[38].domain + ""; let t; let option_value_value; return { c() { option = element("option"); t = text(t_value); - option.__value = option_value_value = ctx[38]; + option.__value = option_value_value = ctx[40]; option.value = option.__value; }, m(target, anchor) { @@ -13953,7 +16244,7 @@ t3 = text("Maximum number of embedded links to display\n "); input = element("input"); if (ctx[3].fhost === void 0) - add_render_callback(() => ctx[33].call(select)); + add_render_callback(() => ctx[35].call(select)); attr(input, "type", "number"); }, m(target, anchor) { @@ -13971,8 +16262,8 @@ set_input_value(input, ctx[3].maxe); if (!mounted) { dispose = [ - listen(select, "change", ctx[33]), - listen(input, "input", ctx[34]) + listen(select, "change", ctx[35]), + listen(input, "input", ctx[36]) ]; mounted = true; } @@ -14075,22 +16366,22 @@ }, p(ctx2, dirty) { const tablist_changes = {}; - if (dirty[1] & 4096) { + if (dirty[1] & 16384) { tablist_changes.$$scope = { dirty, ctx: ctx2 }; } tablist.$set(tablist_changes); const tabpanel0_changes = {}; - if (dirty[0] & 8 | dirty[1] & 4096) { + if (dirty[0] & 8 | dirty[1] & 16384) { tabpanel0_changes.$$scope = { dirty, ctx: ctx2 }; } tabpanel0.$set(tabpanel0_changes); const tabpanel1_changes = {}; - if (dirty[0] & 11 | dirty[1] & 4096) { + if (dirty[0] & 11 | dirty[1] & 16384) { tabpanel1_changes.$$scope = { dirty, ctx: ctx2 }; } tabpanel1.$set(tabpanel1_changes); const tabpanel2_changes = {}; - if (dirty[0] & 8 | dirty[1] & 4096) { + if (dirty[0] & 8 | dirty[1] & 16384) { tabpanel2_changes.$$scope = { dirty, ctx: ctx2 }; } tabpanel2.$set(tabpanel2_changes); @@ -14169,7 +16460,7 @@ }, p(ctx2, dirty) { const tabs_changes = {}; - if (dirty[0] & 11 | dirty[1] & 4096) { + if (dirty[0] & 11 | dirty[1] & 16384) { tabs_changes.$$scope = { dirty, ctx: ctx2 }; } tabs.$set(tabs_changes); @@ -14291,6 +16582,14 @@ $settings.te = this.checked; settings.set($settings); } + function input0_change_handler_1() { + $settings.phash = this.checked; + settings.set($settings); + } + function input_input_handler() { + $settings.mdist = to_number(this.value); + settings.set($settings); + } const func = (source, e) => e.domain == source.domain; const remove_handler = (source) => removeBooru(source.domain); const toggle_handler = (source) => toggleBooru(source.domain); @@ -14331,7 +16630,7 @@ $settings.fhost = select_value(this); settings.set($settings); } - function input_input_handler() { + function input_input_handler_1() { $settings.maxe = to_number(this.value); settings.set($settings); } @@ -14358,6 +16657,8 @@ input10_change_handler, input11_change_handler, input_change_handler_1, + input0_change_handler_1, + input_input_handler, func, remove_handler, toggle_handler, @@ -14370,7 +16671,7 @@ toggle_handler_1, keydown_handler, select_change_handler, - input_input_handler + input_input_handler_1 ]; } var App = class extends SvelteComponent { @@ -16779,7 +19080,7 @@ let if_block2 = ctx[2] && create_if_block_5(ctx); let if_block3 = ctx[5] && create_if_block_4(ctx); let if_block4 = ctx[18] && create_if_block_3(ctx); - let if_block5 = ctx[3] && create_if_block_2(ctx); + let if_block5 = ctx[3] && create_if_block_22(ctx); let if_block6 = ctx[2] && create_if_block_12(ctx); return { c() { @@ -16917,7 +19218,7 @@ if (if_block5) { if_block5.p(ctx2, dirty); } else { - if_block5 = create_if_block_2(ctx2); + if_block5 = create_if_block_22(ctx2); if_block5.c(); if_block5.m(div1, t5); } @@ -17210,7 +19511,7 @@ } }; } - function create_if_block_2(ctx) { + function create_if_block_22(ctx) { let img; let img_alt_value; let img_src_value; @@ -17916,7 +20217,7 @@ } }; } - function create_if_block_22(ctx) { + function create_if_block_23(ctx) { let a; let t; let a_href_value; @@ -18012,7 +20313,7 @@ function click_handler2() { return ctx[9](ctx[11]); } - let if_block0 = ctx[11].source && create_if_block_22(ctx); + let if_block0 = ctx[11].source && create_if_block_23(ctx); let if_block1 = ctx[11].page && create_if_block_13(ctx); let if_block2 = ctx[6] && ctx[2] && create_if_block8(ctx); return { @@ -18057,7 +20358,7 @@ if (if_block0) { if_block0.p(ctx, dirty); } else { - if_block0 = create_if_block_22(ctx); + if_block0 = create_if_block_23(ctx); if_block0.c(); if_block0.m(t1.parentNode, t1); } @@ -18408,6 +20709,7 @@ return a?.textContent || ""; }, getMD5: (post) => post.querySelector("img[data-md5]")?.getAttribute("data-md5") || "", + getThumbnailLink: (post) => post.querySelector("img[data-md5]")?.getAttribute("src") || "", getInfoBox: (post) => post.querySelector("div.fileText") }; var X4chan = { @@ -18423,6 +20725,7 @@ return (origlink.querySelector(".fnfull") || origlink)?.textContent || ""; }, getMD5: (post) => post.querySelector("img[data-md5]")?.getAttribute("data-md5") || "", + getThumbnailLink: (post) => post.querySelector("img[data-md5]")?.getAttribute("src") || "", getInfoBox: (post) => post.querySelector("span.file-info") }; var FoolFuuka = { @@ -18440,6 +20743,7 @@ return a?.title || ""; }, getMD5: (post) => post.querySelector("img[data-md5]")?.getAttribute("data-md5") || "", + getThumbnailLink: (post) => post.querySelector("img[data-md5]")?.getAttribute("src") || "", getInfoBox: (post) => post.querySelector("span.post_controls") }; var getQueryProcessor = (is4chanX) => { @@ -18492,11 +20796,11 @@ } } } - var processImage = async (src, fn, hex, onfound) => { + var processImage = async (src, fn, hex, prevurl, onfound) => { return Promise.all(processors.filter((e) => e.match(fn)).map(async (proc) => { if (proc.skip) { const md5 = import_buffer10.Buffer.from(hex, "base64"); - if (await proc.has_embed(md5, fn) === true) { + if (await proc.has_embed(md5, fn, prevurl) === true) { onfound(); return [await proc.extract(md5, fn), true]; } @@ -18532,7 +20836,10 @@ const origlink = qp.getImageLink(post); if (!origlink) return; - let res2 = await processImage(origlink, qp.getFilename(post), qp.getMD5(post), () => { + const thumbLink = qp.getThumbnailLink(post); + if (!thumbLink) + return; + let res2 = await processImage(origlink, qp.getFilename(post), qp.getMD5(post), thumbLink, () => { post.querySelector(".post")?.classList.add("embedfound"); }); res2 = res2?.filter((e) => e); diff --git a/package-lock.json b/package-lock.json index 16210fc..2dbac14 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,10 +9,14 @@ "version": "1.0.0", "license": "ISC", "dependencies": { + "blockhash": "^0.2.0", "buffer": "^6.0.3", "crc-32": "^1.2.0", "events": "^3.3.0", "file-type": "^17.0.2", + "image-hash": "^5.0.1", + "jpeg-js": "^0.4.3", + "png-js": "^1.0.0", "readable-stream": "^3.6.0", "ts-ebml": "^2.0.2" }, @@ -466,6 +470,19 @@ "node": ">=6.9.0" } }, + "node_modules/@canvas/image-data": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@canvas/image-data/-/image-data-1.0.0.tgz", + "integrity": "sha512-BxOqI5LgsIQP1odU5KMwV9yoijleOPzHL18/YvNqF9KFSGF2K/DLlYAbDQsWqd/1nbaFuSkYD/191dpMtNh4vw==" + }, + "node_modules/@cwasm/webp": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@cwasm/webp/-/webp-0.1.5.tgz", + "integrity": "sha512-ceIZQkyxK+s7mmItNcWqqHdOBiJAxYxTnrnPNgUNjldB1M9j+Bp/3eVIVwC8rUFyN/zoFwuT0331pyY3ackaNA==", + "dependencies": { + "@canvas/image-data": "^1.0.0" + } + }, "node_modules/@eslint/eslintrc": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.5.tgz", @@ -954,7 +971,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -1031,11 +1047,32 @@ "node": ">=0.10.0" } }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "engines": { + "node": ">=0.8" + } + }, "node_modules/async": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async/-/async-1.0.0.tgz", "integrity": "sha1-+PwEyjoTeErenhZBr5hXjPvWR6k=" }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, "node_modules/at-least-node": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", @@ -1045,6 +1082,19 @@ "node": ">= 4.0.0" } }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1070,6 +1120,14 @@ } ] }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -1079,6 +1137,11 @@ "node": ">=8" } }, + "node_modules/blockhash": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/blockhash/-/blockhash-0.2.0.tgz", + "integrity": "sha1-fJea5QF/0lLoGfvnYbCWcDlCzPc=" + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -1215,6 +1278,11 @@ "url": "https://opencollective.com/browserslist" } }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, "node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -1262,6 +1330,17 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -1292,6 +1371,11 @@ "optional": true, "peer": true }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, "node_modules/crc": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/crc/-/crc-3.2.1.tgz", @@ -1360,6 +1444,17 @@ "node": ">=4" } }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/dateformat": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.11.tgz", @@ -1428,6 +1523,14 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/detect-indent": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", @@ -1475,6 +1578,15 @@ "resolved": "https://registry.npmjs.org/ebml-block/-/ebml-block-1.1.2.tgz", "integrity": "sha512-HgNlIsRFP6D9VKU5atCeHRJY7XkJP8bOe8yEhd8NB7B3b4++VWTyauz6g650iiPmLfPLGlVpoJmGSgMfXDYusg==" }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, "node_modules/electron-to-chromium": { "version": "1.4.38", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.38.tgz", @@ -2159,11 +2271,23 @@ "node": ">=0.8" } }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "engines": [ + "node >=0.6.0" + ] + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/fast-glob": { "version": "3.2.7", @@ -2184,8 +2308,7 @@ "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, "node_modules/fast-levenshtein": { "version": "2.0.6", @@ -2299,6 +2422,27 @@ "underscore": "" } }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "engines": { + "node": "*" + } + }, + "node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, "node_modules/fs-extra": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", @@ -2376,6 +2520,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dependencies": { + "assert-plus": "^1.0.0" + } + }, "node_modules/glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", @@ -2461,6 +2613,27 @@ "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", "dev": true }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/hard-rejection": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", @@ -2499,6 +2672,20 @@ "node": ">=10" } }, + "node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, "node_modules/icss-replace-symbols": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", @@ -2545,6 +2732,89 @@ "node": ">= 4" } }, + "node_modules/image-hash": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/image-hash/-/image-hash-5.0.1.tgz", + "integrity": "sha512-rZC3UnQNA0VcStCwAsc46uUnb7FmN3CqT3z+LqCrvgq7R5cyxwTwT5fyg3ClLru74obK+ZySRwyAyGnS6pj6yA==", + "dependencies": { + "@cwasm/webp": "^0.1.5", + "file-type": "^14.6.2", + "jpeg-js": "^0.4.0", + "pngjs": "^3.3.3", + "request": "^2.81.0" + } + }, + "node_modules/image-hash/node_modules/file-type": { + "version": "14.7.1", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-14.7.1.tgz", + "integrity": "sha512-sXAMgFk67fQLcetXustxfKX+PZgHIUFn96Xld9uH8aXPdX3xOp0/jg9OdouVTvQrf7mrn+wAa4jN/y9fUOOiRA==", + "dependencies": { + "readable-web-to-node-stream": "^2.0.0", + "strtok3": "^6.0.3", + "token-types": "^2.0.0", + "typedarray-to-buffer": "^3.1.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sindresorhus/file-type?sponsor=1" + } + }, + "node_modules/image-hash/node_modules/peek-readable": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-4.0.2.tgz", + "integrity": "sha512-9fMaz6zoxw9ypO1KZy5RDJgSupEtu0Q+g/OqqsVHX3rKGR8qehRLYzsFARZ4bVvdvfknKiXvuDbkMnO1g6cRpQ==", + "engines": { + "node": ">=8" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/image-hash/node_modules/readable-web-to-node-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-2.0.0.tgz", + "integrity": "sha512-+oZJurc4hXpaaqsN68GoZGQAQIA3qr09Or4fqEsargABnbe5Aau8hFn6ISVleT3cpY/0n/8drn7huyyEvTbghA==" + }, + "node_modules/image-hash/node_modules/strtok3": { + "version": "6.2.4", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.2.4.tgz", + "integrity": "sha512-GO8IcFF9GmFDvqduIspUBwCzCbqzegyVKIsSymcMgiZKeCfrN9SowtUoi8+b59WZMAjIzVZic/Ft97+pynR3Iw==", + "dependencies": { + "@tokenizer/token": "^0.3.0", + "peek-readable": "^4.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/image-hash/node_modules/token-types": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-2.1.1.tgz", + "integrity": "sha512-wnQcqlreS6VjthyHO3Y/kpK/emflxDBNhlNUPfh7wE39KnuDdOituXomIbyI79vBtF0Ninpkh72mcuRHo+RG3Q==", + "dependencies": { + "@tokenizer/token": "^0.1.1", + "ieee754": "^1.2.1" + }, + "engines": { + "node": ">=0.1.98" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/image-hash/node_modules/token-types/node_modules/@tokenizer/token": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.1.1.tgz", + "integrity": "sha512-XO6INPbZCxdprl+9qa/AAbFFOMzzwqYxpjPgLICrMD6C2FCw6qfJOPcBk6JqqPLSaZ/Qx87qn4rpPmPMwaAK6w==" + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -2667,12 +2937,27 @@ "node": ">=0.10.0" } }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "node_modules/jpeg-js": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.3.tgz", + "integrity": "sha512-ru1HWKek8octvUHFHvE5ZzQ1yAsJmIvRdGWvSoKV52XKyuyYA437QWDttXT8eZXDSbuMpHlLzPDZUPd6idIz+Q==" + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -2690,6 +2975,11 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -2709,11 +2999,15 @@ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -2721,6 +3015,11 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, "node_modules/json5": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", @@ -2750,6 +3049,20 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jsprim": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -2927,6 +3240,25 @@ "mime": "cli.js" } }, + "node_modules/mime-db": { + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", + "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.34", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", + "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "dependencies": { + "mime-db": "1.51.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/min-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", @@ -3041,6 +3373,14 @@ "node": ">=0.10.0" } }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "engines": { + "node": "*" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -3171,6 +3511,11 @@ "url": "https://github.com/sponsors/Borewit" } }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -3189,6 +3534,19 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/png-js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/png-js/-/png-js-1.0.0.tgz", + "integrity": "sha512-k+YsbhpA9e+EFfKjTCH3VW6aoKlyNYI6NYdTfDL4CIvFnvsuO84ttonmZE7rc+v23SLTH8XX+5w/Ak9v0xGY4g==" + }, + "node_modules/pngjs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", + "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==", + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/postcss": { "version": "8.4.5", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.5.tgz", @@ -3333,15 +3691,27 @@ "node": ">=0.4.0" } }, + "node_modules/psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" + }, "node_modules/punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true, "engines": { "node": ">=6" } }, + "node_modules/qs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "engines": { + "node": ">=0.6" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -3473,6 +3843,37 @@ "url": "https://github.com/sponsors/mysticatea" } }, + "node_modules/request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -3558,6 +3959,11 @@ } ] }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, "node_modules/sander": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/sander/-/sander-0.5.1.tgz", @@ -3681,6 +4087,30 @@ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==" }, + "node_modules/sshpk": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", + "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -4012,6 +4442,18 @@ "url": "https://github.com/sponsors/Borewit" } }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/trim-newlines": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-4.0.2.tgz", @@ -4092,6 +4534,22 @@ "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" } }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -4115,6 +4573,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, "node_modules/typescript": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.4.tgz", @@ -4146,7 +4612,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, "dependencies": { "punycode": "^2.1.0" } @@ -4156,6 +4621,15 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, + "node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "bin": { + "uuid": "bin/uuid" + } + }, "node_modules/v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", @@ -4171,6 +4645,19 @@ "spdx-expression-parse": "^3.0.0" } }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -4567,6 +5054,19 @@ "to-fast-properties": "^2.0.0" } }, + "@canvas/image-data": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@canvas/image-data/-/image-data-1.0.0.tgz", + "integrity": "sha512-BxOqI5LgsIQP1odU5KMwV9yoijleOPzHL18/YvNqF9KFSGF2K/DLlYAbDQsWqd/1nbaFuSkYD/191dpMtNh4vw==" + }, + "@cwasm/webp": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@cwasm/webp/-/webp-0.1.5.tgz", + "integrity": "sha512-ceIZQkyxK+s7mmItNcWqqHdOBiJAxYxTnrnPNgUNjldB1M9j+Bp/3eVIVwC8rUFyN/zoFwuT0331pyY3ackaNA==", + "requires": { + "@canvas/image-data": "^1.0.0" + } + }, "@eslint/eslintrc": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.5.tgz", @@ -4904,7 +5404,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -4959,17 +5458,45 @@ "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" }, + "asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, "async": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async/-/async-1.0.0.tgz", "integrity": "sha1-+PwEyjoTeErenhZBr5hXjPvWR6k=" }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, "at-least-node": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", "dev": true }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" + }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -4981,12 +5508,25 @@ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "requires": { + "tweetnacl": "^0.14.3" + } + }, "binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true }, + "blockhash": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/blockhash/-/blockhash-0.2.0.tgz", + "integrity": "sha1-fJea5QF/0lLoGfvnYbCWcDlCzPc=" + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -5071,6 +5611,11 @@ "optional": true, "peer": true }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -5110,6 +5655,14 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, "commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -5142,6 +5695,11 @@ } } }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, "crc": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/crc/-/crc-3.2.1.tgz", @@ -5191,6 +5749,14 @@ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "^1.0.0" + } + }, "dateformat": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.11.tgz", @@ -5240,6 +5806,11 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, "detect-indent": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", @@ -5278,6 +5849,15 @@ "resolved": "https://registry.npmjs.org/ebml-block/-/ebml-block-1.1.2.tgz", "integrity": "sha512-HgNlIsRFP6D9VKU5atCeHRJY7XkJP8bOe8yEhd8NB7B3b4++VWTyauz6g650iiPmLfPLGlVpoJmGSgMfXDYusg==" }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, "electron-to-chromium": { "version": "1.4.38", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.38.tgz", @@ -5745,11 +6325,20 @@ "resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz", "integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==" }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "fast-glob": { "version": "3.2.7", @@ -5767,8 +6356,7 @@ "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, "fast-levenshtein": { "version": "2.0.6", @@ -5857,6 +6445,21 @@ "underscore": "" } }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, "fs-extra": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", @@ -5915,6 +6518,14 @@ "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==" }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + } + }, "glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", @@ -5975,6 +6586,20 @@ "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", "dev": true }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "requires": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + } + }, "hard-rejection": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", @@ -6001,6 +6626,16 @@ "lru-cache": "^6.0.0" } }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, "icss-replace-symbols": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", @@ -6025,6 +6660,66 @@ "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", "dev": true }, + "image-hash": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/image-hash/-/image-hash-5.0.1.tgz", + "integrity": "sha512-rZC3UnQNA0VcStCwAsc46uUnb7FmN3CqT3z+LqCrvgq7R5cyxwTwT5fyg3ClLru74obK+ZySRwyAyGnS6pj6yA==", + "requires": { + "@cwasm/webp": "^0.1.5", + "file-type": "^14.6.2", + "jpeg-js": "^0.4.0", + "pngjs": "^3.3.3", + "request": "^2.81.0" + }, + "dependencies": { + "file-type": { + "version": "14.7.1", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-14.7.1.tgz", + "integrity": "sha512-sXAMgFk67fQLcetXustxfKX+PZgHIUFn96Xld9uH8aXPdX3xOp0/jg9OdouVTvQrf7mrn+wAa4jN/y9fUOOiRA==", + "requires": { + "readable-web-to-node-stream": "^2.0.0", + "strtok3": "^6.0.3", + "token-types": "^2.0.0", + "typedarray-to-buffer": "^3.1.5" + } + }, + "peek-readable": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-4.0.2.tgz", + "integrity": "sha512-9fMaz6zoxw9ypO1KZy5RDJgSupEtu0Q+g/OqqsVHX3rKGR8qehRLYzsFARZ4bVvdvfknKiXvuDbkMnO1g6cRpQ==" + }, + "readable-web-to-node-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-2.0.0.tgz", + "integrity": "sha512-+oZJurc4hXpaaqsN68GoZGQAQIA3qr09Or4fqEsargABnbe5Aau8hFn6ISVleT3cpY/0n/8drn7huyyEvTbghA==" + }, + "strtok3": { + "version": "6.2.4", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.2.4.tgz", + "integrity": "sha512-GO8IcFF9GmFDvqduIspUBwCzCbqzegyVKIsSymcMgiZKeCfrN9SowtUoi8+b59WZMAjIzVZic/Ft97+pynR3Iw==", + "requires": { + "@tokenizer/token": "^0.3.0", + "peek-readable": "^4.0.1" + } + }, + "token-types": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-2.1.1.tgz", + "integrity": "sha512-wnQcqlreS6VjthyHO3Y/kpK/emflxDBNhlNUPfh7wE39KnuDdOituXomIbyI79vBtF0Ninpkh72mcuRHo+RG3Q==", + "requires": { + "@tokenizer/token": "^0.1.1", + "ieee754": "^1.2.1" + }, + "dependencies": { + "@tokenizer/token": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.1.1.tgz", + "integrity": "sha512-XO6INPbZCxdprl+9qa/AAbFFOMzzwqYxpjPgLICrMD6C2FCw6qfJOPcBk6JqqPLSaZ/Qx87qn4rpPmPMwaAK6w==" + } + } + } + } + }, "import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -6114,12 +6809,27 @@ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jpeg-js": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.3.tgz", + "integrity": "sha512-ru1HWKek8octvUHFHvE5ZzQ1yAsJmIvRdGWvSoKV52XKyuyYA437QWDttXT8eZXDSbuMpHlLzPDZUPd6idIz+Q==" + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -6134,6 +6844,11 @@ "argparse": "^2.0.1" } }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -6147,11 +6862,15 @@ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, + "json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -6159,6 +6878,11 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, "json5": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", @@ -6180,6 +6904,17 @@ "universalify": "^2.0.0" } }, + "jsprim": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + } + }, "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -6314,6 +7049,19 @@ "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.6.tgz", "integrity": "sha1-WR2E02U6awtKO5343lqoEI5y5eA=" }, + "mime-db": { + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", + "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==" + }, + "mime-types": { + "version": "2.1.34", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", + "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "requires": { + "mime-db": "1.51.0" + } + }, "min-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", @@ -6401,6 +7149,11 @@ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -6488,6 +7241,11 @@ "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-5.0.0-alpha.5.tgz", "integrity": "sha512-pJohF/tDwV3ntnT5+EkUo4E700q/j/OCDuPxtM+5/kFGjyOai/sK4/We4Cy1MB2OiTQliWU5DxPvYIKQAdPqAA==" }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, "picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -6500,6 +7258,16 @@ "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", "dev": true }, + "png-js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/png-js/-/png-js-1.0.0.tgz", + "integrity": "sha512-k+YsbhpA9e+EFfKjTCH3VW6aoKlyNYI6NYdTfDL4CIvFnvsuO84ttonmZE7rc+v23SLTH8XX+5w/Ak9v0xGY4g==" + }, + "pngjs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", + "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==" + }, "postcss": { "version": "8.4.5", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.5.tgz", @@ -6596,11 +7364,20 @@ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" + }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "qs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==" }, "queue-microtask": { "version": "1.2.3", @@ -6676,6 +7453,33 @@ "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", "dev": true }, + "request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -6720,6 +7524,11 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, "sander": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/sander/-/sander-0.5.1.tgz", @@ -6819,6 +7628,22 @@ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==" }, + "sshpk": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", + "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, "string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -7024,6 +7849,15 @@ "ieee754": "^1.2.1" } }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, "trim-newlines": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-4.0.2.tgz", @@ -7074,6 +7908,19 @@ "tslib": "^1.8.1" } }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -7088,6 +7935,14 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==" }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "requires": { + "is-typedarray": "^1.0.0" + } + }, "typescript": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.4.tgz", @@ -7109,7 +7964,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, "requires": { "punycode": "^2.1.0" } @@ -7119,6 +7973,11 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + }, "v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", @@ -7134,6 +7993,16 @@ "spdx-expression-parse": "^3.0.0" } }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index 9d76e97..96f60bd 100644 --- a/package.json +++ b/package.json @@ -14,10 +14,14 @@ "author": "", "license": "ISC", "dependencies": { + "blockhash": "^0.2.0", "buffer": "^6.0.3", "crc-32": "^1.2.0", "events": "^3.3.0", "file-type": "^17.0.2", + "image-hash": "^5.0.1", + "jpeg-js": "^0.4.3", + "png-js": "^1.0.0", "readable-stream": "^3.6.0", "ts-ebml": "^2.0.2" }, diff --git a/src/Components/App.svelte b/src/Components/App.svelte index ea027b6..96ef5bb 100644 --- a/src/Components/App.svelte +++ b/src/Components/App.svelte @@ -2,7 +2,6 @@ import { hasContext, onDestroy } from 'svelte' import Dialog from './Dialog.svelte' - import Tag from './Tag.svelte' import type { Booru } from '../thirdeye' import Tabs from './Tabs.svelte' @@ -129,6 +128,21 @@ Disable third-eye. {#if !$settings.te} + + {#if $settings.phash} + + {/if}

Booru sources

{#each $settings.rsources as source, i} diff --git a/src/main.ts b/src/main.ts index 6e859d1..bc73666 100644 --- a/src/main.ts +++ b/src/main.ts @@ -27,7 +27,7 @@ import { lolisafe } from "./filehosts"; export interface ImageProcessor { skip?: true; match(fn: string): boolean; - has_embed(b: Buffer, fn?: string): boolean | Promise; + has_embed(b: Buffer, fn?: string, prevurl?: string): boolean | Promise; extract(b: Buffer, fn?: string): EmbeddedFile[] | Promise; inject?(b: File, c: File[]): Buffer | Promise; } @@ -95,13 +95,13 @@ type EmbeddedFileWithoutPreview = { export type EmbeddedFile = EmbeddedFileWithPreview | EmbeddedFileWithoutPreview; -const processImage = async (src: string, fn: string, hex: string, onfound: () => void): Promise<([EmbeddedFile[], boolean] | undefined)[]> => { +const processImage = async (src: string, fn: string, hex: string, prevurl: string, onfound: () => void): Promise<([EmbeddedFile[], boolean] | undefined)[]> => { return Promise.all(processors.filter(e => e.match(fn)).map(async proc => { if (proc.skip) { // skip file downloading, file is referenced from the filename // basically does things like filtering out blacklisted tags const md5 = Buffer.from(hex, 'base64'); - if (await proc.has_embed(md5, fn) === true) { + if (await proc.has_embed(md5, fn, prevurl) === true) { onfound(); return [await proc.extract(md5, fn), true] as [EmbeddedFile[], boolean]; } return; @@ -141,7 +141,10 @@ const processPost = async (post: HTMLDivElement) => { const origlink = qp.getImageLink(post); if (!origlink) return; - let res2 = await processImage(origlink, qp.getFilename(post), qp.getMD5(post), + const thumbLink = qp.getThumbnailLink(post); + if (!thumbLink) + return; + let res2 = await processImage(origlink, qp.getFilename(post), qp.getMD5(post), thumbLink, () => { post.querySelector('.post')?.classList.add("embedfound"); }); @@ -274,7 +277,7 @@ const scrapeBoard = async (self: HTMLButtonElement) => { self.textContent = "Copy Results"; self.disabled = false; self.onclick = () => { - copyTextToClipboard(text); + copyTextToClipboard(text); }; }; diff --git a/src/phash.ts b/src/phash.ts new file mode 100644 index 0000000..2cadbcb --- /dev/null +++ b/src/phash.ts @@ -0,0 +1,68 @@ +const median = (data: number[]) => { + const mdarr = data.slice(0); + mdarr.sort((a, b) => a - b); + if (mdarr.length % 2 === 0) + return (mdarr[mdarr.length / 2 - 1] + mdarr[mdarr.length / 2]) / 2.0; + return mdarr[Math.floor(mdarr.length / 2)]; +}; + +const translate_blocks_to_bits = function (blocks: number[], pixels_per_block: number) { + const half_block_value = pixels_per_block * 256 * 3 / 2; + const bandsize = blocks.length / 4; + + // Compare medians across four horizontal bands + for (let i = 0; i < 4; i++) { + const m = median(blocks.slice(i * bandsize, (i + 1) * bandsize)); + for (let j = i * bandsize; j < (i + 1) * bandsize; j++) { + const v = blocks[j]; + blocks[j] = Number(v > m || (Math.abs(v - m) < 1 && m > half_block_value)); + } + } +}; + +const bits_to_hexhash = (bitsArray: number[]) => { + const hex = []; + for (let i = 0; i < bitsArray.length; i += 4) { + const nibble = bitsArray.slice(i, i + 4); + hex.push(parseInt(nibble.join(''), 2).toString(16)); + } + + return hex.join(''); +}; + +export const bmvbhash_even = (data: { + width: number; + height: number; + data: Uint8Array; +}, bits: number) => { + const blocksize_x = Math.floor(data.width / bits); + const blocksize_y = Math.floor(data.height / bits); + + const result = []; + + for (let y = 0; y < bits; y++) { + for (let x = 0; x < bits; x++) { + let total = 0; + + for (let iy = 0; iy < blocksize_y; iy++) { + for (let ix = 0; ix < blocksize_x; ix++) { + const cx = x * blocksize_x + ix; + const cy = y * blocksize_y + iy; + const ii = (cy * data.width + cx) * 4; + + const alpha = data.data[ii + 3]; + if (alpha === 0) { + total += 765; + } else { + total += data.data[ii] + data.data[ii + 1] + data.data[ii + 2]; + } + } + } + + result.push(total); + } + } + + translate_blocks_to_bits(result, blocksize_x * blocksize_y); + return bits_to_hexhash(result); +}; diff --git a/src/stores.ts b/src/stores.ts index fb39a0c..5bb84d7 100644 --- a/src/stores.ts +++ b/src/stores.ts @@ -23,6 +23,8 @@ export const settings = writable(localLoad('settingsv2', { sh: false, ep: false, expte: false, + mdist: -1, + phash: false, hotlink: false, vercheck: false, fhost: 0, diff --git a/src/thirdeye.ts b/src/thirdeye.ts index fffe92f..f8b1710 100644 --- a/src/thirdeye.ts +++ b/src/thirdeye.ts @@ -2,6 +2,8 @@ import type { EmbeddedFile, ImageProcessor } from "./main"; import { GM_fetch } from "./requests"; import { localLoad, settings } from "./stores"; import { Buffer } from "buffer"; +import jpeg from 'jpeg-js'; +import { bmvbhash_even } from "./phash"; export let csettings: Parameters[0]; settings.subscribe(b => { @@ -50,13 +52,20 @@ const gelquirk: (s: string) => tran = prefix => (a => } as BooruMatch)) || []); let experimentalApi = false; +let black = new Set(); +let phashEn = false; +let mindist = 5; settings.subscribe(s => { experimentalApi = s.expte; boorus = s.rsources.map(e => ({ ...e, quirks: gelquirk(e.view) })); + black = new Set(s.blacklist); + mindist = s.mdist || 5; + phashEn = s.phash; }); + export let boorus: Booru[] = localLoad('settingsv2', { rsources: [] as (Omit & { view: string, disabled?: boolean })[] }) .rsources.map(e => ({ @@ -64,12 +73,6 @@ export let boorus: Booru[] = quirks: gelquirk(e.view) })); -let black = new Set(); - -settings.subscribe(s => { - black = new Set(s.blacklist); -}); - const bufferingTime = 2000; let expired: number | undefined = undefined; type ApiResult = { [md5 in string]: { [domain in string]: BooruMatch[] } }; @@ -157,18 +160,37 @@ const extract = async (b: Buffer, fn?: string) => { const full = result[0].full_url; return [{ source: result[0].source, - page: { title: booru, url: result[0].page }, + page: { + title: booru, + url: result[0].page + }, filename: fn!.substring(0, 33) + result[0].ext, - thumbnail: (await (await GM_fetch(prev || full)).arrayBuffer()), // prefer preview - data: csettings.hotlink ? (full || prev) : async (lsn) => { + thumbnail: (await (await GM_fetch(prev || full)).arrayBuffer()), + data: csettings.hotlink ? (full || prev) : (async (lsn) => { if (!cachedFile) - cachedFile = (await (await GM_fetch(full || prev, undefined, lsn)).arrayBuffer()); // prefer full + cachedFile = (await (await GM_fetch(full || prev, undefined, lsn)).arrayBuffer()); return cachedFile; - } + }) } as EmbeddedFile]; }; -const has_embed = async (b: Buffer, fn?: string) => { +const phash = (b: Buffer) => { + const res = jpeg.decode(b); + return bmvbhash_even(res, 8); +}; + +// a & b are hex strings +const hammingDist = (a: string, b: string) => { + let res = BigInt('0x' + a) ^ BigInt('0x' + b); + let acc = 0; + while (res != 0n) { + acc += Number(res & 1n); + res >>= 1n; + } + return acc; +}; + +const has_embed = async (b: Buffer, fn?: string, prevlink?: string) => { // It's not worth to bother skipping images with filenames that match their md5 because // 4chan reencodes jpegs, which is well over half the files posted @@ -185,6 +207,22 @@ const has_embed = async (b: Buffer, fn?: string) => { if (result.length) break; } + + if ((result && result.length != 0) && phashEn && prevlink) { + const getHash = async (l: string) => { + const ogreq = await GM_fetch(l); + const origPreview = await ogreq.arrayBuffer(); + return await phash(Buffer.from(origPreview)); + }; + const [orighash, tehash] = await Promise.all([ + getHash(prevlink), + getHash(result[0].preview_url) + ]); + const d = hammingDist(orighash, tehash); + console.log(d, prevlink); + return d > mindist; + } + return result && result.length != 0; }; diff --git a/src/websites/index.ts b/src/websites/index.ts index 289594b..1939910 100644 --- a/src/websites/index.ts +++ b/src/websites/index.ts @@ -5,6 +5,7 @@ export type QueryProcessor = { settingsHost: () => HTMLSpanElement; catalogControlHost: () => HTMLDivElement; getImageLink: (post: HTMLElement) => string; + getThumbnailLink: (post: HTMLElement) => string; getFilename: (post: HTMLElement) => string; getMD5: (post: HTMLElement) => string; getInfoBox: (post: HTMLElement) => HTMLElement; @@ -24,6 +25,7 @@ export const V4chan: QueryProcessor = { return a?.textContent || ''; }, getMD5: (post: HTMLElement) => post.querySelector("img[data-md5]")?.getAttribute("data-md5") || '', + getThumbnailLink: (post: HTMLElement) => post.querySelector("img[data-md5]")?.getAttribute("src") || '', getInfoBox: post => post.querySelector("div.fileText")! }; @@ -40,6 +42,7 @@ export const X4chan: QueryProcessor = { return (origlink.querySelector('.fnfull') || origlink)?.textContent || ''; }, getMD5: (post: HTMLElement) => post.querySelector("img[data-md5]")?.getAttribute("data-md5") || '', + getThumbnailLink: (post: HTMLElement) => post.querySelector("img[data-md5]")?.getAttribute("src") || '', getInfoBox: post => post.querySelector("span.file-info")! }; @@ -58,6 +61,7 @@ export const FoolFuuka: QueryProcessor = { return a?.title || ''; }, getMD5: (post: HTMLElement) => post.querySelector("img[data-md5]")?.getAttribute("data-md5") || '', + getThumbnailLink: (post: HTMLElement) => post.querySelector("img[data-md5]")?.getAttribute("src") || '', getInfoBox: post => post.querySelector("span.post_controls")! };