Add oputil fb desc
This commit is contained in:
parent
f4088303ca
commit
c6e176f5bd
|
@ -41,7 +41,8 @@ This document attempts to track **major** changes and additions in ENiGMA½. For
|
|||
* Correly parse oddball `INTL`, `TOPT`, `FMPT`, `Via`, etc. FTN kludge lines
|
||||
* NetMail support! You can now send and receive NetMail. To send a NetMail address a external user using `Name <address>` format from your personal email menu. For example, `Foo Bar <123:123/123>`. The system also detects other formats such asa `Name @ address` (`Foo Bar@123:123/123`)
|
||||
* `oputil.js`: Added `mb areafix` command to quickly send AreaFix messages from the command line. You can manually send them from personal mail as well.
|
||||
* `oputil.js fb rm|remove|del|delete` functionality to remove file base entries
|
||||
* `oputil.js fb rm|remove|del|delete` functionality to remove file base entries.
|
||||
* `oputil.js fb desc` for setting/updating a file entry description.
|
||||
* Users can now (re)set File and Message base pointers
|
||||
* Add `--update` option to `oputil.js fb scan`
|
||||
* Fix @watch path support for event scheduler including FTN, e.g. when looking for a `toss!.now` file produced by Binkd.
|
||||
|
|
|
@ -8,6 +8,12 @@ const fs = require('graceful-fs');
|
|||
const iconv = require('iconv-lite');
|
||||
const moment = require('moment');
|
||||
|
||||
// Descriptions found in the wild that mean "no description" /facepalm.
|
||||
const IgnoredDescriptions = [
|
||||
'No description available',
|
||||
'No ID File Found For This Archive File.',
|
||||
];
|
||||
|
||||
module.exports = class FilesBBSFile {
|
||||
constructor() {
|
||||
this.entries = new Map();
|
||||
|
@ -34,6 +40,10 @@ module.exports = class FilesBBSFile {
|
|||
const lines = iconv.decode(descData, 'cp437').split(/\r?\n/g);
|
||||
const filesBbs = new FilesBBSFile();
|
||||
|
||||
const isBadDescription = (desc) => {
|
||||
return IgnoredDescriptions.find(d => desc.startsWith(d)) ? true : false;
|
||||
};
|
||||
|
||||
//
|
||||
// Contrary to popular belief, there is not a FILES.BBS standard. Instead,
|
||||
// many formats have been used over the years. We'll try to support as much
|
||||
|
@ -84,7 +94,7 @@ module.exports = class FilesBBSFile {
|
|||
const fileName = hdr[1];
|
||||
const timestamp = moment(hdr[2], 'MM/DD/YY');
|
||||
|
||||
if(!timestamp.isValid()) {
|
||||
if(isBadDescription(desc) || !timestamp.isValid()) {
|
||||
continue;
|
||||
}
|
||||
filesBbs.entries.set(fileName, { timestamp, desc } );
|
||||
|
@ -121,6 +131,10 @@ module.exports = class FilesBBSFile {
|
|||
const desc = long.join('\r\n');
|
||||
const fileName = hdr[1];
|
||||
|
||||
if(isBadDescription(desc)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
filesBbs.entries.set(fileName, { desc } );
|
||||
}
|
||||
}
|
||||
|
@ -157,6 +171,10 @@ module.exports = class FilesBBSFile {
|
|||
const desc = long.join('\r\n');
|
||||
const fileName = hdr[1];
|
||||
|
||||
if(isBadDescription(desc)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
filesBbs.entries.set(fileName, { desc } );
|
||||
}
|
||||
}
|
||||
|
@ -182,10 +200,6 @@ module.exports = class FilesBBSFile {
|
|||
}
|
||||
|
||||
const firstDescLine = hdr[4].trimRight();
|
||||
// ugly kludge:
|
||||
if('No ID File Found For This Archive File.' === firstDescLine) {
|
||||
continue;
|
||||
}
|
||||
const long = [ firstDescLine ];
|
||||
for(let j = i + 1; j < lines.length; ++j) {
|
||||
line = lines[j];
|
||||
|
@ -201,7 +215,7 @@ module.exports = class FilesBBSFile {
|
|||
const size = parseInt(hdr[2]);
|
||||
const timestamp = moment(hdr[3], 'MM-DD-YY');
|
||||
|
||||
if(isNaN(size) || !timestamp.isValid()) {
|
||||
if(isBadDescription(desc) || isNaN(size) || !timestamp.isValid()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -235,7 +249,7 @@ module.exports = class FilesBBSFile {
|
|||
const fileName = hdr[1].trim();
|
||||
const desc = hdr[2].trim();
|
||||
|
||||
if(desc) {
|
||||
if(desc && !isBadDescription(desc)) {
|
||||
filesBbs.entries.set(fileName, { desc } );
|
||||
}
|
||||
});
|
||||
|
|
|
@ -413,11 +413,11 @@ function dumpFileInfo(shaOrFileId, cb) {
|
|||
);
|
||||
}
|
||||
|
||||
function displayFileAreaInfo() {
|
||||
function displayFileOrAreaInfo() {
|
||||
// AREA_TAG[@STORAGE_TAG]
|
||||
// SHA256|PARTIAL
|
||||
// SHA256|PARTIAL|FILE_ID|FILENAME_WILDCARD
|
||||
// if sha: dump file info
|
||||
// if area/stoarge dump area(s) +
|
||||
// if area/storage dump area(s) +
|
||||
|
||||
async.series(
|
||||
[
|
||||
|
@ -908,6 +908,75 @@ function importFileAreas() {
|
|||
);
|
||||
}
|
||||
|
||||
function setFileDescription() {
|
||||
//
|
||||
// ./oputil.js fb set-desc CRITERIA # will prompt
|
||||
// ./oputil.js fb set-desc CRITERIA "The new description"
|
||||
//
|
||||
let fileCriteria;
|
||||
let desc;
|
||||
if(argv._.length > 3) {
|
||||
fileCriteria = argv._[argv._.length - 2];
|
||||
desc = argv._[argv._.length - 1];
|
||||
} else {
|
||||
fileCriteria = argv._[argv._.length - 1];
|
||||
}
|
||||
|
||||
async.waterfall(
|
||||
[
|
||||
(callback) => {
|
||||
return initConfigAndDatabases(callback);
|
||||
},
|
||||
(callback) => {
|
||||
getFileEntries(fileCriteria, (err, entries) => {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
if(entries.length > 1) {
|
||||
return callback(Errors.General('Criteria not specific enough.'));
|
||||
}
|
||||
|
||||
return callback(null, entries[0]);
|
||||
});
|
||||
},
|
||||
(fileEntry, callback) => {
|
||||
if(desc) {
|
||||
return callback(null, fileEntry, desc);
|
||||
}
|
||||
|
||||
getAnswers([
|
||||
{
|
||||
name : 'userDesc',
|
||||
message : 'Description:',
|
||||
type : 'editor',
|
||||
}
|
||||
],
|
||||
answers => {
|
||||
if(!answers.userDesc) {
|
||||
return callback(Errors.General('User canceled'));
|
||||
}
|
||||
return callback(null, fileEntry, answers.userDesc);
|
||||
});
|
||||
},
|
||||
(fileEntry, newDesc, callback) => {
|
||||
fileEntry.desc = newDesc;
|
||||
fileEntry.persist(true, err => { // true=isUpdate
|
||||
return callback(err);
|
||||
});
|
||||
}
|
||||
],
|
||||
err => {
|
||||
if(err) {
|
||||
process.exitCode = ExitCodes.ERROR;
|
||||
console.error(err.message);
|
||||
} else {
|
||||
console.info('Description updated.');
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function handleFileBaseCommand() {
|
||||
|
||||
function errUsage() {
|
||||
|
@ -924,7 +993,7 @@ function handleFileBaseCommand() {
|
|||
const action = argv._[1];
|
||||
|
||||
return ({
|
||||
info : displayFileAreaInfo,
|
||||
info : displayFileOrAreaInfo,
|
||||
scan : scanFileAreas,
|
||||
|
||||
mv : moveFiles,
|
||||
|
@ -936,5 +1005,8 @@ function handleFileBaseCommand() {
|
|||
delete : removeFiles,
|
||||
|
||||
'import-areas' : importFileAreas,
|
||||
|
||||
desc : setFileDescription,
|
||||
description : setFileDescription,
|
||||
}[action] || errUsage)();
|
||||
}
|
|
@ -57,9 +57,7 @@ actions:
|
|||
for example: scan some_area *.zip
|
||||
|
||||
info CRITERIA display information about areas and/or files
|
||||
where CRITERIA is one of the following:
|
||||
AREA_TAG|SHA|FILE_ID|FILENAME_WC
|
||||
SHA may be a full or partial SHA-256
|
||||
matching CRITERIA.
|
||||
|
||||
mv SRC [SRC...] DST move entry(s) from SRC to DST
|
||||
SRC: FILENAME_WC|SHA|FILE_ID|AREA_TAG[@STORAGE_TAG]
|
||||
|
@ -67,6 +65,9 @@ actions:
|
|||
|
||||
rm SRC [SRC...] remove entry(s) from the system matching SRC
|
||||
SRC: FILENAME_WC|SHA|FILE_ID|AREA_TAG[@STORAGE_TAG]
|
||||
desc CRITERIA sets a new file description for file base entry
|
||||
matching CRITERIA. Launches an external editor using
|
||||
$VISUAL, $EDITOR, or vim/notepad.
|
||||
import-areas FILEGATE.ZXX import file base areas using FileGate RAID type format
|
||||
|
||||
scan args:
|
||||
|
@ -93,6 +94,9 @@ import-areas args:
|
|||
general information:
|
||||
AREA_TAG[@STORAGE_TAG] can specify an area tag and optionally, a storage specific tag
|
||||
example: retro@bbs
|
||||
|
||||
CRITERIA file base entry criteria. in general, can be AREA_TAG, SHA,
|
||||
FILE_ID, or FILENAME_WC.
|
||||
|
||||
FILENAME_WC filename with * and ? wildcard support. may match 0:n entries
|
||||
SHA full or partial SHA-256
|
||||
|
|
|
@ -99,9 +99,7 @@ actions:
|
|||
for example: scan some_area *.zip
|
||||
|
||||
info CRITERIA display information about areas and/or files
|
||||
where CRITERIA is one of the following:
|
||||
AREA_TAG|SHA|FILE_ID|FILENAME_WC
|
||||
SHA may be a full or partial SHA-256
|
||||
matching CRITERIA.
|
||||
|
||||
mv SRC [SRC...] DST move entry(s) from SRC to DST
|
||||
SRC: FILENAME_WC|SHA|FILE_ID|AREA_TAG[@STORAGE_TAG]
|
||||
|
@ -109,6 +107,9 @@ actions:
|
|||
|
||||
rm SRC [SRC...] remove entry(s) from the system matching SRC
|
||||
SRC: FILENAME_WC|SHA|FILE_ID|AREA_TAG[@STORAGE_TAG]
|
||||
desc CRITERIA sets a new file description for file base entry
|
||||
matching CRITERIA. Launches an external editor using
|
||||
$VISUAL, $EDITOR, or vim/notepad.
|
||||
import-areas FILEGATE.ZXX import file base areas using FileGate RAID type format
|
||||
|
||||
scan args:
|
||||
|
@ -133,6 +134,9 @@ import-areas args:
|
|||
general information:
|
||||
AREA_TAG[@STORAGE_TAG] can specify an area tag and optionally, a storage specific tag
|
||||
example: retro@bbs
|
||||
|
||||
CRITERIA file base entry criteria. in general, can be AREA_TAG, SHA,
|
||||
FILE_ID, or FILENAME_WC.
|
||||
|
||||
FILENAME_WC filename with * and ? wildcard support. may match 0:n entries
|
||||
SHA full or partial SHA-256
|
||||
|
|
Loading…
Reference in New Issue