#!/usr/bin/env node
var program = require('commander');
var request = require('superagent');
var uuid = require('uuid');
var fs = require('fs');
var mkdirp = require('mkdirp');
var async = require('async');
var package = require('./package.json');
program
.version(package.version)
.option('-q, --query [requete]', "La requete (?q=) ", '*')
.option('-c, --corpus [corpus]', "Le corpus souhaité (ex: springer, ecco, ...)", 'istex')
.option('-s, --size [size]', "Quantité de documents à télécharger", 10)
.option('-f, --file [file]', "Fichier contenant tous les mots-clés à rechercher", null)
.option('-o, --output [folder]', "Dossier où seront stockés les fichiers en sortie", null)
.option('-ft, --fulltext [0|1]', "Pour retourner ou pas le plein texte", 0)
.option('-zip, --zip [0|1]', "Pour retourner l'ensemble des fichiers trouvés archivés en zip", 0)
.option('-v, --verbose', "Affiche plus d'informations", false)
.parse(process.argv);
var dstPath = (program.output) ? program.output : process.cwd() + '/' + program.corpus;
mkdirp.sync(dstPath);
var zipName = process.cwd() + '/' + uuid.v1() + '.zip';
var zip = new require('node-zip')();
var data;
// découpe le téléchargement par pages
// pour éviter de faire une énorme requête
var nbHitPerPage = 100;
var nbPages = Math.floor(program.size / nbHitPerPage);
var nbLastPage = program.size - (nbPages * nbHitPerPage);
var ranges = [];
for (var page = 0; page < nbPages; page++) {
ranges.push([page * nbHitPerPage, nbHitPerPage]);
};
ranges.push([nbPages * nbHitPerPage, nbLastPage]);
// si fichier en paramètre, on récupère les mots-clés
if (program.file) {
try {
var raw = fs.readFileSync(program.file, 'utf-8');
var keywords = raw.split('\n'); // Un mot-clé par ligne
var queryFile = '';
for (i = 0; i < keywords.length; i++) {
queryFile += (keywords[i] != '') ? keywords[i] + ' OR ' : ''; // On vérifie qu'il ne s'agit pas d'un mot clé vide
}
program.query = (program.query != '*') ? queryFile + program.query : queryFile.slice(0, -4); // Suppression du dernier OR
} catch (e) {
console.error('Le fichier en paramètre ne peut pas être lu : ' + e);
}
}
// lance les recherches et les téléchargements
console.log("Téléchargement des " + program.size +
" premiers documents (metadata & fulltext) ici : " + dstPath);
// télécharge page par page
var firstPage = true;
async.mapLimit(ranges, 1, function(range, cb) {
downloadPage(range, cb, function(body) {
if (firstPage) {
console.log("Nombre de documents dans le corpus " + program.corpus + " : " + body.total);
firstPage = false;
}
console.log('Téléchargement de la page ' +
(range[0] / nbHitPerPage + 1) + ' (' + (range[0] + range[1]) + ' documents)');
});
}, function(err) {
if (err) return console.log(err);
console.log('Téléchargements terminés');
if (program.zip) {
var data = zip.generate({
base64: false,
compression: 'DEFLATE'
});
fs.writeFileSync(zipName, data, 'binary');
fs.rmdirSync(dstPath);
}
});
var supportedTypes = ['all', 'txt', 'raw', 'pdf', 'tei', 'mods', 'tif', 'tiff', 'png', 'jpg', 'jpeg', 'zip', 'xml', 'html', 'gif'];
//
// Fonction de téléchargement d'une page
//
function downloadPage(range, cb, cbBody) {
var url = 'https://api.istex.fr/document/?q=' + program.query + '&output=metadata' + (program.fulltext != 0 ? ',fulltext' : '') + ((program.corpus == 'istex') ? '' : ('&corpus=' + program.corpus)) + '&from=' + range[0] + '&size=' + range[1];
console.log(url);
// to ignore bad https certificate
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
var agent = request.agent();
agent
.get(url)
.end(function(err, res) {
if (err) {
return cb(new Error(err));
}
if (!res || !res.body || !res.body.hits) {
return cb(new Error('Response error: statusCode=' + res.statusCode));
}
// transmission du body pour les messages
cbBody(res.body);
// lancement des téléchargement de façon séquentielle
async.mapLimit(res.body.hits, 1, function(item1, cb2) {
// extract the MODS from the returned JSON
var mods = {
url: '',
filename: item1.id + '.mods.xml'
};
item1.metadata.forEach(function(item2) {
if (item2.type && item2.type == 'mods') {
mods.url = item2.uri;
}
});
if (program.fulltext) {
var wantedType = (supportedTypes.indexOf(program.fulltext.toLowerCase()) >= 0) ? program.fulltext.toLowerCase() : "pdf";
if (program.fulltext)
// extract the fulltext from the returned JSON
var fulltext = [];
item1.fulltext.forEach(function(item2) {
if (wantedType == 'all' || item2.type == wantedType) {
fulltext.push({
url: '' + item2.uri,
filename: '' + item1.id + '.' + item2.type
});
}
});
}
// download the document (MODS and fulltext)
async.series([
// download the MODS
function(callback) {
var stream = fs.createWriteStream(dstPath + '/' + mods.filename);
var req = request.get(mods.url);
req.pipe(stream);
stream.on('finish', function() {
if (program.verbose) {
console.log(mods.filename);
}
// Si zip, on ajoute le fichier dedans et on supprime le fichier récupéré
if (program.zip) zippage(mods.filename);
callback(null);
});
stream.on('error', callback);
},
// download the fulltext
function(callback) {
if (!program.fulltext) return callback(null);
console.log(fulltext);
if (Array.isArray(fulltext)) {
async.map(fulltext, function(fulltextItem, cbMap) {
var stream = fs.createWriteStream(dstPath + '/' + fulltextItem.filename);
var req = request.get(fulltextItem.url);
req.pipe(stream);
stream.on('finish', function() {
if (program.verbose) {
console.log(fulltextItem.filename);
}
// Si zip, on ajoute le fichier dedans et on supprime le fichier récupéré
if (program.zip) zippage(fulltextItem.filename);
cbMap(null);
});
stream.on('error', cbMap);
}, function(err, results) {
callback(null);
});
} else {
callback(null);
}
},
],
function(err) {
// MODS and fulltext downloaded
process.stdout.write('.');
cb2(err);
});
},
function(err) {
console.log('');
// page downloaded
cb(err, res.body);
});
});
}
//
// Fonction de zippage
//
function zippage(filename) {
zip.file(filename, fs.readFileSync(dstPath + '/' + filename));
fs.unlinkSync(dstPath + '/' + filename); // Suppression du fichier après compression
}