verstak/scripts/download-signed-xpi.js

102 lines
3.2 KiB
JavaScript

const jwt = require('jsonwebtoken');
const http = require('http');
const { execSync } = require('child_process');
const fs = require('fs');
const KEY = 'user:1022172:47';
const SECRET = 'da4e4367277668aa6e048b0a04d1a417ba8bad630f4ac37ccdcea064a9de151e';
function makeJWT() {
return jwt.sign({
iss: KEY, jti: Math.random().toString(36).slice(2),
iat: Math.floor(Date.now() / 1000), exp: Math.floor(Date.now() / 1000) + 300
}, SECRET);
}
function proxyGet(url, auth) {
return new Promise((resolve, reject) => {
const u = new URL(url);
const req = http.request({
hostname: 'localhost', port: 12334,
path: url, method: 'GET',
headers: { 'Host': u.hostname, 'Authorization': auth }
}, res => {
const chunks = [];
res.on('data', c => chunks.push(c));
res.on('end', () => resolve({ status: res.statusCode, body: Buffer.concat(chunks) }));
});
req.on('error', reject);
req.end();
});
}
async function main() {
const token = makeJWT();
const auth = 'JWT ' + token;
const versionId = 6297193;
const addonId = 'verstak-bridge@verstak.app';
// Get full version details
console.log('==> Getting full version details...');
const url = `https://addons.mozilla.org/api/v5/addons/addon/${addonId}/versions/${versionId}/`;
const res = await proxyGet(url, auth);
const data = JSON.parse(res.body.toString());
// The file info is in data.file (singular), not data.files
const file = data.file;
if (!file) {
console.log('No file object in response');
process.exit(1);
}
console.log(` File ID: ${file.id}`);
console.log(` Status: ${file.status}`);
console.log(` Size: ${file.size}`);
console.log(` Hash: ${file.hash}`);
console.log(` URL: ${file.url}`);
console.log(` Download URL: ${file.download_url || file.url}`);
const downloadUrl = file.download_url || file.url;
if (!downloadUrl) {
console.log('No download URL found');
console.log('Full file object:', JSON.stringify(file, null, 2));
process.exit(1);
}
// Download
console.log(`==> Downloading signed XPI...`);
fs.mkdirSync('release/firefox', { recursive: true });
const outPath = 'release/firefox/verstak-firefox-1.0.1.xpi';
try {
execSync(
`curl -s -x http://localhost:12334 -L "${downloadUrl}" -H "Authorization: ${auth}" -H "User-Agent: verstak-release/1.0" -o "${outPath}"`,
{ timeout: 60000 }
);
const size = fs.statSync(outPath).size;
console.log(` Saved: ${outPath} (${(size / 1024).toFixed(1)} KB)`);
// Verify ZIP magic
const fd = fs.openSync(outPath, 'r');
const magic = Buffer.alloc(4);
fs.readSync(fd, magic, 0, 4, 0);
fs.closeSync(fd);
const isZip = magic[0] === 0x50 && magic[1] === 0x4B;
console.log(` ZIP magic: ${isZip ? 'VALID ✓' : 'INVALID ✗'} (${magic.toString('hex')})`);
if (!isZip || size < 1000) {
console.log(' WARNING: File may not be a valid XPI');
console.log(' Content:', fs.readFileSync(outPath).toString('utf8').substring(0, 200));
process.exit(1);
}
console.log('==> DONE ✓');
} catch (e) {
console.error(' Download failed:', e.message);
process.exit(1);
}
}
main().catch(e => { console.error('FATAL:', e.message); process.exit(1); });