Plugins finally load!

This commit is contained in:
TheArcaneBrony committed 2022-09-04 10:48:54 +02:00
1 parent 7b591bae3e
commit 6d17f44f9b
23 files changed
+249 -28

No files matched your search

+6
View File
@@ -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(),
};
@@ -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!!!!!!!");
}
}
+12
View File
@@ -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!");
}
}
+1 -1
View File
@@ -6,5 +6,5 @@
],
"repository": "https://github.com/fosscord/fosscord-server",
"license": "",
"index": "ExamplePlugin.js"
"mainClass": "TestPlugin"
}
+11
View File
@@ -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;
}
+26 -9
View File
@@ -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) {
}
}
+92
View File
@@ -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;
}
+12 -10
View File
@@ -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!`)
}
}
+1 -1
View File
@@ -6,5 +6,5 @@ export class PluginManifest {
license: string;
version: string // semver
versionCode: number // integer
index: string;
mainClass: string;
}
+1
View File
@@ -1,3 +1,4 @@
export * from "./Plugin";
export * from "./PluginLoader";
export * from "./PluginManifest";
export * from "./plugin_data_objects/index";
@@ -0,0 +1,7 @@
export interface PreChannelCreateEventArgs {
}
export interface OnChannelCreateEventArgs {
}
@@ -0,0 +1,7 @@
export interface PreGuildCreateEventArgs {
}
export interface OnGuildCreateEventArgs {
}
@@ -0,0 +1,7 @@
export interface PreLoginEventArgs {
}
export interface OnLoginEventArgs {
}
@@ -0,0 +1,7 @@
export interface PreMessageEventArgs {
}
export interface OnMessageEventArgs {
}
@@ -0,0 +1,3 @@
export interface PluginLoadedEventArgs {
}
@@ -0,0 +1,7 @@
export interface PreRegisterEventArgs {
}
export interface OnRegisterEventArgs {
}
@@ -0,0 +1,7 @@
export interface PreTypingEventArgs {
}
export interface OnTypingEventArgs {
}
+21
View File
@@ -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
+7
View File
@@ -0,0 +1,7 @@
Register
Message
Login
GuildCreate
ChannelCreate
Typing
StatusChange
@@ -0,0 +1 @@
Voice events when we do voice.
@@ -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";
+3
View File
@@ -0,0 +1,3 @@
export class Environment {
static isDebug: boolean = /--debug|--inspect/.test(process.execArgv.join(' '));
}
+3
View File
@@ -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";