2019-02-09 00:02:19 -05:00
|
|
|
const process = require('process');
|
|
|
|
const needle = require('needle');
|
|
|
|
const cheerio = require('cheerio');
|
|
|
|
const minimist = require('minimist');
|
|
|
|
|
|
|
|
const config = minimist(process.argv.slice(2), {default: {
|
|
|
|
root: 'https://content.minetest.net/',
|
|
|
|
user: false,
|
|
|
|
pass: false,
|
|
|
|
pkg: false,
|
|
|
|
version: false,
|
|
|
|
min: 'none',
|
|
|
|
max: 'none',
|
2019-03-29 06:17:05 -04:00
|
|
|
branch: 'master',
|
|
|
|
timeout: 60,
|
|
|
|
poll: 2
|
2019-02-09 00:02:19 -05:00
|
|
|
}});
|
|
|
|
const missing = [];
|
|
|
|
Object.keys(config).sort().forEach(k => {
|
|
|
|
if(k === '_') return;
|
|
|
|
const v = config[k];
|
2019-03-29 06:17:05 -04:00
|
|
|
if(!v || v === false)
|
2019-02-09 00:02:19 -05:00
|
|
|
missing.push(k);
|
|
|
|
});
|
|
|
|
if(missing.length)
|
|
|
|
throw 'missing/invalid options: ' + missing.join(', ');
|
|
|
|
config.root = config.root.replace(/\/+$/, '');
|
|
|
|
|
|
|
|
const cookiejar = {};
|
|
|
|
async function fetch(uri, meth, data, opts, ref, ...rest) {
|
|
|
|
meth = meth || 'get';
|
|
|
|
opts = opts || {};
|
|
|
|
opts.headers = opts.headers || {};
|
|
|
|
opts.headers.Referer = 'https://content.minetest.net';
|
|
|
|
opts.cookies = cookiejar;
|
|
|
|
const r = await needle(meth, uri, data, opts, ...rest);
|
|
|
|
if(r.cookies)
|
|
|
|
Object.keys(r.cookies).forEach(k => cookiejar[k] = r.cookies[k]);
|
|
|
|
const $ = cheerio.load(r.body.toString());
|
|
|
|
let err;
|
|
|
|
$('h1').each(function() {
|
|
|
|
const t = $(this).text();
|
|
|
|
if(/^\s*Oops!/.test(t))
|
|
|
|
err = t;
|
|
|
|
});
|
|
|
|
if(err) throw err;
|
|
|
|
return $;
|
|
|
|
}
|
|
|
|
|
|
|
|
function getfields($, sel) {
|
|
|
|
const fields = {};
|
|
|
|
$('input').each(function() {
|
|
|
|
const e = $(this);
|
|
|
|
const n = e.attr('name');
|
|
|
|
if(!n) return;
|
|
|
|
const v = e.attr('value');
|
|
|
|
if(v) fields[n] = v;
|
|
|
|
});
|
|
|
|
return fields;
|
|
|
|
}
|
|
|
|
|
|
|
|
async function login() {
|
|
|
|
const uri = config.root + '/user/sign-in';
|
2019-03-29 06:17:05 -04:00
|
|
|
console.log('fetching sign-in page...');
|
2019-02-09 00:02:19 -05:00
|
|
|
let $ = await fetch(uri);
|
|
|
|
const fields = getfields($);
|
|
|
|
fields.username = config.user;
|
|
|
|
fields.password = config.pass;
|
2019-03-29 06:17:05 -04:00
|
|
|
console.log('submitting sign-in form...');
|
2019-02-09 00:02:19 -05:00
|
|
|
$ = await fetch(uri, 'post', fields);
|
|
|
|
let success;
|
|
|
|
$('h1').each(function() {
|
|
|
|
success = success || /^\s*Redirecting\b/i.test($(this).text());
|
|
|
|
});
|
|
|
|
if(!success) throw $('body').text();
|
|
|
|
}
|
|
|
|
|
2019-03-29 06:17:05 -04:00
|
|
|
async function checkalready() {
|
2019-02-09 00:02:19 -05:00
|
|
|
const uri = config.root + '/packages/' + config.user + '/' + config.pkg + '/';
|
2019-03-29 06:17:05 -04:00
|
|
|
console.log('fetching release list...');
|
2019-02-09 00:02:19 -05:00
|
|
|
let $ = await fetch(uri);
|
2019-03-29 06:17:05 -04:00
|
|
|
let already;
|
2019-02-09 00:02:19 -05:00
|
|
|
$('a').each(function() {
|
2019-03-29 06:17:05 -04:00
|
|
|
if(already) return;
|
2019-02-09 00:02:19 -05:00
|
|
|
const a = $(this);
|
|
|
|
const h = a.attr('href');
|
|
|
|
if(!h || !/\/releases\/\d+\/download\//.test(h)) return;
|
2019-03-29 06:17:05 -04:00
|
|
|
if(a.text().trim() === config.version.trim())
|
|
|
|
already = true;
|
2019-02-09 00:02:19 -05:00
|
|
|
});
|
2019-03-29 06:17:05 -04:00
|
|
|
return already;
|
2019-02-09 00:02:19 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
function findversion($, sel, name) {
|
|
|
|
let v;
|
|
|
|
$(sel).each(function() {
|
|
|
|
const o = $(this);
|
|
|
|
const t = o.text();
|
|
|
|
if(t.toLowerCase() === name.toLowerCase())
|
|
|
|
v = o.attr('value');
|
|
|
|
});
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
|
|
|
async function makerelease() {
|
|
|
|
const uri = config.root + '/packages/' + config.user + '/' + config.pkg + '/releases/new/';
|
2019-03-29 06:17:05 -04:00
|
|
|
console.log('fetching new release page...');
|
2019-02-09 00:02:19 -05:00
|
|
|
let $ = await fetch(uri);
|
|
|
|
const fields = getfields($);
|
|
|
|
fields.min_rel = findversion($, 'select#min_rel option', config.min);
|
|
|
|
fields.max_rel = findversion($, 'select#max_rel option', config.max);
|
|
|
|
fields.vcsLabel = config.branch;
|
|
|
|
fields.uploadOpt = 'vcs';
|
|
|
|
fields.title = config.version;
|
2019-03-29 06:17:05 -04:00
|
|
|
console.log('submitting new release...');
|
2019-02-09 00:02:19 -05:00
|
|
|
$ = await fetch(uri, 'post', fields, {follow_max: 10});
|
|
|
|
}
|
|
|
|
|
|
|
|
(async () => {
|
2019-03-29 06:17:05 -04:00
|
|
|
await login();
|
|
|
|
console.log('checking if new version is already released...');
|
|
|
|
if(await checkalready()) {
|
2019-02-09 00:02:19 -05:00
|
|
|
console.log('version ' + config.version + ' already released');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
await makerelease();
|
2019-03-29 06:17:05 -04:00
|
|
|
console.log('waiting for new submission to be listed...');
|
|
|
|
for(let i = 0; i < config.timeout; i += config.poll) {
|
|
|
|
if(await checkalready()) {
|
|
|
|
console.log('version ' + config.version + ' release successful');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
await new Promise(r => setTimeout(r, config.poll * 1000));
|
|
|
|
}
|
2019-02-09 00:02:19 -05:00
|
|
|
})();
|