mirror of
https://github.com/dessant/buster.git
synced 2024-11-18 03:25:42 +00:00
42149b35b7
BREAKING CHANGE: browser versions older than Chrome 123, Edge 123, Firefox 115 and Opera 109 are no longer supported
288 lines
7.5 KiB
JavaScript
Executable File
288 lines
7.5 KiB
JavaScript
Executable File
const path = require('node:path');
|
|
const {exec} = require('node:child_process');
|
|
const {
|
|
lstatSync,
|
|
readdirSync,
|
|
readFileSync,
|
|
writeFileSync,
|
|
rmSync
|
|
} = require('node:fs');
|
|
|
|
const {series, parallel, src, dest} = require('gulp');
|
|
const postcss = require('gulp-postcss');
|
|
const gulpif = require('gulp-if');
|
|
const jsonMerge = require('gulp-merge-json');
|
|
const jsonmin = require('gulp-jsonmin');
|
|
const htmlmin = require('gulp-htmlmin');
|
|
const imagemin = require('gulp-imagemin');
|
|
const {ensureDirSync, readJsonSync} = require('fs-extra');
|
|
const sharp = require('sharp');
|
|
const CryptoJS = require('crypto-js');
|
|
|
|
const appVersion = require('./package.json').version;
|
|
|
|
const targetEnv = process.env.TARGET_ENV || 'chrome';
|
|
const isProduction = process.env.NODE_ENV === 'production';
|
|
const enableContributions =
|
|
(process.env.ENABLE_CONTRIBUTIONS || 'true') === 'true';
|
|
|
|
const mv3 = ['chrome'].includes(targetEnv);
|
|
|
|
const distDir = path.join(__dirname, 'dist', targetEnv);
|
|
|
|
function initEnv() {
|
|
process.env.BROWSERSLIST_ENV = targetEnv;
|
|
}
|
|
|
|
function init(done) {
|
|
initEnv();
|
|
|
|
rmSync(distDir, {recursive: true, force: true});
|
|
ensureDirSync(distDir);
|
|
done();
|
|
}
|
|
|
|
function js(done) {
|
|
exec('webpack-cli build --color', function (err, stdout, stderr) {
|
|
console.log(stdout);
|
|
console.log(stderr);
|
|
done(err);
|
|
});
|
|
}
|
|
|
|
function html() {
|
|
const htmlSrc = ['src/**/*.html'];
|
|
|
|
if (mv3) {
|
|
htmlSrc.push('!src/background/*.html');
|
|
}
|
|
|
|
if (!enableContributions) {
|
|
htmlSrc.push('!src/contribute/*.html');
|
|
}
|
|
|
|
if (!(mv3 && !['firefox', 'safari'].includes(targetEnv))) {
|
|
htmlSrc.push('!src/offscreen/*.html');
|
|
}
|
|
|
|
return src(htmlSrc, {base: '.'})
|
|
.pipe(gulpif(isProduction, htmlmin({collapseWhitespace: true})))
|
|
.pipe(dest(distDir));
|
|
}
|
|
|
|
function css() {
|
|
return src('src/base/*.css', {base: '.'}).pipe(postcss()).pipe(dest(distDir));
|
|
}
|
|
|
|
async function images(done) {
|
|
ensureDirSync(path.join(distDir, 'src/assets/icons/app'));
|
|
const appIconSvg = readFileSync('src/assets/icons/app/icon.svg');
|
|
const appIconSizes = [16, 19, 24, 32, 38, 48, 64, 96, 128];
|
|
if (targetEnv === 'safari') {
|
|
appIconSizes.push(256, 512, 1024);
|
|
}
|
|
for (const size of appIconSizes) {
|
|
await sharp(appIconSvg, {density: (72 * size) / 24})
|
|
.resize(size)
|
|
.toFile(path.join(distDir, `src/assets/icons/app/icon-${size}.png`));
|
|
}
|
|
|
|
// Chrome Web Store does not correctly display optimized icons
|
|
if (isProduction && targetEnv !== 'chrome') {
|
|
await new Promise(resolve => {
|
|
src(path.join(distDir, 'src/assets/icons/app/*.png'), {
|
|
base: '.',
|
|
encoding: false
|
|
})
|
|
.pipe(imagemin())
|
|
.pipe(dest('.'))
|
|
.on('error', done)
|
|
.on('finish', resolve);
|
|
});
|
|
}
|
|
|
|
await new Promise(resolve => {
|
|
src('src/assets/icons/@(app|misc)/*.@(png|svg)', {
|
|
base: '.',
|
|
encoding: false
|
|
})
|
|
.pipe(gulpif(isProduction, imagemin()))
|
|
.pipe(dest(distDir))
|
|
.on('error', done)
|
|
.on('finish', resolve);
|
|
});
|
|
|
|
if (enableContributions) {
|
|
await new Promise(resolve => {
|
|
src(
|
|
'node_modules/vueton/components/contribute/assets/*.@(png|webp|svg)',
|
|
{encoding: false}
|
|
)
|
|
.pipe(gulpif(isProduction, imagemin()))
|
|
.pipe(dest(path.join(distDir, 'src/contribute/assets')))
|
|
.on('error', done)
|
|
.on('finish', resolve);
|
|
});
|
|
}
|
|
}
|
|
|
|
async function fonts(done) {
|
|
await new Promise(resolve => {
|
|
src('src/assets/fonts/roboto.css', {base: '.'})
|
|
.pipe(postcss())
|
|
.pipe(dest(distDir))
|
|
.on('error', done)
|
|
.on('finish', resolve);
|
|
});
|
|
|
|
await new Promise(resolve => {
|
|
src(
|
|
'node_modules/@fontsource/roboto/files/roboto-latin-@(400|500|700)-normal.woff2',
|
|
{encoding: false}
|
|
)
|
|
.pipe(dest(path.join(distDir, 'src/assets/fonts/files')))
|
|
.on('error', done)
|
|
.on('finish', resolve);
|
|
});
|
|
}
|
|
|
|
async function locale(done) {
|
|
const localesRootDir = path.join(__dirname, 'src/assets/locales');
|
|
const localeDirs = readdirSync(localesRootDir).filter(function (file) {
|
|
return lstatSync(path.join(localesRootDir, file)).isDirectory();
|
|
});
|
|
for (const localeDir of localeDirs) {
|
|
const localePath = path.join(localesRootDir, localeDir);
|
|
await new Promise(resolve => {
|
|
src(
|
|
[
|
|
path.join(localePath, 'messages.json'),
|
|
path.join(localePath, `messages-${targetEnv}.json`)
|
|
],
|
|
{allowEmpty: true}
|
|
)
|
|
.pipe(
|
|
jsonMerge({
|
|
fileName: 'messages.json',
|
|
edit: (parsedJson, file) => {
|
|
if (isProduction) {
|
|
for (let [key, value] of Object.entries(parsedJson)) {
|
|
if (value.hasOwnProperty('description')) {
|
|
delete parsedJson[key].description;
|
|
}
|
|
}
|
|
}
|
|
return parsedJson;
|
|
}
|
|
})
|
|
)
|
|
.pipe(gulpif(isProduction, jsonmin()))
|
|
.pipe(dest(path.join(distDir, '_locales', localeDir)))
|
|
.on('error', done)
|
|
.on('finish', resolve);
|
|
});
|
|
}
|
|
}
|
|
|
|
function manifest() {
|
|
return src(`src/assets/manifest/${targetEnv}.json`)
|
|
.pipe(
|
|
jsonMerge({
|
|
fileName: 'manifest.json',
|
|
edit: (parsedJson, file) => {
|
|
parsedJson.version = appVersion;
|
|
return parsedJson;
|
|
}
|
|
})
|
|
)
|
|
.pipe(gulpif(isProduction, jsonmin()))
|
|
.pipe(dest(distDir));
|
|
}
|
|
|
|
function license(done) {
|
|
let year = '2018';
|
|
const currentYear = new Date().getFullYear().toString();
|
|
if (year !== currentYear) {
|
|
year = `${year}-${currentYear}`;
|
|
}
|
|
|
|
let notice = `Buster: Captcha Solver for Humans
|
|
Copyright (c) ${year} Armin Sebastian
|
|
`;
|
|
|
|
if (['safari', 'samsung'].includes(targetEnv)) {
|
|
writeFileSync(path.join(distDir, 'NOTICE'), notice);
|
|
done();
|
|
} else {
|
|
notice = `${notice}
|
|
This software is released under the terms of the GNU General Public License v3.0.
|
|
See the LICENSE file for further information.
|
|
`;
|
|
writeFileSync(path.join(distDir, 'NOTICE'), notice);
|
|
return src('LICENSE').pipe(dest(distDir));
|
|
}
|
|
}
|
|
|
|
function secrets(done) {
|
|
try {
|
|
let data = process.env.BUSTER_SECRETS;
|
|
if (data) {
|
|
data = JSON.parse(data);
|
|
} else {
|
|
data = readJsonSync('secrets.json');
|
|
}
|
|
data = JSON.stringify(data);
|
|
|
|
const key = CryptoJS.SHA256(
|
|
readFileSync(path.join(distDir, 'src/background/script.js')).toString() +
|
|
readFileSync(path.join(distDir, 'src/base/script.js')).toString()
|
|
).toString();
|
|
|
|
const ciphertext = CryptoJS.AES.encrypt(data, key).toString();
|
|
|
|
writeFileSync(path.join(distDir, 'secrets.txt'), ciphertext);
|
|
} catch (err) {
|
|
console.log(
|
|
'Secrets are missing, secrets.txt will not be included in the extension package.'
|
|
);
|
|
}
|
|
|
|
done();
|
|
}
|
|
|
|
function zip(done) {
|
|
exec(
|
|
`web-ext build -s dist/${targetEnv} -a artifacts/${targetEnv} -n "{name}-{version}-${targetEnv}.zip" --overwrite-dest`,
|
|
function (err, stdout, stderr) {
|
|
console.log(stdout);
|
|
console.log(stderr);
|
|
done(err);
|
|
}
|
|
);
|
|
}
|
|
|
|
function inspect(done) {
|
|
initEnv();
|
|
|
|
exec(
|
|
`npm run build:prod:chrome && \
|
|
webpack --profile --json > report.json && \
|
|
webpack-bundle-analyzer --mode static report.json dist/chrome/src && \
|
|
sleep 3 && rm report.{json,html}`,
|
|
function (err, stdout, stderr) {
|
|
console.log(stdout);
|
|
console.log(stderr);
|
|
done(err);
|
|
}
|
|
);
|
|
}
|
|
|
|
exports.build = series(
|
|
init,
|
|
parallel(js, html, css, images, fonts, locale, manifest, license),
|
|
secrets
|
|
);
|
|
exports.zip = zip;
|
|
exports.inspect = inspect;
|
|
exports.secrets = secrets;
|