2018-02-11 23:07:23 +01:00
|
|
|
/**
|
|
|
|
* BetterDiscord Plugin Api
|
|
|
|
* 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-03-02 20:42:17 +01:00
|
|
|
import { ClientLogger as Logger, ClientIPC } from 'common';
|
2018-02-13 23:37:24 +01:00
|
|
|
import Settings from './settings';
|
2018-02-13 23:24:04 +01:00
|
|
|
import ExtModuleManager from './extmodulemanager';
|
2018-02-12 23:49:44 +01:00
|
|
|
import PluginManager from './pluginmanager';
|
|
|
|
import ThemeManager from './thememanager';
|
2018-02-12 00:04:07 +01:00
|
|
|
import Events from './events';
|
2018-03-02 21:48:29 +01:00
|
|
|
import { Modals, DOM } from 'ui';
|
|
|
|
import SettingsModal from '../ui/components/bd/modals/SettingsModal.vue';
|
2018-03-02 20:42:17 +01:00
|
|
|
|
|
|
|
class EventsWrapper {
|
|
|
|
constructor(eventemitter) {
|
|
|
|
this.__eventemitter = eventemitter;
|
|
|
|
}
|
|
|
|
|
|
|
|
get eventSubs() {
|
|
|
|
return this._eventSubs || (this._eventSubs = []);
|
|
|
|
}
|
|
|
|
|
|
|
|
subscribe(event, callback) {
|
|
|
|
if (this.eventSubs.find(e => e.event === event && e.callback === callback)) return;
|
|
|
|
this.eventSubs.push({
|
|
|
|
event,
|
|
|
|
callback
|
|
|
|
});
|
|
|
|
this.__eventemitter.on(event, callback);
|
|
|
|
}
|
|
|
|
|
|
|
|
unsubscribe(event, callback) {
|
|
|
|
for (let index of this.eventSubs) {
|
|
|
|
if (this.eventSubs[index].event !== event || (callback && this.eventSubs[index].callback === callback)) return;
|
|
|
|
this.__eventemitter.off(event, this.eventSubs[index].callback);
|
|
|
|
this.eventSubs.splice(index, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
unsubscribeAll() {
|
|
|
|
for (let event of this.eventSubs) {
|
|
|
|
this.__eventemitter.off(event.event, event.callback);
|
|
|
|
}
|
|
|
|
this._eventSubs = [];
|
|
|
|
}
|
|
|
|
}
|
2018-02-11 23:07:23 +01:00
|
|
|
|
|
|
|
export default class PluginApi {
|
|
|
|
|
|
|
|
constructor(pluginInfo) {
|
|
|
|
this.pluginInfo = pluginInfo;
|
2018-03-02 20:42:17 +01:00
|
|
|
this.Events = new EventsWrapper(Events);
|
2018-02-11 23:07:23 +01:00
|
|
|
}
|
|
|
|
|
2018-03-02 20:42:17 +01:00
|
|
|
get plugin() {
|
|
|
|
return PluginManager.getPluginById(this.pluginInfo.id || this.pluginInfo.name.toLowerCase().replace(/[^a-zA-Z0-9-]/g, '-').replace(/--/g, '-'));
|
|
|
|
}
|
|
|
|
|
|
|
|
loggerLog(...message) { Logger.log(this.pluginInfo.name, message) }
|
|
|
|
loggerErr(...message) { Logger.err(this.pluginInfo.name, message) }
|
|
|
|
loggerWarn(...message) { Logger.warn(this.pluginInfo.name, message) }
|
|
|
|
loggerInfo(...message) { Logger.info(this.pluginInfo.name, message) }
|
|
|
|
loggerDbg(...message) { Logger.dbg(this.pluginInfo.name, message) }
|
2018-02-11 23:07:23 +01:00
|
|
|
get Logger() {
|
|
|
|
return {
|
|
|
|
log: this.loggerLog.bind(this),
|
|
|
|
err: this.loggerErr.bind(this),
|
|
|
|
warn: this.loggerWarn.bind(this),
|
|
|
|
info: this.loggerInfo.bind(this),
|
|
|
|
dbg: this.loggerDbg.bind(this)
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-03-02 20:42:17 +01:00
|
|
|
get Utils() {
|
|
|
|
return {
|
|
|
|
overload: () => Utils.overload.apply(Utils, arguments),
|
|
|
|
tryParseJson: () => Utils.tryParseJson.apply(Utils, arguments),
|
|
|
|
toCamelCase: () => Utils.toCamelCase.apply(Utils, arguments),
|
|
|
|
compare: () => Utils.compare.apply(Utils, arguments),
|
|
|
|
deepclone: () => Utils.deepclone.apply(Utils, arguments)
|
|
|
|
};
|
2018-02-12 00:04:07 +01:00
|
|
|
}
|
2018-02-11 23:07:23 +01:00
|
|
|
|
2018-03-02 20:42:17 +01:00
|
|
|
getInternalSetting(set, category, setting) {
|
|
|
|
return Settings.get(set, category, setting);
|
2018-02-12 00:04:07 +01:00
|
|
|
}
|
2018-03-02 20:42:17 +01:00
|
|
|
get InternalSettings() {
|
2018-02-11 23:07:23 +01:00
|
|
|
return {
|
2018-03-02 20:42:17 +01:00
|
|
|
get: this.getInternalSetting.bind(this)
|
|
|
|
};
|
2018-02-11 23:07:23 +01:00
|
|
|
}
|
2018-02-12 23:49:44 +01:00
|
|
|
|
2018-03-02 20:42:17 +01:00
|
|
|
get injectedStyles() {
|
|
|
|
return this._injectedStyles || (this._injectedStyles = []);
|
|
|
|
}
|
|
|
|
compileSass(scss, options) {
|
|
|
|
return ClientIPC.send('bd-compileSass', Object.assign({ data: scss }, options));
|
|
|
|
}
|
|
|
|
getConfigAsSCSS(settingsset) {
|
|
|
|
return ThemeManager.getConfigAsSCSS(settingsset ? settingsset : this.plugin.settings);
|
|
|
|
}
|
|
|
|
injectStyle(id, css) {
|
|
|
|
if (id && !css) css = id, id = undefined;
|
|
|
|
this.deleteStyle(id);
|
|
|
|
const styleid = `plugin-${this.getPlugin().id}-${id}`;
|
|
|
|
this.injectedStyles.push(styleid);
|
|
|
|
DOM.injectStyle(css, styleid);
|
|
|
|
}
|
|
|
|
async injectSass(id, scss, options) {
|
|
|
|
// In most cases a plugin's styles should be precompiled instead of using this
|
|
|
|
if (id && !scss && !options) scss = id, id = undefined;
|
|
|
|
const css = await this.compileSass(scss, options);
|
|
|
|
this.injectStyle(id, css, options);
|
|
|
|
}
|
|
|
|
deleteStyle(id) {
|
|
|
|
const styleid = `plugin-${this.getPlugin().id}-${id}`;
|
|
|
|
this.injectedStyles.splice(this.injectedStyles.indexOf(styleid), 1);
|
|
|
|
DOM.deleteStyle(styleid);
|
|
|
|
}
|
|
|
|
deleteAllStyles(id, css) {
|
|
|
|
for (let id of this.injectedStyles) {
|
|
|
|
this.deleteStyle(id);
|
|
|
|
}
|
2018-02-13 23:37:24 +01:00
|
|
|
}
|
2018-03-02 20:42:17 +01:00
|
|
|
get CssUtils() {
|
2018-02-13 23:37:24 +01:00
|
|
|
return {
|
2018-03-02 20:42:17 +01:00
|
|
|
compileSass: this.compileSass.bind(this),
|
|
|
|
getConfigAsSCSS: this.getConfigAsSCSS.bind(this),
|
|
|
|
injectStyle: this.injectStyle.bind(this),
|
|
|
|
injectSass: this.injectSass.bind(this),
|
|
|
|
deleteStyle: this.deleteStyle.bind(this),
|
|
|
|
deleteAllStyles: this.deleteAllStyles.bind(this)
|
2018-02-13 23:37:24 +01:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-03-02 21:19:59 +01:00
|
|
|
get modalStack() {
|
|
|
|
return this._modalStack || (this._modalStack = []);
|
|
|
|
}
|
2018-03-02 21:48:29 +01:00
|
|
|
addModal(_modal, component) {
|
|
|
|
const modal = Modals.add(_modal, component);
|
|
|
|
modal.close = force => this.closeModal(modal, force);
|
|
|
|
this.modalStack.push(modal);
|
|
|
|
return modal;
|
2018-03-02 21:19:59 +01:00
|
|
|
}
|
|
|
|
async closeModal(modal, force) {
|
|
|
|
await Modals.close(modal, force);
|
|
|
|
this._modalStack = this.modalStack.filter(m => m !== modal);
|
|
|
|
}
|
|
|
|
closeAllModals() {
|
|
|
|
for (let modal of this.modalStack)
|
|
|
|
modal.close();
|
|
|
|
}
|
|
|
|
closeLastModal() {
|
|
|
|
if (!this.modalStack.length) return;
|
|
|
|
this.modalStack[this.modalStack.length - 1].close();
|
|
|
|
}
|
2018-03-02 21:48:29 +01:00
|
|
|
settingsModal(settingsset, headertext, options) {
|
|
|
|
return this.addModal(Object.assign({
|
|
|
|
headertext: headertext ? headertext : settingsset.headertext,
|
|
|
|
settings: settingsset,
|
|
|
|
schemes: settingsset.schemes
|
|
|
|
}, options), SettingsModal);
|
|
|
|
}
|
2018-03-02 21:19:59 +01:00
|
|
|
get Modals() {
|
2018-03-02 21:48:29 +01:00
|
|
|
return Object.defineProperty({
|
2018-03-02 21:19:59 +01:00
|
|
|
add: this.addModal.bind(this),
|
|
|
|
close: this.closeModal.bind(this),
|
|
|
|
closeAll: this.closeAllModals.bind(this),
|
2018-03-02 21:48:29 +01:00
|
|
|
closeLast: this.closeLastModal.bind(this),
|
|
|
|
settings: this.settingsModal.bind(this)
|
|
|
|
}, 'stack', {
|
|
|
|
get: () => this.modalStack
|
|
|
|
});
|
2018-03-02 21:19:59 +01:00
|
|
|
}
|
|
|
|
|
2018-02-12 23:49:44 +01:00
|
|
|
async getPlugin(plugin_id) {
|
|
|
|
// This should require extra permissions
|
|
|
|
return await PluginManager.waitForPlugin(plugin_id);
|
|
|
|
}
|
2018-03-02 20:42:17 +01:00
|
|
|
listPlugins(plugin_id) {
|
2018-02-12 23:49:44 +01:00
|
|
|
return PluginManager.localContent.map(plugin => plugin.id);
|
|
|
|
}
|
|
|
|
get Plugins() {
|
|
|
|
return {
|
|
|
|
getPlugin: this.getPlugin.bind(this),
|
2018-03-02 20:42:17 +01:00
|
|
|
listPlugins: this.listPlugins.bind(this)
|
2018-02-12 23:49:44 +01:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
async getTheme(theme_id) {
|
|
|
|
// This should require extra permissions
|
|
|
|
return await ThemeManager.waitForContent(theme_id);
|
|
|
|
}
|
2018-03-02 20:42:17 +01:00
|
|
|
listThemes(plugin_id) {
|
2018-02-12 23:49:44 +01:00
|
|
|
return ThemeManager.localContent.map(theme => theme.id);
|
|
|
|
}
|
|
|
|
get Themes() {
|
|
|
|
return {
|
|
|
|
getTheme: this.getTheme.bind(this),
|
2018-03-02 20:42:17 +01:00
|
|
|
getThemes: this.listThemes.bind(this)
|
2018-02-12 23:49:44 +01:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-02-13 17:43:44 +01:00
|
|
|
async bridge(plugin_id) {
|
2018-02-12 23:49:44 +01:00
|
|
|
const plugin = await PluginManager.waitForPlugin(plugin_id);
|
2018-02-13 17:43:44 +01:00
|
|
|
return plugin.bridge;
|
2018-02-12 23:49:44 +01:00
|
|
|
}
|
|
|
|
|
2018-02-13 17:43:44 +01:00
|
|
|
get require() { return this.import }
|
2018-02-13 17:18:01 +01:00
|
|
|
import(m) {
|
2018-02-13 23:24:04 +01:00
|
|
|
const module = ExtModuleManager.findModule(m);
|
2018-02-13 17:18:01 +01:00
|
|
|
if (module && module.__require) return module.__require;
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2018-02-11 23:07:23 +01:00
|
|
|
}
|