chore: switch from unzipper to yauzl-promise

This commit is contained in:
Jonathan Barrow
2025-09-02 18:04:07 -04:00
parent a088c29822
commit 1ef20edd72
3 changed files with 310 additions and 131 deletions

View File

@@ -1,63 +1,10 @@
const { Readable } = require('node:stream');
const { pipeline } = require('node:stream/promises');
const fs = require('node:fs');
const path = require('node:path');
const unzipper = require('unzipper');
const yauzl = require('yauzl-promise');
require('dotenv').config();
// * unzipper wants to use the "request" module, which is deprecated and insecure.
// * Just wrap native fetch to avoid another dependancy here
// TODO - This is kinda ugly, can this be better?
function request(options) {
const url = typeof options === 'string' ? options : options.url;
const headers = options.headers || {};
const stream = new Readable({
read() {} // * Noop. Push data manually
});
fetch(url, { headers }).then((response) => {
if (!response.ok) {
const error = new Error(`HTTP ${response.status}: ${response.statusText}`);
error.statusCode = response.status;
stream.emit('error', error);
return;
}
stream.emit('response', {
statusCode: response.status,
headers: Object.fromEntries(response.headers.entries())
});
const reader = response.body.getReader();
function pump() {
reader.read().then(({ done, value }) => {
if (done) {
stream.push(null);
} else {
stream.push(Buffer.from(value));
pump();
}
}).catch((error) => {
stream.emit('error', error);
});
}
pump();
}).catch((error) => {
stream.emit('error', error);
});
stream.abort = function () {
stream.destroy();
};
return stream;
}
const databases = {
DB3LITEBIN: {
file_name: 'IP2LOCATION-LITE-DB3.BIN',
@@ -72,10 +19,24 @@ const databases = {
async function main() {
for (const name in databases) {
const database = databases[name];
const directory = await unzipper.Open.url(request, `https://www.ip2location.com/download/?token=${process.env.PN_ACT_CONFIG_IP2LOCATION_TOKEN}&file=${name}`);
const file = directory.files.find(file => file.path === database.file_name);
const content = await file.buffer();
fs.writeFileSync(database.save_path, content);
const response = await fetch(`https://www.ip2location.com/download/?token=${process.env.PN_ACT_CONFIG_IP2LOCATION_TOKEN}&file=${name}`);
const arrayBuffer = await response.arrayBuffer();
const buffer = Buffer.from(arrayBuffer);
const zip = await yauzl.fromBuffer(buffer);
try {
for await (const entry of zip) {
console.log(entry.filename);
if (entry.filename === database.file_name) {
const readStream = await entry.openReadStream();
const writeStream = fs.createWriteStream(database.save_path);
await pipeline(readStream, writeStream);
}
}
} finally {
await zip.close();
}
}
}