diff --git a/src/Server.ts b/src/Server.ts
index e672bd0c..85de728f 100644
--- a/src/Server.ts
+++ b/src/Server.ts
@@ -8,6 +8,7 @@ import { Config, getOrInitialiseDatabase } from "@fosscord/util";
import * as Sentry from "@sentry/node";
import * as Tracing from "@sentry/tracing";
import { PluginLoader } from "@fosscord/util";
+import { PluginConfig } from "util/plugin/PluginConfig";
const app = express();
const server = http.createServer();
@@ -34,6 +35,7 @@ process.on("SIGTERM", () => {
async function main() {
await getOrInitialiseDatabase();
await Config.init();
+ await PluginConfig.init();
//Sentry
if (Config.get().sentry.enabled) {
@@ -61,7 +63,7 @@ async function main() {
}
console.log(`[Server] ${green(`listening on port ${bold(port)}`)}`);
- PluginLoader.loadPlugins();
+ await PluginLoader.loadPlugins();
}
main().catch(console.error);
diff --git a/src/api/Server.ts b/src/api/Server.ts
index 560014d0..a3e6f23b 100644
--- a/src/api/Server.ts
+++ b/src/api/Server.ts
@@ -12,6 +12,7 @@ import TestClient from "./middlewares/TestClient";
import { initTranslation } from "./middlewares/Translation";
import { initInstance } from "./util/handlers/Instance";
import fs from "fs";
+import { PluginConfig } from "util/plugin/PluginConfig";
export interface FosscordServerOptions extends ServerOptions {}
@@ -35,6 +36,7 @@ export class FosscordServer extends Server {
async start() {
await getOrInitialiseDatabase();
await Config.init();
+ await PluginConfig.init();
await initEvent();
await initInstance();
diff --git a/src/api/middlewares/ErrorHandler.ts b/src/api/middlewares/ErrorHandler.ts
index 813adc18..a3333be5 100644
--- a/src/api/middlewares/ErrorHandler.ts
+++ b/src/api/middlewares/ErrorHandler.ts
@@ -10,8 +10,12 @@ export function ErrorHandler(error: Error, req: Request, res: Response, next: Ne
let httpcode = code;
let message = error?.toString();
let errors = undefined;
+ let data = undefined;
- if (error instanceof HTTPError && error.code) code = httpcode = error.code;
+ if (error instanceof HTTPError && error.code) {
+ code = httpcode = error.code;
+ if(error.data) data = error.data;
+ }
else if (error instanceof ApiError) {
code = error.code;
message = error.message;
@@ -35,7 +39,7 @@ export function ErrorHandler(error: Error, req: Request, res: Response, next: Ne
if (httpcode > 511) httpcode = 400;
- res.status(httpcode).json({ code: code, message, errors });
+ res.status(httpcode).json({ code: code, message, errors, data });
} catch (error) {
console.error(`[Internal Server Error] 500`, error);
return res.status(500).json({ code: 500, message: "Internal Server Error" });
diff --git a/src/api/routes/channels/#channel_id/messages/index.ts b/src/api/routes/channels/#channel_id/messages/index.ts
index 5fdcb6f9..d542ea0f 100644
--- a/src/api/routes/channels/#channel_id/messages/index.ts
+++ b/src/api/routes/channels/#channel_id/messages/index.ts
@@ -13,7 +13,11 @@ import {
MessageCreateEvent,
MessageCreateSchema,
Snowflake,
- uploadFile
+ uploadFile,
+ Member,
+ MessageCreateSchema,
+ PluginEventHandler,
+ PreMessageEventArgs
} from "@fosscord/util";
import { Request, Response, Router } from "express";
import multer from "multer";
@@ -206,9 +210,9 @@ router.post(
})
);
}
-
- //Defining member fields
- var member = await Member.findOneOrFail({ where: { id: req.user_id }, relations: ["roles"] });
+
+ //Defining member fields
+ var member = await Member.findOneOrFail({ where: { id: req.user_id }, relations: ["roles", "user"] });
// TODO: This doesn't work either
// member.roles = member.roles.filter((role) => {
// return role.id !== role.guild_id;
@@ -220,6 +224,11 @@ router.post(
// delete message.member.last_message_id;
// delete message.member.index;
+ let blocks = (await PluginEventHandler.preMessageEvent({
+ message
+ } as PreMessageEventArgs)).filter(x=>x.cancel);
+ if(blocks.length > 0) throw new HTTPError("Message denied.", 400, blocks.filter(x=>x.blockReason).map(x=>x.blockReason));
+
await Promise.all([
message.save(),
emitEvent({ event: "MESSAGE_CREATE", channel_id: channel_id, data: message } as MessageCreateEvent),
diff --git a/src/api/util/handlers/Message.ts b/src/api/util/handlers/Message.ts
index d760d27c..07ed11ad 100644
--- a/src/api/util/handlers/Message.ts
+++ b/src/api/util/handlers/Message.ts
@@ -21,6 +21,13 @@ import {
Role,
ROLE_MENTION,
User,
+ Application,
+ Webhook,
+ Attachment,
+ Config,
+ MessageCreateSchema,
+ PluginEventHandler,
+ PreMessageEventArgs,
USER_MENTION,
Webhook
} from "@fosscord/util";
@@ -205,6 +212,10 @@ export async function postHandleMessage(message: Message) {
export async function sendMessage(opts: MessageOptions) {
const message = await handleMessage({ ...opts, timestamp: new Date() });
+ if((await PluginEventHandler.preMessageEvent({
+ message
+ } as PreMessageEventArgs)).filter(x=>x.cancel).length > 0) return;
+
//TODO: check this, removed toJSON call
await Promise.all([
Message.insert(message),
diff --git a/src/cdn/Server.ts b/src/cdn/Server.ts
index 9cedaa02..8b684b53 100644
--- a/src/cdn/Server.ts
+++ b/src/cdn/Server.ts
@@ -5,6 +5,8 @@ import path from "path";
import avatarsRoute from "./routes/avatars";
import guildProfilesRoute from "./routes/guild-profiles";
import iconsRoute from "./routes/role-icons";
+import bodyParser from "body-parser";
+import { PluginConfig } from "util/plugin/PluginConfig";
export interface CDNServerOptions extends ServerOptions {}
@@ -18,6 +20,7 @@ export class CDNServer extends Server {
async start() {
await getOrInitialiseDatabase();
await Config.init();
+ await PluginConfig.init();
this.app.use((req, res, next) => {
res.set("Access-Control-Allow-Origin", "*");
// TODO: use better CSP policy
diff --git a/src/gateway/Server.ts b/src/gateway/Server.ts
index 97da3fa0..60a82d8f 100644
--- a/src/gateway/Server.ts
+++ b/src/gateway/Server.ts
@@ -3,6 +3,8 @@ import dotenv from "dotenv";
import http from "http";
import ws from "ws";
import { Connection } from "./events/Connection";
+import http from "http";
+import { PluginConfig } from "util/plugin/PluginConfig";
dotenv.config();
export class Server {
@@ -40,6 +42,7 @@ export class Server {
async start(): Promise<void> {
await getOrInitialiseDatabase();
await Config.init();
+ await PluginConfig.init();
await initEvent();
if (!this.server.listening) {
this.server.listen(this.port);
diff --git a/src/plugins/example-plugin/TestPlugin.ts b/src/plugins/example-plugin/TestPlugin.ts
index 7a86aab2..18e634f7 100644
--- a/src/plugins/example-plugin/TestPlugin.ts
+++ b/src/plugins/example-plugin/TestPlugin.ts
@@ -1,12 +1,26 @@
-import { Plugin } from "@fosscord/util";
+import { setupListener } from "@fosscord/gateway";
+import { Channel, Guild, Plugin, PluginLoadedEventArgs, PluginLoader, PluginManifest, PreMessageEventArgs, PreMessageEventResult } from "@fosscord/util";
+import { TestSettings } from "./TestSettings";
export default class TestPlugin implements Plugin {
- pluginPath: string;
- async initConfig(): Promise<void> {
-
- }
- onPluginLoaded() {
+ pluginManifest?: PluginManifest | undefined;
+ settings: TestSettings = new TestSettings();
+ async onPluginLoaded(env: PluginLoadedEventArgs) {
console.log("Test plugin active!");
+ if(this.pluginManifest) this.settings = PluginLoader.getPluginConfig(this.pluginManifest.id, this.settings) as TestSettings;
+ }
+ async onPreMessage(data: PreMessageEventArgs): Promise<PreMessageEventResult> {
+ let channel = await Channel.findOne({ where: { id: data.message.channel_id } });
+ let guild = await Guild.findOne({ where: { id: data.message.guild_id } });
+ let block = data.message.content?.includes('UwU');
+
+ let result = {cancel: block} as PreMessageEventResult;
+
+ if(block) {
+ console.log(`[TestPlugin] Blocked message in ${guild?.name}/#${channel?.name} by ${data.message.author?.username}: ${data.message.content}`);
+ result.blockReason = "[TestPlugin] Your message contains UwU! Get bamboozled!";
+ }
+
+ return result;
}
-
}
\ No newline at end of file
diff --git a/src/plugins/example-plugin/TestSettings.ts b/src/plugins/example-plugin/TestSettings.ts
new file mode 100644
index 00000000..d8c52187
--- /dev/null
+++ b/src/plugins/example-plugin/TestSettings.ts
@@ -0,0 +1,11 @@
+export class TestSettings {
+ someInt: number = 10;
+ someStr: string = "asdf";
+ someBool: boolean = true;
+ someDate: Date = new Date();
+ subSettings: SubSettings = new SubSettings();
+}
+
+export class SubSettings {
+ someStr: string = "jklm";
+}
\ No newline at end of file
diff --git a/src/start.ts b/src/start.ts
index cf1a42a5..9d01ce9c 100644
--- a/src/start.ts
+++ b/src/start.ts
@@ -7,6 +7,8 @@ import { bold, cyan, red, yellow } from "picocolors";
import "reflect-metadata";
import { initStats } from "./stats";
config();
+import { execSync } from "child_process";
+import { Logo } from "util/util/Logo";
// TODO: add socket event transmission
let cores = 1;
@@ -25,17 +27,15 @@ if (cluster.isMaster) {
}
}
const commit = getCommitOrFail();
-
- console.log(
- bold(`
-███████╗ ██████╗ ███████╗███████╗ ██████╗ ██████╗ ██████╗ ██████╗
-██╔════╝██╔═══██╗██╔════╝██╔════╝██╔════╝██╔═══██╗██╔══██╗██╔══██╗
-█████╗ ██║ ██║███████╗███████╗██║ ██║ ██║██████╔╝██║ ██║
-██╔══╝ ██║ ██║╚════██║╚════██║██║ ██║ ██║██╔══██╗██║ ██║
-██║ ╚██████╔╝███████║███████║╚██████╗╚██████╔╝██║ ██║██████╔╝
-╚═╝ ╚═════╝ ╚══════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═════╝
-
- fosscord-server | ${yellow(`Pre-release (${commit !== null ? commit.slice(0, 7) : "Unknown (Git cannot be found)"})`)}
+Logo.printLogo();
+console.log(bold(`
+ fosscord-server | ${yellow(
+ `Pre-release (${
+ commit !== null
+ ? commit.slice(0, 7)
+ : "Unknown (Git cannot be found)"
+ })`
+ )}
Commit Hash: ${commit !== null ? `${cyan(commit)} (${yellow(commit.slice(0, 7))})` : "Unknown (Git cannot be found)"}
Cores: ${cyan(os.cpus().length)} (Using ${cores} thread(s).)
diff --git a/src/util/entities/PluginConfig.ts b/src/util/entities/PluginConfig.ts
index a1364912..87de5167 100644
--- a/src/util/entities/PluginConfig.ts
+++ b/src/util/entities/PluginConfig.ts
@@ -7,5 +7,5 @@ export class PluginConfigEntity extends BaseClassWithoutId {
key: string;
@Column({ type: "simple-json", nullable: true })
- value: number | boolean | null | string | undefined;
+ value: number | boolean | null | string | Date | undefined;
}
\ No newline at end of file
diff --git a/src/util/entities/User.ts b/src/util/entities/User.ts
index 1237b676..57afb132 100644
--- a/src/util/entities/User.ts
+++ b/src/util/entities/User.ts
@@ -233,6 +233,26 @@ export class User extends BaseClass {
}
}
+ /**
+ *
+ *
+ * @static
+ * @param {{
+ * username: string;
+ * password?: string;
+ * email?: string;
+ * date_of_birth?: Date; // "2000-04-03"
+ * req?: any;
+ * }} {
+ * email,
+ * username,
+ * password,
+ * date_of_birth,
+ * req,
+ * }
+ * @return {*}
+ * @memberof User
+ */
static async register({
email,
username,
diff --git a/src/util/entities/index.ts b/src/util/entities/index.ts
index 2b91c2ba..444a7e49 100644
--- a/src/util/entities/index.ts
+++ b/src/util/entities/index.ts
@@ -31,3 +31,8 @@ export * from "./User";
export * from "./UserSettings";
export * from "./VoiceState";
export * from "./Webhook";
+export * from "./ClientRelease";
+export * from "./BackupCodes";
+export * from "./Note";
+export * from "./UserSettings";
+export * from "./PluginConfig";
diff --git a/src/util/migrations/mariadb/1660404644371-PluginConfigs.ts b/src/util/migrations/mariadb/1660404644371-PluginConfigs.ts
new file mode 100644
index 00000000..73953ca8
--- /dev/null
+++ b/src/util/migrations/mariadb/1660404644371-PluginConfigs.ts
@@ -0,0 +1,42 @@
+import { MigrationInterface, QueryRunner } from "typeorm";
+
+export class PluginConfigs1660404644371 implements MigrationInterface {
+ name = 'PluginConfigs1660404644371'
+
+ public async up(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ DROP INDEX \`IDX_76ba283779c8441fd5ff819c8c\` ON \`users\`
+ `);
+ await queryRunner.query(`
+ CREATE TABLE \`plugin_config\` (
+ \`key\` varchar(255) NOT NULL,
+ \`value\` text NULL,
+ PRIMARY KEY (\`key\`)
+ ) ENGINE = InnoDB
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`channels\`
+ ADD \`flags\` int NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`channels\`
+ ADD \`default_thread_rate_limit_per_user\` int NULL
+ `);
+ }
+
+ public async down(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ ALTER TABLE \`channels\` DROP COLUMN \`default_thread_rate_limit_per_user\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`channels\` DROP COLUMN \`flags\`
+ `);
+ await queryRunner.query(`
+ DROP TABLE \`plugin_config\`
+ `);
+ await queryRunner.query(`
+ CREATE UNIQUE INDEX \`IDX_76ba283779c8441fd5ff819c8c\` ON \`users\` (\`settingsId\`)
+ `);
+ }
+
+}
diff --git a/src/util/migrations/mariadb/1660534571948-UpdateMigrations.ts b/src/util/migrations/mariadb/1660534571948-UpdateMigrations.ts
new file mode 100644
index 00000000..d799fe80
--- /dev/null
+++ b/src/util/migrations/mariadb/1660534571948-UpdateMigrations.ts
@@ -0,0 +1,229 @@
+import { MigrationInterface, QueryRunner } from "typeorm";
+
+export class UpdateMigrations1660534571948 implements MigrationInterface {
+ name = 'UpdateMigrations1660534571948'
+
+ public async up(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP FOREIGN KEY \`FK_e5bf78cdbbe9ba91062d74c5aba\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`invites\` DROP FOREIGN KEY \`FK_15c35422032e0b22b4ada95f48f\`
+ `);
+ await queryRunner.query(`
+ DROP INDEX \`IDX_76ba283779c8441fd5ff819c8c\` ON \`users\`
+ `);
+ await queryRunner.query(`
+ CREATE TABLE \`plugin_config\` (
+ \`key\` varchar(255) NOT NULL,
+ \`value\` text NULL,
+ PRIMARY KEY (\`key\`)
+ ) ENGINE = InnoDB
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`rpc_origins\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`primary_sku_id\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`slug\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`guild_id\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`type\` text NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`hook\` tinyint NOT NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`redirect_uris\` text NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`rpc_application_state\` int NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`store_application_state\` int NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`verification_state\` int NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`interactions_endpoint_url\` varchar(255) NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`integration_public\` tinyint NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`integration_require_code_grant\` tinyint NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`discoverability_state\` int NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`discovery_eligibility_flags\` int NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`tags\` text NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`install_params\` text NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`bot_user_id\` varchar(255) NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD UNIQUE INDEX \`IDX_2ce5a55796fe4c2f77ece57a64\` (\`bot_user_id\`)
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`channels\`
+ ADD \`flags\` int NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`channels\`
+ ADD \`default_thread_rate_limit_per_user\` int NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` CHANGE \`description\` \`description\` varchar(255) NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`flags\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`flags\` int NOT NULL
+ `);
+ await queryRunner.query(`
+ CREATE UNIQUE INDEX \`REL_2ce5a55796fe4c2f77ece57a64\` ON \`applications\` (\`bot_user_id\`)
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD CONSTRAINT \`FK_2ce5a55796fe4c2f77ece57a647\` FOREIGN KEY (\`bot_user_id\`) REFERENCES \`users\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`invites\`
+ ADD CONSTRAINT \`FK_15c35422032e0b22b4ada95f48f\` FOREIGN KEY (\`inviter_id\`) REFERENCES \`users\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ }
+
+ public async down(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ ALTER TABLE \`invites\` DROP FOREIGN KEY \`FK_15c35422032e0b22b4ada95f48f\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP FOREIGN KEY \`FK_2ce5a55796fe4c2f77ece57a647\`
+ `);
+ await queryRunner.query(`
+ DROP INDEX \`REL_2ce5a55796fe4c2f77ece57a64\` ON \`applications\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`flags\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`flags\` varchar(255) NOT NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` CHANGE \`description\` \`description\` varchar(255) NOT NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`channels\` DROP COLUMN \`default_thread_rate_limit_per_user\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`channels\` DROP COLUMN \`flags\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP INDEX \`IDX_2ce5a55796fe4c2f77ece57a64\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`bot_user_id\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`install_params\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`tags\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`discovery_eligibility_flags\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`discoverability_state\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`integration_require_code_grant\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`integration_public\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`interactions_endpoint_url\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`verification_state\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`store_application_state\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`rpc_application_state\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`redirect_uris\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`hook\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`type\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`guild_id\` varchar(255) NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`slug\` varchar(255) NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`primary_sku_id\` varchar(255) NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`rpc_origins\` text NULL
+ `);
+ await queryRunner.query(`
+ DROP TABLE \`plugin_config\`
+ `);
+ await queryRunner.query(`
+ CREATE UNIQUE INDEX \`IDX_76ba283779c8441fd5ff819c8c\` ON \`users\` (\`settingsId\`)
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`invites\`
+ ADD CONSTRAINT \`FK_15c35422032e0b22b4ada95f48f\` FOREIGN KEY (\`inviter_id\`) REFERENCES \`users\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD CONSTRAINT \`FK_e5bf78cdbbe9ba91062d74c5aba\` FOREIGN KEY (\`guild_id\`) REFERENCES \`guilds\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ }
+
+}
diff --git a/src/util/migrations/postgres/1660404619978-PluginConfigs.ts b/src/util/migrations/postgres/1660404619978-PluginConfigs.ts
new file mode 100644
index 00000000..d8a5ab4d
--- /dev/null
+++ b/src/util/migrations/postgres/1660404619978-PluginConfigs.ts
@@ -0,0 +1,22 @@
+import { MigrationInterface, QueryRunner } from "typeorm";
+
+export class PluginConfigs1660404619978 implements MigrationInterface {
+ name = 'PluginConfigs1660404619978'
+
+ public async up(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ CREATE TABLE "plugin_config" (
+ "key" character varying NOT NULL,
+ "value" text,
+ CONSTRAINT "PK_aa929ece56c59233b85a16f62ef" PRIMARY KEY ("key")
+ )
+ `);
+ }
+
+ public async down(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ DROP TABLE "plugin_config"
+ `);
+ }
+
+}
diff --git a/src/util/migrations/sqlite/1660534525799-UpdateMigrations.ts b/src/util/migrations/sqlite/1660534525799-UpdateMigrations.ts
new file mode 100644
index 00000000..54a59fab
--- /dev/null
+++ b/src/util/migrations/sqlite/1660534525799-UpdateMigrations.ts
@@ -0,0 +1,829 @@
+import { MigrationInterface, QueryRunner } from "typeorm";
+
+export class UpdateMigrations1660534525799 implements MigrationInterface {
+ name = 'UpdateMigrations1660534525799'
+
+ public async up(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ CREATE TABLE "temporary_applications" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "name" varchar NOT NULL,
+ "icon" varchar,
+ "description" varchar NOT NULL,
+ "rpc_origins" text,
+ "bot_public" boolean NOT NULL,
+ "bot_require_code_grant" boolean NOT NULL,
+ "terms_of_service_url" varchar,
+ "privacy_policy_url" varchar,
+ "summary" varchar,
+ "verify_key" varchar NOT NULL,
+ "primary_sku_id" varchar,
+ "slug" varchar,
+ "cover_image" varchar,
+ "flags" varchar NOT NULL,
+ "owner_id" varchar,
+ "team_id" varchar,
+ "guild_id" varchar,
+ CONSTRAINT "FK_a36ed02953077f408d0f3ebc424" FOREIGN KEY ("team_id") REFERENCES "teams" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_e57508958bf92b9d9d25231b5e8" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_applications"(
+ "id",
+ "name",
+ "icon",
+ "description",
+ "rpc_origins",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "primary_sku_id",
+ "slug",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id",
+ "guild_id"
+ )
+ SELECT "id",
+ "name",
+ "icon",
+ "description",
+ "rpc_origins",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "primary_sku_id",
+ "slug",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id",
+ "guild_id"
+ FROM "applications"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "applications"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_applications"
+ RENAME TO "applications"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_applications" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "name" varchar NOT NULL,
+ "icon" varchar,
+ "description" varchar NOT NULL,
+ "bot_public" boolean NOT NULL,
+ "bot_require_code_grant" boolean NOT NULL,
+ "terms_of_service_url" varchar,
+ "privacy_policy_url" varchar,
+ "summary" varchar,
+ "verify_key" varchar NOT NULL,
+ "cover_image" varchar,
+ "flags" varchar NOT NULL,
+ "owner_id" varchar,
+ "team_id" varchar,
+ CONSTRAINT "FK_a36ed02953077f408d0f3ebc424" FOREIGN KEY ("team_id") REFERENCES "teams" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_e57508958bf92b9d9d25231b5e8" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_applications"(
+ "id",
+ "name",
+ "icon",
+ "description",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id"
+ )
+ SELECT "id",
+ "name",
+ "icon",
+ "description",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id"
+ FROM "applications"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "applications"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_applications"
+ RENAME TO "applications"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_applications" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "name" varchar NOT NULL,
+ "icon" varchar,
+ "description" varchar NOT NULL,
+ "bot_public" boolean NOT NULL,
+ "bot_require_code_grant" boolean NOT NULL,
+ "terms_of_service_url" varchar,
+ "privacy_policy_url" varchar,
+ "summary" varchar,
+ "verify_key" varchar NOT NULL,
+ "cover_image" varchar,
+ "flags" varchar NOT NULL,
+ "owner_id" varchar,
+ "team_id" varchar,
+ "type" text,
+ "hook" boolean NOT NULL,
+ "redirect_uris" text,
+ "rpc_application_state" integer,
+ "store_application_state" integer,
+ "verification_state" integer,
+ "interactions_endpoint_url" varchar,
+ "integration_public" boolean,
+ "integration_require_code_grant" boolean,
+ "discoverability_state" integer,
+ "discovery_eligibility_flags" integer,
+ "tags" text,
+ "install_params" text,
+ "bot_user_id" varchar,
+ CONSTRAINT "UQ_b7f6e13565e920916d902e1f431" UNIQUE ("bot_user_id"),
+ CONSTRAINT "FK_a36ed02953077f408d0f3ebc424" FOREIGN KEY ("team_id") REFERENCES "teams" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_e57508958bf92b9d9d25231b5e8" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_applications"(
+ "id",
+ "name",
+ "icon",
+ "description",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id"
+ )
+ SELECT "id",
+ "name",
+ "icon",
+ "description",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id"
+ FROM "applications"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "applications"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_applications"
+ RENAME TO "applications"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_applications" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "name" varchar NOT NULL,
+ "icon" varchar,
+ "description" varchar,
+ "bot_public" boolean NOT NULL,
+ "bot_require_code_grant" boolean NOT NULL,
+ "terms_of_service_url" varchar,
+ "privacy_policy_url" varchar,
+ "summary" varchar,
+ "verify_key" varchar NOT NULL,
+ "cover_image" varchar,
+ "flags" integer NOT NULL,
+ "owner_id" varchar,
+ "team_id" varchar,
+ "type" text,
+ "hook" boolean NOT NULL,
+ "redirect_uris" text,
+ "rpc_application_state" integer,
+ "store_application_state" integer,
+ "verification_state" integer,
+ "interactions_endpoint_url" varchar,
+ "integration_public" boolean,
+ "integration_require_code_grant" boolean,
+ "discoverability_state" integer,
+ "discovery_eligibility_flags" integer,
+ "tags" text,
+ "install_params" text,
+ "bot_user_id" varchar,
+ CONSTRAINT "UQ_b7f6e13565e920916d902e1f431" UNIQUE ("bot_user_id"),
+ CONSTRAINT "FK_a36ed02953077f408d0f3ebc424" FOREIGN KEY ("team_id") REFERENCES "teams" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_e57508958bf92b9d9d25231b5e8" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_applications"(
+ "id",
+ "name",
+ "icon",
+ "description",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id",
+ "type",
+ "hook",
+ "redirect_uris",
+ "rpc_application_state",
+ "store_application_state",
+ "verification_state",
+ "interactions_endpoint_url",
+ "integration_public",
+ "integration_require_code_grant",
+ "discoverability_state",
+ "discovery_eligibility_flags",
+ "tags",
+ "install_params",
+ "bot_user_id"
+ )
+ SELECT "id",
+ "name",
+ "icon",
+ "description",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id",
+ "type",
+ "hook",
+ "redirect_uris",
+ "rpc_application_state",
+ "store_application_state",
+ "verification_state",
+ "interactions_endpoint_url",
+ "integration_public",
+ "integration_require_code_grant",
+ "discoverability_state",
+ "discovery_eligibility_flags",
+ "tags",
+ "install_params",
+ "bot_user_id"
+ FROM "applications"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "applications"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_applications"
+ RENAME TO "applications"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_applications" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "name" varchar NOT NULL,
+ "icon" varchar,
+ "description" varchar,
+ "bot_public" boolean NOT NULL,
+ "bot_require_code_grant" boolean NOT NULL,
+ "terms_of_service_url" varchar,
+ "privacy_policy_url" varchar,
+ "summary" varchar,
+ "verify_key" varchar NOT NULL,
+ "cover_image" varchar,
+ "flags" integer NOT NULL,
+ "owner_id" varchar,
+ "team_id" varchar,
+ "type" text,
+ "hook" boolean NOT NULL,
+ "redirect_uris" text,
+ "rpc_application_state" integer,
+ "store_application_state" integer,
+ "verification_state" integer,
+ "interactions_endpoint_url" varchar,
+ "integration_public" boolean,
+ "integration_require_code_grant" boolean,
+ "discoverability_state" integer,
+ "discovery_eligibility_flags" integer,
+ "tags" text,
+ "install_params" text,
+ "bot_user_id" varchar,
+ CONSTRAINT "UQ_b7f6e13565e920916d902e1f431" UNIQUE ("bot_user_id"),
+ CONSTRAINT "FK_a36ed02953077f408d0f3ebc424" FOREIGN KEY ("team_id") REFERENCES "teams" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_e57508958bf92b9d9d25231b5e8" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_2ce5a55796fe4c2f77ece57a647" FOREIGN KEY ("bot_user_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_applications"(
+ "id",
+ "name",
+ "icon",
+ "description",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id",
+ "type",
+ "hook",
+ "redirect_uris",
+ "rpc_application_state",
+ "store_application_state",
+ "verification_state",
+ "interactions_endpoint_url",
+ "integration_public",
+ "integration_require_code_grant",
+ "discoverability_state",
+ "discovery_eligibility_flags",
+ "tags",
+ "install_params",
+ "bot_user_id"
+ )
+ SELECT "id",
+ "name",
+ "icon",
+ "description",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id",
+ "type",
+ "hook",
+ "redirect_uris",
+ "rpc_application_state",
+ "store_application_state",
+ "verification_state",
+ "interactions_endpoint_url",
+ "integration_public",
+ "integration_require_code_grant",
+ "discoverability_state",
+ "discovery_eligibility_flags",
+ "tags",
+ "install_params",
+ "bot_user_id"
+ FROM "applications"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "applications"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_applications"
+ RENAME TO "applications"
+ `);
+ }
+
+ public async down(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ RENAME TO "temporary_applications"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "applications" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "name" varchar NOT NULL,
+ "icon" varchar,
+ "description" varchar,
+ "bot_public" boolean NOT NULL,
+ "bot_require_code_grant" boolean NOT NULL,
+ "terms_of_service_url" varchar,
+ "privacy_policy_url" varchar,
+ "summary" varchar,
+ "verify_key" varchar NOT NULL,
+ "cover_image" varchar,
+ "flags" integer NOT NULL,
+ "owner_id" varchar,
+ "team_id" varchar,
+ "type" text,
+ "hook" boolean NOT NULL,
+ "redirect_uris" text,
+ "rpc_application_state" integer,
+ "store_application_state" integer,
+ "verification_state" integer,
+ "interactions_endpoint_url" varchar,
+ "integration_public" boolean,
+ "integration_require_code_grant" boolean,
+ "discoverability_state" integer,
+ "discovery_eligibility_flags" integer,
+ "tags" text,
+ "install_params" text,
+ "bot_user_id" varchar,
+ CONSTRAINT "UQ_b7f6e13565e920916d902e1f431" UNIQUE ("bot_user_id"),
+ CONSTRAINT "FK_a36ed02953077f408d0f3ebc424" FOREIGN KEY ("team_id") REFERENCES "teams" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_e57508958bf92b9d9d25231b5e8" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "applications"(
+ "id",
+ "name",
+ "icon",
+ "description",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id",
+ "type",
+ "hook",
+ "redirect_uris",
+ "rpc_application_state",
+ "store_application_state",
+ "verification_state",
+ "interactions_endpoint_url",
+ "integration_public",
+ "integration_require_code_grant",
+ "discoverability_state",
+ "discovery_eligibility_flags",
+ "tags",
+ "install_params",
+ "bot_user_id"
+ )
+ SELECT "id",
+ "name",
+ "icon",
+ "description",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id",
+ "type",
+ "hook",
+ "redirect_uris",
+ "rpc_application_state",
+ "store_application_state",
+ "verification_state",
+ "interactions_endpoint_url",
+ "integration_public",
+ "integration_require_code_grant",
+ "discoverability_state",
+ "discovery_eligibility_flags",
+ "tags",
+ "install_params",
+ "bot_user_id"
+ FROM "temporary_applications"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_applications"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ RENAME TO "temporary_applications"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "applications" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "name" varchar NOT NULL,
+ "icon" varchar,
+ "description" varchar NOT NULL,
+ "bot_public" boolean NOT NULL,
+ "bot_require_code_grant" boolean NOT NULL,
+ "terms_of_service_url" varchar,
+ "privacy_policy_url" varchar,
+ "summary" varchar,
+ "verify_key" varchar NOT NULL,
+ "cover_image" varchar,
+ "flags" varchar NOT NULL,
+ "owner_id" varchar,
+ "team_id" varchar,
+ "type" text,
+ "hook" boolean NOT NULL,
+ "redirect_uris" text,
+ "rpc_application_state" integer,
+ "store_application_state" integer,
+ "verification_state" integer,
+ "interactions_endpoint_url" varchar,
+ "integration_public" boolean,
+ "integration_require_code_grant" boolean,
+ "discoverability_state" integer,
+ "discovery_eligibility_flags" integer,
+ "tags" text,
+ "install_params" text,
+ "bot_user_id" varchar,
+ CONSTRAINT "UQ_b7f6e13565e920916d902e1f431" UNIQUE ("bot_user_id"),
+ CONSTRAINT "FK_a36ed02953077f408d0f3ebc424" FOREIGN KEY ("team_id") REFERENCES "teams" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_e57508958bf92b9d9d25231b5e8" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "applications"(
+ "id",
+ "name",
+ "icon",
+ "description",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id",
+ "type",
+ "hook",
+ "redirect_uris",
+ "rpc_application_state",
+ "store_application_state",
+ "verification_state",
+ "interactions_endpoint_url",
+ "integration_public",
+ "integration_require_code_grant",
+ "discoverability_state",
+ "discovery_eligibility_flags",
+ "tags",
+ "install_params",
+ "bot_user_id"
+ )
+ SELECT "id",
+ "name",
+ "icon",
+ "description",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id",
+ "type",
+ "hook",
+ "redirect_uris",
+ "rpc_application_state",
+ "store_application_state",
+ "verification_state",
+ "interactions_endpoint_url",
+ "integration_public",
+ "integration_require_code_grant",
+ "discoverability_state",
+ "discovery_eligibility_flags",
+ "tags",
+ "install_params",
+ "bot_user_id"
+ FROM "temporary_applications"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_applications"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ RENAME TO "temporary_applications"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "applications" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "name" varchar NOT NULL,
+ "icon" varchar,
+ "description" varchar NOT NULL,
+ "bot_public" boolean NOT NULL,
+ "bot_require_code_grant" boolean NOT NULL,
+ "terms_of_service_url" varchar,
+ "privacy_policy_url" varchar,
+ "summary" varchar,
+ "verify_key" varchar NOT NULL,
+ "cover_image" varchar,
+ "flags" varchar NOT NULL,
+ "owner_id" varchar,
+ "team_id" varchar,
+ CONSTRAINT "FK_a36ed02953077f408d0f3ebc424" FOREIGN KEY ("team_id") REFERENCES "teams" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_e57508958bf92b9d9d25231b5e8" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "applications"(
+ "id",
+ "name",
+ "icon",
+ "description",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id"
+ )
+ SELECT "id",
+ "name",
+ "icon",
+ "description",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id"
+ FROM "temporary_applications"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_applications"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ RENAME TO "temporary_applications"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "applications" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "name" varchar NOT NULL,
+ "icon" varchar,
+ "description" varchar NOT NULL,
+ "rpc_origins" text,
+ "bot_public" boolean NOT NULL,
+ "bot_require_code_grant" boolean NOT NULL,
+ "terms_of_service_url" varchar,
+ "privacy_policy_url" varchar,
+ "summary" varchar,
+ "verify_key" varchar NOT NULL,
+ "primary_sku_id" varchar,
+ "slug" varchar,
+ "cover_image" varchar,
+ "flags" varchar NOT NULL,
+ "owner_id" varchar,
+ "team_id" varchar,
+ "guild_id" varchar,
+ CONSTRAINT "FK_a36ed02953077f408d0f3ebc424" FOREIGN KEY ("team_id") REFERENCES "teams" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_e57508958bf92b9d9d25231b5e8" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "applications"(
+ "id",
+ "name",
+ "icon",
+ "description",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id"
+ )
+ SELECT "id",
+ "name",
+ "icon",
+ "description",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id"
+ FROM "temporary_applications"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_applications"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ RENAME TO "temporary_applications"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "applications" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "name" varchar NOT NULL,
+ "icon" varchar,
+ "description" varchar NOT NULL,
+ "rpc_origins" text,
+ "bot_public" boolean NOT NULL,
+ "bot_require_code_grant" boolean NOT NULL,
+ "terms_of_service_url" varchar,
+ "privacy_policy_url" varchar,
+ "summary" varchar,
+ "verify_key" varchar NOT NULL,
+ "primary_sku_id" varchar,
+ "slug" varchar,
+ "cover_image" varchar,
+ "flags" varchar NOT NULL,
+ "owner_id" varchar,
+ "team_id" varchar,
+ "guild_id" varchar,
+ CONSTRAINT "FK_e5bf78cdbbe9ba91062d74c5aba" FOREIGN KEY ("guild_id") REFERENCES "guilds" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_a36ed02953077f408d0f3ebc424" FOREIGN KEY ("team_id") REFERENCES "teams" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_e57508958bf92b9d9d25231b5e8" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "applications"(
+ "id",
+ "name",
+ "icon",
+ "description",
+ "rpc_origins",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "primary_sku_id",
+ "slug",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id",
+ "guild_id"
+ )
+ SELECT "id",
+ "name",
+ "icon",
+ "description",
+ "rpc_origins",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "primary_sku_id",
+ "slug",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id",
+ "guild_id"
+ FROM "temporary_applications"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_applications"
+ `);
+ }
+
+}
diff --git a/src/util/plugin/Plugin.ts b/src/util/plugin/Plugin.ts
index 0fb1732f..6a6f03f4 100644
--- a/src/util/plugin/Plugin.ts
+++ b/src/util/plugin/Plugin.ts
@@ -1,13 +1,22 @@
import EventEmitter from "events";
-import { PluginLoadedEventArgs, TypedEventEmitter } from "@fosscord/util";
+import { PluginLoadedEventArgs, PluginManifest, TypedEventEmitter } from "@fosscord/util";
+import { PluginConfig } from "./PluginConfig";
+import { PreRegisterEventArgs, PreRegisterEventResult, OnRegisterEventArgs } from '.';
+import { PreMessageEventArgs, PreMessageEventResult, OnMessageEventArgs } from '.';
+import { PreLoginEventArgs, PreLoginEventResult, OnLoginEventArgs } from '.';
+import { PreGuildCreateEventArgs, PreGuildCreateEventResult, OnGuildCreateEventArgs } from '.';
+import { PreChannelCreateEventArgs, PreChannelCreateEventResult, OnChannelCreateEventArgs } from '.';
+import { PreTypingEventArgs, PreTypingEventResult, OnTypingEventArgs } from '.';
+import { PreStatusChangeEventArgs, PreStatusChangeEventResult, OnStatusChangeEventArgs } from '.';
-type PluginEvents = {
+
+/*type PluginEvents = {
error: (error: Error | unknown) => void;
loaded: () => void;
-};
+};*/
//this doesnt work, check later:
- //EventEmitter as new () => TypedEventEmitter<PluginEvents>
+//EventEmitter as new () => TypedEventEmitter<PluginEvents>
export class Plugin {
/**
* Path the plugin resides in.
@@ -15,23 +24,137 @@ export class Plugin {
* @type {string}
* @memberof Plugin
*/
- pluginPath: string;
- /**
- *
- *
- * @memberof Plugin
- */
- async initConfig() {
- // insert default config into database?
- console.log("did you forget to implement initConfig?");
- }
+ pluginPath?: string;
+ pluginManifest?: PluginManifest;
/**
*
*
* @param {PluginLoadedEventArgs} args Info about plugin environment
* @memberof Plugin
*/
- onPluginLoaded?(args?: PluginLoadedEventArgs) {
-
+ async onPluginLoaded?(args?: PluginLoadedEventArgs) {
+
}
+
+ //generated
+ /**
+ * RegisterEvent: document me
+ *
+ * @param {OnRegisterEventArgs} args Info about what's going on
+ * @memberof Plugin
+ */
+ async onRegister?(args: OnRegisterEventArgs): Promise<void>;
+
+ /**
+ * RegisterEvent: Executed before changes are announced
+ * document me.
+ *
+ * @param {PreRegisterEventArgs} args Info about what's going on
+ * @return {PreRegisterEventResult} How event should be handled
+ * @memberof Plugin
+ */
+ async onPreRegister?(args: PreRegisterEventArgs): Promise<PreRegisterEventResult>;
+ /**
+ * MessageEvent: document me
+ *
+ * @param {OnMessageEventArgs} args Info about what's going on
+ * @memberof Plugin
+ */
+ async onMessage?(args: OnMessageEventArgs): Promise<void>;
+
+ /**
+ * MessageEvent: Executed before changes are announced
+ * document me.
+ *
+ * @param {PreMessageEventArgs} args Info about what's going on
+ * @return {PreMessageEventResult} How event should be handled
+ * @memberof Plugin
+ */
+ async onPreMessage?(args: PreMessageEventArgs): Promise<PreMessageEventResult>;
+ /**
+ * LoginEvent: document me
+ *
+ * @param {OnLoginEventArgs} args Info about what's going on
+ * @memberof Plugin
+ */
+ async onLogin?(args: OnLoginEventArgs): Promise<void>;
+
+ /**
+ * LoginEvent: Executed before changes are announced
+ * document me.
+ *
+ * @param {PreLoginEventArgs} args Info about what's going on
+ * @return {PreLoginEventResult} How event should be handled
+ * @memberof Plugin
+ */
+ async onPreLogin?(args: PreLoginEventArgs): Promise<PreLoginEventResult>;
+ /**
+ * GuildCreateEvent: document me
+ *
+ * @param {OnGuildCreateEventArgs} args Info about what's going on
+ * @memberof Plugin
+ */
+ async onGuildCreate?(args: OnGuildCreateEventArgs): Promise<void>;
+
+ /**
+ * GuildCreateEvent: Executed before changes are announced
+ * document me.
+ *
+ * @param {PreGuildCreateEventArgs} args Info about what's going on
+ * @return {PreGuildCreateEventResult} How event should be handled
+ * @memberof Plugin
+ */
+ async onPreGuildCreate?(args: PreGuildCreateEventArgs): Promise<PreGuildCreateEventResult>;
+ /**
+ * ChannelCreateEvent: document me
+ *
+ * @param {OnChannelCreateEventArgs} args Info about what's going on
+ * @memberof Plugin
+ */
+ async onChannelCreate?(args: OnChannelCreateEventArgs): Promise<void>;
+
+ /**
+ * ChannelCreateEvent: Executed before changes are announced
+ * document me.
+ *
+ * @param {PreChannelCreateEventArgs} args Info about what's going on
+ * @return {PreChannelCreateEventResult} How event should be handled
+ * @memberof Plugin
+ */
+ async onPreChannelCreate?(args: PreChannelCreateEventArgs): Promise<PreChannelCreateEventResult>;
+ /**
+ * TypingEvent: document me
+ *
+ * @param {OnTypingEventArgs} args Info about what's going on
+ * @memberof Plugin
+ */
+ async onTyping?(args: OnTypingEventArgs): Promise<void>;
+
+ /**
+ * TypingEvent: Executed before changes are announced
+ * document me.
+ *
+ * @param {PreTypingEventArgs} args Info about what's going on
+ * @return {PreTypingEventResult} How event should be handled
+ * @memberof Plugin
+ */
+ async onPreTyping?(args: PreTypingEventArgs): Promise<PreTypingEventResult>;
+ /**
+ * StatusChangeEvent: document me
+ *
+ * @param {OnStatusChangeEventArgs} args Info about what's going on
+ * @memberof Plugin
+ */
+ async onStatusChange?(args: OnStatusChangeEventArgs): Promise<void>;
+
+ /**
+ * StatusChangeEvent: Executed before changes are announced
+ * document me.
+ *
+ * @param {PreStatusChangeEventArgs} args Info about what's going on
+ * @return {PreStatusChangeEventResult} How event should be handled
+ * @memberof Plugin
+ */
+ async onPreStatusChange?(args: PreStatusChangeEventArgs): Promise<PreStatusChangeEventResult>;
+
}
diff --git a/src/util/plugin/PluginConfig.ts b/src/util/plugin/PluginConfig.ts
index c7a7db87..883bca7c 100644
--- a/src/util/plugin/PluginConfig.ts
+++ b/src/util/plugin/PluginConfig.ts
@@ -1,26 +1,26 @@
-import { ConfigEntity } from "../entities/Config";
import fs from "fs";
import { OrmUtils, Environment } from "..";
+import { PluginConfigEntity } from "util/entities/PluginConfig";
// TODO: yaml instead of json
const overridePath = process.env.PLUGIN_CONFIG_PATH ?? "";
let config: any;
-let pairs: ConfigEntity[];
+let pairs: PluginConfigEntity[];
// TODO: use events to inform about config updates
// Config keys are separated with _
-export const Config = {
+export const PluginConfig = {
init: async function init() {
if (config) return config;
- console.log('[Config] Loading configuration...')
- pairs = await ConfigEntity.find();
+ console.log('[PluginConfig] Loading configuration...')
+ pairs = await PluginConfigEntity.find();
config = pairsToConfig(pairs);
//config = (config || {}).merge(new ConfigValue());
//config = OrmUtils.mergeDeep(new ConfigValue(), config)
- if(process.env.CONFIG_PATH)
+ if(process.env.PLUGIN_CONFIG_PATH)
try {
const overrideConfig = JSON.parse(fs.readFileSync(overridePath, { encoding: "utf8" }));
config = overrideConfig.merge(config);
@@ -48,26 +48,32 @@ export const Config = {
function applyConfig(val: any) {
async function apply(obj: any, key = ""): Promise<any> {
- if (typeof obj === "object" && obj !== null)
+ if (typeof obj === "object" && obj !== null && !(obj instanceof Date))
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();
+ if (!pair) pair = new PluginConfigEntity();
pair.key = key;
pair.value = obj;
- return pair.save();
+ if(!pair.key || pair.key == null) {
+ console.log(`[PluginConfig] WARN: Empty key`)
+ console.log(pair);
+ if(Environment.isDebug) debugger;
+ }
+ else
+ return pair.save();
}
- if(process.env.CONFIG_PATH) {
+ if(process.env.PLUGIN_CONFIG_PATH) {
if(Environment.isDebug)
- console.log(`Writing config: ${process.env.CONFIG_PATH}`)
+ console.log(`Writing config: ${process.env.PLUGIN_CONFIG_PATH}`)
fs.writeFileSync(overridePath, JSON.stringify(val, null, 4));
}
return apply(val);
}
-function pairsToConfig(pairs: ConfigEntity[]) {
+function pairsToConfig(pairs: PluginConfigEntity[]) {
let value: any = {};
pairs.forEach((p) => {
diff --git a/src/util/plugin/PluginEventHandler.ts b/src/util/plugin/PluginEventHandler.ts
new file mode 100644
index 00000000..d5fc67f4
--- /dev/null
+++ b/src/util/plugin/PluginEventHandler.ts
@@ -0,0 +1,67 @@
+import { PreRegisterEventArgs, OnRegisterEventArgs, PreRegisterEventResult } from './event_types';
+import { PreMessageEventArgs, OnMessageEventArgs, PreMessageEventResult } from './event_types';
+import { PreLoginEventArgs, OnLoginEventArgs, PreLoginEventResult } from './event_types';
+import { PreGuildCreateEventArgs, OnGuildCreateEventArgs, PreGuildCreateEventResult } from './event_types';
+import { PreChannelCreateEventArgs, OnChannelCreateEventArgs, PreChannelCreateEventResult } from './event_types';
+import { PreTypingEventArgs, OnTypingEventArgs, PreTypingEventResult } from './event_types';
+import { PreStatusChangeEventArgs, OnStatusChangeEventArgs, PreStatusChangeEventResult } from './event_types';
+import { PluginStore } from ".";
+
+export class PluginEventHandler {
+ public static async preRegisterEvent(args: PreRegisterEventArgs): Promise<PreRegisterEventResult[]> {
+ return (await Promise.all(PluginStore.plugins.filter(x=>x.onPreRegister).map(x=>x.onPreRegister && x.onPreRegister(args)))).filter(x=>x) as PreRegisterEventResult[];
+ }
+
+ public static async onRegisterEvent(args: OnRegisterEventArgs): Promise<void> {
+ await Promise.all(PluginStore.plugins.filter(x=>x.onRegister).map(x=>x.onRegister && x.onRegister(args)));
+ }
+
+ public static async preMessageEvent(args: PreMessageEventArgs): Promise<PreMessageEventResult[]> {
+ return (await Promise.all(PluginStore.plugins.filter(x=>x.onPreMessage).map(x=>x.onPreMessage && x.onPreMessage(args)))).filter(x=>x) as PreMessageEventResult[];
+ }
+
+ public static async onMessageEvent(args: OnMessageEventArgs): Promise<void> {
+ await Promise.all(PluginStore.plugins.filter(x=>x.onMessage).map(x=>x.onMessage && x.onMessage(args)));
+ }
+
+ public static async preLoginEvent(args: PreLoginEventArgs): Promise<PreLoginEventResult[]> {
+ return (await Promise.all(PluginStore.plugins.filter(x=>x.onPreLogin).map(x=>x.onPreLogin && x.onPreLogin(args)))).filter(x=>x) as PreLoginEventResult[];
+ }
+
+ public static async onLoginEvent(args: OnLoginEventArgs): Promise<void> {
+ await Promise.all(PluginStore.plugins.filter(x=>x.onLogin).map(x=>x.onLogin && x.onLogin(args)));
+ }
+
+ public static async preGuildCreateEvent(args: PreGuildCreateEventArgs): Promise<PreGuildCreateEventResult[]> {
+ return (await Promise.all(PluginStore.plugins.filter(x=>x.onPreGuildCreate).map(x=>x.onPreGuildCreate && x.onPreGuildCreate(args)))).filter(x=>x) as PreGuildCreateEventResult[];
+ }
+
+ public static async onGuildCreateEvent(args: OnGuildCreateEventArgs): Promise<void> {
+ await Promise.all(PluginStore.plugins.filter(x=>x.onGuildCreate).map(x=>x.onGuildCreate && x.onGuildCreate(args)));
+ }
+
+ public static async preChannelCreateEvent(args: PreChannelCreateEventArgs): Promise<PreChannelCreateEventResult[]> {
+ return (await Promise.all(PluginStore.plugins.filter(x=>x.onPreChannelCreate).map(x=>x.onPreChannelCreate && x.onPreChannelCreate(args)))).filter(x=>x) as PreChannelCreateEventResult[];
+ }
+
+ public static async onChannelCreateEvent(args: OnChannelCreateEventArgs): Promise<void> {
+ await Promise.all(PluginStore.plugins.filter(x=>x.onChannelCreate).map(x=>x.onChannelCreate && x.onChannelCreate(args)));
+ }
+
+ public static async preTypingEvent(args: PreTypingEventArgs): Promise<PreTypingEventResult[]> {
+ return (await Promise.all(PluginStore.plugins.filter(x=>x.onPreTyping).map(x=>x.onPreTyping && x.onPreTyping(args)))).filter(x=>x) as PreTypingEventResult[];
+ }
+
+ public static async onTypingEvent(args: OnTypingEventArgs): Promise<void> {
+ await Promise.all(PluginStore.plugins.filter(x=>x.onTyping).map(x=>x.onTyping && x.onTyping(args)));
+ }
+
+ public static async preStatusChangeEvent(args: PreStatusChangeEventArgs): Promise<PreStatusChangeEventResult[]> {
+ return (await Promise.all(PluginStore.plugins.filter(x=>x.onPreStatusChange).map(x=>x.onPreStatusChange && x.onPreStatusChange(args)))).filter(x=>x) as PreStatusChangeEventResult[];
+ }
+
+ public static async onStatusChangeEvent(args: OnStatusChangeEventArgs): Promise<void> {
+ await Promise.all(PluginStore.plugins.filter(x=>x.onStatusChange).map(x=>x.onStatusChange && x.onStatusChange(args)));
+ }
+
+}
diff --git a/src/util/plugin/PluginLoader.ts b/src/util/plugin/PluginLoader.ts
index 8c140d29..4dc0129a 100644
--- a/src/util/plugin/PluginLoader.ts
+++ b/src/util/plugin/PluginLoader.ts
@@ -1,14 +1,17 @@
import path from "path";
import fs from "fs";
-import { Plugin, PluginLoadedEventArgs, PluginManifest } from "./";
+import { Plugin, PluginLoadedEventArgs, PluginManifest, PluginStore } from "./";
import { PluginIndex } from "plugins/PluginIndex";
+import { PluginConfig } from "./PluginConfig";
+import { OrmUtils, PluginConfigEntity } from "..";
const root = process.env.PLUGIN_LOCATION || "dist/plugins";
let pluginsLoaded = false;
export class PluginLoader {
- public static plugins: Plugin[] = [];
- public static loadPlugins() {
+ public static async loadPlugins() {
+ if(pluginsLoaded) return;
+ PluginConfig.init();
console.log(`Plugin root directory: ${path.resolve(root)}`);
const dirs = fs.readdirSync(root).filter((x) => {
try {
@@ -18,24 +21,45 @@ export class PluginLoader {
return false;
}
});
- console.log(dirs);
- PluginIndex.forEach((x: any)=>{
- console.log(x.onPluginLoaded)
- })
+ //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}`);
+ //console.log(`Trying to load plugin: ${modPath}`);
const manifest = require(path.join(modPath, "plugin.json")) as PluginManifest;
console.log(
`Plugin info: ${manifest.name} (${manifest.id}), written by ${manifest.authors}, available at ${manifest.repository}`
);
- const module_ = PluginIndex["example-plugin"];
+ const module_ = PluginIndex[manifest.id];
module_.pluginPath = modPath;
- if(module_.onPluginLoaded) module_.onPluginLoaded({} as PluginLoadedEventArgs);
- this.plugins.push(module_);
+ module_.pluginManifest = manifest;
+ Object.freeze(module_.pluginPath);
+ Object.freeze(module_.pluginManifest);
+
+ if(module_.onPluginLoaded) await module_.onPluginLoaded({} as PluginLoadedEventArgs);
+ PluginStore.plugins.push(module_);
});
- console.log(`Done loading ${this.plugins.length} plugins!`)
+ console.log(`Done loading ${PluginStore.plugins.length} plugins!`);
+ }
+
+ public static getPluginConfig(id: string, defaults?: any): any {
+ let cfg = PluginConfig.get()[id];
+ if(defaults) {
+ if(cfg)
+ cfg = OrmUtils.mergeDeep(defaults, cfg);
+ else
+ cfg = defaults;
+ this.setPluginConfig(id, cfg);
+ }
+ if(!cfg) console.log(`[PluginConfig/WARN] Getting plugin settings for '${id}' returned null! (Did you forget to add settings?)`);
+ return cfg;
+ }
+ public static async setPluginConfig(id: string, config: Partial<any>): Promise<void> {
+ if(!config) console.log(`[PluginConfig/WARN] ${id} tried to set config=null!`);
+ await PluginConfig.set({ [id]: OrmUtils.mergeDeep(PluginLoader.getPluginConfig(id) || {}, config) });
}
}
diff --git a/src/util/plugin/PluginStore.ts b/src/util/plugin/PluginStore.ts
new file mode 100644
index 00000000..60d7f7b7
--- /dev/null
+++ b/src/util/plugin/PluginStore.ts
@@ -0,0 +1,12 @@
+import path from "path";
+import fs from "fs";
+import { Plugin, PluginLoadedEventArgs, PluginManifest } from "./";
+import { PluginIndex } from "plugins/PluginIndex";
+import { PluginConfig } from "./PluginConfig";
+import { OrmUtils, PluginConfigEntity } from "..";
+
+const root = process.env.PLUGIN_LOCATION || "dist/plugins";
+
+export class PluginStore {
+ public static plugins: Plugin[] = [];
+}
diff --git a/src/util/plugin/event_types/ChannelCreateEventArgs.ts b/src/util/plugin/event_types/ChannelCreateEventArgs.ts
new file mode 100644
index 00000000..87fa3691
--- /dev/null
+++ b/src/util/plugin/event_types/ChannelCreateEventArgs.ts
@@ -0,0 +1,17 @@
+import { Channel, Guild, User } from "util/entities";
+import { EventResult } from ".";
+
+export interface PreChannelCreateEventArgs {
+ channel: Channel,
+ guild: Guild,
+ user: User
+}
+export interface PreChannelCreateEventResult extends EventResult {
+ channel: Partial<Channel>
+}
+
+export interface OnChannelCreateEventArgs {
+ channel: Channel,
+ guild: Guild,
+ user: User
+}
diff --git a/src/util/plugin/event_types/GuildCreateEventArgs.ts b/src/util/plugin/event_types/GuildCreateEventArgs.ts
new file mode 100644
index 00000000..7724b4f3
--- /dev/null
+++ b/src/util/plugin/event_types/GuildCreateEventArgs.ts
@@ -0,0 +1,15 @@
+import { Guild, User } from "util/entities";
+import { EventResult } from ".";
+
+export interface PreGuildCreateEventArgs {
+ user: User,
+ guild: Guild
+}
+export interface PreGuildCreateEventResult extends EventResult {
+ guild: Partial<Guild>
+}
+
+export interface OnGuildCreateEventArgs {
+ user: User,
+ guild: Guild
+}
diff --git a/src/util/plugin/event_types/LoginEventArgs.ts b/src/util/plugin/event_types/LoginEventArgs.ts
new file mode 100644
index 00000000..8f80b69f
--- /dev/null
+++ b/src/util/plugin/event_types/LoginEventArgs.ts
@@ -0,0 +1,15 @@
+import { User } from "util/entities";
+import { EventResult } from ".";
+
+export interface PreLoginEventArgs {
+ ip: String,
+ user: User
+}
+export interface PreLoginEventResult extends EventResult {
+
+}
+
+export interface OnLoginEventArgs {
+ ip: String,
+ user: User
+}
diff --git a/src/util/plugin/event_types/MessageEventArgs.ts b/src/util/plugin/event_types/MessageEventArgs.ts
new file mode 100644
index 00000000..ab276429
--- /dev/null
+++ b/src/util/plugin/event_types/MessageEventArgs.ts
@@ -0,0 +1,15 @@
+import { Message, User } from "util/entities";
+import { EventResult } from ".";
+
+export interface PreMessageEventArgs {
+ user: User,
+ message: Message;
+}
+export interface PreMessageEventResult extends EventResult {
+ message: Partial<Message>
+}
+
+export interface OnMessageEventArgs {
+ user: User,
+ message: Message
+}
diff --git a/src/util/plugin/plugin_data_objects/PluginLoadedEventArgs.ts b/src/util/plugin/event_types/PluginLoadedEventArgs.ts
index 58829f15..58829f15 100644
--- a/src/util/plugin/plugin_data_objects/PluginLoadedEventArgs.ts
+++ b/src/util/plugin/event_types/PluginLoadedEventArgs.ts
diff --git a/src/util/plugin/event_types/RegisterEventArgs.ts b/src/util/plugin/event_types/RegisterEventArgs.ts
new file mode 100644
index 00000000..d36d7e64
--- /dev/null
+++ b/src/util/plugin/event_types/RegisterEventArgs.ts
@@ -0,0 +1,17 @@
+import { User } from "util/entities";
+import { EventResult } from ".";
+
+export interface PreRegisterEventArgs {
+ age: any,
+ user: User,
+ ip: String
+}
+export interface PreRegisterEventResult extends EventResult {
+ user: Partial<User>
+}
+
+export interface OnRegisterEventArgs {
+ age: any,
+ user: User,
+ ip: String
+}
diff --git a/src/util/plugin/event_types/StatusChangeEventArgs.ts b/src/util/plugin/event_types/StatusChangeEventArgs.ts
new file mode 100644
index 00000000..c1a67112
--- /dev/null
+++ b/src/util/plugin/event_types/StatusChangeEventArgs.ts
@@ -0,0 +1,16 @@
+import { User } from "util/entities";
+import { Presence } from "util/interfaces";
+import { EventResult } from ".";
+
+export interface PreStatusChangeEventArgs {
+ user: User,
+ presence: Presence
+}
+export interface PreStatusChangeEventResult extends EventResult {
+ presence: Partial<Presence>
+}
+
+export interface OnStatusChangeEventArgs {
+ user: User,
+ presence: Presence
+}
diff --git a/src/util/plugin/event_types/TypingEventArgs.ts b/src/util/plugin/event_types/TypingEventArgs.ts
new file mode 100644
index 00000000..3ac59b41
--- /dev/null
+++ b/src/util/plugin/event_types/TypingEventArgs.ts
@@ -0,0 +1,17 @@
+import { Channel, Guild, User } from "util/entities";
+import { EventResult } from ".";
+
+export interface PreTypingEventArgs {
+ channel: Channel,
+ guild: Guild,
+ user: User
+}
+export interface PreTypingEventResult extends EventResult {
+
+}
+
+export interface OnTypingEventArgs {
+ channel: Channel,
+ guild: Guild,
+ user: User
+}
diff --git a/src/util/plugin/event_types/_gen.sh b/src/util/plugin/event_types/_gen.sh
new file mode 100755
index 00000000..9f761d1e
--- /dev/null
+++ b/src/util/plugin/event_types/_gen.sh
@@ -0,0 +1,74 @@
+#!/bin/sh
+rm -f ../plugin.eventfuncs.generated
+rm -f ../plugin.imports.generated
+while read event
+do
+ echo Making event $event...
+ (
+ echo 'import { EventResult } from ".";'
+ echo ''
+ echo "export interface Pre${event}EventArgs {"
+ echo ' '
+ echo '}'
+ echo "export interface Pre${event}EventResult extends EventResult {"
+ echo ' '
+ echo '}'
+ echo ''
+ echo "export interface On${event}EventArgs {"
+ echo ' '
+ echo '}'
+ ) > ${event}EventArgs.ts.generated
+ (
+ echo " public static async pre${event}Event(args: Pre${event}EventArgs): Promise<Pre${event}EventResult[]> {"
+ echo " return (await Promise.all(PluginStore.plugins.filter(x=>x.onPre${event}).map(x=>x.onPre${event} && x.onPre${event}(args)))).filter(x=>x) as Pre${event}EventResult[];"
+ echo ' }'
+ echo ' '
+ echo " public static async on${event}Event(args: On${event}EventArgs): Promise<void> {"
+ echo " await Promise.all(PluginStore.plugins.filter(x=>x.on${event}).map(x=>x.on${event} && x.on${event}(args)));"
+ echo ' }'
+ echo ' '
+ ) >> ../PluginEventHandler.ts.3
+ (
+ echo " /**"
+ echo " * ${event}Event: document me"
+ echo " *"
+ echo " * @param {On${event}EventArgs} args Info about what's going on"
+ echo " * @memberof Plugin"
+ echo " */"
+ echo " async on${event}?(args: On${event}EventArgs): Promise<void>;"
+ echo ' '
+ echo " /**"
+ echo " * ${event}Event: Executed before changes are announced"
+ echo " * document me."
+ echo " *"
+ echo " * @param {Pre${event}EventArgs} args Info about what's going on"
+ echo " * @return {Pre${event}EventResult} How event should be handled"
+ echo " * @memberof Plugin"
+ echo " */"
+ echo " async onPre${event}?(args: Pre${event}EventArgs): Promise<Pre${event}EventResult>;"
+ ) >> ../plugin.eventfuncs.generated
+
+ echo "import { Pre${event}EventArgs, On${event}EventArgs, Pre${event}EventResult } from './event_types';" >> ../PluginEventHandler.ts.1
+ echo "import { Pre${event}EventArgs, Pre${event}EventResult, On${event}EventArgs } from '.';" >> ../plugin.imports.generated
+ cmp --silent "${event}EventArgs.ts" "${event}EventArgs.ts.generated" && rm -f "${event}EventArgs.ts.generated"
+done < _pdo
+
+echo 'Building PluginEventHandler...'
+
+rm -f ../PluginEventHandler.ts.generated
+(
+ echo 'import { PluginStore } from ".";'
+ echo ''
+ echo 'export class PluginEventHandler {'
+) > ../PluginEventHandler.ts.2
+echo '}' > ../PluginEventHandler.ts.4
+for i in {1..4}
+do
+ cat "../PluginEventHandler.ts.$i" >> ../PluginEventHandler.ts.generated
+ rm -f ../PluginEventHandler.ts.$i
+done
+cmp --silent ../PluginEventHandler.ts ../PluginEventHandler.ts.generated && rm -f ../PluginEventHandler.ts.generated
+
+echo 'Rebuilding indexes...'
+node ../../../../scripts/gen_index.js .. --recursive
+echo 'Done!'
\ No newline at end of file
diff --git a/src/util/plugin/plugin_data_objects/_pdo b/src/util/plugin/event_types/_pdo
index fa207f77..f6127174 100644
--- a/src/util/plugin/plugin_data_objects/_pdo
+++ b/src/util/plugin/event_types/_pdo
@@ -4,4 +4,5 @@ Login
GuildCreate
ChannelCreate
Typing
-StatusChange
\ No newline at end of file
+StatusChange
+UserProfileUpdate
\ No newline at end of file
diff --git a/src/util/plugin/plugin_data_objects/_todo.txt b/src/util/plugin/event_types/_todo.txt
index a6a78c7e..a6a78c7e 100644
--- a/src/util/plugin/plugin_data_objects/_todo.txt
+++ b/src/util/plugin/event_types/_todo.txt
diff --git a/src/util/plugin/event_types/base/EventResult.ts b/src/util/plugin/event_types/base/EventResult.ts
new file mode 100644
index 00000000..f18837cd
--- /dev/null
+++ b/src/util/plugin/event_types/base/EventResult.ts
@@ -0,0 +1,4 @@
+export interface EventResult {
+ cancel?: boolean;
+ blockReason?: string;
+}
\ No newline at end of file
diff --git a/src/util/plugin/event_types/base/index.ts b/src/util/plugin/event_types/base/index.ts
new file mode 100644
index 00000000..fd0dbd03
--- /dev/null
+++ b/src/util/plugin/event_types/base/index.ts
@@ -0,0 +1 @@
+export * from "./EventResult";
diff --git a/src/util/plugin/plugin_data_objects/index.ts b/src/util/plugin/event_types/index.ts
index c75d43f9..4a585dc0 100644
--- a/src/util/plugin/plugin_data_objects/index.ts
+++ b/src/util/plugin/event_types/index.ts
@@ -4,4 +4,6 @@ export * from "./LoginEventArgs";
export * from "./MessageEventArgs";
export * from "./PluginLoadedEventArgs";
export * from "./RegisterEventArgs";
+export * from "./StatusChangeEventArgs";
export * from "./TypingEventArgs";
+export * from "./base/index";
diff --git a/src/util/plugin/index.ts b/src/util/plugin/index.ts
index 5974a065..7a297981 100644
--- a/src/util/plugin/index.ts
+++ b/src/util/plugin/index.ts
@@ -1,4 +1,7 @@
export * from "./Plugin";
+export * from "./PluginConfig";
+export * from "./PluginEventHandler";
export * from "./PluginLoader";
export * from "./PluginManifest";
-export * from "./plugin_data_objects/index";
+export * from "./PluginStore";
+export * from "./event_types/index";
diff --git a/src/util/plugin/plugin_data_objects/ChannelCreateEventArgs.ts b/src/util/plugin/plugin_data_objects/ChannelCreateEventArgs.ts
deleted file mode 100644
index ce7dec87..00000000
--- a/src/util/plugin/plugin_data_objects/ChannelCreateEventArgs.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-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
deleted file mode 100644
index e10e675a..00000000
--- a/src/util/plugin/plugin_data_objects/GuildCreateEventArgs.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-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
deleted file mode 100644
index 391b852e..00000000
--- a/src/util/plugin/plugin_data_objects/LoginEventArgs.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-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
deleted file mode 100644
index 0a3498c2..00000000
--- a/src/util/plugin/plugin_data_objects/MessageEventArgs.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-export interface PreMessageEventArgs {
-
-}
-
-export interface OnMessageEventArgs {
-
-}
diff --git a/src/util/plugin/plugin_data_objects/RegisterEventArgs.ts b/src/util/plugin/plugin_data_objects/RegisterEventArgs.ts
deleted file mode 100644
index 7f7c0c76..00000000
--- a/src/util/plugin/plugin_data_objects/RegisterEventArgs.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-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
deleted file mode 100644
index f6660692..00000000
--- a/src/util/plugin/plugin_data_objects/TypingEventArgs.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-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
deleted file mode 100755
index 9fbd1749..00000000
--- a/src/util/plugin/plugin_data_objects/_gen.sh
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/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/util/Logo.ts b/src/util/util/Logo.ts
new file mode 100644
index 00000000..b1627198
--- /dev/null
+++ b/src/util/util/Logo.ts
@@ -0,0 +1,41 @@
+import { existsSync } from "fs";
+import { execSync } from "child_process";
+
+export class Logo {
+ public static printLogo(){
+ if(existsSync("/usr/bin/chafa"))
+ return execSync("chafa https://raw.githubusercontent.com/fosscord/fosscord/master/assets-rebrand/svg/Fosscord-Wordmark-Orange.svg", {
+ env: process.env,
+ encoding: "utf-8",
+ stdio: "inherit",
+
+ });
+ else console.log(Logo.logoVersions['1'] as string)
+ }
+ private static getConsoleColors(): number {
+ return 1;
+ if(!process.env.TERM) return 1;
+ else {
+ switch (process.env.TERM) {
+ case "":
+
+ break;
+
+ default:
+ break;
+ }
+ }
+ return 1;
+ }
+ private static logoVersions: any = {
+ '1':
+ `███████╗ ██████╗ ███████╗███████╗ ██████╗ ██████╗ ██████╗ ██████╗
+ ██╔════╝██╔═══██╗██╔════╝██╔════╝██╔════╝██╔═══██╗██╔══██╗██╔══██╗
+ █████╗ ██║ ██║███████╗███████╗██║ ██║ ██║██████╔╝██║ ██║
+ ██╔══╝ ██║ ██║╚════██║╚════██║██║ ██║ ██║██╔══██╗██║ ██║
+ ██║ ╚██████╔╝███████║███████║╚██████╗╚██████╔╝██║ ██║██████╔╝
+ ╚═╝ ╚═════╝ ╚══════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═════╝`,
+ '2':``
+
+ }
+}
\ No newline at end of file
diff --git a/src/util/util/imports/HTTPError.ts b/src/util/util/imports/HTTPError.ts
index 70ba92a8..3439bd00 100644
--- a/src/util/util/imports/HTTPError.ts
+++ b/src/util/util/imports/HTTPError.ts
@@ -1,5 +1,5 @@
export class HTTPError extends Error {
- constructor(message: string, public code: number = 400) {
+ constructor(message: string, public code: number = 400, public data: any = null) {
super(message);
}
}
|