diff --git a/core/client_connections.js b/core/client_connections.js index d81d0922..176b027a 100644 --- a/core/client_connections.js +++ b/core/client_connections.js @@ -77,7 +77,10 @@ function addNewClient(client, clientSock) { client.log.info(connInfo, 'Client connected'); - Events.emit('codes.l33t.enigma.system.connected', { client : client, connectionCount : clientConnections.length } ); + Events.emit( + Events.getSystemEvents().ClientConnected, + { client : client, connectionCount : clientConnections.length } + ); return id; } @@ -97,7 +100,10 @@ function removeClient(client) { 'Client disconnected' ); - Events.emit('codes.l33t.enigma.system.disconnected', { client : client, connectionCount : clientConnections.length } ); + Events.emit( + Events.getSystemEvents().ClientDisconnected, + { client : client, connectionCount : clientConnections.length } + ); } } diff --git a/core/connect.js b/core/connect.js index 8593dff8..51ee4e37 100644 --- a/core/connect.js +++ b/core/connect.js @@ -177,7 +177,7 @@ function connectEntry(client, nextMenu) { displayBanner(term); // fire event - Events.emit('codes.l33t.enigma.system.term_detected', { client : client } ); + Events.emit(Events.getSystemEvents().TermDetected, { client : client } ); setTimeout( () => { return client.menuStack.goto(nextMenu); diff --git a/core/download_queue.js b/core/download_queue.js index 0f45b04d..0c31b13c 100644 --- a/core/download_queue.js +++ b/core/download_queue.js @@ -1,7 +1,10 @@ /* jslint node: true */ 'use strict'; -const FileEntry = require('./file_entry.js'); +const FileEntry = require('./file_entry.js'); + +// deps +const { partition } = require('lodash'); module.exports = class DownloadQueue { constructor(client) { @@ -24,21 +27,22 @@ module.exports = class DownloadQueue { this.client.user.downloadQueue = []; } - toggle(fileEntry) { + toggle(fileEntry, systemFile=false) { if(this.isQueued(fileEntry)) { this.client.user.downloadQueue = this.client.user.downloadQueue.filter(e => fileEntry.fileId !== e.fileId); } else { - this.add(fileEntry); + this.add(fileEntry, systemFile); } } - add(fileEntry) { + add(fileEntry, systemFile=false) { this.client.user.downloadQueue.push({ fileId : fileEntry.fileId, areaTag : fileEntry.areaTag, fileName : fileEntry.fileName, path : fileEntry.filePath, byteSize : fileEntry.meta.byte_size || 0, + systemFile : systemFile, }); } @@ -47,7 +51,9 @@ module.exports = class DownloadQueue { fileIds = [ fileIds ]; } - this.client.user.downloadQueue = this.client.user.downloadQueue.filter(e => ( -1 === fileIds.indexOf(e.fileId) ) ); + const [ remain, removed ] = partition(this.client.user.downloadQueue, e => ( -1 === fileIds.indexOf(e.fileId) )); + this.client.user.downloadQueue = remain; + return removed; } isQueued(entryOrId) { diff --git a/core/events.js b/core/events.js index b1e15c21..e50c5723 100644 --- a/core/events.js +++ b/core/events.js @@ -4,25 +4,20 @@ const paths = require('path'); const events = require('events'); const Log = require('./logger.js').log; +const SystemEvents = require('./system_events.js'); // deps const _ = require('lodash'); const async = require('async'); const glob = require('glob'); -const SYSTEM_EVENTS = { - ClientConnected : 'codes.l33t.enigma.system.connected', - ClientDisconnected : 'codes.l33t.enigma.system.disconnected', - TermDetected : 'codes.l33t.enigma.term_detected', -}; - module.exports = new class Events extends events.EventEmitter { constructor() { super(); } getSystemEvents() { - return SYSTEM_EVENTS; + return SystemEvents; } addListener(event, listener) { diff --git a/core/file_area_web.js b/core/file_area_web.js index b8a630fc..928be942 100644 --- a/core/file_area_web.js +++ b/core/file_area_web.js @@ -14,6 +14,7 @@ const User = require('./user.js'); const Log = require('./logger.js').log; const getConnectionByUserId = require('./client_connections.js').getConnectionByUserId; const webServerPackageName = require('./servers/content/web.js').moduleInfo.packageName; +const Events = require('./events.js'); // deps const hashids = require('hashids'); @@ -337,7 +338,7 @@ class FileAreaWebAccess { resp.on('finish', () => { // transfer completed fully - this.updateDownloadStatsForUserIdAndSystem(servedItem.userId, stats.size); + this.updateDownloadStatsForUserIdAndSystem(servedItem.userId, stats.size, [ fileEntry ]); }); const headers = { @@ -382,24 +383,21 @@ class FileAreaWebAccess { ); }, function loadFileEntries(fileIds, callback) { - const filePaths = []; - async.eachSeries(fileIds, (fileId, nextFileId) => { + async.map(fileIds, (fileId, nextFileId) => { const fileEntry = new FileEntry(); fileEntry.load(fileId, err => { - if(!err) { - filePaths.push(fileEntry.filePath); - } - return nextFileId(err); + return nextFileId(err, fileEntry); }); - }, err => { + }, (err, fileEntries) => { if(err) { - return callback(Errors.DoesNotExist('Coudl not load file IDs for batch')); + return callback(Errors.DoesNotExist('Could not load file IDs for batch')); } - return callback(null, filePaths); + return callback(null, fileEntries); }); }, - function createAndServeStream(filePaths, callback) { + function createAndServeStream(fileEntries, callback) { + const filePaths = fileEntries.map(fe => fe.filePath); Log.trace( { filePaths : filePaths }, 'Creating zip archive for batch web request'); const zipFile = new yazl.ZipFile(); @@ -430,7 +428,7 @@ class FileAreaWebAccess { resp.on('finish', () => { // transfer completed fully - self.updateDownloadStatsForUserIdAndSystem(servedItem.userId, finalZipSize); + self.updateDownloadStatsForUserIdAndSystem(servedItem.userId, finalZipSize, fileEntries); }); const batchFileName = `batch_${servedItem.hashId}.zip`; @@ -457,7 +455,7 @@ class FileAreaWebAccess { ); } - updateDownloadStatsForUserIdAndSystem(userId, dlBytes, cb) { + updateDownloadStatsForUserIdAndSystem(userId, dlBytes, fileEntries) { async.waterfall( [ function fetchActiveUser(callback) { @@ -477,14 +475,19 @@ class FileAreaWebAccess { StatLog.incrementSystemStat('dl_total_count', 1); StatLog.incrementSystemStat('dl_total_bytes', dlBytes); + return callback(null, user); + }, + function sendEvent(user, callback) { + Events.emit( + Events.getSystemEvents().UserDownload, + { + user : user, + files : fileEntries, + } + ); return callback(null); } - ], - err => { - if(cb) { - return cb(err); - } - } + ] ); } } diff --git a/core/file_base_user_list_export.js b/core/file_base_user_list_export.js index 2dba52ad..0b30d582 100644 --- a/core/file_base_user_list_export.js +++ b/core/file_base_user_list_export.js @@ -223,7 +223,7 @@ exports.getModule = class FileBaseListExport extends MenuModule { if(!err) { // queue it! const dlQueue = new DownloadQueue(self.client); - dlQueue.add(newEntry); + dlQueue.add(newEntry, true); // true=systemFile // clean up after ourselves when the session ends const thisClientId = self.client.session.id; diff --git a/core/file_transfer.js b/core/file_transfer.js index 19388bab..a7aee20c 100644 --- a/core/file_transfer.js +++ b/core/file_transfer.js @@ -10,6 +10,7 @@ const DownloadQueue = require('./download_queue.js'); const StatLog = require('./stat_log.js'); const FileEntry = require('./file_entry.js'); const Log = require('./logger.js').log; +const Events = require('./events.js'); // deps const async = require('async'); @@ -545,7 +546,16 @@ exports.getModule = class TransferFileModule extends MenuModule { if(sentFileIds.length > 0) { // remove items we sent from the D/L queue const dlQueue = new DownloadQueue(self.client); - dlQueue.removeItems(sentFileIds); + const dlFileEntries = dlQueue.removeItems(sentFileIds); + + // fire event for downloaded entries + Events.emit( + Events.getSystemEvents().UserDownload, + { + user : self.client.user, + files : dlFileEntries + } + ); self.sentFileIds = sentFileIds; } diff --git a/core/upload.js b/core/upload.js index b4130433..4ff6b3fb 100644 --- a/core/upload.js +++ b/core/upload.js @@ -16,6 +16,7 @@ const Log = require('./logger.js').log; const Errors = require('./enig_error.js').Errors; const FileEntry = require('./file_entry.js'); const isAnsi = require('./string_util.js').isAnsi; +const Events = require('./events.js'); // deps const async = require('async'); @@ -567,8 +568,18 @@ exports.getModule = class UploadModule extends MenuModule { // here as I/O can take quite a bit of time. Log any failures. // self.moveAndPersistUploadsToDatabase(scanResults.newEntries); - return callback(null); + return callback(null, scanResults.newEntries); }, + function sendEvent(uploadedEntries, callback) { + Events.emit( + Events.getSystemEvents().UserUpload, + { + user : self.client.user, + files : uploadedEntries, + } + ); + return callback(null); + } ], err => { if(err) {