/[sudobot]/trunk/docs/app/(docs)/extensions/creating-extensions-for-v9/page.mdx
ViewVC logotype

Contents of /trunk/docs/app/(docs)/extensions/creating-extensions-for-v9/page.mdx

Parent Directory Parent Directory | Revision Log Revision Log


Revision 623 - (show annotations)
Fri Aug 30 10:10:15 2024 UTC (7 months ago) by rakinar2
File size: 10069 byte(s)
docs: update pages

1 ---
2 title: Creating Extensions for SudoBot v9
3 short_name: Creating Extensions for SudoBot v9
4 ---
5
6 import Callout from "@/components/Alerts/Callout";
7
8 # Creating Extensions for SudoBot v9
9
10 SudoBot has support for extensions, and it was introduced in version 6.17. Extensions can extend the bot's feature, by adding commands, event listeners, services and a lot more stuff. You can install/uninstall/disable extensions, or create your own to make the bot behave exactly how you want. Extensions can be written using JavaScript and TypeScript.
11
12 In this article, you'll learn how SudoBot's extension system works.
13
14 ## The extensions directory
15
16 To start using extensions, you need to create a root directory where extensions will be installed.
17 In this guide, we'll name the directory `installed_extensions/`. To create a directory named `installed_extensions/` in the main project root, run the following:
18
19 ```bash
20 mkdir installed_extensions
21 ```
22
23 Every installed extension goes inside this directory.
24
25 Now to tell SudoBot where to look for extensions, add the `EXTENSIONS_DIRECTORY` environment variable to your `.env` file:
26
27 ```bash
28 # Path to the extensions root directory
29 EXTENSIONS_DIRECTORY=/example/path/to/extensions/directory
30 ```
31
32 Each installed extension has a directory associated with it inside the `installed_extensions/` directory. Inside of that inner directory, there is a special file `extension.json` which contains meta information about the extension, and how to build it.
33
34 The `extension.json` file looks something like this:
35
36 ```json5
37 {
38 id: "org.example.sudobot.extension.hello" /* Extension ID */,
39 main: "index.js" /* The entry point file name. */,
40 src_main: "index.ts" /* The entry point file name. */,
41 commands: "commands" /* Commands directory. The bot will load commands from this directory. */,
42 events: "events" /* Event handlers directory. The bot will load event handlers from this directory. */,
43 language: "typescript" /* The language being used for this extension. Can be either "javascript" or "typescript". */,
44 main_directory: "./build" /* The main directory where the entry point is located. */,
45 src_directory: "./src" /* The source directory where the source file of the entry point is located. */,
46 build_command: "npm run build" /* Command to build the extension. In this case `npm run build` invokes `tsc`. */,
47 }
48 ```
49
50 ## Creating your first SudoBot extension
51
52 To get started, first create a directory named `installed_extensions` inside the project root. In that directory, create another directory for your extension. The name of this directory usually should be your extension's name. In this example, we'll name the extension "hello".
53
54 Then inside your extension's directory, create the `extension.json` file, and the `src/` directory. Inside `src`, create `events` and `commands` directories. The final directory tree should look something like this:
55
56 ```
57 + sudobot/ [project root]
58 + installed_extensions/
59 + hello/
60 + src/
61 + commands/
62 + events/
63 - extension.json
64 ```
65
66 Now add the following to your `extension.json` file:
67
68 ```json
69 {
70 id: "org.example.sudobot.extension.hello",
71 main: "index.js",
72 src_main: "index.ts",
73 commands: "commands",
74 events: "events",
75 language: "typescript",
76 main_directory: "./build",
77 src_directory: "./src",
78 build_command: "npm run build"
79 }
80 ```
81
82 We'll be using TypeScript to write the extension in this example. If you'd like to use JavaScript instead, you can set `language` to `javascript` and you don't need to specify a build command, and your main directory will be the directory where you put your JavaScript files (usually `src/`). You should also adjust the paths to point to that directory (rather than `build/` which is used in this example).
83
84 #### Setting up TypeScript and Dependencies
85
86 First, run `npm init` to initialize your extension project. This will ask you a few questions and create a `package.json` file. Then run:
87
88 ```bash
89 npm install --save ../.. # Path to the sudobot project root
90 ```
91
92 <Callout type="info">
93 Remember **this is a really important step** to make sure your extension can
94 access SudoBot's core utilities to initialize itself. If you don't link
95 SudoBot with your extension, it will fail to import the necessary files.
96 </Callout>
97
98 Then we can go ahead and install the dependencies and also set up TypeScript.
99
100 ```shell
101 npm install module-alias
102 npm install -D typescript @types/node
103 npx tsc --init
104 ```
105
106 This will add `typescript` as a dev dependency and also create a `tsconfig.node.json` file which contains the configuration for the TypeScript compiler.
107
108 Now open up `tsconfig.node.json` file, and add the following (you can tweak these options if you want):
109
110 ```json
111 {
112 "compilerOptions": {
113 "target": "ES2021",
114 "module": "commonjs",
115 "rootDir": "./src",
116 "baseUrl": "./",
117 "paths": {
118 "@sudobot/*": ["node_modules/sudobot/build/out/main/typescript/*"],
119 "@framework/*": [
120 "node_modules/sudobot/build/out/framework/typescript/*"
121 ]
122 },
123 "resolveJsonModule": true,
124 "outDir": "./build",
125 "newLine": "lf",
126 "noEmitHelpers": true,
127 "noEmitOnError": true,
128 "allowSyntheticDefaultImports": true,
129 "esModuleInterop": true,
130 "forceConsistentCasingInFileNames": true,
131 "strict": true,
132 "skipLibCheck": true
133 },
134 "exclude": ["./tests", "./build"]
135 }
136 ```
137
138 This sets up the `@sudobot` and `@framework` import aliases for TypeScript, specifies the source root and build directory, and a few other things that are needed.
139 After this, create a symbolic link named `tsconfig.json` that points to `tsconfig.node.json`. On windows, just copy the file. The command to create the symbolic link
140 on a Unix/Linux based system would be the following:
141
142 ```bash
143 ln -s ./tsconfig.node.json ./tsconfig.json
144 ```
145
146 <Callout type="info">
147 Remember to build the bot beforehand! As you can see, this alias points to
148 the `build` directory which is created when you build the bot.
149 </Callout>
150
151 Then open up `package.json` file and add the following inside the root object:
152
153 ```json
154 "_moduleAliases": {
155 "@framework": "node_modules/sudobot/build/out/framework/typescript",
156 "@sudobot": "node_modules/sudobot/build/out/main/typescript"
157 },
158 "scripts": {
159 "build": "tsc"
160 }
161 ```
162
163 You might be thinking, why do we need to add the module aliases twice? It's because TypeScript doesn't actually deal with these module aliases, it just checks the types and imports. In runtime, we need another way to resolve these imports. We use `module-alias` for that.
164
165 #### The entry point
166
167 We need to create the entry point now! Make a file `src/index.ts` and put the following code inside of that file:
168
169 ```typescript
170 import "module-alias/register";
171 import { Extension } from "@sudobot/core/Extension";
172
173 class HelloExtension extends Extension {
174 // ...
175 }
176
177 export default HelloExtension;
178 ```
179
180 That's actually all we need inside this file.
181
182 #### Adding commands to the extension
183
184 Alright, let's add a command to the extension! Create a file `src/commands/HelloCommand.ts` and inside of that file, put the following code:
185
186 ```typescript
187 import { Command, type CommandMessage } from "@framework/commands/Command";
188 import type Context from "@framework/commands/Context";
189
190 class HelloCommand extends Command {
191 public override readonly name = "hello";
192 public override readonly description = "A simple hello-world command.";
193
194 public override async execute(context: Context<CommandMessage>) {
195 await context.reply("Hello world, from the hello extension!");
196 }
197 }
198
199 export default HelloCommand;
200 ```
201
202 This command just responds to the user with "Hello world, from the hello extension!".
203
204 #### Adding event listeners to the extension
205
206 Now, let's add an event listener to the extension! Create a file `src/events/MessageCreateEventListener.ts` and inside of that file, put the following code:
207
208 ```typescript
209 import EventListener from "@framework/events/EventListener";
210 import { Events } from "@framework/types/ClientEvents";
211 import type { Message } from "discord.js";
212
213 class MessageCreateEventListener extends EventListener<Events.MessageCreate> {
214 public override readonly name = Events.MessageCreate;
215
216 public override async execute(message: Message<boolean>): Promise<void> {
217 if (message.author.bot) {
218 return;
219 }
220
221 if (message.content === "ping") {
222 await message.reply("Pong, from the hello extension!");
223 }
224 }
225 }
226
227 export default MessageCreateEventListener;
228 ```
229
230 This event listener listens to `MessageCreate` event, and whenever someone sends a message with content "ping", it will reply to them.
231
232 #### Building the extension
233
234 Building your newly created extension involves the same procedures as any other TypeScript project.
235 Install the dependencies and run the TypeScript compiler from the extension's directory (installed_extensions/hello):
236
237 ```bash
238 npm install -D
239 npm run build
240 ```
241
242 If using [Bun](https://bun.sh):
243
244 ```bash
245 bun install -D
246 bun run build
247 ```
248
249 This will take a little bit time. After that, you're ready to go. You can now start the bot from the main project root (assuming you've built it already):
250
251 ```bash
252 npm start
253 ```
254
255 **Please note that if you're using Bun to run the bot, the extensions will need to be configured differently. We'll include the instructions on how to do it
256 manually and also how you can automate it, very soon.**
257
258 And then if everything was configured correctly, the `hello` command will be loaded and can be executed on any server.
259
260 Congratulations, you've just built an extension for SudoBot!
261
262 ### Help and Support
263
264 If you need help with anything, feel free to create a discussion topic at the [GitHub repo](https://github.com/onesoft-sudo/sudobot). You can also contact via email at [[email protected]](mailto:[email protected]), or join our [Discord Server](https://discord.gg/892GWhTzgs).

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26