diff options
Diffstat (limited to 'src')
23 files changed, 249 insertions, 28 deletions
diff --git a/src/plugins/PluginIndex.ts b/src/plugins/PluginIndex.ts new file mode 100644 index 00000000..502161a1 --- /dev/null +++ b/src/plugins/PluginIndex.ts @@ -0,0 +1,6 @@ +import { Plugin } from "util/plugin"; +import * as example_plugin from "./example-plugin/TestPlugin"; + +export const PluginIndex: any = { + "example-plugin": new example_plugin.default(), +}; \ No newline at end of file diff --git a/src/plugins/example-plugin/ExamplePlugin.ts b/src/plugins/example-plugin/ExamplePlugin.ts deleted file mode 100644 index e6f70657..00000000 --- a/src/plugins/example-plugin/ExamplePlugin.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { Plugin } from "@fosscord/util"; - -export default class TestPlugin extends Plugin { - onPluginLoaded(): void { - console.log("Hello from test plugin! IT WORKS!!!!!!!"); - } -} \ No newline at end of file diff --git a/src/plugins/example-plugin/TestPlugin.ts b/src/plugins/example-plugin/TestPlugin.ts new file mode 100644 index 00000000..7a86aab2 --- /dev/null +++ b/src/plugins/example-plugin/TestPlugin.ts @@ -0,0 +1,12 @@ +import { Plugin } from "@fosscord/util"; + +export default class TestPlugin implements Plugin { + pluginPath: string; + async initConfig(): Promise<void> { + + } + onPluginLoaded() { + console.log("Test plugin active!"); + } + +} \ No newline at end of file diff --git a/src/plugins/example-plugin/plugin.json b/src/plugins/example-plugin/plugin.json index 2fcb7a00..f6c1b7ff 100644 --- a/src/plugins/example-plugin/plugin.json +++ b/src/plugins/example-plugin/plugin.json @@ -6,5 +6,5 @@ ], "repository": "https://github.com/fosscord/fosscord-server", "license": "", - "index": "ExamplePlugin.js" + "mainClass": "TestPlugin" } diff --git a/src/util/entities/PluginConfig.ts b/src/util/entities/PluginConfig.ts new file mode 100644 index 00000000..a1364912 --- /dev/null +++ b/src/util/entities/PluginConfig.ts @@ -0,0 +1,11 @@ +import { Column, Entity } from "typeorm"; +import { BaseClassWithoutId, PrimaryIdColumn } from "./BaseClass"; + +@Entity("plugin_config") +export class PluginConfigEntity extends BaseClassWithoutId { + @PrimaryIdColumn() + key: string; + + @Column({ type: "simple-json", nullable: true }) + value: number | boolean | null | string | undefined; +} \ No newline at end of file diff --git a/src/util/plugin/Plugin.ts b/src/util/plugin/Plugin.ts index 1c86a006..0fb1732f 100644 --- a/src/util/plugin/Plugin.ts +++ b/src/util/plugin/Plugin.ts @@ -1,5 +1,5 @@ import EventEmitter from "events"; -import { TypedEventEmitter } from "@fosscord/util"; +import { PluginLoadedEventArgs, TypedEventEmitter } from "@fosscord/util"; type PluginEvents = { error: (error: Error | unknown) => void; @@ -7,14 +7,31 @@ type PluginEvents = { }; //this doesnt work, check later: - //(EventEmitter as new () => TypedEventEmitter<PluginEvents>) { -export class Plugin extends EventEmitter { - private _untypedOn = this.on - private _untypedEmit = this.emit - public on = <K extends keyof PluginEvents>(event: K, listener: PluginEvents[K]): this => this._untypedOn(event, listener) - public emit = <K extends keyof PluginEvents>(event: K, ...args: Parameters<PluginEvents[K]>): boolean => this._untypedEmit(event, ...args) - - async init() { + //EventEmitter as new () => TypedEventEmitter<PluginEvents> +export class Plugin { + /** + * Path the plugin resides in. + * + * @type {string} + * @memberof Plugin + */ + pluginPath: string; + /** + * + * + * @memberof Plugin + */ + async initConfig() { // insert default config into database? + console.log("did you forget to implement initConfig?"); + } + /** + * + * + * @param {PluginLoadedEventArgs} args Info about plugin environment + * @memberof Plugin + */ + onPluginLoaded?(args?: PluginLoadedEventArgs) { + } } diff --git a/src/util/plugin/PluginConfig.ts b/src/util/plugin/PluginConfig.ts new file mode 100644 index 00000000..c7a7db87 --- /dev/null +++ b/src/util/plugin/PluginConfig.ts @@ -0,0 +1,92 @@ +import { ConfigEntity } from "../entities/Config"; +import fs from "fs"; +import { OrmUtils, Environment } from ".."; + +// TODO: yaml instead of json +const overridePath = process.env.PLUGIN_CONFIG_PATH ?? ""; + +let config: any; +let pairs: ConfigEntity[]; + +// TODO: use events to inform about config updates +// Config keys are separated with _ + +export const Config = { + init: async function init() { + if (config) return config; + console.log('[Config] Loading configuration...') + pairs = await ConfigEntity.find(); + config = pairsToConfig(pairs); + //config = (config || {}).merge(new ConfigValue()); + //config = OrmUtils.mergeDeep(new ConfigValue(), config) + + if(process.env.CONFIG_PATH) + try { + const overrideConfig = JSON.parse(fs.readFileSync(overridePath, { encoding: "utf8" })); + config = overrideConfig.merge(config); + } catch (error) { + fs.writeFileSync(overridePath, JSON.stringify(config, null, 4)); + } + + return this.set(config); + }, + get: function get() { + if(!config) { + if(Environment.isDebug) + console.log("Oops.. trying to get config without config existing... Returning defaults... (Is the database still initialising?)"); + return {}; + } + return config; + }, + set: function set(val: Partial<any>) { + if (!config || !val) return; + config = val.merge(config); + + return applyConfig(config); + }, +}; + +function applyConfig(val: any) { + async function apply(obj: any, key = ""): Promise<any> { + if (typeof obj === "object" && obj !== null) + return Promise.all(Object.keys(obj).map((k) => apply(obj[k], key ? `${key}_${k}` : k))); + + let pair = pairs.find((x) => x.key === key); + if (!pair) pair = new ConfigEntity(); + + pair.key = key; + pair.value = obj; + return pair.save(); + } + if(process.env.CONFIG_PATH) { + if(Environment.isDebug) + console.log(`Writing config: ${process.env.CONFIG_PATH}`) + fs.writeFileSync(overridePath, JSON.stringify(val, null, 4)); + } + + return apply(val); +} + +function pairsToConfig(pairs: ConfigEntity[]) { + let value: any = {}; + + pairs.forEach((p) => { + const keys = p.key.split("_"); + let obj = value; + let prev = ""; + let prevObj = obj; + let i = 0; + + for (const key of keys) { + if (!isNaN(Number(key)) && !prevObj[prev]?.length) prevObj[prev] = obj = []; + if (i++ === keys.length - 1) obj[key] = p.value; + else if (!obj[key]) obj[key] = {}; + + prev = key; + prevObj = obj; + obj = obj[key]; + } + }); + + return value; +} diff --git a/src/util/plugin/PluginLoader.ts b/src/util/plugin/PluginLoader.ts index e69cb499..8c140d29 100644 --- a/src/util/plugin/PluginLoader.ts +++ b/src/util/plugin/PluginLoader.ts @@ -1,11 +1,13 @@ import path from "path"; import fs from "fs"; -import { Plugin, PluginManifest } from "./"; +import { Plugin, PluginLoadedEventArgs, PluginManifest } from "./"; +import { PluginIndex } from "plugins/PluginIndex"; const root = process.env.PLUGIN_LOCATION || "dist/plugins"; let pluginsLoaded = false; export class PluginLoader { + public static plugins: Plugin[] = []; public static loadPlugins() { console.log(`Plugin root directory: ${path.resolve(root)}`); const dirs = fs.readdirSync(root).filter((x) => { @@ -17,6 +19,9 @@ export class PluginLoader { } }); console.log(dirs); + PluginIndex.forEach((x: any)=>{ + console.log(x.onPluginLoaded) + }) dirs.forEach(async (x) => { let modPath = path.resolve(path.join(root, x)); console.log(`Trying to load plugin: ${modPath}`); @@ -24,16 +29,13 @@ export class PluginLoader { console.log( `Plugin info: ${manifest.name} (${manifest.id}), written by ${manifest.authors}, available at ${manifest.repository}` ); - const module_ = require(path.join(modPath, manifest.index)) as Plugin; - try { - await module_.init(); - module_.emit("loaded"); - } catch (error) { - module_.emit("error", error); - } + const module_ = PluginIndex["example-plugin"]; + + module_.pluginPath = modPath; + if(module_.onPluginLoaded) module_.onPluginLoaded({} as PluginLoadedEventArgs); + this.plugins.push(module_); }); - // - //module_.pluginPath = + console.log(`Done loading ${this.plugins.length} plugins!`) } } diff --git a/src/util/plugin/PluginManifest.ts b/src/util/plugin/PluginManifest.ts index 01b2b084..79ecc465 100644 --- a/src/util/plugin/PluginManifest.ts +++ b/src/util/plugin/PluginManifest.ts @@ -6,5 +6,5 @@ export class PluginManifest { license: string; version: string // semver versionCode: number // integer - index: string; + mainClass: string; } \ No newline at end of file diff --git a/src/util/plugin/index.ts b/src/util/plugin/index.ts index c4c0c2ac..5974a065 100644 --- a/src/util/plugin/index.ts +++ b/src/util/plugin/index.ts @@ -1,3 +1,4 @@ export * from "./Plugin"; export * from "./PluginLoader"; export * from "./PluginManifest"; +export * from "./plugin_data_objects/index"; diff --git a/src/util/plugin/plugin_data_objects/ChannelCreateEventArgs.ts b/src/util/plugin/plugin_data_objects/ChannelCreateEventArgs.ts new file mode 100644 index 00000000..ce7dec87 --- /dev/null +++ b/src/util/plugin/plugin_data_objects/ChannelCreateEventArgs.ts @@ -0,0 +1,7 @@ +export interface PreChannelCreateEventArgs { + +} + +export interface OnChannelCreateEventArgs { + +} diff --git a/src/util/plugin/plugin_data_objects/GuildCreateEventArgs.ts b/src/util/plugin/plugin_data_objects/GuildCreateEventArgs.ts new file mode 100644 index 00000000..e10e675a --- /dev/null +++ b/src/util/plugin/plugin_data_objects/GuildCreateEventArgs.ts @@ -0,0 +1,7 @@ +export interface PreGuildCreateEventArgs { + +} + +export interface OnGuildCreateEventArgs { + +} diff --git a/src/util/plugin/plugin_data_objects/LoginEventArgs.ts b/src/util/plugin/plugin_data_objects/LoginEventArgs.ts new file mode 100644 index 00000000..391b852e --- /dev/null +++ b/src/util/plugin/plugin_data_objects/LoginEventArgs.ts @@ -0,0 +1,7 @@ +export interface PreLoginEventArgs { + +} + +export interface OnLoginEventArgs { + +} diff --git a/src/util/plugin/plugin_data_objects/MessageEventArgs.ts b/src/util/plugin/plugin_data_objects/MessageEventArgs.ts new file mode 100644 index 00000000..0a3498c2 --- /dev/null +++ b/src/util/plugin/plugin_data_objects/MessageEventArgs.ts @@ -0,0 +1,7 @@ +export interface PreMessageEventArgs { + +} + +export interface OnMessageEventArgs { + +} diff --git a/src/util/plugin/plugin_data_objects/PluginLoadedEventArgs.ts b/src/util/plugin/plugin_data_objects/PluginLoadedEventArgs.ts new file mode 100644 index 00000000..58829f15 --- /dev/null +++ b/src/util/plugin/plugin_data_objects/PluginLoadedEventArgs.ts @@ -0,0 +1,3 @@ +export interface PluginLoadedEventArgs { + +} \ No newline at end of file diff --git a/src/util/plugin/plugin_data_objects/RegisterEventArgs.ts b/src/util/plugin/plugin_data_objects/RegisterEventArgs.ts new file mode 100644 index 00000000..7f7c0c76 --- /dev/null +++ b/src/util/plugin/plugin_data_objects/RegisterEventArgs.ts @@ -0,0 +1,7 @@ +export interface PreRegisterEventArgs { + +} + +export interface OnRegisterEventArgs { + +} diff --git a/src/util/plugin/plugin_data_objects/TypingEventArgs.ts b/src/util/plugin/plugin_data_objects/TypingEventArgs.ts new file mode 100644 index 00000000..f6660692 --- /dev/null +++ b/src/util/plugin/plugin_data_objects/TypingEventArgs.ts @@ -0,0 +1,7 @@ +export interface PreTypingEventArgs { + +} + +export interface OnTypingEventArgs { + +} diff --git a/src/util/plugin/plugin_data_objects/_gen.sh b/src/util/plugin/plugin_data_objects/_gen.sh new file mode 100755 index 00000000..9fbd1749 --- /dev/null +++ b/src/util/plugin/plugin_data_objects/_gen.sh @@ -0,0 +1,21 @@ +#!/bin/sh +while read event +do + if [ ! -f "${event}EventArgs.ts" ] + then + echo Making event $event... + ( + echo "export interface Pre${event}EventArgs {" + echo ' ' + echo '}' + echo '' + echo "export interface On${event}EventArgs {" + echo ' ' + echo '}' + ) > ${event}EventArgs.ts + fi +done < _pdo + +echo '' + +node ../../../../scripts/gen_index.js .. --recursive \ No newline at end of file diff --git a/src/util/plugin/plugin_data_objects/_pdo b/src/util/plugin/plugin_data_objects/_pdo new file mode 100644 index 00000000..fa207f77 --- /dev/null +++ b/src/util/plugin/plugin_data_objects/_pdo @@ -0,0 +1,7 @@ +Register +Message +Login +GuildCreate +ChannelCreate +Typing +StatusChange \ No newline at end of file diff --git a/src/util/plugin/plugin_data_objects/_todo.txt b/src/util/plugin/plugin_data_objects/_todo.txt new file mode 100644 index 00000000..a6a78c7e --- /dev/null +++ b/src/util/plugin/plugin_data_objects/_todo.txt @@ -0,0 +1 @@ +Voice events when we do voice. \ No newline at end of file diff --git a/src/util/plugin/plugin_data_objects/index.ts b/src/util/plugin/plugin_data_objects/index.ts new file mode 100644 index 00000000..c75d43f9 --- /dev/null +++ b/src/util/plugin/plugin_data_objects/index.ts @@ -0,0 +1,7 @@ +export * from "./ChannelCreateEventArgs"; +export * from "./GuildCreateEventArgs"; +export * from "./LoginEventArgs"; +export * from "./MessageEventArgs"; +export * from "./PluginLoadedEventArgs"; +export * from "./RegisterEventArgs"; +export * from "./TypingEventArgs"; diff --git a/src/util/util/Environment.ts b/src/util/util/Environment.ts new file mode 100644 index 00000000..a6d68785 --- /dev/null +++ b/src/util/util/Environment.ts @@ -0,0 +1,3 @@ +export class Environment { + static isDebug: boolean = /--debug|--inspect/.test(process.execArgv.join(' ')); +} diff --git a/src/util/util/index.ts b/src/util/util/index.ts index 11f0b72a..8135c107 100644 --- a/src/util/util/index.ts +++ b/src/util/util/index.ts @@ -23,3 +23,6 @@ export * from "./Snowflake"; export * from "./String"; export * from "./Token"; export * from "./TraverseDirectory"; +export * from "./InvisibleCharacters"; +export * from "./Environment"; +export * from "./Paths"; \ No newline at end of file |