diff --git a/guide-en/README.md b/guide-en/README.md index abdede8f2..5b73ec60c 100644 --- a/guide-en/README.md +++ b/guide-en/README.md @@ -4,432 +4,23 @@ Welcome to sern's official guide. This guide will go through all the core featur Thank you for choosing sern! - Teaching the discord.js library and / or Javascript / Typescript is out of scope of this project, so the documentation assumes you already know these elements. - discord.js@dev is the only supported version at the moment. There are plans to roll out a version of sern in discord.js@13.xx.xx in the future. - discord.js@dev is the only supported version at the moment. There are plans to roll out a version of sern in discord.js@13.xx.xx in the future. ## You will learn -* sern's goal -* How to use sern with the [CLI](https://github.com/sern-handler/cli) -* Your first command -* The Context class +* [sern's goal](guide-en/walkthrough/goal.md) +* How to use sern with the [CLI](guide-en/walkthrough/cli.md) +* [Your first command](guide-en/walkthrough/first-command.md) +* [The Context class](guide-en/walkthrough/first-command.md#context-class) ### Working with plugins -* Plugins - - Command Plugins - - Event Plugins +* [Plugins](guide-en/walkthrough/plugins.md) + - [Command Plugins](guide-en/walkthrough/plugins.md#command-plugins) + - [Event Plugins](guide-en/walkthrough/plugins.md#event-plugins) ### Events -* The SernEmitter class -* Your first event +* [The SernEmitter class](guide-en/walkthrough/sern-emitter.md) +* [Your first event](guide-en/walkthrough/first-event.md) ### Good to know - -* Your sern.config.json - ---- - -# Goal - -Sern strives to be minimalist, but with all batteries included. Meaning, this framework provides the necessary tools -to start up a bot in minutes, and leaves plenty room space to customize your experience and create an amazing project. -It should include all the tools for any bot at any scale. - - -# CLI - -Setting up the [CLI](https://github.com/sern-handler/cli) is easy.
-- To start a brand new project, run : -``` -sern init (-y) -``` -Include the `-y` flag if you want to set up defaults. The default langauge is [Typescript](https://www.typescriptlang.org/)
- -- To install [plugins](#plugins) maintained by the community [repository](https://github.com/sern-handler/awesome-plugins), -``` -sern plugins -``` -This will display a menu selection of all installable plugins.
-**Note**: You must have a [sern.config.json](todo) to use this command. -If you want to view plugins, visit the repository linked above. - -- To install extra utilities into your project -``` -sern extra -``` - -# First Command -We will dissect a basic command. -If you installed a new project via the cli, This is the `ping` command located in src/commands folder. - -Typescript -```typescript -import { commandModule, CommandType } from '@sern/handler'; - -export default commandModule({ - type: CommandType.Both, - plugins: [], - description: 'A ping command', - //alias : [], - execute: async (ctx, args) => { - await ctx.reply({ content: 'Pong 🏓' }); - }, -}); -``` -Javascript -```javascript -const { CommandType, commandModule } = require('@sern/handler'); - -exports.default = commandModule({ - type: CommandType.Both, - plugins: [], - description: 'A ping command', - //alias : [], - execute: async (ctx, args) => { - await ctx.reply('Pong 🏓'); - }, -}) -``` -### Essential properties of a command - -- **module.type** (Required) - - The type of your module. For example, a command listening to messages would have the type CommandType.Text -- **module.execute** (Required) - - This function is called when the command is triggered. Do your logic here! -- **module.name** (Optional) - - Give your command a name. **(defaults to its filename)** -- **module.description** (Optional) - - Give your command a description. **(defaults to `..`)** -- **module.plugins** (Optional) - - A list of [plugins](#plugins) that will modify and change the behavior of your command.
- -### Types of command modules -Every command module `type` is part of an enum. This field allows type inference for the rest of a module's fields.
-All available command types : -``` -CommandType.Text = A Text Command -CommandType.Slash = A Slash Command -CommandType.Both = A Command supporting either text or slash -CommandType.Modal = A Command listening to Modal interactions -CommandType.MenuSelect = A Command listening to select menu interactions -CommandType.MenuUser = A Command listening to context menu user interactions -CommandType.MenuMsg = A Command listening to context menu message interactions -CommandType.Button = A Command listening to button interactions -``` -So, lets say you want to make a command module that listens to modals.
-**Note**: Keep in mind you'll need to send a modal with a custom id `dm-me`. This example below is the response to a modal being sent.
- -Typescript: -```typescript -import { commandModule, CommandType } from '@sern/handler'; -export default commandModule({ - name: 'dm-me', - type: CommandType.Modal, - async execute (modal) { - const value = modal.fields.getTextInputValue('message'); - modal.client.users.fetch('182326315813306368').then( u => - u.send(value + ` from ${modal.user}`) - ); - modal.reply( { ephemeral:true, content: 'Sent' }) - } -}); -``` -Javascript: -```javascript -const { CommandType, commandModule } = require('@sern/handler'); -exports.default = commandModule({ - name: 'dm-me', - type: CommandType.Modal, - async execute (modal) { - const value = modal.fields.getTextInputValue('message'); - modal.client.users.fetch('182326315813306368').then( u => - u.send(value + ` from ${modal.user}`) - ); - modal.reply( { ephemeral:true, content: 'Sent' }) - } -}); -``` -Commands are straight forward. Keep in mind, every other property on the commandModule object is -optional **except** the type and execute function. - -# Context class -The provided Context class helps with modules of `CommandType.Both` ( A mixture of slash / legacy commands ) -In short, Slash Commands, Both Commands, Text Commands carry a Context data structure - -The Context class is passed into modules with type : -- `CommandType.Both` -- `CommandType.Slash` -- `CommandType.Text` - -Typescript: -```typescript -export default commandModule({ - name: 'ping', - type: CommandType.Both, - async execute(ctx: Context) { - await ctx.reply(`pong ${ctx.user}`) - // .reply is shared between both message and interaction! - // So is an User object! - } -}); -``` -Javascript: -```javascript -exports.default = commandModule({ - name: 'ping', - type: CommandType.Both, - async execute(ctx) { //ctx is a Context instance - await ctx.reply(`pong ${ctx.user}`) - // .reply is shared between both message and interaction! - // So is an User object! - } -}); -``` - -# Plugins - -As of now, modules seem a little underwhelming. It appears that sern doesn't have all the features of a standard handler, -which manages permissions, categorizes, cool-downs, publishes application commands, role permissions, etc. Many important -parts that manage access and help streamline command creation to make are apparently absent. -Below is an example of an event plugin, one of the types of plugins. - -Typescript: -```typescript -export function serenOnly(): EventPlugin { - return { - type: PluginType.Event, - async execute([ctx, args], controller) { - if (ctx.user.id !== "182326315813306368") { - await ctx.reply({content: "You cannot use this command"}) - return controller.stop() - } - return controller.next(); - } - } -} -``` -Javascript: -```javascript -export function serenOnly(): EventPlugin { - return { - type: PluginType.Event, - async execute([ctx, args], controller) { - if (ctx.user.id !== "182326315813306368") { - await ctx.reply({content: "You cannot use this command"}) - return controller.stop() - } - return controller.next(); - } - } -} -``` - -
As part of sern's extensibility, the plugins feature make sern just as powerful, if not more powerful than -standard handlers. -Plugins modify and add new behavior to standard modules, extending customizability and implementing automation. - -
At the moment, there are two types of plugins: - -- Command Plugins -- Event Plugins - -## Command Plugins -All modules are registered into sern's system. With command plugins, you can modify how commands are loaded, -or do some kind of preprocessing before they are loaded into sern. -### The controller object -```typescript -export interface Controller { - next: () => Ok; - stop: () => Err; -} -``` -An instance of the above object is passed into every plugin.
-This controls whether a module is stored into sern.
-Typescript: -```typescript -export function loggable(): CommandPlugin { - return { - type: PluginType.Command, - async execute(wrapper, { absPath, module }, controller) { - console.log(+new Date(), `${module.name} loaded correctly`) - return controller.next(); - } - } -} -``` -Javascript: -```javascript -export function inDir(dir : string) { - return { - type: PluginType.Command, - async execute(wrapper, { absPath, module }, controller) { - if(path.dirname(absPath) !== dir) { - console.log(+new Date(), `${module.name} is not in the correct directory!`); - return controller.stop() - } - console.log(+new Date(), `${module.name} is in the correct directory!`); - return controller.next(); //continue - } - } -} -``` -Above, this simple plugin logs that the module has been loaded along with a timestamp.
-Again, it is up to **you** to define plugin logic! The possibilities to customize your bots is endless. - -## Event Plugins -![event-plugins](/assets/images/eventplugins.drawio.svg)
-- An event is emitted by discord.js. -- This event is passed to all plugins (**in order!!**), -- If all are successful, - -The command is executed. Calling `controller.stop()` notifies sern that this command should not be run, -and this event is ignored. -

-This flexible structure allows you to write reusable preconditions, permissions verifiers, -argument verifiers, and much more. - -

So, what does a command module look like with plugins?

- -Typescript: -```typescript -import { commandModule, CommandType } from '@sern/handler'; - -export default commandModule({ - type: CommandType.Both, - plugins: [ - inDir("other"), - serenOnly() - ], - description: 'A ping command', - //alias : [], - execute: async (ctx, args) => { - await ctx.reply({ content: 'Pong 🏓' }); - }, -}); -``` -Javascript: -```typescript -const { commandModule, CommandType } = require('@sern/handler'); - -exports.default = commandModule({ - type: CommandType.Both, - plugins: [ - inDir("other"), - serenOnly() //The plugins in this section applied to this module! - ], - description: 'A ping command', - //alias : [], - execute: async (ctx, args) => { - await ctx.reply({ content: 'Pong 🏓' }); - }, -}); -``` -Can you predict the behavior of this command? - -- Before loading into sern, this command module will check if this module is in the correct directory `other`. -- Before an event occurs, this command module will check if the user has the id `182326315813306368`. - -If all plugins return `controller.next()`, this command replies `Pong 🏓` - -# The SernEmitter class -You're shipped with the SernEmitter. This EventEmitter listens to -- command modules executing and its status, the `module.activate` event -- command modules registered and its status, the `module.register` event -- Any errors that are recoverable, the `error` event - -
You can put these and other event listeners into event modules! - -# Your first event module -We will dissect a basic event module.
-Typescript: -```typescript -export default eventModule({ - type: EventType.Sern, - plugins : [], //NOT SUPPORTED YET!! - name: 'module.activate', //name of event. - execute(event) { - console.log(event); - } -}) -``` -Javascript: -```javascript -exports.default = eventModule({ - type: EventType.Sern, - plugins : [], //NOT SUPPORTED YET!! - name: 'module.activate', - execute(event) { - console.log(event); - } -}) -``` -Like command modules, the `type` property denotes what kind of event it is. -``` -EventType.Sern = an event listening to the SernEmitter -EventType.Discord = an event listening to the discord.js Client -EventType.External = an event listening to any class extending an EventEmitter -``` -### Essential properties of an event module - -- **module.type** (Required) - - The type of your module. ( Check previous message ^^^) -- **module.execute** (Required) - - This function is called when the event module is triggered. Do your logic here! -- **module.name** (Optional) - - The name of the event. **(defaults to its filename, however it is recommended to fill this out!!)** -- **module.description** (Optional) - - Give your command a description. **(defaults to `..`)** -- **module.plugins** (Optional) -- A list of [plugins](#plugins) that will modify and change the behavior of your command.
- -
-Event modules are laid out similarly to command modules. These listen to any and all event you provide. -In the current version 1.1.0-beta, plugins are not supported. - -### Another example of an event module - -Typescript: -```typescript -export default eventModule({ - type: EventType.Discord, - plugins : [], //NOT SUPPORTED YET!! - name: 'guildMemberAdd', //name of event. - async execute(member) { - await member.client.channels.fetch('channel-id').send(`Welcome, ${member}`); - } -}) -``` - -Javascript: -```typescript -exports.default = eventModule({ - type: EventType.Discord, - plugins : [], //NOT SUPPORTED YET!! - name: 'guildMemberAdd', //name of event. - async execute(member) { - await member.client.channels.fetch('channel-id').send(`Welcome, ${member}`); - } -}) -``` -# Good to know - -## sern.config.json -A sern.config.json, although not necessary, allows your project to communicate with our cli. -For example, when installing typescript plugins, the language property is necessary to install from our -[open source repository](https://github.com/sern-handler/awesome-plugins). -Using the cli and running `sern init --sync` on pre-existing projects should install this json file in the root directory given. -Or, if this is a brand-new project, `sern init` automatically installs it. - -```json -{ - "language": "typescript", - "paths": { - "base": "src", - "commands": "commands" - } -} -``` - -# Conclusion -If you reached this far, thank you for reading! We hope you have learned the necessities you need -to create a bot with the sern framework. If you have any other questions, bugs, concerns, please join our -[community server](https://discord.gg/QgnfxWzrcj), and we'll be glad to answer your questions. \ No newline at end of file +[//]: <> (Maybe redirect to the sern.config.json section in future) +* [sern.config.json](guide-en/walkthrough/good-to-know.md) diff --git a/guide-en/walkthrough/cli.md b/guide-en/walkthrough/cli.md new file mode 100644 index 000000000..e93fa76f1 --- /dev/null +++ b/guide-en/walkthrough/cli.md @@ -0,0 +1,21 @@ +# CLI + +Setting up the [CLI](https://github.com/sern-handler/cli) is easy.
+- To start a brand new project, run : +``` +sern init (-y) +``` +Include the `-y` flag if you want to set up defaults. The default langauge is [Typescript](https://www.typescriptlang.org/)
+ +- To install [plugins](plugins.md) maintained by the community [repository](https://github.com/sern-handler/awesome-plugins), +``` +sern plugins +``` +This will display a menu selection of all installable plugins.
+**Note**: You must have a [sern.config.json](good-to-know.md) to use this command. +If you want to view plugins, visit the repository linked above. + +- To install extra utilities into your project +``` +sern extra +``` \ No newline at end of file diff --git a/guide-en/walkthrough/conclusion.md b/guide-en/walkthrough/conclusion.md new file mode 100644 index 000000000..553cb9f1c --- /dev/null +++ b/guide-en/walkthrough/conclusion.md @@ -0,0 +1,4 @@ +# Conclusion +If you reached this far, thank you for reading! We hope you have learned the necessities you need +to create a bot with the sern framework. If you have any other questions, bugs, feature requests, concerns, please join our +[community server](https://discord.gg/QgnfxWzrcj), and we'll be glad to answer your questions. \ No newline at end of file diff --git a/guide-en/walkthrough/first-command.md b/guide-en/walkthrough/first-command.md new file mode 100644 index 000000000..eeb426f86 --- /dev/null +++ b/guide-en/walkthrough/first-command.md @@ -0,0 +1,127 @@ +# First Command +We will dissect a basic command. +If you installed a new project via the cli, This is the `ping` command located in src/commands folder. + +Typescript +```typescript +import { commandModule, CommandType } from '@sern/handler'; + +export default commandModule({ + type: CommandType.Both, + plugins: [], + description: 'A ping command', + //alias : [], + execute: async (ctx, args) => { + await ctx.reply({ content: 'Pong 🏓' }); + }, +}); +``` +Javascript +```javascript +const { CommandType, commandModule } = require('@sern/handler'); + +exports.default = commandModule({ + type: CommandType.Both, + plugins: [], + description: 'A ping command', + //alias : [], + execute: async (ctx, args) => { + await ctx.reply('Pong 🏓'); + }, +}) +``` +### Essential properties of a command + +- **module.type** (Required) + - The type of your module. For example, a command listening to messages would have the type CommandType.Text +- **module.execute** (Required) + - This function is called when the command is triggered. Do your logic here! +- **module.name** (Optional) + - Give your command a name. **(defaults to its filename)** +- **module.description** (Optional) + - Give your command a description. **(defaults to `..`)** +- **module.plugins** (Optional) + - A list of [plugins](guide-en/walkthrough/plugins.md) that will modify and change the behavior of your command.
+ +### Types of command modules +Every command module `type` is part of an enum. This field allows type inference for the rest of a module's fields.
+All available command types : +``` +CommandType.Text = A Text Command +CommandType.Slash = A Slash Command +CommandType.Both = A Command supporting either text or slash +CommandType.Modal = A Command listening to Modal interactions +CommandType.MenuSelect = A Command listening to select menu interactions +CommandType.MenuUser = A Command listening to context menu user interactions +CommandType.MenuMsg = A Command listening to context menu message interactions +CommandType.Button = A Command listening to button interactions +``` +So, lets say you want to make a command module that listens to modals.
+**Note**: Keep in mind you'll need to send a modal with a custom id `dm-me`. This example below is the response to a modal being sent.
+ +Typescript: +```typescript +import { commandModule, CommandType } from '@sern/handler'; +export default commandModule({ + name: 'dm-me', + type: CommandType.Modal, + async execute (modal) { + const value = modal.fields.getTextInputValue('message'); + modal.client.users.fetch('182326315813306368').then( u => + u.send(value + ` from ${modal.user}`) + ); + modal.reply( { ephemeral:true, content: 'Sent' }) + } +}); +``` +Javascript: +```javascript +const { CommandType, commandModule } = require('@sern/handler'); +exports.default = commandModule({ + name: 'dm-me', + type: CommandType.Modal, + async execute (modal) { + const value = modal.fields.getTextInputValue('message'); + modal.client.users.fetch('182326315813306368').then( u => + u.send(value + ` from ${modal.user}`) + ); + modal.reply( { ephemeral:true, content: 'Sent' }) + } +}); +``` +Commands are straight forward. Keep in mind, every other property on the commandModule object is +optional **except** the type and execute function. + +# Context class +The provided Context class helps with modules of `CommandType.Both` ( A mixture of slash / legacy commands ) +In short, Slash Commands, Both Commands, Text Commands carry a Context data structure + +The Context class is passed into modules with type : +- `CommandType.Both` +- `CommandType.Slash` +- `CommandType.Text` + +Typescript: +```typescript +export default commandModule({ + name: 'ping', + type: CommandType.Both, + async execute(ctx: Context) { + await ctx.reply(`pong ${ctx.user}`) + // .reply is shared between both message and interaction! + // So is an User object! + } +}); +``` +Javascript: +```javascript +exports.default = commandModule({ + name: 'ping', + type: CommandType.Both, + async execute(ctx) { //ctx is a Context instance + await ctx.reply(`pong ${ctx.user}`) + // .reply is shared between both message and interaction! + // So is an User object! + } +}); +``` diff --git a/guide-en/walkthrough/first-event.md b/guide-en/walkthrough/first-event.md new file mode 100644 index 000000000..a8aaac70d --- /dev/null +++ b/guide-en/walkthrough/first-event.md @@ -0,0 +1,72 @@ +# Your first event module +We will dissect a basic event module.
+Typescript: +```typescript +export default eventModule({ + type: EventType.Sern, + plugins : [], //NOT SUPPORTED YET!! + name: 'module.activate', //name of event. + execute(event) { + console.log(event); + } +}) +``` +Javascript: +```javascript +exports.default = eventModule({ + type: EventType.Sern, + plugins : [], //NOT SUPPORTED YET!! + name: 'module.activate', + execute(event) { + console.log(event); + } +}) +``` +Like command modules, the `type` property denotes what kind of event it is. +``` +EventType.Sern = an event listening to the SernEmitter +EventType.Discord = an event listening to the discord.js Client +EventType.External = an event listening to any class extending an EventEmitter +``` +### Essential properties of an event module + +- **module.type** (Required) + - The type of your module. ( Check previous message ^^^) +- **module.execute** (Required) + - This function is called when the event module is triggered. Do your logic here! +- **module.name** (Optional) + - The name of the event. **(defaults to its filename, however it is recommended to fill this out!!)** +- **module.description** (Optional) + - Give your command a description. **(defaults to `..`)** +- **module.plugins** (Optional) +- A list of [plugins](plugins.md) that will modify and change the behavior of your command.
+ +
+Event modules are laid out similarly to command modules. These listen to any and all event you provide. +In the current version 1.1.0-beta, plugins are not supported. + +### Another example of an event module + +Typescript: +```typescript +export default eventModule({ + type: EventType.Discord, + plugins : [], //NOT SUPPORTED YET!! + name: 'guildMemberAdd', //name of event. + async execute(member) { + await member.client.channels.fetch('channel-id').send(`Welcome, ${member}`); + } +}) +``` + +Javascript: +```typescript +exports.default = eventModule({ + type: EventType.Discord, + plugins : [], //NOT SUPPORTED YET!! + name: 'guildMemberAdd', //name of event. + async execute(member) { + await member.client.channels.fetch('channel-id').send(`Welcome, ${member}`); + } +}) +``` \ No newline at end of file diff --git a/guide-en/walkthrough/goal.md b/guide-en/walkthrough/goal.md new file mode 100644 index 000000000..9c70bca5b --- /dev/null +++ b/guide-en/walkthrough/goal.md @@ -0,0 +1,6 @@ + +# Goal + +Sern strives to be minimalist, but with all batteries included. Meaning, this framework provides the necessary tools +to start up a bot in minutes, and leaves plenty room space to customize your experience and create an amazing project. +It should include all the tools for any bot at any scale. diff --git a/guide-en/walkthrough/good-to-know.md b/guide-en/walkthrough/good-to-know.md new file mode 100644 index 000000000..3d04e5492 --- /dev/null +++ b/guide-en/walkthrough/good-to-know.md @@ -0,0 +1,18 @@ +# Good to know + +## sern.config.json +A sern.config.json, although not necessary, allows your project to communicate with our cli. +For example, when installing typescript plugins, the language property is necessary to install from our +[open source repository](https://github.com/sern-handler/awesome-plugins). +Using the cli and running `sern init --sync` on pre-existing projects should install this json file in the root directory given. +Or, if this is a brand-new project, `sern init` automatically installs it. + +```json +{ + "language": "typescript", + "paths": { + "base": "src", + "commands": "commands" + } +} +``` \ No newline at end of file diff --git a/guide-en/walkthrough/plugins.md b/guide-en/walkthrough/plugins.md new file mode 100644 index 000000000..549ffe983 --- /dev/null +++ b/guide-en/walkthrough/plugins.md @@ -0,0 +1,148 @@ +# Plugins + +As of now, modules seem a little underwhelming. It appears that sern doesn't have all the features of a standard handler, +which manages permissions, categorizes, cool-downs, publishes application commands, role permissions, etc. Many important +parts that manage access and help streamline command creation to make are apparently absent. +Below is an example of an event plugin, one of the types of plugins. + +Typescript: +```typescript +export function serenOnly(): EventPlugin { + return { + type: PluginType.Event, + async execute([ctx, args], controller) { + if (ctx.user.id !== "182326315813306368") { + await ctx.reply({content: "You cannot use this command"}) + return controller.stop() + } + return controller.next(); + } + } +} +``` +Javascript: +```javascript +export function serenOnly() { + return { + type: PluginType.Event, + async execute([ctx, args], controller) { + if (ctx.user.id !== "182326315813306368") { + await ctx.reply({content: "You cannot use this command"}) + return controller.stop() + } + return controller.next(); + } + } +} +``` + +
As part of sern's extensibility, the plugins feature make sern just as powerful, if not more powerful than +standard handlers. +Plugins modify and add new behavior to standard modules, extending customizability and implementing automation. + +
At the moment, there are two types of plugins: + +- Command Plugins +- Event Plugins + +## Command Plugins +All modules are registered into sern's system. With command plugins, you can modify how commands are loaded, +or do some kind of preprocessing before they are loaded into sern. +### The controller object +```typescript +export interface Controller { + next: () => Ok; + stop: () => Err; +} +``` +An instance of the above object is passed into every plugin.
+This controls whether a module is stored into sern.
+Typescript: +```typescript +export function inDir(dir : string) : CommandPlugin { + return { + type: PluginType.Command, + async execute(wrapper, { absPath, module }, controller) { + if(path.dirname(absPath) !== dir) { + console.log(+new Date(), `${module.name} is not in the correct directory!`); + return controller.stop() + } + console.log(+new Date(), `${module.name} is in the correct directory!`); + return controller.next(); //continue + } + } +} +``` +Javascript: +```javascript +export function inDir(dir : string) { + return { + type: PluginType.Command, + async execute(wrapper, { absPath, module }, controller) { + if(path.dirname(absPath) !== dir) { + console.log(+new Date(), `${module.name} is not in the correct directory!`); + return controller.stop() + } + console.log(+new Date(), `${module.name} is in the correct directory!`); + return controller.next(); //continue + } + } +} +``` +Above, this simple plugin logs that the module has been loaded along with a timestamp.
+Again, it is up to **you** to define plugin logic! The possibilities to customize your bots is endless. + +## Event Plugins +![event-plugins](/assets/images/eventplugins.drawio.svg)
+- An event is emitted by discord.js. +- This event is passed to all plugins (**in order!!**), +- If all are successful, + +The command is executed. Calling `controller.stop()` notifies sern that this command should not be run, +and this event is ignored. +

+This flexible structure allows you to write reusable preconditions, permissions verifiers, +argument verifiers, and much more. + +

So, what does a command module look like with plugins?

+ +Typescript: +```typescript +import { commandModule, CommandType } from '@sern/handler'; + +export default commandModule({ + type: CommandType.Both, + plugins: [ + inDir("other"), + serenOnly() + ], + description: 'A ping command', + //alias : [], + execute: async (ctx, args) => { + await ctx.reply({ content: 'Pong 🏓' }); + }, +}); +``` +Javascript: +```typescript +const { commandModule, CommandType } = require('@sern/handler'); + +exports.default = commandModule({ + type: CommandType.Both, + plugins: [ + inDir("other"), + serenOnly() //The plugins in this section applied to this module! + ], + description: 'A ping command', + //alias : [], + execute: async (ctx, args) => { + await ctx.reply({ content: 'Pong 🏓' }); + }, +}); +``` +Can you predict the behavior of this command? + +- Before loading into sern, this command module will check if this module is in the correct directory `other`. +- Before an event occurs, this command module will check if the user has the id `182326315813306368`. + +If all plugins return `controller.next()`, this command replies `Pong 🏓` \ No newline at end of file diff --git a/guide-en/walkthrough/sern-emitter.md b/guide-en/walkthrough/sern-emitter.md new file mode 100644 index 000000000..d4640f33c --- /dev/null +++ b/guide-en/walkthrough/sern-emitter.md @@ -0,0 +1,7 @@ +# The SernEmitter class +You're shipped with the SernEmitter. This EventEmitter listens to +- command modules executing and its status, the `module.activate` event +- command modules registered and its status, the `module.register` event +- any errors that are recoverable, the `error` event + +
You can put these and other event listeners into event modules!