From f471fd0ebecbd38b7c0c523c8dc37517ffd8d2e0 Mon Sep 17 00:00:00 2001 From: Bryan Ashby Date: Sun, 25 Nov 2018 20:13:48 -0700 Subject: [PATCH] Finally implement "Total Calls Today" MCI: TT + Add findSystemLogEntries() to StatLog amongst others --- art/themes/luciano_blocktronics/SYSSTAT.ANS | Bin 2860 -> 2877 bytes art/themes/luciano_blocktronics/theme.hjson | 1 + core/bbs.js | 17 +++ core/database.js | 2 +- core/predefined_mci.js | 7 +- core/stat_log.js | 130 ++++++++++++++------ core/system_property.js | 3 + core/user_login.js | 1 + docs/art/mci.md | 3 +- 9 files changed, 121 insertions(+), 43 deletions(-) diff --git a/art/themes/luciano_blocktronics/SYSSTAT.ANS b/art/themes/luciano_blocktronics/SYSSTAT.ANS index 97beb53d8a39949e2982fb876b065d599cc6d492..19a3d39e0b11353a7c8b7415742ea3870a3c6fcb 100644 GIT binary patch delta 42 xcmZ1@wpVOJJ*SX#v_Y { + if(!err) { + StatLog.setNonPersistentSystemStat(SysProps.LoginsToday, callsToday); + } + return callback(null); + }); + }, function initMCI(callback) { return require('./predefined_mci.js').init(callback); }, diff --git a/core/database.js b/core/database.js index 90f15692..55fdb1c7 100644 --- a/core/database.js +++ b/core/database.js @@ -73,7 +73,7 @@ function getISOTimestampString(ts) { } ts = moment(ts); } - return ts.utc().format('YYYY-MM-DDTHH:mm:ss.SSS[Z]'); + return ts.format('YYYY-MM-DDTHH:mm:ss.SSS[Z]'); } function sanatizeString(s) { diff --git a/core/predefined_mci.js b/core/predefined_mci.js index 5b92e0e3..39310559 100644 --- a/core/predefined_mci.js +++ b/core/predefined_mci.js @@ -15,6 +15,7 @@ const { formatByteSize } = require('./string_util.js'); const ANSI = require('./ansi_term.js'); const UserProps = require('./user_property.js'); const SysProps = require('./system_property.js'); +const SysLogKeys = require('./system_log.js'); // deps const packageJson = require('../package.json'); @@ -30,7 +31,7 @@ function init(cb) { } function setNextRandomRumor(cb) { - StatLog.getSystemLogEntries('system_rumorz', StatLog.Order.Random, 1, (err, entry) => { + StatLog.getSystemLogEntries(SysLogKeys.UserAddedRumorz, StatLog.Order.Random, 1, (err, entry) => { if(entry) { entry = entry[0]; } @@ -191,6 +192,9 @@ const PREDEFINED_MCI_GENERATORS = { AN : function activeNodes() { return clientConnections.getActiveConnections().length.toString(); }, TC : function totalCalls() { return StatLog.getSystemStat(SysProps.LoginCount).toLocaleString(); }, + TT : function totalCallsToday() { + return StatLog.getSystemStat(SysProps.LoginsToday).toLocaleString(); + }, RR : function randomRumor() { // start the process of picking another random one @@ -227,7 +231,6 @@ const PREDEFINED_MCI_GENERATORS = { // :TODO: PT - Messages posted *today* (Obv/2) // -> Include FTN/etc. // :TODO: NT - New users today (Obv/2) - // :TODO: CT - Calls *today* (Obv/2) // :TODO: FT - Files uploaded/added *today* (Obv/2) // :TODO: DD - Files downloaded *today* (iNiQUiTY) // :TODO: TP - total message/posts on the system (Obv/2) diff --git a/core/stat_log.js b/core/stat_log.js index 80840ddb..805198bd 100644 --- a/core/stat_log.js +++ b/core/stat_log.js @@ -5,9 +5,11 @@ const sysDb = require('./database.js').dbs.system; const { getISOTimestampString } = require('./database.js'); +const Errors = require('./enig_error.js'); // deps const _ = require('lodash'); +const moment = require('moment'); /* System Event Log & Stats @@ -74,6 +76,19 @@ class StatLog { this.systemStats[statName] = statValue; } + incrementNonPersistentSystemStat(statName, incrementBy) { + incrementBy = incrementBy || 1; + + let newValue = parseInt(this.systemStats[statName]); + if(!isNaN(newValue)) { + newValue += incrementBy; + } else { + newValue = incrementBy; + } + this.setNonPersistentSystemStat(statName, newValue); + return newValue; + } + setSystemStat(statName, statValue, cb) { // live stats this.systemStats[statName] = statValue; @@ -99,19 +114,7 @@ class StatLog { } incrementSystemStat(statName, incrementBy, cb) { - incrementBy = incrementBy || 1; - - let newValue = parseInt(this.systemStats[statName]); - if(newValue) { - if(!_.isNumber(newValue)) { - return cb(new Error(`Value for ${statName} is not a number!`)); - } - - newValue += incrementBy; - } else { - newValue = incrementBy; - } - + const newValue = this.incrementNonPersistentSystemStat(statName, incrementBy); return this.setSystemStat(statName, newValue, cb); } @@ -216,26 +219,78 @@ class StatLog { ); } - getSystemLogEntries(logName, order, limit, cb) { - let sql = - `SELECT timestamp, log_value - FROM system_event_log - WHERE log_name = ?`; + /* + Find System Log entries by |filter|: - switch(order) { - case 'timestamp' : - case 'timestamp_asc' : - sql += ' ORDER BY timestamp ASC'; - break; - - case 'timestamp_desc' : - sql += ' ORDER BY timestamp DESC'; - break; - - case 'random' : - sql += ' ORDER BY RANDOM()'; + filter.logName (required) + filter.resultType = (obj) | count + where obj contains timestamp and log_value + filter.limit + filter.date - exact date to filter against + filter.order = (timestamp) | timestamp_asc | timestamp_desc | random + */ + findSystemLogEntries(filter, cb) { + filter = filter || {}; + if(!_.isString(filter.logName)) { + return cb(Errors.MissingParam('filter.logName is required')); } + filter.resultType = filter.resultType || 'obj'; + filter.order = filter.order || 'timestamp'; + + let sql; + if('count' === filter.resultType) { + sql = + `SELECT COUNT() AS count + FROM system_event_log`; + } else { + sql = + `SELECT timestamp, log_value + FROM system_event_log`; + } + + sql += ' WHERE log_name = ?'; + + if(filter.date) { + filter.date = moment(filter.date); + sql += ` AND DATE(timestamp) = DATE("${filter.date.format('YYYY-MM-DD')}")`; + } + + if('count' !== filter.resultType) { + switch(filter.order) { + case 'timestamp' : + case 'timestamp_asc' : + sql += ' ORDER BY timestamp ASC'; + break; + + case 'timestamp_desc' : + sql += ' ORDER BY timestamp DESC'; + break; + + case 'random' : + sql += ' ORDER BY RANDOM()'; + break; + } + } + + if(_.isNumber(filter.limit) && 0 !== filter.limit) { + sql += ` LIMIT ${filter.limit}`; + } + + sql += ';'; + + if('count' === filter.resultType) { + sysDb.get(sql, [ filter.logName ], (err, row) => { + return cb(err, row ? row.count : 0); + }); + } else { + sysDb.all(sql, [ filter.logName ], (err, rows) => { + return cb(err, rows); + }); + } + } + + getSystemLogEntries(logName, order, limit, cb) { if(!cb && _.isFunction(limit)) { cb = limit; limit = 0; @@ -243,15 +298,12 @@ class StatLog { limit = limit || 0; } - if(0 !== limit) { - sql += ` LIMIT ${limit}`; - } - - sql += ';'; - - sysDb.all(sql, [ logName ], (err, rows) => { - return cb(err, rows); - }); + const filter = { + logName, + order, + limit, + }; + return this.findSystemLogEntries(filter, cb); } appendUserLogEntry(user, logName, logValue, keepDays, cb) { diff --git a/core/system_property.js b/core/system_property.js index f2743088..52830a06 100644 --- a/core/system_property.js +++ b/core/system_property.js @@ -9,17 +9,20 @@ // module.exports = { LoginCount : 'login_count', + LoginsToday : 'logins_today', // non-persistent FileBaseAreaStats : 'file_base_area_stats', // object - see file_base_area.js::getAreaStats FileUlTotalCount : 'ul_total_count', FileUlTotalBytes : 'ul_total_bytes', + // begin +op non-persistent... SysOpUsername : 'sysop_username', SysOpRealName : 'sysop_real_name', SysOpLocation : 'sysop_location', SysOpAffiliations : 'sysop_affiliation', SysOpSex : 'sysop_sex', SysOpEmailAddress : 'sysop_email_address', + // end +op non-persistent NextRandomRumor : 'random_rumor', }; diff --git a/core/user_login.js b/core/user_login.js index b02066a1..2959e3a7 100644 --- a/core/user_login.js +++ b/core/user_login.js @@ -88,6 +88,7 @@ function userLogin(client, username, password, cb) { return callback(null); }, function updateSystemLoginCount(callback) { + StatLog.incrementNonPersistentSystemStat(SysProps.LoginsToday, 1); return StatLog.incrementSystemStat(SysProps.LoginCount, 1, callback); }, function recordLastLogin(callback) { diff --git a/docs/art/mci.md b/docs/art/mci.md index 04e177c2..4f351dad 100644 --- a/docs/art/mci.md +++ b/docs/art/mci.md @@ -65,7 +65,8 @@ for a full listing. Many codes attempt to pay homage to Oblivion/2, iNiQUiTY, et | `SC` | System CPU model | | `NV` | System underlying Node.js version | | `AN` | Current active node count | -| `TC` | Total login/calls to system | +| `TC` | Total login/calls to the system *ever* | +| `TT` | Total login/calls to the system *today* | | `RR` | Displays a random rumor | | `SD` | Total downloads, system wide | | `SO` | Total downloaded amount, system wide (formatted to appropriate bytes/megs/etc.) |