File area updates WIP
This commit is contained in:
parent
c81b6789f4
commit
ac35d3506d
|
@ -0,0 +1,30 @@
|
||||||
|
/* jslint node: true */
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// deps
|
||||||
|
const _ = require('lodash');
|
||||||
|
|
||||||
|
exports.sortAreasOrConfs = sortAreasOrConfs;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Method for sorting message, file, etc. areas and confs
|
||||||
|
// If the sort key is present and is a number, sort in numerical order;
|
||||||
|
// Otherwise, use a locale comparison on the sort key or name as a fallback
|
||||||
|
//
|
||||||
|
function sortAreasOrConfs(areasOrConfs, type) {
|
||||||
|
let entryA;
|
||||||
|
let entryB;
|
||||||
|
|
||||||
|
areasOrConfs.sort((a, b) => {
|
||||||
|
entryA = a[type];
|
||||||
|
entryB = b[type];
|
||||||
|
|
||||||
|
if(_.isNumber(entryA.sort) && _.isNumber(entryB.sort)) {
|
||||||
|
return entryA.sort - entryB.sort;
|
||||||
|
} else {
|
||||||
|
const keyA = entryA.sort ? entryA.sort.toString() : entryA.name;
|
||||||
|
const keyB = entryB.sort ? entryB.sort.toString() : entryB.name;
|
||||||
|
return keyA.localeCompare(keyB);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
|
@ -236,7 +236,7 @@ function getDefaultConfig() {
|
||||||
},
|
},
|
||||||
|
|
||||||
zmodem8kSexyz : {
|
zmodem8kSexyz : {
|
||||||
name : 'ZModem 8k',
|
name : 'ZModem (SEXYZ)',
|
||||||
type : 'external',
|
type : 'external',
|
||||||
external : {
|
external : {
|
||||||
// :TODO: Look into shipping sexyz binaries or at least hosting them somewhere for common systems
|
// :TODO: Look into shipping sexyz binaries or at least hosting them somewhere for common systems
|
||||||
|
@ -244,7 +244,7 @@ function getDefaultConfig() {
|
||||||
sendArgs : [
|
sendArgs : [
|
||||||
'-telnet', 'sz', '{filePath}'
|
'-telnet', 'sz', '{filePath}'
|
||||||
],
|
],
|
||||||
escapeTelnet : true, // set to true to escape Telnet codes such as IAC
|
escapeTelnet : false, // -telnet option does this for us
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,14 +19,12 @@ class EnigError extends Error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// :TODO: Just use EnigError for all
|
|
||||||
class EnigMenuError extends EnigError { }
|
|
||||||
|
|
||||||
exports.EnigError = EnigError;
|
exports.EnigError = EnigError;
|
||||||
exports.EnigMenuError = EnigMenuError;
|
|
||||||
|
|
||||||
exports.Errors = {
|
exports.Errors = {
|
||||||
General : (reason, reasonCode) => new EnigError('An error occurred', -33000, reason, reasonCode),
|
General : (reason, reasonCode) => new EnigError('An error occurred', -33000, reason, reasonCode),
|
||||||
MenuStack : (reason, reasonCode) => new EnigMenuError('Menu stack error', -33001, reason, reasonCode),
|
MenuStack : (reason, reasonCode) => new EnigError('Menu stack error', -33001, reason, reasonCode),
|
||||||
DoesNotExist : (reason, reasonCode) => new EnigError('Object does not exist', -33002, reason, reasonCode),
|
DoesNotExist : (reason, reasonCode) => new EnigError('Object does not exist', -33002, reason, reasonCode),
|
||||||
|
AccessDenied : (reason, reasonCode) => new EnigError('Access denied', -32003, reason, reasonCode),
|
||||||
|
Invalid : (reason, reasonCode) => new EnigError('Invalid', -32004, reason, reasonCode),
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,29 +3,101 @@
|
||||||
|
|
||||||
// ENiGMA½
|
// ENiGMA½
|
||||||
const Config = require('./config.js').config;
|
const Config = require('./config.js').config;
|
||||||
const Log = require('./logger.js').log;
|
const Errors = require('./enig_error.js').Errors;
|
||||||
|
const sortAreasOrConfs = require('./conf_area_util.js').sortAreasOrConfs;
|
||||||
|
|
||||||
// deps
|
// deps
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
|
const async = require('async');
|
||||||
|
|
||||||
exports.getAvailableFileAreas = getAvailableFileAreas;
|
exports.getAvailableFileAreas = getAvailableFileAreas;
|
||||||
|
exports.getSortedAvailableFileAreas = getSortedAvailableFileAreas;
|
||||||
|
exports.getDefaultFileArea = getDefaultFileArea;
|
||||||
exports.getFileAreaByTag = getFileAreaByTag;
|
exports.getFileAreaByTag = getFileAreaByTag;
|
||||||
|
exports.changeFileAreaWithOptions = changeFileAreaWithOptions;
|
||||||
|
|
||||||
|
const WellKnownAreaTags = exports.WellKnownAreaTags = {
|
||||||
|
Invalid : '',
|
||||||
|
MessageAreaAttach : 'message_area_attach',
|
||||||
|
};
|
||||||
|
|
||||||
function getAvailableFileAreas(client, options) {
|
function getAvailableFileAreas(client, options) {
|
||||||
options = options || { includeSystemInternal : false };
|
options = options || { includeSystemInternal : false };
|
||||||
|
|
||||||
// perform ACS check per conf & omit system_internal if desired
|
// perform ACS check per conf & omit system_internal if desired
|
||||||
return _.omit(Config.fileAreas.areas, (area, areaTag) => {
|
return _.omit(Config.fileAreas.areas, (area, areaTag) => {
|
||||||
/* if(!options.includeSystemInternal && 'system_internal' === confTag) {
|
if(!options.includeSystemInternal && WellKnownAreaTags.MessageAreaAttach === areaTag) {
|
||||||
return true;
|
return true;
|
||||||
}*/
|
}
|
||||||
|
|
||||||
return !client.acs.hasFileAreaRead(area);
|
return !client.acs.hasFileAreaRead(area);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getSortedAvailableFileAreas(client, options) {
|
||||||
|
const areas = _.map(getAvailableFileAreas(client, options), (v, k) => {
|
||||||
|
return {
|
||||||
|
areaTag : k,
|
||||||
|
area : v
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
sortAreasOrConfs(areas, 'area');
|
||||||
|
return areas;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDefaultFileArea(client, disableAcsCheck) {
|
||||||
|
let defaultArea = _.findKey(Config.fileAreas, o => o.default);
|
||||||
|
if(defaultArea) {
|
||||||
|
const area = Config.fileAreas.areas[defaultArea];
|
||||||
|
if(true === disableAcsCheck || client.acs.hasFileAreaRead(area)) {
|
||||||
|
return defaultArea;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// just use anything we can
|
||||||
|
defaultArea = _.findKey(Config.fileAreas.areas, (area, areaTag) => {
|
||||||
|
return WellKnownAreaTags.MessageAreaAttach !== areaTag && (true === disableAcsCheck || client.acs.hasFileAreaRead(area));
|
||||||
|
});
|
||||||
|
|
||||||
|
return defaultArea;
|
||||||
|
}
|
||||||
|
|
||||||
function getFileAreaByTag(areaTag) {
|
function getFileAreaByTag(areaTag) {
|
||||||
return Config.fileAreas.areas[areaTag];
|
return Config.fileAreas.areas[areaTag];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function changeFileAreaWithOptions(client, areaTag, options, cb) {
|
||||||
|
async.waterfall(
|
||||||
|
[
|
||||||
|
function getArea(callback) {
|
||||||
|
const area = getFileAreaByTag(areaTag);
|
||||||
|
return callback(area ? null : Errors.Invalid('Invalid file areaTag'), area);
|
||||||
|
},
|
||||||
|
function validateAccess(area, callback) {
|
||||||
|
if(!client.acs.hasFileAreaRead(area)) {
|
||||||
|
return callback(Errors.AccessDenied('No access to this area'));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
function changeArea(area, callback) {
|
||||||
|
if(true === options.persist) {
|
||||||
|
client.user.persistProperty('file_area_tag', areaTag, err => {
|
||||||
|
return callback(err, area);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
client.user.properties['file_area_tag'] = areaTag;
|
||||||
|
return callback(null, area);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
(err, area) => {
|
||||||
|
if(!err) {
|
||||||
|
client.log.info( { areaTag : areaTag, area : area }, 'Current file area changed');
|
||||||
|
} else {
|
||||||
|
client.log.warn( { areaTag : areaTag, area : area, error : err.message }, 'Could not change file area');
|
||||||
|
}
|
||||||
|
|
||||||
|
return cb(err);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -20,10 +20,10 @@ const FILE_WELL_KNOWN_META = {
|
||||||
file_md5 : null,
|
file_md5 : null,
|
||||||
file_sha256 : null,
|
file_sha256 : null,
|
||||||
file_crc32 : null,
|
file_crc32 : null,
|
||||||
est_release_year : parseInt,
|
est_release_year : (y) => parseInt(y) || new Date().getFullYear(),
|
||||||
dl_count : parseInt,
|
dl_count : (d) => parseInt(d) || 0,
|
||||||
byte_size : parseInt,
|
byte_size : (b) => parseInt(b) || 0,
|
||||||
user_rating : parseInt,
|
user_rating : (r) => Math.min(parseInt(r) || 0, 5),
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = class FileEntry {
|
module.exports = class FileEntry {
|
||||||
|
|
|
@ -7,6 +7,7 @@ const Config = require('./config.js').config;
|
||||||
const Message = require('./message.js');
|
const Message = require('./message.js');
|
||||||
const Log = require('./logger.js').log;
|
const Log = require('./logger.js').log;
|
||||||
const msgNetRecord = require('./msg_network.js').recordMessage;
|
const msgNetRecord = require('./msg_network.js').recordMessage;
|
||||||
|
const sortAreasOrConfs = require('./conf_area_util.js').sortAreasOrConfs;
|
||||||
|
|
||||||
// deps
|
// deps
|
||||||
const async = require('async');
|
const async = require('async');
|
||||||
|
@ -32,29 +33,6 @@ exports.updateMessageAreaLastReadId = updateMessageAreaLastReadId;
|
||||||
exports.persistMessage = persistMessage;
|
exports.persistMessage = persistMessage;
|
||||||
exports.trimMessageAreasScheduledEvent = trimMessageAreasScheduledEvent;
|
exports.trimMessageAreasScheduledEvent = trimMessageAreasScheduledEvent;
|
||||||
|
|
||||||
//
|
|
||||||
// Method for sorting Message areas and conferences
|
|
||||||
// If the sort key is present and is a number, sort in numerical order;
|
|
||||||
// Otherwise, use a locale comparison on the sort key or name as a fallback
|
|
||||||
//
|
|
||||||
function sortAreasOrConfs(areasOrConfs, type) {
|
|
||||||
let entryA;
|
|
||||||
let entryB;
|
|
||||||
|
|
||||||
areasOrConfs.sort((a, b) => {
|
|
||||||
entryA = a[type];
|
|
||||||
entryB = b[type];
|
|
||||||
|
|
||||||
if(_.isNumber(entryA.sort) && _.isNumber(entryB.sort)) {
|
|
||||||
return entryA.sort - entryB.sort;
|
|
||||||
} else {
|
|
||||||
const keyA = entryA.sort ? entryA.sort.toString() : entryA.name;
|
|
||||||
const keyB = entryB.sort ? entryB.sort.toString() : entryB.name;
|
|
||||||
return keyA.localeCompare(keyB);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getAvailableMessageConferences(client, options) {
|
function getAvailableMessageConferences(client, options) {
|
||||||
options = options || { includeSystemInternal : false };
|
options = options || { includeSystemInternal : false };
|
||||||
|
|
||||||
|
@ -269,7 +247,7 @@ function changeMessageConference(client, confTag, cb) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeMessageAreaWithOptions(client, areaTag, options, cb) {
|
function changeMessageAreaWithOptions(client, areaTag, options, cb) {
|
||||||
options = options || {};
|
options = options || {}; // :TODO: this is currently pointless... cb is required...
|
||||||
|
|
||||||
async.waterfall(
|
async.waterfall(
|
||||||
[
|
[
|
||||||
|
@ -305,7 +283,7 @@ function changeMessageAreaWithOptions(client, areaTag, options, cb) {
|
||||||
client.log.warn( { areaTag : areaTag, area : area, error : err.message }, 'Could not change message area');
|
client.log.warn( { areaTag : areaTag, area : area, error : err.message }, 'Could not change message area');
|
||||||
}
|
}
|
||||||
|
|
||||||
cb(err);
|
return cb(err);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,7 +151,6 @@ exports.getModule = class FileAreaList extends MenuModule {
|
||||||
const descView = self.viewControllers.browse.getView(MciViewIds.browse.desc);
|
const descView = self.viewControllers.browse.getView(MciViewIds.browse.desc);
|
||||||
if(descView) {
|
if(descView) {
|
||||||
descView.setText(self.currentFileEntry.desc);
|
descView.setText(self.currentFileEntry.desc);
|
||||||
//descView.redraw();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,6 +158,7 @@ exports.getModule = class FileAreaList extends MenuModule {
|
||||||
const uploadTimestampFormat = config.browseUploadTimestampFormat || config.uploadTimestampFormat || 'YYYY-MMM-DD';
|
const uploadTimestampFormat = config.browseUploadTimestampFormat || config.uploadTimestampFormat || 'YYYY-MMM-DD';
|
||||||
const area = FileArea.getFileAreaByTag(currEntry.areaTag);
|
const area = FileArea.getFileAreaByTag(currEntry.areaTag);
|
||||||
const hashTagsSep = config.hashTagsSep || ', ';
|
const hashTagsSep = config.hashTagsSep || ', ';
|
||||||
|
|
||||||
const entryInfo = {
|
const entryInfo = {
|
||||||
fileId : currEntry.fileId,
|
fileId : currEntry.fileId,
|
||||||
areaTag : currEntry.areaTag,
|
areaTag : currEntry.areaTag,
|
||||||
|
@ -183,6 +183,13 @@ exports.getModule = class FileAreaList extends MenuModule {
|
||||||
entryInfo[_.camelCase(name)] = value;
|
entryInfo[_.camelCase(name)] = value;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const userRatingChar = config.userRatingChar ? config.userRatingChar[0] : '*';
|
||||||
|
if(_.isNumber(entryInfo.userRating)) {
|
||||||
|
entryInfo.userRatingString = new Array(entryInfo.userRating).join(userRatingChar);
|
||||||
|
} else {
|
||||||
|
entryInfo.userRatingString = '';
|
||||||
|
}
|
||||||
|
|
||||||
// 10+ are custom textviews
|
// 10+ are custom textviews
|
||||||
let textView;
|
let textView;
|
||||||
let customMciId = 10;
|
let customMciId = 10;
|
||||||
|
@ -197,6 +204,8 @@ exports.getModule = class FileAreaList extends MenuModule {
|
||||||
|
|
||||||
++customMciId;
|
++customMciId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return callback(null);
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
err => {
|
err => {
|
||||||
|
|
Loading…
Reference in New Issue