2018-01-30 14:20:24 +01:00
|
|
|
/**
|
|
|
|
* BetterDiscord Plugin Manager Module
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2018-04-29 02:57:09 +02:00
|
|
|
import { Events, Permissions } from 'modules';
|
|
|
|
import { Modals } from 'ui';
|
|
|
|
import { ErrorEvent } from 'structs';
|
|
|
|
import { ClientLogger as Logger } from 'common';
|
2018-05-28 02:42:59 +02:00
|
|
|
import Globals from './globals';
|
2018-01-30 16:59:27 +01:00
|
|
|
import ContentManager from './contentmanager';
|
2018-02-14 08:56:55 +01:00
|
|
|
import ExtModuleManager from './extmodulemanager';
|
2018-01-30 16:59:27 +01:00
|
|
|
import Plugin from './plugin';
|
2018-02-11 23:07:23 +01:00
|
|
|
import PluginApi from './pluginapi';
|
|
|
|
import Vendor from './vendor';
|
2018-01-30 14:20:24 +01:00
|
|
|
|
2018-01-30 16:59:27 +01:00
|
|
|
export default class extends ContentManager {
|
2018-01-30 14:20:24 +01:00
|
|
|
|
|
|
|
static get localPlugins() {
|
2018-01-30 16:59:27 +01:00
|
|
|
return this.localContent;
|
|
|
|
}
|
|
|
|
|
2018-02-07 17:02:27 +01:00
|
|
|
static get contentType() {
|
|
|
|
return 'plugin';
|
|
|
|
}
|
|
|
|
|
2018-01-30 16:59:27 +01:00
|
|
|
static get moduleName() {
|
2018-02-13 17:57:05 +01:00
|
|
|
return 'Plugin Manager';
|
2018-01-30 14:20:24 +01:00
|
|
|
}
|
|
|
|
|
2018-01-30 16:59:27 +01:00
|
|
|
static get pathId() {
|
|
|
|
return 'plugins';
|
2018-01-30 14:25:35 +01:00
|
|
|
}
|
|
|
|
|
2018-02-14 00:23:52 +01:00
|
|
|
static async loadAllPlugins(suppressErrors) {
|
2018-02-21 18:46:27 +01:00
|
|
|
this.loaded = false;
|
2018-03-02 20:42:17 +01:00
|
|
|
const loadAll = await this.loadAllContent(true);
|
2018-02-21 18:46:27 +01:00
|
|
|
this.loaded = true;
|
|
|
|
for (let plugin of this.localPlugins) {
|
2018-03-06 01:24:14 +01:00
|
|
|
if (!plugin.enabled) continue;
|
|
|
|
plugin.userConfig.enabled = false;
|
|
|
|
|
2018-03-02 20:42:17 +01:00
|
|
|
try {
|
2018-03-06 01:24:14 +01:00
|
|
|
plugin.start(false);
|
2018-03-02 20:42:17 +01:00
|
|
|
} catch (err) {
|
|
|
|
// Disable the plugin but don't save it - the next time BetterDiscord is started the plugin will attempt to start again
|
|
|
|
this.errors.push(new ErrorEvent({
|
|
|
|
module: this.moduleName,
|
|
|
|
message: `Failed to start ${plugin.name}`,
|
|
|
|
err
|
|
|
|
}));
|
|
|
|
|
|
|
|
Logger.err(this.moduleName, [`Failed to start plugin ${plugin.name}:`, err]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.errors.length && !suppressErrors) {
|
|
|
|
Modals.error({
|
|
|
|
header: `${this.moduleName} - ${this.errors.length} ${this.contentType}${this.errors.length !== 1 ? 's' : ''} failed to load`,
|
|
|
|
module: this.moduleName,
|
|
|
|
type: 'err',
|
|
|
|
content: this.errors
|
|
|
|
});
|
|
|
|
this._errors = [];
|
2018-02-21 18:46:27 +01:00
|
|
|
}
|
2018-02-13 17:22:48 +01:00
|
|
|
|
|
|
|
return loadAll;
|
|
|
|
}
|
2018-01-30 23:21:06 +01:00
|
|
|
static get refreshPlugins() { return this.refreshContent }
|
2018-01-30 16:59:27 +01:00
|
|
|
|
|
|
|
static get loadContent() { return this.loadPlugin }
|
2018-02-28 20:34:12 +01:00
|
|
|
static async loadPlugin(paths, configs, info, main, dependencies, permissions) {
|
|
|
|
if (permissions && permissions.length > 0) {
|
|
|
|
for (let perm of permissions) {
|
2018-03-21 00:24:31 +01:00
|
|
|
Logger.log(this.moduleName, `Permission: ${Permissions.permissionText(perm).HEADER} - ${Permissions.permissionText(perm).BODY}`);
|
2018-02-28 20:34:12 +01:00
|
|
|
}
|
|
|
|
try {
|
|
|
|
const allowed = await Modals.permissions(`${info.name} wants to:`, info.name, permissions).promise;
|
|
|
|
} catch (err) {
|
2018-03-21 00:24:31 +01:00
|
|
|
return;
|
2018-02-28 20:34:12 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-29 02:57:09 +02:00
|
|
|
const deps = {};
|
2018-02-14 08:56:55 +01:00
|
|
|
if (dependencies) {
|
|
|
|
for (const [key, value] of Object.entries(dependencies)) {
|
|
|
|
const extModule = ExtModuleManager.findModule(key);
|
|
|
|
if (!extModule) {
|
2018-03-22 03:13:32 +01:00
|
|
|
throw {message: `Dependency ${key}:${value} is not loaded.`};
|
2018-02-14 08:56:55 +01:00
|
|
|
}
|
2018-02-14 09:05:34 +01:00
|
|
|
deps[key] = extModule.__require;
|
2018-02-14 08:56:55 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-28 02:42:59 +02:00
|
|
|
const plugin = Globals.require(paths.mainPath)(Plugin, new PluginApi(info, paths.contentPath), Vendor, deps);
|
2018-03-09 00:43:26 +01:00
|
|
|
if (!(plugin.prototype instanceof Plugin))
|
|
|
|
throw {message: `Plugin ${info.name} did not return a class that extends Plugin.`};
|
|
|
|
|
2018-02-21 18:46:27 +01:00
|
|
|
const instance = new plugin({
|
|
|
|
configs, info, main,
|
|
|
|
paths: {
|
|
|
|
contentPath: paths.contentPath,
|
|
|
|
dirName: paths.dirName,
|
|
|
|
mainPath: paths.mainPath
|
|
|
|
}
|
|
|
|
});
|
2018-01-30 23:21:06 +01:00
|
|
|
|
2018-03-06 01:24:14 +01:00
|
|
|
if (instance.enabled && this.loaded) {
|
|
|
|
instance.userConfig.enabled = false;
|
|
|
|
instance.start(false);
|
|
|
|
}
|
2018-02-21 18:46:27 +01:00
|
|
|
return instance;
|
2018-01-30 23:21:06 +01:00
|
|
|
}
|
|
|
|
|
2018-02-21 18:46:27 +01:00
|
|
|
static get unloadPlugin() { return this.unloadContent }
|
|
|
|
static get reloadPlugin() { return this.reloadContent }
|
2018-01-31 09:17:15 +01:00
|
|
|
|
2018-03-22 03:13:32 +01:00
|
|
|
/**
|
|
|
|
* Stops a plugin.
|
|
|
|
* @param {Plugin|String} plugin
|
|
|
|
* @return {Promise}
|
|
|
|
*/
|
|
|
|
static stopPlugin(plugin) {
|
|
|
|
plugin = this.isPlugin(plugin) ? plugin : this.getPluginById(plugin);
|
|
|
|
return plugin.stop();
|
2018-01-31 09:32:20 +01:00
|
|
|
}
|
|
|
|
|
2018-03-22 03:13:32 +01:00
|
|
|
/**
|
|
|
|
* Starts a plugin.
|
|
|
|
* @param {Plugin|String} plugin
|
|
|
|
* @return {Promise}
|
|
|
|
*/
|
|
|
|
static startPlugin(plugin) {
|
|
|
|
plugin = this.isPlugin(plugin) ? plugin : this.getPluginById(plugin);
|
|
|
|
return plugin.start();
|
2018-01-31 09:32:20 +01:00
|
|
|
}
|
|
|
|
|
2018-02-21 18:46:27 +01:00
|
|
|
static get isPlugin() { return this.isThisContent }
|
|
|
|
static isThisContent(plugin) {
|
|
|
|
return plugin instanceof Plugin;
|
|
|
|
}
|
|
|
|
|
2018-01-30 23:21:06 +01:00
|
|
|
static get findPlugin() { return this.findContent }
|
|
|
|
static get getPluginIndex() { return this.getContentIndex }
|
|
|
|
static get getPluginByName() { return this.getContentByName }
|
|
|
|
static get getPluginById() { return this.getContentById }
|
|
|
|
static get getPluginByPath() { return this.getContentByPath }
|
|
|
|
static get getPluginByDirName() { return this.getContentByDirName }
|
|
|
|
|
2018-02-12 23:49:44 +01:00
|
|
|
static get waitForPlugin() { return this.waitForContent }
|
|
|
|
|
2018-01-30 14:20:24 +01:00
|
|
|
}
|