echolist-csv2hpt
Version:
Copies Fidonet echomail area descriptions from a CSV echolist to an HPT areas file.
180 lines (159 loc) • 6.19 kB
JavaScript
var fs = require('fs');
var path = require('path');
var iconv = require('iconv-lite');
var clog = console.log;
// tribute to the “R.O.D” 2001—2002 anime OVA
var readOrDie = function(filename, encoding, rusMode){
try {
return iconv.decode( fs.readFileSync(filename), encoding );
} catch(err) {
clog('');
if( rusMode ){
clog('Файл ' + filename + ' не может быть прочитан.');
} else {
clog('File ' + filename + ' cannot be read.');
}
clog('');
throw err;
}
};
var writeOrDie = function(filename, content, encoding, rusMode){
try {
fs.writeFileSync(filename, iconv.encode(content, encoding));
} catch(err) {
clog('');
if( rusMode ){
clog('Файл ' + filename + ' не может быть записан.');
} else {
clog('File ' + filename + ' cannot be written.');
}
clog('');
throw err;
}
};
var getDescriptionElementFromContentCSV = function(contentCSV, lcEchotag){
return contentCSV.map(function(fileCSV){
var foundElement = fileCSV.find(
elementCSV => elementCSV.lcEchotag === lcEchotag
);
if( typeof foundElement === 'undefined' ) return null;
return foundElement;
}).filter( nextElement => nextElement !== null )[0];
};
module.exports = function(filenamesCSV, filenameHPT, options){
filenamesCSV = filenamesCSV.map(
nextFilename => path.resolve(__dirname, nextFilename)
);
filenameHPT = path.resolve(__dirname, filenameHPT);
var contentCSV = filenamesCSV.map(function(nextFilename){
return readOrDie(
nextFilename, options.inputEncoding, options.rusMode
).split(/(?:\r|\n)+/).map(function(nextLine){
if( nextLine.length < 1 ) return null; // empty line
if( nextLine.indexOf(';') === 0 ) return null; // comment line
var lineParts = nextLine.split(',');
if( lineParts.length !== 6 ){
clog('');
if( options.rusMode ){
clog('В файле ' + nextFilename);
clog('обнаружена строка с неожиданным количеством запятых:');
} else {
clog('In the file ' + nextFilename);
clog('a line with unexpected number of commas is detected:');
}
clog(nextLine);
if( options.rusMode ){
clog('Эта строка проигнорирована.');
} else {
clog('That line is ignored.');
}
return null; // weird line
}
return {
lcEchotag: lineParts[1].toLowerCase(),
description: lineParts[2].replace(/"/g, '') // kill double quotes
};
}).filter( nextLine => nextLine !== null );
});
var contentHPT = readOrDie(
filenameHPT, options.outputEncoding, options.rusMode
).split(/([\r\n]+)/).map(function(nextLine, idx){
if( idx % 2 === 1 ) return nextLine; // line separator's index: 1, 3, 5…
var lineParts = nextLine.split(/(\s+)/);
var echoAreaLine = (
lineParts[0].length > 0 &&
lineParts[0].toLowerCase() === 'echoarea' &&
typeof lineParts[2] !== 'undefined' && // echotag element
typeof lineParts[4] !== 'undefined' // path element
) || (
lineParts[0].length < 1 &&
typeof lineParts[2] !== 'undefined' &&
lineParts[2].toLowerCase() === 'echoarea' &&
typeof lineParts[4] !== 'undefined' && // echotag element
typeof lineParts[6] !== 'undefined' // path element
);
if( !echoAreaLine ) return nextLine; // not an echoarea line
var lcEchotagHPT;
if( lineParts.indexOf('-d') > -1 || lineParts.indexOf('-D') > -1 ){
// this echoarea line already has a description
if(!( options.replaceMode )) return nextLine;
// entered the mode of replacement
var parts = /^(\s*EchoArea\s+)(\S+)(\s.+\s-d\s+")([^"]+)(".*)$/.exec(
nextLine
);
if( parts === null ){
clog('');
if( options.rusMode ){
clog('В файле ' + filenameHPT);
clog('обнаружен неожиданный формат описания области:');
} else {
clog('In the file ' + filenameHPT);
clog('an unexpected format of area description is detected:');
}
clog(nextLine);
if( options.rusMode ){
clog('Эта строка проигнорирована.');
} else {
clog('That line is ignored.');
}
return nextLine;
}
lcEchotagHPT = parts[2].toLowerCase();
var elDescription = getDescriptionElementFromContentCSV(
contentCSV, lcEchotagHPT
);
if( typeof elDescription === 'undefined' ) return nextLine;
return [
parts[1], // EchoArea
parts[2], // an echotag
parts[3], // pre-description
elDescription.description,
parts[5] // post-description
].join('');
}
var echotagIDX, pathIDX;
if( lineParts[0].length > 0 ){
echotagIDX = 2;
pathIDX = 4;
} else {
echotagIDX = 4;
pathIDX = 6;
}
lcEchotagHPT = lineParts[echotagIDX].toLowerCase();
var descriptionElement = getDescriptionElementFromContentCSV(
contentCSV, lcEchotagHPT
);
if( typeof descriptionElement === 'undefined' ) return nextLine;
lineParts[pathIDX] += ' -d "' + descriptionElement.description + '"';
return lineParts.join('');
}).join('');
writeOrDie(
filenameHPT, contentHPT, options.outputEncoding, options.rusMode
);
clog('');
if( options.rusMode ){
clog('Готово.');
} else {
clog('Done.');
}
};