/** * BetterDiscord Content Base * Copyright (c) 2015-present Jiiks/JsSucks - https://github.com/Jiiks / https://github.com/JsSucks * All rights reserved. * https://betterdiscord.net * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ import { Utils, ClientLogger as Logger, AsyncEventEmitter } from 'common'; import { Modals } from 'ui'; import Database from './database'; export default class Content extends AsyncEventEmitter { constructor(internals) { super(); internals.loaded = Date.now(); internals.started = undefined; internals.stopped = undefined; Utils.deepfreeze(internals.info); Object.freeze(internals.paths); this.__internals = internals; this.settings.on('setting-updated', event => this.emit('setting-updated', event)); this.settings.on('settings-updated', event => this.emit('settings-updated', event)); this.settings.on('settings-updated', event => this.__settingsUpdated(event)); // Add hooks if (this.onstart) this.on('start', event => this.onstart(event)); if (this.onStart) this.on('start', event => this.onStart(event)); if (this.onstop) this.on('stop', event => this.onstop(event)); if (this.onStop) this.on('stop', event => this.onStop(event)); if (this.onunload) this.on('unload', event => this.onunload(event)); if (this.onUnload) this.on('unload', event => this.onUnload(event)); if (this.settingUpdated) this.on('setting-updated', event => this.settingUpdated(event)); if (this.settingsUpdated) this.on('settings-updated', event => this.settingsUpdated(event)); } get type() { return undefined } get configs() { return this.__internals.configs } get info() { return this.__internals.info } get paths() { return this.__internals.paths } get main() { return this.__internals.main } get defaultConfig() { return this.configs.defaultConfig } get userConfig() { return this.configs.userConfig } get configSchemes() { return this.configs.schemes } get id() { return this.info.id || this.name.toLowerCase().replace(/[^a-zA-Z0-9-]/g, '-').replace(/--/g, '-') } get name() { return this.info.name } get icon() { return this.info.icon } get description() { return this.info.description } get authors() { return this.info.authors } get version() { return this.info.version } get loadedTimestamp() { return this.__internals.loaded } get startedTimestamp() { return this.__internals.started } get stoppedTimestamp() { return this.__internals.stopped } get contentPath() { return this.paths.contentPath } get dirName() { return this.paths.dirName } get enabled() { return this.userConfig.enabled } get settings() { return this.userConfig.config } get config() { return this.settings.categories } get data() { return this.userConfig.data || (this.userConfig.data = {}) } get packed() { return this.dirName.packed } get packagePath() { return this.dirName.packagePath } get packageName() { return this.dirName.pkg } /** * Opens a settings modal for this content. * @return {Modal} */ showSettingsModal() { return Modals.contentSettings(this); } /** * Whether this content has any settings. */ get hasSettings() { return !!this.settings.findSetting(() => true); } /** * Saves the content's current configuration. * @return {Promise} */ async saveConfiguration() { try { Database.insertOrUpdate({ type: `${this.type}-config`, id: this.id }, { type: `${this.type}-config`, id: this.id, enabled: this.enabled, config: this.settings.strip().settings, data: this.data }); this.settings.setSaved(); } catch (err) { Logger.err(this.name, ['Failed to save configuration', err]); throw err; } } /** * Called when settings are updated. * This can be overridden by other content types. */ __settingsUpdated(event) { return this.saveConfiguration(); } /** * Enables the content. * @param {Boolean} save Whether to save the new enabled state * @return {Promise} */ async enable(save = true) { if (this.enabled) return; await this.emit('enable'); await this.emit('start'); this.__internals.started = Date.now(); this.__internals.stopped = undefined; this.userConfig.enabled = true; if (save) await this.saveConfiguration(); } /** * Disables the content. * @param {Boolean} save Whether to save the new enabled state * @return {Promise} */ async disable(save = true) { if (!this.enabled) return; await this.emit('stop'); await this.emit('disable'); this.__internals.started = undefined; this.__internals.stopped = Date.now(); this.userConfig.enabled = false; if (save) await this.saveConfiguration(); } } Object.freeze(Content.prototype);