diff --git a/client/src/index.js b/client/src/index.js index 9a23739b..e732a0e7 100644 --- a/client/src/index.js +++ b/client/src/index.js @@ -23,6 +23,7 @@ class BetterDiscord { constructor() { Logger.file = tests ? path.resolve(__dirname, '..', '..', 'tests', 'log.txt') : path.join(__dirname, 'log.txt'); + Logger.trimLogFile(); Logger.log('main', 'BetterDiscord starting'); this._bd = { diff --git a/client/src/modules/eventhook.js b/client/src/modules/eventhook.js index c2665e18..eccad42e 100644 --- a/client/src/modules/eventhook.js +++ b/client/src/modules/eventhook.js @@ -22,7 +22,6 @@ import * as SocketStructs from '../structs/socketstructs'; export default class extends EventListener { init() { - Logger.log('EventHook', SocketStructs); this.hook(); } @@ -38,18 +37,16 @@ export default class extends EventListener { hook() { const self = this; - const orig = this.eventsModule.prototype.emit; - this.eventsModule.prototype.emit = function (...args) { + const Events = WebpackModules.getModuleByName('Events'); + + const orig = Events.prototype.emit; + Events.prototype.emit = function (...args) { orig.call(this, ...args); self.wsc = this; self.emit(...args); }; } - get eventsModule() { - return WebpackModules.getModuleByName('Events'); - } - /** * Discord emit overload * @param {any} event @@ -68,22 +65,29 @@ export default class extends EventListener { * @param {any} event Event * @param {any} data Event data */ - dispatch(e, d) { - Events.emit('raw-event', { type: e, data: d }); - if (e === this.actions.READY || e === this.actions.RESUMED) { - Events.emit(e, d); + dispatch(type, data) { + Events.emit('raw-event', { type, data }); + + if (type === this.actions.READY || type === this.actions.RESUMED) { + Events.emit(type, data); return; } - if (!Object.keys(SocketStructs).includes(e)) return; - const evt = new SocketStructs[e](d); - Events.emit(`discord:${e}`, evt); + + if (!Object.keys(SocketStructs).includes(type)) return; + Events.emit(`discord:${type}`, new SocketStructs[type](data)); + } + + get SocketStructs() { + return SocketStructs; } /** * All known socket actions */ get actions() { - return { + if (this._actions) return this._actions; + + return this._actions = { READY: 'READY', // Socket ready RESUMED: 'RESUMED', // Socket resumed TYPING_START: 'TYPING_START', // User typing start diff --git a/common/modules/logger.js b/common/modules/logger.js index b0c2ba5b..9ed5d5a3 100644 --- a/common/modules/logger.js +++ b/common/modules/logger.js @@ -62,6 +62,24 @@ export default class Logger { return (new Date()).toLocaleString('en-GB'); } + trimLogFile() { + if (!this.file) throw new Error('This logger does not have a file.'); + return Logger.trimLogFile(this.file); + } + + static async trimLogFile(file) { + const stat = await FileUtils.stat(file); + if (stat.size < 20 * 1024 * 1024) return; // 20 MB + + const logs = await FileUtils.readFile(file); + + // Trim to about 1 MB + const trimFrom = logs.substr(0 - 1024 * 1024).lastIndexOf('\nLOG : ['); + if (trimFrom < 0) return; + + await FileUtils.writeFile(file, logs.substr(trimFrom)); + } + } export const ClientLogger = new Logger(); diff --git a/common/modules/utils.js b/common/modules/utils.js index 05175937..4bf701ce 100644 --- a/common/modules/utils.js +++ b/common/modules/utils.js @@ -87,16 +87,23 @@ export class Utils { /** * Clones an object and all it's properties. * @param {Any} value The value to clone + * @param {Function} exclude A function to filter objects that shouldn't be cloned * @return {Any} The cloned value */ - static deepclone(value) { + static deepclone(value, exclude) { + try { + if (exclude && exclude(value)) return value; + } catch (err) { + console.error(arguments, err); + } + if (typeof value === 'object') { - if (value instanceof Array) return value.map(i => this.deepclone(i)); + if (value instanceof Array) return value.map(i => this.deepclone(i, exclude)); const clone = Object.assign({}, value); for (let key in clone) { - clone[key] = this.deepclone(clone[key]); + clone[key] = this.deepclone(clone[key], exclude); } return clone; @@ -108,7 +115,7 @@ export class Utils { /** * Freezes an object and all it's properties. * @param {Any} object The object to freeze - * @param {Function} exclude A function to filter object that shouldn't be frozen + * @param {Function} exclude A function to filter objects that shouldn't be frozen */ static deepfreeze(object, exclude) { if (exclude && exclude(object)) return; @@ -178,49 +185,49 @@ export class Utils { export class FileUtils { /** - * Checks if a file exists and is a file. + * Gets information about a file. * @param {String} path The file's path * @return {Promise} */ - static async fileExists(path) { + static async stat(path) { return new Promise((resolve, reject) => { - fs.stat(path, (err, stats) => { + fs.stat(path, (err, stat) => { if (err) return reject({ message: `No such file or directory: ${err.path}`, err }); - if (!stats.isFile()) return reject({ - message: `Not a file: ${path}`, - stats - }); - - resolve(); + resolve(stat); }); }); } + /** + * Checks if a file exists and is a file. + * @param {String} path The file's path + * @return {Promise} + */ + static async fileExists(path) { + const stat = await this.stat(path); + + if (!stat.isFile()) throw { + message: `Not a file: ${path}`, + stats + }; + } + /** * Checks if a directory exists and is a directory. * @param {String} path The directory's path * @return {Promise} */ static async directoryExists(path) { - return new Promise((resolve, reject) => { - fs.stat(path, (err, stats) => { - if (err) return reject({ - message: `Directory does not exist: ${path}`, - err - }); + const stat = await this.stat(path); - if (!stats.isDirectory()) return reject({ - message: `Not a directory: ${path}`, - stats - }); - - resolve(); - }); - }); + if (!stat.isDirectory()) throw { + message: `Not a directory: ${path}`, + stats + }; } /** @@ -247,12 +254,8 @@ export class FileUtils { await this.directoryExists(path); return true; } catch (err) { - try { - await this.createDirectory(path); - return true; - } catch (err) { - throw err; - } + await this.createDirectory(path); + return true; } } @@ -262,11 +265,7 @@ export class FileUtils { * @return {Promise} */ static async readFile(path) { - try { - await this.fileExists(path); - } catch (err) { - throw err; - } + await this.fileExists(path); return new Promise((resolve, reject) => { fs.readFile(path, 'utf-8', (err, data) => { @@ -287,11 +286,7 @@ export class FileUtils { * @return {Promise} */ static async readFileBuffer(path, options) { - try { - await this.fileExists(path); - } catch (err) { - throw err; - } + await this.fileExists(path); return new Promise((resolve, reject) => { fs.readFile(path, options || {}, (err, data) => { @@ -337,12 +332,7 @@ export class FileUtils { * @return {Promise} */ static async readJsonFromFile(path) { - let readFile; - try { - readFile = await this.readFile(path); - } catch (err) { - throw (err); - } + const readFile = await this.readFile(path); try { return await Utils.tryParseJson(readFile); @@ -368,6 +358,7 @@ export class FileUtils { */ static async listDirectory(path) { await this.directoryExists(path); + return new Promise((resolve, reject) => { fs.readdir(path, (err, files) => { if (err) reject(err);