@tryty/easydc-js 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # easydc-js
2
2
 
3
- Bot Discord **super mudah** di atas [discord.js](https://discord.js.org). Kamu cukup menulis perintah dengan sintaks `$fungsi[argumen]` seperti aoi.js, tanpa harus mengurus event, embed, tombol, atau database secara manual.
3
+ A **super easy** Discord Bot wrapper built on top of [discord.js](https://discord.js.org). You only need to write commands using the `$function[argument]` syntax, without having to manually manage events, embeds, buttons, or databases.
4
4
 
5
5
  ```js
6
6
  const { Bot } = require('easydc-js');
@@ -12,62 +12,63 @@ bot.command({ name: 'ping', code: '🏓 Pong! $ping ms' });
12
12
  bot.connect();
13
13
  ```
14
14
 
15
- Ketik `!ping` di Discord → bot menjawab `🏓 Pong! 42 ms`.
15
+ Type `!ping` in Discord → the bot replies `🏓 Pong! 42 ms`.
16
16
 
17
- > **Catatan:** ini package independen, bukan bagian resmi dari discord.js maupun aoi.js. Package ini memakai discord.js di belakang layar.
17
+ > **Note:** This is an independent package, not an official part of discord.js. This package uses discord.js under the hood.
18
18
 
19
19
  ---
20
20
 
21
- ## Daftar isi
22
-
23
- 1. [Instalasi](#1-instalasi)
24
- 2. [Membuat bot di Discord](#2-membuat-bot-di-discord)
25
- 3. [Bot pertama](#3-bot-pertama)
26
- 4. [Cara kerja sintaks `$fungsi`](#4-cara-kerja-sintaks-fungsi)
27
- 5. [Jenis handler](#5-jenis-handler)
28
- 6. [Opsi Bot](#6-opsi-bot)
29
- 7. [Variabel & database](#7-variabel--database)
30
- 8. [Kondisi `$if`](#8-kondisi-if)
31
- 9. [Embed, tombol, select menu](#9-embed-tombol-select-menu)
32
- 10. [Fitur lanjutan: modal, autocomplete, menu klik-kanan, poll, thread, webhook](#10-fitur-lanjutan)
33
- 11. [Eval (khusus owner)](#11-eval-khusus-owner)
34
- 12. [Membuat fungsi sendiri](#12-membuat-fungsi-sendiri)
35
- 13. [Memisah command ke banyak file](#13-memisah-command-ke-banyak-file)
36
- 14. [Keamanan](#14-keamanan)
37
- 15. [Pemecahan masalah](#15-pemecahan-masalah)
38
- 16. [Daftar semua fungsi](#16-daftar-semua-fungsi)
21
+ ## Table of Contents
22
+
23
+ 1. [Installation](#1-installation)
24
+ 2. [Creating a Bot on Discord](#2-creating-a-bot-on-discord)
25
+ 3. [Your First Bot](#3-your-first-bot)
26
+ 4. [How the `$function` Syntax Works](#4-how-the-function-syntax-works)
27
+ 5. [Handler Types](#5-handler-types)
28
+ 6. [Bot Options](#6-bot-options)
29
+ 7. [Variables & Database](#7-variables--database)
30
+ 8. [The `$if` Condition](#8-the-if-condition)
31
+ 9. [Embeds, Buttons, Select Menus](#9-embeds-buttons-select-menus)
32
+ 10. [Advanced Features: Modals, Autocomplete, Right-Click Menus, Polls, Threads, Webhooks](#10-advanced-features)
33
+ 11. [Eval (Owner Only)](#11-eval-owner-only)
34
+ 12. [Database & Plugins (MongoDB)](#12-database--plugins-mongodb)
35
+ 13. [Creating Custom Functions](#13-creating-custom-functions)
36
+ 14. [Splitting Commands into Multiple Files](#14-splitting-commands-into-multiple-files)
37
+ 15. [Security](#15-security)
38
+ 16. [Troubleshooting](#16-troubleshooting)
39
+ 17. [List of All Functions](#17-list of-all-functions)
39
40
 
40
41
  ---
41
42
 
42
- ## 1. Instalasi
43
+ ## 1. Installation
43
44
 
44
- Butuh **Node.js 18.17 atau lebih baru**.
45
+ Requires **Node.js 18.17 or newer**.
45
46
 
46
47
  ```bash
47
48
  npm install easydc-js discord.js
48
49
  ```
49
50
 
50
- ## 2. Membuat bot di Discord
51
+ ## 2. Creating a Bot on Discord
51
52
 
52
- 1. Buka <https://discord.com/developers/applications> → **New Application**.
53
- 2. Menu **Bot** → **Reset Token** → salin token. **Jangan dibagikan ke siapa pun.**
54
- 3. Di halaman yang sama, aktifkan **Privileged Gateway Intents**:
55
- - **Message Content Intent** (wajib agar command berawalan `!` terbaca)
56
- - **Server Members Intent** (untuk event member masuk/keluar & info member)
57
- 4. Menu **OAuth2 → URL Generator** → centang `bot` dan `applications.commands` → pilih izin yang dibutuhkan → buka URL hasilnya untuk mengundang bot.
53
+ 1. Open <https://discord.com/developers/applications> → **New Application**.
54
+ 2. Go to the **Bot** menu → **Reset Token** → copy the token. **Do not share it with anyone.**
55
+ 3. On the same page, enable **Privileged Gateway Intents**:
56
+ - **Message Content Intent** (required for commands starting with prefix `!` to be read)
57
+ - **Server Members Intent** (for member join/leave events & member info)
58
+ 4. Go to the **OAuth2 → URL Generator** menu → check `bot` and `applications.commands` → select the required permissions → open the generated URL to invite the bot.
58
59
 
59
- Simpan token di variabel lingkungan, jangan ditulis di kode:
60
+ Store the token in environment variables, do not write it directly in your code:
60
61
 
61
62
  ```bash
62
63
  # Linux / macOS
63
- TOKEN="token_kamu" node index.js
64
+ TOKEN="your_token" node index.js
64
65
  # Windows PowerShell
65
- $env:TOKEN="token_kamu"; node index.js
66
+ $env:TOKEN="your_token"; node index.js
66
67
  ```
67
68
 
68
- ## 3. Bot pertama
69
+ ## 3. Your First Bot
69
70
 
70
- Buat `index.js`:
71
+ Create `index.js`:
71
72
 
72
73
  ```js
73
74
  const { Bot } = require('easydc-js');
@@ -78,721 +79,835 @@ const bot = new Bot({
78
79
  timezone: 'Asia/Jakarta',
79
80
  });
80
81
 
81
- bot.variables({ uang: 100 });
82
+ bot.variables({ money: 100 });
82
83
 
83
84
  bot.command({
84
- name: 'uang',
85
- code: '💰 $username punya $getUserVar[uang] koin',
85
+ name: 'money',
86
+ code: '💰 $username has $getUserVar[money] coins',
86
87
  });
87
88
 
88
89
  bot.command({
89
- name: 'kerja',
90
+ name: 'work',
90
91
  code: `
91
- $cooldown[1m;Istirahat dulu, tunggu %time%.]
92
- $setUserVar[uang;$math[$getUserVar[uang]+25]]
93
- Kamu dapat 25 koin! Total: $getUserVar[uang]
92
+ $cooldown[1m;Take a rest first, please wait %time%.]
93
+ $setUserVar[money;$math[$getUserVar[money]+25]]
94
+ You got 25 coins! Total: $getUserVar[money]
94
95
  `,
95
96
  });
96
97
 
97
98
  bot.connect();
98
99
  ```
99
100
 
100
- Contoh lengkap ada di [`examples/basic.js`](examples/basic.js).
101
+ A complete example can be found in [`examples/basic.js`](examples/basic.js).
101
102
 
102
- ## 4. Cara kerja sintaks `$fungsi`
103
+ ## 4. How the `$function` Syntax Works
103
104
 
104
105
  ```
105
- $namaFungsi[argumen1;argumen2;...]
106
+ $functionName[argument1;argument2;...]
106
107
  ```
107
108
 
108
- - Argumen dipisah dengan **titik koma** `;`.
109
- - Fungsi boleh **bersarang**: `$toUpperCase[$username]`, `$math[$getUserVar[uang]*2]`.
110
- - Nama fungsi **tidak peka huruf besar/kecil** (`$Username` = `$username`).
111
- - Fungsi yang tidak butuh argumen ditulis tanpa kurung: `$ping`, `$serverName`.
112
- - Hasil akhir seluruh teks (setelah semua `$fungsi` dijalankan) dikirim sebagai jawaban bot.
113
- - Teks yang panjangnya lebih dari 2000 karakter otomatis dipecah jadi beberapa pesan.
109
+ - Arguments are separated by a **semicolon** `;`.
110
+ - Functions can be **nested**: `$toUpperCase[$username]`, `$math[$getUserVar[money]*2]`.
111
+ - Function names are **case-insensitive** (`$Username` = `$username`).
112
+ - Functions that do not require arguments are written without parentheses: `$ping`, `$serverName`.
113
+ - The final result of the entire text (after all `$functions` are executed) is sent as the bot's reply.
114
+ - Texts exceeding 2000 characters are automatically split into multiple messages.
114
115
 
115
- ### Menulis karakter khusus
116
+ ### Writing Special Characters
116
117
 
117
- Untuk menulis karakter `$ [ ] ;` sebagai teks biasa, beri backslash di depannya:
118
+ To write `$ [ ] ;` characters as literal text, escape them with a backslash:
118
119
 
119
- | Tulis | Hasil |
120
+ | Write | Result |
120
121
  |---|---|
121
- | `\$ping` | `$ping` (bukan dijalankan) |
122
+ | `\$ping` | `$ping` (will not be executed) |
122
123
  | `\[` `\]` | `[` `]` |
123
- | `\;` | `;` (tidak memisah argumen) |
124
- | `\\` | `\` |
124
+ | `\;` | `;` (will not separate arguments) |
125
+ | `\` | `\` |
125
126
 
126
- Atau pakai fungsi `$semicolon`, `$leftBracket`, `$rightBracket`, `$dollar`.
127
- Tanda `$` yang diikuti angka atau spasi (misal `harga $5`) otomatis dianggap teks biasa.
127
+ Alternatively, use the functions `$semicolon`, `$leftBracket`, `$rightBracket`, `$dollar`.
128
+ A `$` sign followed by a number or space (e.g., `price $5`) is automatically treated as plain text.
128
129
 
129
- > Di dalam template string JavaScript (tanda `` ` ``), backslash perlu **digandakan**: `` `\\$ping` ``. Jika tidak mau repot, pakai `$dollar`.
130
+ > Inside JavaScript template strings (backticks `` ` ``), backslashes need to be **doubled**: `` `\$ping` ``. If you want to avoid this, use `$dollar`.
130
131
 
131
- ### Kode dicek sebelum bot menyala
132
+ ### Code Validation Before Bot Starts
132
133
 
133
- Saat `bot.connect()` dipanggil, **semua kode diperiksa dulu**. Kalau ada fungsi salah ketik, jumlah argumen salah, atau `$if` tanpa `$endif`, bot **tidak login** dan kamu mendapat daftar lengkap masalahnya, contoh:
134
+ When `bot.connect()` is called, **all code is validated first**. If there is a misspelled function, wrong number of arguments, or an `$if` without an `$endif`, the bot **will not log in** and you will get a full list of issues, for example:
134
135
 
135
136
  ```
136
- Ditemukan 2 masalah pada kode:
137
- - command "ban": Fungsi $bann tidak dikenal (baris 3, kolom 1)
138
- - command "cek": $if tidak ditutup, tambahkan $endif (baris 1, kolom 1)
137
+ Found 2 issues in the code:
138
+ - command "ban": Unknown function $bann (line 3, column 1)
139
+ - command "check": $if is not closed, add $endif (line 1, column 1)
139
140
  ```
140
141
 
141
- ## 5. Jenis handler
142
+ ## 5. Handler Types
142
143
 
143
- ### Command prefix
144
+ ### Prefix Commands
144
145
 
145
146
  ```js
146
- bot.command({ name: 'sapa', aliases: ['hai', 'halo'], code: 'Halo $username!' });
147
+ bot.command({ name: 'greet', aliases: ['hi', 'hello'], code: 'Hello $username!' });
147
148
  ```
148
149
 
149
- Argumen setelah nama command: `$message` (semua), `$message[1]` (kata ke-1), `$argsCount`.
150
+ Arguments after the command name: `$message` (all), `$message[1]` (1st word), `$argsCount`.
150
151
 
151
- ### Slash command
152
+ ### Slash Commands
152
153
 
153
154
  ```js
154
155
  bot.slashCommand({
155
- name: 'halo', // huruf kecil, tanpa spasi
156
- description: 'Menyapa seseorang',
156
+ name: 'hello', // lowercase, no spaces
157
+ description: 'Greets someone',
157
158
  options: [
158
- { name: 'nama', description: 'Nama', type: 'string', required: true },
159
- { name: 'umur', description: 'Umur', type: 'integer', minValue: 1 },
159
+ { name: 'name', description: 'Name', type: 'string', required: true },
160
+ { name: 'age', description: 'Age', type: 'integer', minValue: 1 },
160
161
  ],
161
- code: 'Halo, $option[nama]!',
162
+ code: 'Hello, $option[name]!',
162
163
  });
163
164
  ```
164
165
 
165
- Tipe opsi: `string integer boolean user channel role mentionable number attachment`.
166
- Slash command didaftarkan otomatis saat bot siap. Untuk uji coba cepat, isi `slashGuild: 'ID_SERVER'` (muncul seketika; kalau global bisa butuh waktu).
167
- Jika proses lebih dari 3 detik, taruh `$defer` di awal kode.
166
+ Option types: `string integer boolean user channel role mentionable number attachment`.
167
+ Slash commands are automatically registered when the bot is ready. For fast testing, set `slashGuild: 'GUILD_ID'` (appears instantly; global registration can take time).
168
+ If the process takes longer than 3 seconds, put `$defer` at the top of the code.
168
169
 
169
- ### Tombol & select menu
170
+ ### Buttons & Select Menus
170
171
 
171
172
  ```js
172
173
  bot.command({
173
- name: 'tombol',
174
- code: '$addButton[Klik;primary;klik_1]$addButton[Web;link;https://example.com]Pilih:',
174
+ name: 'button',
175
+ code: '$addButton[Click;primary;click_1]$addButton[Web;link;https://example.com]Choose:',
175
176
  });
176
177
 
177
- bot.button({ customId: 'klik_*', code: '$ephemeral Kamu menekan `$customID`' }); // * = wildcard
178
+ bot.button({ customId: 'click_*', code: '$ephemeral You pressed `$customID`' }); // * = wildcard
178
179
 
179
180
  bot.command({
180
181
  name: 'menu',
181
- code: `Pilih buah:
182
- $addSelectMenu[buah;Pilih...]
183
- $addSelectOption[Apel;apel;Buah merah]
184
- $addSelectOption[Jeruk;jeruk]`,
182
+ code: `Choose a fruit:
183
+ $addSelectMenu[fruit;Choose...]
184
+ $addSelectOption[Apple;apple;Red fruit]
185
+ $addSelectOption[Orange;orange]`,
185
186
  });
186
- bot.select({ customId: 'buah', code: 'Kamu memilih: $interactionValues' });
187
+ bot.select({ customId: 'fruit', code: 'You chose: $interactionValues' });
187
188
  ```
188
189
 
189
- Gunakan `$update` agar tombol/select mengubah pesan aslinya (bukan mengirim pesan baru).
190
+ Use `$update` so that buttons/selects edit the original message instead of sending a new one.
190
191
 
191
- ### Event
192
+ ### Events
192
193
 
193
- | Pendek | Dijalankan saat |
194
+ | Short form | Executed when |
194
195
  |---|---|
195
- | `bot.onReady(code)` | bot siap |
196
- | `bot.onMemberJoin(code)` | member masuk server |
197
- | `bot.onMemberLeave(code)` | member keluar |
198
- | `bot.onMessageDelete(code)` | pesan dihapus |
199
- | `bot.onMessageUpdate(code)` | pesan diedit |
200
- | `bot.onReactionAdd(code)` / `onReactionRemove` | reaksi ditambah / dihapus |
201
- | `bot.onGuildJoin(code)` / `onGuildLeave` | bot masuk / keluar server |
202
- | `bot.onMessage(code)` | setiap pesan yang **bukan** command |
203
- | `bot.onMemberBan(code)` / `onMemberUnban` | user di-ban / ban dicabut (`$targetID`, `$targetName`) |
204
- | `bot.onChannelCreate(code)` / `onChannelDelete` | channel dibuat / dihapus (`$targetName`) |
205
- | `bot.onRoleCreate(code)` / `onRoleDelete` | role dibuat / dihapus (`$targetName`) |
206
- | `bot.onThreadCreate(code)` | thread baru (jawaban dikirim ke thread itu) |
207
- | `bot.onVoiceJoin(code)` / `onVoiceLeave` | member masuk / keluar voice (`$targetName` = nama voice). Pindah channel memicu keduanya |
208
-
209
- Secara bawaan jawaban dikirim ke channel sistem server. Pilih channel lain dengan bentuk objek:
196
+ | `bot.onReady(code)` | bot is ready |
197
+ | `bot.onMemberJoin(code)` | member joins the server |
198
+ | `bot.onMemberLeave(code)` | member leaves |
199
+ | `bot.onMessageDelete(code)` | message is deleted |
200
+ | `bot.onMessageUpdate(code)` | message is edited |
201
+ | `bot.onReactionAdd(code)` / `onReactionRemove` | reaction is added / removed |
202
+ | `bot.onGuildJoin(code)` / `onGuildLeave` | bot joins / leaves a server |
203
+ | `bot.onMessage(code)` | every message that is **not** a command |
204
+ | `bot.onMemberBan(code)` / `onMemberUnban` | user is banned / ban lifted (`$targetID`, `$targetName`) |
205
+ | `bot.onChannelCreate(code)` / `onChannelDelete` | channel is created / deleted (`$targetName`) |
206
+ | `bot.onRoleCreate(code)` / `onRoleDelete` | role is created / deleted (`$targetName`) |
207
+ | `bot.onThreadCreate(code)` | new thread (reply is sent to that thread) |
208
+ | `bot.onVoiceJoin(code)` / `onVoiceLeave` | member joins / leaves voice (`$targetName` = voice name). Changing channels triggers both |
209
+
210
+ By default, replies are sent to the system channel of the server. Choose another channel using an object format:
210
211
 
211
212
  ```js
212
- bot.onMemberJoin({ channel: 'ID_CHANNEL', code: 'Selamat datang $mention! Kita sekarang $memberCount orang.' });
213
+ bot.onMemberJoin({ channel: 'CHANNEL_ID', code: 'Welcome $mention! We are now $memberCount people.' });
213
214
  ```
214
215
 
215
- ## 6. Opsi Bot
216
+ ## 6. Bot Options
216
217
 
217
218
  ```js
218
219
  new Bot({
219
- token: 'WAJIB',
220
- prefix: '!', // atau ['!', '?']
221
- mentionPrefix: true, // @bot command juga bisa
222
- ignoreBots: true, // abaikan pesan dari bot lain
223
- owners: ['ID_KAMU'], // untuk $onlyOwner dan $isOwner
224
- timezone: 'Asia/Jakarta', // untuk $date
220
+ token: 'REQUIRED',
221
+ prefix: '!', // or ['!', '?']
222
+ mentionPrefix: true, // @bot command works too
223
+ ignoreBots: true, // ignore messages from other bots
224
+ owners: ['YOUR_ID'], // for $onlyOwner and $isOwner
225
+ timezone: 'Asia/Jakarta', // for $date
225
226
  intents: 'default', // 'default' | 'all' | ['Guilds', ...]
226
- status: { text: 'dengan kode', type: 'Playing', status: 'online' },
227
- slashGuild: null, // ID server untuk slash cepat (null = global)
228
- syncSlash: true, // daftarkan slash otomatis
229
- database: { path: './easydc-data.json' }, // atau { memory: true }
230
- messages: { cooldown: '⏳ Tunggu %time%.', error: '❌ Terjadi kesalahan.' },
231
- debug: false, // true = tampilkan penyebab error di chat (hanya saat pengembangan!)
232
- onError: (err, ctx) => {}, // tangani error sendiri
227
+ status: { text: 'with code', type: 'Playing', status: 'online' },
228
+ slashGuild: null, // server ID for fast slash deployment (null = global)
229
+ syncSlash: true, // auto register slash commands
230
+ database: { path: './easydc-data.json' }, // or { memory: true }
231
+ messages: { cooldown: '⏳ Wait %time%.', error: '❌ An error occurred.' },
232
+ debug: false, // true = show error causes in chat (development only!)
233
+ onError: (err, ctx) => {}, // handle errors manually
233
234
  });
234
235
  ```
235
236
 
236
- Intent bawaan: `Guilds, GuildMessages, MessageContent, GuildMembers, GuildMessageReactions, DirectMessages, GuildModeration, GuildVoiceStates`.
237
+ Default intents: `Guilds, GuildMessages, MessageContent, GuildMembers, GuildMessageReactions, DirectMessages, GuildModeration, GuildVoiceStates`.
237
238
 
238
- Opsi tambahan: `eval: false` (nyalakan `$eval` / `$jsEval`, lihat [bagian 11](#11-eval-khusus-owner)).
239
+ Additional option: `eval: false` (turns on `$eval` / `$jsEval`, see [section 11](#11-eval-owner-only)).
239
240
 
240
- ## 7. Variabel & database
241
+ ## 7. Variables & Database
241
242
 
242
- Variabel disimpan permanen di file JSON (`easydc-data.json`). Deklarasikan dulu dengan nilai awal:
243
+ Variables are permanently stored in a JSON file (`easydc-data.json`). Declare them first with default values:
243
244
 
244
245
  ```js
245
- bot.variables({ uang: 0, bio: 'Belum diisi' });
246
+ bot.variables({ money: 0, bio: 'Not filled yet' });
246
247
  ```
247
248
 
248
- | Fungsi | Cakupan |
249
+ | Function | Scope |
249
250
  |---|---|
250
- | `$getUserVar[nama;userID?]` `$setUserVar[nama;nilai;userID?]` `$resetUserVar` | per user |
251
+ | `$getUserVar[name;userID?]` `$setUserVar[name;value;userID?]` `$resetUserVar` | per user |
251
252
  | `$getServerVar` `$setServerVar` `$resetServerVar` | per server |
252
253
  | `$getChannelVar` `$setChannelVar` `$resetChannelVar` | per channel |
253
- | `$getGlobalVar` `$setGlobalVar` `$resetGlobalVar` | satu untuk semua |
254
+ | `$getGlobalVar` `$setGlobalVar` `$resetGlobalVar` | one for everyone |
254
255
 
255
- Semua nilai tersimpan sebagai **teks**. Gunakan `$math[...]` untuk berhitung.
256
- Variabel sementara selama satu command: `$let[nama;nilai]` dan `$get[nama]`.
256
+ All values are stored as **strings**. Use `$math[...]` for calculations.
257
+ Temporary variables during a single command execution: `$let[name;value]` and `$get[name]`.
257
258
 
258
- - Berkas database ditulis secara aman dan otomatis. Jika file rusak, ia **dicadangkan** (`*.corrupt-<waktu>`) dan bot mulai dari kosong, bukan crash.
259
- - Untuk bot besar (ribuan user aktif) pertimbangkan database sungguhan; `Database` bawaan cocok untuk bot kecil sampai menengah.
260
- - **Satu file database hanya boleh dipakai satu proses bot.**
259
+ - To use MongoDB, see [section 12](#12-database--plugins-mongodb).
260
+ - The database file is written safely and automatically. If the file is corrupted, it is **backed up** (`*.corrupt-<timestamp>`) and the bot starts fresh instead of crashing.
261
+ - For large bots (thousands of active users), consider using a real database; the built-in `Database` is suitable for small to medium bots.
262
+ - **A single database file must only be used by one bot process.**
261
263
 
262
- ## 8. Kondisi `$if`
264
+ ## 8. The `$if` Condition
263
265
 
264
266
  ```
265
- $if[kondisi]
267
+ $if[condition]
266
268
  ...
267
- $elseif[kondisi]
269
+ $elseif[condition]
268
270
  ...
269
271
  $else
270
272
  ...
271
273
  $endif
272
274
  ```
273
275
 
274
- Operator: `== != > < >= <=`, digabung dengan `&&` (dan) / `||` (atau). Tanpa tanda kurung.
275
- Jika kedua sisi angka, dibandingkan sebagai angka (`10>9` benar); selain itu sebagai teks.
276
+ Operators: `== != > < >= <=`, combined with `&&` (and) / `||` (or). No parentheses required.
277
+ If both sides are numbers, they are compared numerically (`10>9` is true); otherwise, they are compared as text.
276
278
 
277
279
  ```
278
- $if[$getUserVar[uang]>=100&&$isAdmin==true]
279
- Kaya dan admin
280
- $elseif[$getUserVar[uang]>=100]
281
- Kaya
280
+ $if[$getUserVar[money]>=100&&$isAdmin==true]
281
+ Rich and admin
282
+ $elseif[$getUserVar[money]>=100]
283
+ Rich
282
284
  $else
283
- Miskin
285
+ Poor
284
286
  $endif
285
287
  ```
286
288
 
287
- **Aman dari injeksi:** nilai dinamis seperti `$message` tidak bisa dipakai pengguna untuk menyisipkan operator `&&`, `||`, dan sejenisnya ke dalam kondisi. Isi pesan pengguna selalu diperlakukan sebagai teks biasa.
289
+ **Injection safe:** dynamic values like `$message` cannot be used by users to inject operators like `&&`, `||`, and similar into the condition. The user content is always treated as a plain text string.
288
290
 
289
- Pembatas lain: `$onlyIf[kondisi;pesan?]`, `$stop[pesan?]`, `$onlyPerms`, `$onlyAdmin`, `$onlyOwner`, `$onlyForIDs`, `$onlyInServer`, `$argsCheck`, `$cooldown`.
291
+ Other constraints: `$onlyIf[condition;message?]`, `$stop[message?]`, `$onlyPerms`, `$onlyAdmin`, `$onlyOwner`, `$onlyForIDs`, `$onlyInServer`, `$argsCheck`, `$cooldown`.
290
292
 
291
- ## 9. Embed, tombol, select menu
293
+ ## 9. Embeds, Buttons, Select Menus
292
294
 
293
295
  ```js
294
296
  bot.command({
295
297
  name: 'info',
296
298
  code: `
297
299
  $title[Info $serverName]
298
- $description[Server ini punya $memberCount member.]
300
+ $description[This server has $memberCount members.]
299
301
  $color[#5865F2]
300
302
  $thumbnail[$serverIcon]
301
- $addField[Dibuat;$discordTime[$serverCreatedAt;D];true]
303
+ $addField[Created;$discordTime[$serverCreatedAt;D];true]
302
304
  $addField[Ping;$ping ms;true]
303
- $footer[Diminta oleh $username]
305
+ $footer[Requested by $username]
304
306
  $addTimestamp
305
307
  `,
306
308
  });
307
309
  ```
308
310
 
309
- - Embed pertama dibuat otomatis; `$newEmbed` memulai embed berikutnya (maksimal 10).
310
- - Warna: `#RRGGBB`, nama (`red green blue yellow orange purple pink white black grey blurple`), atau `random`.
311
- - Tombol: maksimal 5 per baris, 5 baris per pesan. Baris baru dibuat otomatis, atau paksa dengan `$newRow`.
312
- - Panjang teks dicek sesuai batas Discord, dengan pesan error yang jelas jika terlampaui.
311
+ - The first embed is created automatically; `$newEmbed` starts the next embed (maximum 10).
312
+ - Colors: `#RRGGBB`, names (`red green blue yellow orange purple pink white black grey blurple`), or `random`.
313
+ - Buttons: maximum 5 per row, 5 rows per message. New rows are made automatically, or can be forced using `$newRow`.
314
+ - Text length is validated against Discord limits, providing clear error messages if exceeded.
313
315
 
314
- ## 10. Fitur lanjutan
316
+ ## 10. Advanced Features
315
317
 
316
- ### Modal (form pop-up)
318
+ ### Modals (Pop-up Forms)
317
319
 
318
- Modal harus menjadi respons **pertama** dari slash command, tombol, atau select menu (jangan pakai `$defer` sebelumnya; teks lain di command itu diabaikan).
320
+ Modals must be the **first** response to a slash command, button, or select menu interaction (do not use `$defer` beforehand; other texts in that command will be ignored).
319
321
 
320
322
  ```js
321
323
  bot.slashCommand({
322
- name: 'lapor',
323
- description: 'Kirim laporan',
324
+ name: 'report',
325
+ description: 'Send a report',
324
326
  code: `
325
- $addModal[lapor_form;Form Laporan]
326
- $addTextInput[judul;Judul;short;Ringkas saja;true;3;50]
327
- $addTextInput[isi;Isi laporan;paragraph]
327
+ $addModal[report_form;Report Form]
328
+ $addTextInput[title;Title;short;Keep it brief;true;3;50]
329
+ $addTextInput[content;Report content;paragraph]
328
330
  `,
329
331
  });
330
332
 
331
333
  bot.modal({
332
- customId: 'lapor_form', // boleh wildcard: 'lapor_*'
333
- code: '$ephemeral Terima kasih! Judul: $modalValue[judul] | Isi: $modalValue[isi]',
334
+ customId: 'report_form', // card wildcards allowed: 'report_*'
335
+ code: '$ephemeral Thank you! Title: $modalValue[title] | Content: $modalValue[content]',
334
336
  });
335
337
  ```
336
338
 
337
- Maksimal 5 kolom per modal. `$addTextInput[customID;label;gaya?;placeholder?;wajib?;min?;max?;nilaiAwal?]`, gaya `short` atau `paragraph`.
339
+ Maximum 5 inputs per modal. `$addTextInput[customID;label;style?;placeholder?;required?;min?;max?;initialValue?]`, styles are `short` or `paragraph`.
338
340
 
339
- ### Autocomplete (pilihan dinamis di slash command)
341
+ ### Autocomplete (Dynamic Choices in Slash Commands)
340
342
 
341
343
  ```js
342
344
  bot.slashCommand({
343
- name: 'buah',
344
- description: 'Pilih buah',
345
- options: [{ name: 'nama', description: 'Nama buah', autocomplete: true }], // tidak bisa bersama "choices"
346
- code: 'Kamu memilih $option[nama]',
345
+ name: 'fruit',
346
+ description: 'Select a fruit',
347
+ options: [{ name: 'name', description: 'Fruit name', autocomplete: true }], // cannot be used together with "choices"
348
+ code: 'You selected $option[name]',
347
349
  });
348
350
 
349
351
  bot.autocomplete({
350
- command: 'buah',
351
- option: 'nama', // kosongkan untuk semua opsi autocomplete di command itu
352
+ command: 'fruit',
353
+ option: 'name', // leave empty for all autocomplete options in that command
352
354
  code: `
353
- $if[$checkContains[apel;$toLowerCase[$focusedValue]]==true]$addChoice[Apel;apel]$endif
354
- $addChoice[Jeruk;jeruk]
355
- $addChoice[Mangga;mangga]
355
+ $if[$checkContains[apple;$toLowerCase[$focusedValue]]==true]$addChoice[Apple;apple]$endif
356
+ $addChoice[Orange;orange]
357
+ $addChoice[Mango;mangga]
356
358
  `,
357
359
  });
358
360
  ```
359
361
 
360
- `$focusedValue` = teks yang sedang diketik. `$addChoice[nama;nilai?]` maksimal 25. Untuk opsi `integer`/`number`, nilai pilihan harus angka. Discord memberi waktu 3 detik, jadi jangan pakai `$wait`.
362
+ `$focusedValue` = the text currently typed by the user. `$addChoice[name;value?]` max 25 choices. For `integer`/`number` options, the choice value must be a number. Discord gives 3 seconds to respond, so do not use `$wait`.
361
363
 
362
- ### Menu klik-kanan (context menu)
364
+ ### Right-Click Menus (Context Menus)
363
365
 
364
366
  ```js
365
- bot.contextMenu({ name: 'Lihat Profil', menu: 'user', code: '$ephemeral Profil: $targetName (ID $targetID)' });
366
- bot.contextMenu({ name: 'Laporkan', menu: 'message', code: '$ephemeral Pesan "$targetContent" dari $targetName dilaporkan.' });
367
+ bot.contextMenu({ name: 'View Profile', menu: 'user', code: '$ephemeral Profile: $targetName (ID $targetID)' });
368
+ bot.contextMenu({ name: 'Report Message', menu: 'message', code: '$ephemeral Message "$targetContent" from $targetName reported.' });
367
369
  ```
368
370
 
369
- Muncul di menu *Apps* ketika pengguna klik kanan user atau pesan. Didaftarkan otomatis bersama slash command.
371
+ Appears under the *Apps* menu when a user right-clicks a user or a message. Automatically registered alongside slash commands.
370
372
 
371
- ### Select menu user / role / channel
373
+ ### User / Role / Channel Select Menus
372
374
 
373
375
  ```
374
- $addUserSelect[pilih_user;Pilih user;1;3]
375
- $addRoleSelect[pilih_role]
376
- $addMentionableSelect[pilih_apa_saja]
377
- $addChannelSelect[pilih_channel;Pilih channel;;;text,voice]
376
+ $addUserSelect[select_user;Select user;1;3]
377
+ $addRoleSelect[select_role]
378
+ $addMentionableSelect[select_anything]
379
+ $addChannelSelect[select_channel;Select channel;;;text,voice]
378
380
  ```
379
381
 
380
- Daftarkan handler dengan `bot.select({ customId: 'pilih_user', code: 'Dipilih: $interactionValues' })`. Nilainya berupa ID, dipisah koma.
382
+ Register handlers via `bot.select({ customId: 'select_user', code: 'Selected: $interactionValues' })`. Values are comma-separated IDs.
381
383
 
382
- ### Lampiran, polling, webhook
384
+ ### Attachments, Polls, Webhooks
383
385
 
384
386
  ```
385
- $addAttachment[https://example.com/gambar.png;gambar.png]
386
- $addTextFile[catatan.txt;isi file teks buatan sendiri]
387
- $poll[Makan apa?;24;false;Nasi;Mie;Roti]
388
- $sendWebhook[https://discord.com/api/webhooks/ID/TOKEN;Halo!;Nama Bot;https://example.com/avatar.png]
387
+ $addAttachment[https://example.com/image.png;image.png]
388
+ $addTextFile[notes.txt;custom text file content created on the fly]
389
+ $poll[What to eat?;24;false;Chips;Noodles;Bread]
390
+ $sendWebhook[https://discord.com/api/webhooks/ID/TOKEN;Hello!;Bot Name;https://example.com/avatar.png]
389
391
  ```
390
392
 
391
- Lampiran hanya dari URL `http(s)` atau teks buatan sendiri (bot tidak membaca file dari disk). `$poll[pertanyaan;jam;multi;opsi...]` butuh 2-10 opsi.
393
+ Attachments only accept `http(s)` URLs or custom on-the-fly text strings (the bot does not read files from disk). `$poll[question;hours;multi;options...]` requires 2-10 options.
392
394
 
393
- ### Thread, forum, dan manajemen server
395
+ ### Threads, Forums, and Guild Management
394
396
 
395
397
  ```
396
- $createThread[Diskusi;$messageID;1440] -> mengembalikan ID thread
397
- $createForumPost[ID_FORUM;Judul;Isi]
398
- $unban[ID;alasan] $isBanned[ID] $banCount
399
- $createChannel[info;text;ID_KATEGORI;Topik] $lockChannel $unlockChannel
398
+ $createThread[Discussion;$messageID;1440] -> returns thread ID
399
+ $createForumPost[FORUM_ID;Title;Content]
400
+ $unban[ID;reason] $isBanned[ID] $banCount
401
+ $createChannel[info;text;CATEGORY_ID;Topic] $lockChannel $unlockChannel
400
402
  $createRole[VIP;#ff0000;true] $createInvite[;3600;10]
401
- $createEvent[Nobar;MULAI_MS;SELESAI_MS;Voice 1;Deskripsi]
403
+ $createEvent[WatchParty;START_MS;END_MS;Voice 1;Description]
402
404
  ```
403
405
 
404
- Fungsi manajemen memakai **izin bot**, jadi lindungi dengan `$onlyPerms[...]` seperti di bagian [Keamanan](#14-keamanan). Daftar lengkapnya ada di bagian [Daftar semua fungsi](#16-daftar-semua-fungsi).
406
+ Management functions use **bot permissions**, so make sure to protect them with `$onlyPerms[...]` as explained in the [Security](#15-security) section. The full list is located in the [List of All Functions](#17-list-of-all-functions) section.
405
407
 
406
408
  ---
407
409
 
408
- ## 11. Eval (khusus owner)
410
+ ## 11. Eval (Owner Only)
409
411
 
410
- Eval menjalankan kode yang diketik saat bot berjalan, berguna untuk debugging. Ada dua jenis:
412
+ Eval executes code inputted dynamically while the bot is running, which is useful for debugging. There are two types:
411
413
 
412
- | Fungsi | Bahasa kode yang dijalankan |
414
+ | Function | Code Language Executed |
413
415
  |---|---|
414
- | `$eval[kode]` | kode versi port, yaitu sintaks `$fungsi` package ini |
415
- | `$jsEval[kode]` | JavaScript / **discord.js asli** |
416
+ | `$eval[code]` | Wrapper-version code, which uses this package's `$function` syntax |
417
+ | `$jsEval[code]` | JavaScript / **native discord.js** |
416
418
 
417
- Di `$jsEval` tersedia variabel: `ctx` `client` `bot` `guild` `channel` `message` `user` `member` `interaction` `discord` (modul discord.js) `db` `require`. Ekspresi tunggal langsung dikembalikan hasilnya; untuk beberapa pernyataan, tulis `return`. Boleh memakai `await`.
419
+ In `$jsEval`, the following variables are available: `ctx` `client` `bot` `guild` `channel` `message` `user` `member` `interaction` `discord` (discord.js module) `db` `require`. A single expression is directly returned; for multiple statements, use `return`. Supports `await`.
418
420
 
419
- ### Cara pakai paling mudah
421
+ ### Easiest Way to Use
420
422
 
421
423
  ```js
422
424
  const bot = new Bot({
423
425
  token: process.env.TOKEN,
424
- owners: ['ID_DISCORD_KAMU'],
425
- eval: true, // eval MATI kecuali dinyalakan di sini
426
+ owners: ['YOUR_DISCORD_ID'],
427
+ eval: true, // eval is DISABLED unless turned on here
426
428
  });
427
429
 
428
- bot.evalCommand(); // memasang command "eval" (nama bisa diganti: { name: 'e', aliases: ['ev'] })
430
+ bot.evalCommand(); // mounts the "eval" command (name can be changed: { name: 'e', aliases: ['ev'] })
429
431
  ```
430
432
 
431
- Lalu di Discord:
433
+ Then in Discord:
432
434
 
433
435
  ```
434
- !eval $math[6*7] -> kode versi port
435
- !eval Halo $username dari $serverName
436
- !eval js client.guilds.cache.size -> discord.js asli
436
+ !eval $math[6*7] -> wrapper syntax version
437
+ !eval Hello $username from $serverName
438
+ !eval js client.guilds.cache.size -> native discord.js
437
439
  !eval js guild.members.cache.filter(m => m.user.bot).size
438
440
  !eval js const g = await client.guilds.fetch(guild.id);
439
441
  return g.memberCount;
440
442
  ```
441
443
 
442
- Hasil dikirim dalam blok kode (maksimal ±1800 karakter), error ditampilkan sebagai `❌ ...`, dan **token otomatis disensor** dari hasil.
444
+ Results are sent inside a code block (max ±1800 characters), errors are displayed as `❌ ...`, and **tokens are automatically censored** from the output.
443
445
 
444
- Bisa juga dipakai di command buatan sendiri: `$eval[$message]` dan `$jsEval[$message]`. Gunakan `$messageFrom[2]` untuk mengambil semua teks mulai kata ke-2 (spasi dan baris baru terjaga).
446
+ Can also be used in custom commands: `$eval[$message]` and `$jsEval[$message]`. Use `$messageFrom[2]` to get all text starting from the 2nd word (preserving spaces and newlines).
445
447
 
446
- ### ⚠️ Peringatan keamanan
448
+ ### ⚠️ Security Warnings
447
449
 
448
- - **`$jsEval` memberi akses PENUH** ke bot dan mesin tempat bot berjalan: membaca file, variabel lingkungan, mengirim data keluar, bahkan mematikan proses. Eval hanya berjalan bila `eval: true` **dan** pengirim ada di `owners`; selain itu langsung ditolak.
449
- - Isi `owners` hanya dengan ID **Anda sendiri**. Jangan beri akses kepada orang lain, termasuk "admin kepercayaan".
450
- - Jika akun Discord owner dibajak, penyerang bisa mengambil alih server hosting. Aktifkan 2FA.
451
- - Matikan `eval` (hapus `eval: true`) di bot produksi yang tidak membutuhkannya.
452
- - Sensor token hanya pencegah kecelakaan, bukan pengaman: kode JS tetap bisa membaca token dan mengirimnya ke tempat lain.
453
- - `$eval` bersarang dibatasi 3 tingkat. Perulangan tak berujung (`while(true){}`) di `$jsEval` tidak bisa dihentikan, dan akan membekukan bot sampai di-restart.
450
+ - **`$jsEval` grants FULL access** to the bot and the machine it runs on: reading files, environment variables, sending data out, and even terminating the process. Eval only runs if `eval: true` **and** the sender is listed in `owners`; otherwise, it is rejected immediately.
451
+ - Only include **YOUR OWN** ID in `owners`. Do not grant access to anyone else, including "trusted admins".
452
+ - If the owner's Discord account is compromised, the attacker can take over your hosting server. Enable 2FA.
453
+ - Disable `eval` (remove `eval: true`) in production bots that do not need it.
454
+ - Token censoring is just an accidental leaks prevention tool, not a foolproof security measure: JS code can still read tokens and send them elsewhere.
455
+ - Nested `$eval` calls are limited to 3 levels. Infinite loops (`while(true){}`) in `$jsEval` cannot be stopped and will freeze the bot until it is restarted.
454
456
 
455
457
  ---
456
458
 
457
- ## 12. Membuat fungsi sendiri
459
+ ## 12. Database & Plugins (MongoDB)
460
+
461
+ By default, variable data is saved in the `easydc-data.json` file. For production bots (where data shouldn't be lost when a hosting provider deletes files, or when running across multiple servers), use **MongoDB** via a plugin.
462
+
463
+ ### Install the MongoDB Plugin
464
+
465
+ ```bash
466
+ npm install easydc-js discord.js mongodb
467
+ ```
468
+
469
+ ```js
470
+ const { Bot } = require('easydc-js');
471
+ const { mongodb } = require('easydc-js/mongodb');
472
+
473
+ const bot = new Bot({ token: process.env.TOKEN, prefix: '!' });
474
+
475
+ bot.use(mongodb({
476
+ uri: process.env.MONGO_URI, // e.g., mongodb+srv://user:pass@cluster0.xxxx.mongodb.net
477
+ dbName: 'mybot', // database name (automatically created by MongoDB)
478
+ }));
479
+
480
+ bot.variables({ money: 100 });
481
+ bot.command({ name: 'work', code: '$incUserVar[money;25]Your money is now $getUserVar[money]' });
482
+
483
+ bot.connect();
484
+ ```
485
+
486
+ That's the only change required: all `$getUserVar`, `$setUserVar`, etc., will automatically use MongoDB. `bot.use(...)` must be called **before** `bot.connect()`.
487
+
488
+ How to get free MongoDB: create a cluster on MongoDB Atlas (M0 tier), create a database user, whitelist your hosting IP in *Network Access*, and copy the *connection string*. Store it in the `MONGO_URI` environment variable, **do not write it in the code**.
489
+
490
+ ### Plugin Options
491
+
492
+ | Option | Description |
493
+ |---|---|
494
+ | `uri` | MongoDB URI string (required). |
495
+ | `dbName` | Database name. If empty, uses the database name from the URI, or `test`. |
496
+ | `collection` | Collection name, defaults to `easydc`. Each variable = one document `{ _id, v, t }`. |
497
+ | `cache` | Defaults to `true`: read data is cached in RAM for speed. **Change to `false` if multiple bot processes share the database**, otherwise data can become stale. |
498
+ | `cacheLimit` | Maximum keys in cache (defaults to 10000). |
499
+ | `client` | Custom `MongoClient` instance (will not be automatically closed by the bot). |
500
+ | `clientOptions` | Additional options passed to `new MongoClient(uri, options)`. |
501
+
502
+ If MongoDB cannot be reached, the bot **will not log in** and prints `Failed to connect to database: ...` (timeout is 10 seconds).
503
+
504
+ ### Migrating Old Data (JSON → MongoDB)
505
+
506
+ A one-time script, run it in the bot's root folder before using the plugin:
507
+
508
+ ```js
509
+ const { Database, copyDatabase } = require('easydc-js');
510
+ const { MongoDatabase } = require('easydc-js/mongodb');
511
+
512
+ (async () => {
513
+ const oldDb = new Database({ path: './easydc-data.json' });
514
+ const newDb = new MongoDatabase({ uri: process.env.MONGO_URI, dbName: 'mybot' });
515
+ await newDb.connect();
516
+ console.log(await copyDatabase(oldDb, newDb)); // { copied: 120, skipped: 0 }
517
+ await newDb.close();
518
+ })();
519
+ ```
520
+
521
+ Existing data in MongoDB will not be overwritten. Pass `{ overwrite: true }` as the third argument if you wish to overwrite it.
522
+
523
+ ### `$inc...Var`: Safely Incrementing Numbers
524
+
525
+ The `$setUserVar[money;$math[$getUserVar[money]+10]]` pattern can **lose data** if two commands execute concurrently (both reading the old value). Instead, use:
526
+
527
+ ```
528
+ $incUserVar[money;10] $incUserVar[money;-5] (decrease)
529
+ $incServerVar $incChannelVar $incGlobalVar
530
+ ```
531
+
532
+ `$incUserVar[name;amount;userID?]` executes sequentially per variable, ensuring they do not overwrite each other. This safety applies within a **single bot process**; if you run multiple bot instances on the same database, cross-process collisions can still occur.
533
+
534
+ ### Creating a Custom Plugin / Database Adapter
535
+
536
+ A plugin is either a function or an object `{ name, install(bot, options) }`; `install` must be synchronous.
537
+
538
+ ```js
539
+ bot.use({
540
+ name: 'hello',
541
+ install(bot) {
542
+ bot.addFunction({ name: '$hello', params: 0, run: () => 'Hello from plugin!' });
543
+ },
544
+ });
545
+ ```
546
+
547
+ A database adapter (for Redis, SQLite, etc.) just needs to be an object with the following methods; all of them can be `async`:
548
+
549
+ | Method | Required | Description |
550
+ |---|---|---|
551
+ | `get(key)` | yes | Return the value (string) or `undefined` if missing. |
552
+ | `set(key, value)` | yes | Store a string value. |
553
+ | `delete(key)` | yes | Delete a key. |
554
+ | `keys(prefix?)` | no | Needed for `copyDatabase`. |
555
+ | `connect()` / `close()` | no | Called before logging into Discord / when the bot shuts down. |
556
+ | `flush()` | no | Save pending data. |
557
+
558
+ Install using `bot.setDatabase(adapter)` or `new Bot({ database: adapter })`.
559
+
560
+ > **Changes from version 1.1:** `bot.getVar`, `bot.setVar`, `bot.resetVar` now return a **Promise** (use `await`). `$function` styled commands are unaffected.
561
+
562
+ ---
563
+
564
+ ## 13. Creating Custom Functions
458
565
 
459
566
  ```js
460
567
  bot.addFunction({
461
- name: '$salam',
462
- params: 1, // jumlah argumen tepat (atau pakai min/max)
463
- description: 'Menyapa seseorang',
464
- run: (ctx, [nama]) => `Selamat datang, ${nama}! (diminta oleh ${ctx.user.username})`,
568
+ name: '$greetUser',
569
+ params: 1, // exact number of arguments (or use min/max)
570
+ description: 'Greets someone',
571
+ run: (ctx, [name]) => `Welcome, ${name}! (requested by ${ctx.user.username})`,
465
572
  });
466
573
 
467
- bot.command({ name: 'tes', code: '$salam[Budi]' });
574
+ bot.command({ name: 'test', code: '$greetUser[Budi]' });
468
575
  ```
469
576
 
470
- `run` boleh `async`. `ctx` berisi `bot`, `client`, `guild`, `channel`, `member`, `user`, `message`, `interaction`, `args`. Lempar `new Error('pesan')` bila gagal; pesan itu akan dicatat di log.
471
- Opsi `override: true` mengganti fungsi bawaan.
577
+ `run` can be `async`. `ctx` contains `bot`, `client`, `guild`, `channel`, `member`, `user`, `message`, `interaction`, `args`. Throw `new Error('message')` on failure; the message will be printed to logs.
578
+ The option `override: true` overwrites built-in functions.
472
579
 
473
- ## 13. Memisah command ke banyak file
580
+ ## 14. Splitting Commands into Multiple Files
474
581
 
475
582
  ```
476
- proyek/
583
+ project/
477
584
  ├── index.js
478
585
  └── commands/
479
- ├── umum.js
480
- └── moderasi.js
586
+ ├── general.js
587
+ └── moderation.js
481
588
  ```
482
589
 
483
590
  ```js
484
591
  bot.loadCommands('./commands');
485
592
  ```
486
593
 
487
- Setiap file mengekspor satu objek atau array. Tambahkan `type` untuk selain command biasa (`'slash'`, `'button'`, `'select'`, `'modal'`, `'autocomplete'`, `'contextMenu'`, atau nama event seperti `'memberJoin'`). Contoh lengkap: [`examples/advanced/lanjutan.js`](examples/advanced/lanjutan.js).
594
+ Each file exports a single object or an array. Add a `type` for anything other than regular prefix commands (`'slash'`, `'button'`, `'select'`, `'modal'`, `'autocomplete'`, `'contextMenu'`, or an event name like `'memberJoin'`). Complete example: [`examples/advanced/lanjutan.js`](examples/advanced/lanjutan.js).
488
595
 
489
596
  ```js
490
597
  module.exports = [
491
- { name: 'halo', code: 'Halo $username' },
492
- { type: 'slash', name: 'ping', description: 'Cek ping', code: '$ping ms' },
493
- { type: 'button', customId: 'ok_*', code: 'Oke!' },
494
- { type: 'memberJoin', code: 'Selamat datang $mention' },
598
+ { name: 'hello', code: 'Hello $username' },
599
+ { type: 'slash', name: 'ping', description: 'Check ping', code: '$ping ms' },
600
+ { type: 'button', customId: 'ok_*', code: 'Ok!' },
601
+ { type: 'memberJoin', code: 'Welcome $mention' },
495
602
  ];
496
603
  ```
497
604
 
498
- ## 14. Keamanan
605
+ ## 15. Security
499
606
 
500
- - **Jangan taruh token di kode** atau di GitHub. Pakai variabel lingkungan. Jika token bocor, segera *Reset Token* di Developer Portal.
501
- - Fungsi aksi dan manajemen (`$ban`, `$unban`, `$kick`, `$timeout`, `$addRole`, `$clear`, `$sendDM`, `$createChannel`, `$deleteChannel`, `$deleteRole`, `$lockChannel`, `$leaveServer`, ...) memakai **izin bot**, bukan izin pengirim. **Selalu** lindungi dengan `$onlyPerms[...]`, `$onlyAdmin`, atau `$onlyOwner` di baris pertama command.
502
- - Mention yang dikirim bot dibatasi ke user saja (`@everyone` dan role tidak akan menyebut siapa pun). Ubah lewat opsi `allowedMentions` bila perlu.
503
- - Kalkulator `$math` tidak memakai `eval`, jadi aman dari eksekusi kode.
504
- - Biarkan `debug: false` di produksi supaya detail error tidak tampil ke pengguna (tetap tercatat di konsol).
607
+ - **Never put tokens in your code** or push them to GitHub. Use environment variables. If a token leaks, immediately *Reset Token* in the Developer Portal.
608
+ - Action and management functions (`$ban`, `$unban`, `$kick`, `$timeout`, `$addRole`, `$clear`, `$sendDM`, `$createChannel`, `$deleteChannel`, `$deleteRole`, `$lockChannel`, `$leaveServer`, ...) run using **bot permissions**, not the sender's permissions. **Always** protect them with `$onlyPerms[...]`, `$onlyAdmin`, or `$onlyOwner` on the first line of the command.
609
+ - Mentions sent by the bot are restricted to users only (`@everyone` and roles will not ping anyone). Modify this via the `allowedMentions` option if necessary.
610
+ - The `$math` calculator does not use `eval`, making it safe from arbitrary code execution.
611
+ - Leave `debug: false` in production so that detailed error messages are not revealed to users (they will still be logged to the console).
505
612
 
506
- ## 15. Pemecahan masalah
613
+ ## 16. Troubleshooting
507
614
 
508
- | Masalah | Penyebab / solusi |
615
+ | Issue | Cause / Solution |
509
616
  |---|---|
510
- | Bot online tapi tidak merespons `!ping` | Aktifkan **Message Content Intent** di Developer Portal. |
511
- | `Used disallowed intents` saat login | Aktifkan intent yang diminta di Developer Portal (Server Members / Message Content), atau kurangi `intents`. |
512
- | Event member masuk/keluar tidak jalan | Aktifkan **Server Members Intent**. |
513
- | Slash command tidak muncul | Undang bot dengan scope `applications.commands`. Pakai `slashGuild` agar langsung muncul; global bisa butuh waktu. |
514
- | `Fungsi $xxx tidak dikenal` | Salah ketik. Jika maksudnya teks biasa, tulis `\$xxx` (atau `$dollar`). |
515
- | `... membutuhkan N argumen` | Jumlah `;` tidak sesuai. Tulis `\;` bila `;` bagian dari teks. |
516
- | Variabel "belum dideklarasikan" | Tambahkan di `bot.variables({ ... })` sebelum `bot.connect()`. |
517
- | Tombol/select tidak merespons | Pastikan `customId` di tombol sama dengan di `bot.button({ customId })`. |
518
- | `Missing Permissions` di log | Bot kurang izin / posisi role bot di bawah role target. |
519
- | `Token belum diisi` | `process.env.TOKEN` kosong. Cek cara menjalankan di bagian 2. |
520
- | Interaksi gagal ("This interaction failed") | Proses > 3 detik. Taruh `$defer` di awal. |
521
- | Modal tidak muncul / "Modal harus jadi respons pertama" | Jangan pakai `$defer` atau kirim pesan sebelum `$addModal`. Modal hanya dari slash/tombol/select, bukan command prefix. |
522
- | Autocomplete kosong | Opsi harus dibuat dengan `autocomplete: true`, dan handler `bot.autocomplete({ command, option })` cocok. Proses harus selesai < 3 detik. |
523
- | `$eval ... dimatikan` | Tambahkan `eval: true` dan `owners: ['ID_KAMU']` pada `new Bot({...})`. |
524
- | Event ban / voice tidak jalan | Intent `GuildModeration` / `GuildVoiceStates` sudah aktif secara bawaan; jika kamu mengatur `intents` sendiri, tambahkan keduanya. |
617
+ | Bot is online but does not respond to `!ping` | Enable **Message Content Intent** in the Developer Portal. |
618
+ | `Used disallowed intents` when logging in | Enable requested intents in the Developer Portal (Server Members / Message Content), or reduce your `intents`. |
619
+ | Member join/leave events are not working | Enable **Server Members Intent**. |
620
+ | Slash commands do not appear | Invite the bot with the `applications.commands` scope. Use `slashGuild` for immediate updates; global commands can take time. |
621
+ | `Unknown function $xxx` | Misspelling. If intended as plain text, write `\$xxx` (or `$dollar`). |
622
+ | `... requires N arguments` | Semicolon `;` count mismatch. Write `\;` if the semicolon is part of the text. |
623
+ | Variable "not declared" | Add it inside `bot.variables({ ... })` before calling `bot.connect()`. |
624
+ | Buttons/select menus do not respond | Ensure the `customId` on the button matches the one in `bot.button({ customId })`. |
625
+ | `Missing Permissions` in logs | The bot lacks permissions / the bot's highest role is below the target role. |
626
+ | `Token not provided` | `process.env.TOKEN` is empty. Check how to run the bot in section 2. |
627
+ | Interaction failed ("This interaction failed") | Process took > 3 seconds. Place `$defer` at the top of the command. |
628
+ | Modal does not appear / "Modal must be the first response" | Do not use `$defer` or send messages before `$addModal`. Modals are only available from slash/button/select triggers, not prefix commands. |
629
+ | Autocomplete list is empty | Options must be defined with `autocomplete: true`, and the `bot.autocomplete({ command, option })` handler must match. Process must finish in < 3 seconds. |
630
+ | `Package "mongodb" not found` | Run `npm install mongodb` (on panel hosting: add `mongodb` to *Additional Node Packages*). |
631
+ | `Failed to connect to database` | Check `MONGO_URI`, user & password, and whitelist your hosting IP in MongoDB Atlas (*Network Access*). Passwords with special characters (`@ : /`) must be URL-encoded. |
632
+ | Data in MongoDB does not update / looks stale | There is more than one bot process running on the same database: set `cache: false`. |
633
+ | `$eval ... is disabled` | Add `eval: true` and `owners: ['YOUR_ID']` inside `new Bot({...})`. |
634
+ | Ban / voice events are not working | `GuildModeration` / `GuildVoiceStates` intents are enabled by default; if you set `intents` manually, add both. |
525
635
 
526
636
  ---
527
637
 
528
- ## 16. Daftar semua fungsi
638
+ ## 17. List of All Functions
529
639
 
530
- Tanda `?` berarti argumen opsional. Daftar ini dibuat otomatis dari kode (`npm run docs`).
640
+ The `?` symbol means the argument is optional. This list is automatically generated from the source code (`npm run docs`).
531
641
 
532
642
  <!-- FUNCTIONS:START -->
533
643
 
534
- ### Info (user, server, bot, pesan, waktu)
644
+ ### Info (user, server, bot, message, time)
535
645
 
536
- | Fungsi | Keterangan |
646
+ | Function | Description |
537
647
  |---|---|
538
- | `$username[userID?]` | Username (tanpa ID = pengirim) |
539
- | `$usertag[userID?]` | Tag user |
540
- | `$displayName[userID?]` | Nama tampilan (nickname server / nama global / username) |
541
- | `$nickname[userID?]` | Nickname di server (kosong -> username) |
542
- | `$authorID` | ID pengirim pesan / pengguna interaksi |
543
- | `$userAvatar[userID?;ukuran?]` | URL avatar (ukuran 16-4096) |
544
- | `$isBot[userID?]` | true/false: apakah user adalah bot |
545
- | `$userCreatedAt[userID?]` | Waktu akun dibuat (ms) |
546
- | `$mentioned[nomor;fallbackAuthor?]` | ID user yang di-mention ke-N (isi 2: yes = pakai pengirim bila tidak ada) |
547
- | `$mention[userID?]` | Mention user, contoh <@123> |
548
- | `$serverName` | Nama server |
549
- | `$serverID` | ID server |
550
- | `$serverIcon` | URL ikon server |
551
- | `$memberCount` | Jumlah member server |
552
- | `$ownerID` | ID pemilik server |
553
- | `$serverCreatedAt` | Waktu server dibuat (ms) |
554
- | `$roleCount` | Jumlah role |
555
- | `$channelCount` | Jumlah channel |
556
- | `$channelName[channelID?]` | Nama channel (tanpa ID = channel ini) |
557
- | `$channelID` | ID channel saat ini |
558
- | `$channelMention[channelID?]` | Mention channel, contoh <#123> |
559
- | `$roleName[roleID]` | Nama role |
560
- | `$roleMention[roleID]` | Mention role, contoh <@&123> |
561
- | `$botID` | ID bot |
562
- | `$botName` | Username bot |
563
- | `$ping` | Ping websocket (ms) |
564
- | `$uptime` | Lama bot menyala, contoh "1d 2h 3m 4s" |
565
- | `$serverCount` | Jumlah server tempat bot berada |
566
- | `$message[nomor?]` | Semua argumen setelah command, atau argumen ke-N |
567
- | `$argsCount` | Jumlah argumen |
568
- | `$messageID` | ID pesan / interaksi |
569
- | `$messageContent` | Isi lengkap pesan pemicu |
570
- | `$commandName` | Nama command yang berjalan |
571
- | `$option[nama]` | Nilai opsi slash command |
572
- | `$customID` | customId tombol/select yang ditekan |
573
- | `$interactionValues[nomor?]` | Nilai yang dipilih di select menu |
574
- | `$reactionEmoji` | Emoji pada event reaksi |
575
- | `$timestamp` | Waktu sekarang (ms) |
576
- | `$unix` | Waktu sekarang (detik) |
577
- | `$date[format?;ms?]` | Tanggal/jam. Token: YYYY MM DD HH mm ss. Zona waktu dari opsi timezone |
578
- | `$discordTime[ms?;gaya?]` | Format waktu Discord <t:..>. Gaya: t T d D f F R |
579
-
580
- ### Teks, matematika & pengecekan
581
-
582
- | Fungsi | Keterangan |
648
+ | `$username[userID?]` | Username (without ID = sender) |
649
+ | `$usertag[userID?]` | User tag |
650
+ | `$displayName[userID?]` | Display name (server nickname / global name / username) |
651
+ | `$nickname[userID?]` | Nickname in the server (empty -> username) |
652
+ | `$authorID` | ID of the message author / interaction user |
653
+ | `$userAvatar[userID?;size?]` | Avatar URL (size 16-4096) |
654
+ | `$isBot[userID?]` | true/false: whether the user is a bot |
655
+ | `$userCreatedAt[userID?]` | Account creation timestamp (ms) |
656
+ | `$mentioned[number;fallbackAuthor?]` | ID of the N-th mentioned user (if 2nd arg is yes = defaults to sender if absent) |
657
+ | `$mention[userID?]` | Mention a user, e.g., <@123> |
658
+ | `$serverName` | Server name |
659
+ | `$serverID` | Server ID |
660
+ | `$serverIcon` | Server icon URL |
661
+ | `$memberCount` | Number of server members |
662
+ | `$ownerID` | Server owner ID |
663
+ | `$serverCreatedAt` | Server creation timestamp (ms) |
664
+ | `$roleCount` | Number of roles |
665
+ | `$channelCount` | Number of channels |
666
+ | `$channelName[channelID?]` | Channel name (without ID = current channel) |
667
+ | `$channelID` | Current channel ID |
668
+ | `$channelMention[channelID?]` | Mention a channel, e.g., <#123> |
669
+ | `$roleName[roleID]` | Role name |
670
+ | `$roleMention[roleID]` | Mention a role, e.g., <@&123> |
671
+ | `$botID` | Bot ID |
672
+ | `$botName` | Bot username |
673
+ | `$ping` | Websocket ping (ms) |
674
+ | `$uptime` | Duration the bot has been online, e.g., "1d 2h 3m 4s" |
675
+ | `$serverCount` | Number of servers the bot is in |
676
+ | `$message[number?]` | All arguments after the command, or the N-th argument |
677
+ | `$argsCount` | Argument count |
678
+ | `$messageID` | Message / interaction ID |
679
+ | `$messageContent` | Full text content of the triggering message |
680
+ | `$commandName` | Name of the currently running command |
681
+ | `$option[name]` | Value of a slash command option |
682
+ | `$customID` | customId of the pressed button/select menu |
683
+ | `$interactionValues[number?]` | Selected values in a select menu |
684
+ | `$reactionEmoji` | Emoji from a reaction event |
685
+ | `$timestamp` | Current timestamp (ms) |
686
+ | `$unix` | Current timestamp (seconds) |
687
+ | `$date[format?;ms?]` | Date/time string. Tokens: YYYY MM DD HH mm ss. Timezone comes from bot option |
688
+ | `$discordTime[ms?;style?]` | Discord timestamp format <t:..>. Styles: t T d D f F R |
689
+
690
+ ### Text, Math & Validation
691
+
692
+ | Function | Description |
583
693
  |---|---|
584
- | `$math[ekspresi]` | Hitung aman. Dukung + - * / % ^ ( ) sqrt abs round floor ceil min max pow pi e |
585
- | `$sum[a;b;...]` | Jumlah semua angka |
694
+ | `$math[expression]` | Safe evaluation. Supports + - * / % ^ ( ) sqrt abs round floor ceil min max pow pi e |
695
+ | `$sum[a;b;...]` | Sum of all numbers |
586
696
  | `$sub[a;b]` | a - b |
587
- | `$multiply[a;b;...]` | Kali semua angka |
697
+ | `$multiply[a;b;...]` | Multiply all numbers |
588
698
  | `$divide[a;b]` | a / b |
589
- | `$modulo[a;b]` | Sisa bagi a % b |
590
- | `$round[angka;desimal?]` | Bulatkan angka |
591
- | `$max[a;b;...]` | Angka terbesar |
592
- | `$min[a;b;...]` | Angka terkecil |
593
- | `$random[min;max]` | Bilangan bulat acak (inklusif) |
594
- | `$randomText[a;b;...]` | Pilih salah satu teks secara acak |
595
- | `$numberSeparator[angka;pemisah?]` | 1234567 -> 1,234,567 |
596
- | `$toUpperCase[teks]` | HURUF BESAR |
597
- | `$toLowerCase[teks]` | huruf kecil |
598
- | `$capitalize[teks]` | Huruf pertama jadi besar |
599
- | `$titleCase[teks]` | Huruf Pertama Tiap Kata Besar |
600
- | `$trimSpace[teks]` | Hapus spasi di awal/akhir |
601
- | `$length[teks]` | Jumlah karakter |
602
- | `$reverse[teks]` | Balik urutan teks |
603
- | `$repeat[teks;jumlah]` | Ulang teks (maks 100x) |
604
- | `$substring[teks;awal;akhir?]` | Potong teks (indeks mulai 0) |
605
- | `$replaceText[teks;cari;ganti;batas?]` | Ganti teks (semua, atau N pertama) |
606
- | `$split[teks;pemisah;nomor]` | Ambil bagian ke-N setelah memecah teks |
607
- | `$urlEncode[teks]` | Encode untuk URL |
608
- | `$semicolon` | Karakter ; |
609
- | `$leftBracket` | Karakter [ |
610
- | `$rightBracket` | Karakter ] |
611
- | `$dollar` | Karakter $ |
612
- | `$isNumber[teks]` | true/false: apakah angka |
613
- | `$checkContains[teks;cari1;cari2;...]` | true bila teks memuat salah satu kata |
614
- | `$checkCondition[kondisi]` | true/false. Operator: == != > < >= <= && \|\| |
615
- | `$hasRole[roleID;userID?]` | true/false: member punya role |
616
- | `$hasPerms[izin1,izin2;userID?]` | true/false: member punya semua izin (nama izin discord.js) |
617
- | `$isAdmin[userID?]` | true/false: member administrator |
618
- | `$isOwner[userID?]` | true/false: user ada di daftar owners bot |
619
- | `$isTrue[teks]` | true bila teks bernilai true/yes/1/on |
620
-
621
- ### Kontrol alur & batasan
622
-
623
- | Fungsi | Keterangan |
699
+ | `$modulo[a;b]` | Remainder of division a % b |
700
+ | `$round[number;decimals?]` | Round a number |
701
+ | `$max[a;b;...]` | Largest number |
702
+ | `$min[a;b;...]` | Smallest number |
703
+ | `$random[min;max]` | Random integer (inclusive) |
704
+ | `$randomText[a;b;...]` | Randomly select one text block |
705
+ | `$numberSeparator[number;separator?]` | 1234567 -> 1,234,567 |
706
+ | `$toUpperCase[text]` | UPPERCASE |
707
+ | `$toLowerCase[text]` | lowercase |
708
+ | `$capitalize[text]` | Capitalize the first letter |
709
+ | `$titleCase[text]` | Capitalize The First Letter Of Each Word |
710
+ | `$trimSpace[text]` | Trim leading/trailing spaces |
711
+ | `$length[text]` | Character count |
712
+ | `$reverse[text]` | Reverse string order |
713
+ | `$repeat[text;count]` | Repeat text (max 100x) |
714
+ | `$substring[text;start;end?]` | Extract substring (0-based index) |
715
+ | `$replaceText[text;search;replace;limit?]` | Replace text (all, or first N occurrences) |
716
+ | `$split[text;delimiter;number]` | Get the N-th element after splitting text |
717
+ | `$urlEncode[text]` | URL encode a string |
718
+ | `$semicolon` | Literal character ; |
719
+ | `$leftBracket` | Literal character [ |
720
+ | `$rightBracket` | Literal character ] |
721
+ | `$dollar` | Literal character $ |
722
+ | `$isNumber[text]` | true/false: whether it's a number |
723
+ | `$checkContains[text;search1;search2;...]` | true if text contains any of the search words |
724
+ | `$checkCondition[condition]` | true/false. Operators: == != > < >= <= && \|\| |
725
+ | `$hasRole[roleID;userID?]` | true/false: member has role |
726
+ | `$hasPerms[perms1,perms2;userID?]` | true/false: member has all permissions (discord.js permission names) |
727
+ | `$isAdmin[userID?]` | true/false: member is an administrator |
728
+ | `$isOwner[userID?]` | true/false: user is listed in the bot's owners |
729
+ | `$isTrue[text]` | true if text evaluates to true/yes/1/on |
730
+
731
+ ### Flow Control & Constraints
732
+
733
+ | Function | Description |
624
734
  |---|---|
625
- | `$if[kondisi]` | Mulai blok kondisi. Tutup dengan $endif |
626
- | `$elseif[kondisi]` | Kondisi alternatif |
627
- | `$else` | Jika semua kondisi sebelumnya salah |
628
- | `$endif` | Menutup blok $if |
629
- | `$stop[pesan?]` | Hentikan eksekusi (opsional kirim pesan) |
630
- | `$onlyIf[kondisi;pesan?]` | Lanjut hanya jika kondisi benar |
631
- | `$onlyPerms[Izin1,Izin2;pesan?]` | Lanjut hanya jika pengirim punya semua izin (mis. BanMembers) |
632
- | `$onlyBotPerms[Izin1,Izin2;pesan?]` | Lanjut hanya jika bot punya izin tersebut di server |
633
- | `$onlyAdmin[pesan?]` | Lanjut hanya jika pengirim administrator |
634
- | `$onlyOwner[pesan?]` | Lanjut hanya jika pengirim ada di opsi owners |
635
- | `$onlyForIDs[id1,id2;pesan?]` | Lanjut hanya untuk user dengan ID tertentu |
636
- | `$onlyInServer[pesan?]` | Lanjut hanya jika dipakai di server (bukan DM) |
637
- | `$argsCheck[syarat;pesan?]` | Cek jumlah argumen. "2" = minimal 2; juga >=1 <=3 >1 <3 =2 |
638
- | `$cooldown[waktu;pesan?]` | Cooldown per user per command. %time% di pesan = sisa waktu |
639
- | `$wait[waktu]` | Tunggu sebentar (maks 60 detik) |
640
- | `$deleteCommand` | Hapus pesan perintah milik pengirim setelah dijawab |
641
- | `$deleteIn[waktu]` | Hapus jawaban bot setelah waktu tertentu (maks 24 jam) |
642
- | `$ephemeral` | Slash/tombol: jawaban hanya terlihat oleh pengguna |
643
- | `$reply` | Jawab dengan fitur reply pada pesan perintah |
644
- | `$update` | Tombol/select: ubah pesan asal, bukan kirim pesan baru |
645
- | `$typing` | Tampilkan "sedang mengetik" |
646
- | `$defer` | Slash/tombol: tunda jawaban (untuk proses > 3 detik). Taruh $ephemeral sebelum ini bila perlu |
647
- | `$let[nama;nilai]` | Simpan variabel sementara (hanya selama command berjalan) |
648
- | `$get[nama]` | Ambil variabel sementara dari $let |
649
-
650
- ### Variabel & database
651
-
652
- | Fungsi | Keterangan |
735
+ | `$if[condition]` | Start conditional block. Close with $endif |
736
+ | `$elseif[condition]` | Alternative condition |
737
+ | `$else` | If all previous conditions are false |
738
+ | `$endif` | Close $if block |
739
+ | `$stop[message?]` | Halt execution (optionally send a message) |
740
+ | `$onlyIf[condition;message?]` | Proceed only if the condition is true |
741
+ | `$onlyPerms[Perms1,Perms2;message?]` | Proceed only if the sender has all permissions (e.g., BanMembers) |
742
+ | `$onlyBotPerms[Perms1,Perms2;message?]` | Proceed only if the bot has those permissions in the server |
743
+ | `$onlyAdmin[message?]` | Proceed only if the sender is an administrator |
744
+ | `$onlyOwner[message?]` | Proceed only if the sender is in the owners option |
745
+ | `$onlyForIDs[id1,id2;message?]` | Proceed only for specific user IDs |
746
+ | `$onlyInServer[message?]` | Proceed only if used inside a server (not DMs) |
747
+ | `$argsCheck[requirement;message?]` | Check argument count. "2" = at least 2; also supports >=1 <=3 >1 <3 =2 |
748
+ | `$cooldown[time;message?]` | Cooldown per user per command. %time% in message = remaining time |
749
+ | `$wait[time]` | Pause execution briefly (max 60 seconds) |
750
+ | `$deleteCommand` | Delete the command message sent by the user after replying |
751
+ | `$deleteIn[time]` | Delete the bot's reply after a certain time (max 24 hours) |
752
+ | `$ephemeral` | Slash/button: make reply visible only to the user |
753
+ | `$reply` | Reply to the triggering command message directly using inline replies |
754
+ | `$update` | Button/select: edit original message instead of sending a new one |
755
+ | `$typing` | Display "is typing" status |
756
+ | `$defer` | Slash/button: defer reply (for processes > 3s). Put $ephemeral before this if needed |
757
+ | `$let[name;value]` | Save a temporary variable (lasts only during command execution) |
758
+ | `$get[name]` | Retrieve a temporary variable from $let |
759
+
760
+ ### Variables & Database
761
+
762
+ | Function | Description |
653
763
  |---|---|
654
- | `$setUserVar[nama;nilai;userID?]` | Simpan variabel user (harus dideklarasikan dengan bot.variables) |
655
- | `$getUserVar[nama;userID?]` | Baca variabel user |
656
- | `$resetUserVar[nama;userID?]` | Kembalikan variabel user ke nilai awal |
657
- | `$setServerVar[nama;nilai;serverID?]` | Simpan variabel server (harus dideklarasikan dengan bot.variables) |
658
- | `$getServerVar[nama;serverID?]` | Baca variabel server |
659
- | `$resetServerVar[nama;serverID?]` | Kembalikan variabel server ke nilai awal |
660
- | `$setChannelVar[nama;nilai;channelID?]` | Simpan variabel channel (harus dideklarasikan dengan bot.variables) |
661
- | `$getChannelVar[nama;channelID?]` | Baca variabel channel |
662
- | `$resetChannelVar[nama;channelID?]` | Kembalikan variabel channel ke nilai awal |
663
- | `$setGlobalVar[nama;nilai]` | Simpan variabel global |
664
- | `$getGlobalVar[nama]` | Baca variabel global |
665
- | `$resetGlobalVar[nama]` | Kembalikan variabel global ke nilai awal |
666
-
667
- ### Embed
668
-
669
- | Fungsi | Keterangan |
764
+ | `$setUserVar[name;value;userID?]` | Save a user variable (must be declared via bot.variables) |
765
+ | `$getUserVar[name;userID?]` | Read a user variable |
766
+ | `$resetUserVar[name;userID?]` | Reset a user variable to its initial value |
767
+ | `$incUserVar[name;amount;userID?]` | Increment a numeric user var (negative = decrease). Safe from race conditions. Prints nothing |
768
+ | `$setServerVar[name;value;serverID?]` | Save a server variable (must be declared via bot.variables) |
769
+ | `$getServerVar[name;serverID?]` | Read a server variable |
770
+ | `$resetServerVar[name;serverID?]` | Reset a server variable to its initial value |
771
+ | `$incServerVar[name;amount;serverID?]` | Increment a numeric server var (negative = decrease). Safe from race conditions. Prints nothing |
772
+ | `$setChannelVar[name;value;channelID?]` | Save a channel variable (must be declared via bot.variables) |
773
+ | `$getChannelVar[name;channelID?]` | Read a channel variable |
774
+ | `$resetChannelVar[name;channelID?]` | Reset a channel variable to its initial value |
775
+ | `$incChannelVar[name;amount;channelID?]` | Increment a numeric channel var (negative = decrease). Safe from race conditions. Prints nothing |
776
+ | `$setGlobalVar[name;value]` | Save a global variable |
777
+ | `$getGlobalVar[name]` | Read a global variable |
778
+ | `$resetGlobalVar[name]` | Reset a global variable to its initial value |
779
+ | `$incGlobalVar[name;amount]` | Increment a numeric global var (negative = decrease) |
780
+
781
+ ### Embeds
782
+
783
+ | Function | Description |
670
784
  |---|---|
671
- | `$newEmbed` | Mulai embed baru (embed pertama dibuat otomatis). Maks 10 |
672
- | `$title[teks]` | Judul embed (maks 256) |
673
- | `$embedURL[url]` | Tautan pada judul embed |
674
- | `$description[teks]` | Isi embed (maks 4096) |
675
- | `$color[#hex|nama|random]` | Warna embed |
676
- | `$footer[teks;ikonURL?]` | Footer embed (maks 2048) |
677
- | `$author[nama;ikonURL?;url?]` | Penulis embed (maks 256) |
678
- | `$thumbnail[url]` | Gambar kecil embed |
679
- | `$image[url]` | Gambar besar embed |
680
- | `$addField[nama;isi;inline?]` | Tambah field (maks 25; inline = true/false) |
681
- | `$addTimestamp[ms?]` | Tambah cap waktu di embed (default: sekarang) |
682
-
683
- ### Tombol & select menu
684
-
685
- | Fungsi | Keterangan |
785
+ | `$newEmbed` | Start a new embed block (the first one is created automatically). Max 10 |
786
+ | `$title[text]` | Embed title (max 256) |
787
+ | `$embedURL[url]` | URL link on the embed title |
788
+ | `$description[text]` | Embed description body (max 4096) |
789
+ | `$color[#hex|name|random]` | Embed color |
790
+ | `$footer[text;iconURL?]` | Embed footer text (max 2048) |
791
+ | `$author[name;iconURL?;url?]` | Embed author name (max 256) |
792
+ | `$thumbnail[url]` | Embed small thumbnail image URL |
793
+ | `$image[url]` | Embed large main image URL |
794
+ | `$addField[name;value;inline?]` | Add a field (max 25; inline = true/false) |
795
+ | `$addTimestamp[ms?]` | Add a timestamp to the embed (default: current time) |
796
+
797
+ ### Buttons & Select Menus
798
+
799
+ | Function | Description |
686
800
  |---|---|
687
- | `$addUserSelect[customID;placeholder?;min?;max?]` | Select menu pilih user (nilai terpilih lewat $interactionValues) |
688
- | `$addRoleSelect[customID;placeholder?;min?;max?]` | Select menu pilih role (nilai terpilih lewat $interactionValues) |
689
- | `$addMentionableSelect[customID;placeholder?;min?;max?]` | Select menu pilih user atau role (nilai terpilih lewat $interactionValues) |
690
- | `$addChannelSelect[customID;placeholder?;min?;max?;tipe?]` | Select menu pilih channel (nilai terpilih lewat $interactionValues). Tipe: text voice category announcement stage forum, pisah koma |
691
- | `$newRow` | Mulai baris tombol baru (otomatis tiap 5 tombol) |
692
- | `$addButton[label;gaya;customID/URL;nonaktif?;emoji?]` | Tambah tombol. Gaya: primary secondary success danger link |
693
- | `$addSelectMenu[customID;placeholder?;min?;max?]` | Buat select menu (lanjutkan dengan $addSelectOption) |
694
- | `$addSelectOption[label;nilai;deskripsi?;emoji?;default?]` | Tambah opsi ke select menu terakhir (maks 25) |
695
-
696
- ### Aksi & moderasi
697
-
698
- | Fungsi | Keterangan |
801
+ | `$addUserSelect[customID;placeholder?;min?;max?]` | User select menu (retrieve selected items via $interactionValues) |
802
+ | `$addRoleSelect[customID;placeholder?;min?;max?]` | Role select menu (retrieve selected items via $interactionValues) |
803
+ | `$addMentionableSelect[customID;placeholder?;min?;max?]` | Mentionable select menu (retrieve selected items via $interactionValues) |
804
+ | `$addChannelSelect[customID;placeholder?;min?;max?;types?]` | Channel select menu (retrieve via $interactionValues). Types: text voice category announcement stage forum, comma-separated |
805
+ | `$newRow` | Start a new action row for buttons (automatic every 5 buttons) |
806
+ | `$addButton[label;style;customID/URL;disabled?;emoji?]` | Add a button. Styles: primary secondary success danger link |
807
+ | `$addSelectMenu[customID;placeholder?;min?;max?]` | Create a base string select menu (follow up with $addSelectOption) |
808
+ | `$addSelectOption[label;value;description?;emoji?;default?]` | Add a choice to the last select menu (max 25) |
809
+
810
+ ### Actions & Moderation
811
+
812
+ | Function | Description |
699
813
  |---|---|
700
- | `$sendMessage[channelID;teks]` | Kirim pesan ke channel lain |
701
- | `$sendDM[userID;teks]` | Kirim DM ke user |
702
- | `$react[emoji1;emoji2;...]` | Beri reaksi pada pesan perintah |
703
- | `$ban[userID;alasan?;hariHapusPesan?]` | Ban user (hapus pesan 0-7 hari) |
704
- | `$kick[userID;alasan?]` | Kick member |
705
- | `$timeout[userID;waktu;alasan?]` | Timeout member (maks 28 hari) |
706
- | `$untimeout[userID;alasan?]` | Cabut timeout member |
707
- | `$addRole[userID;roleID;alasan?]` | Beri role |
708
- | `$removeRole[userID;roleID;alasan?]` | Cabut role |
709
- | `$setNickname[userID;nickname]` | Ubah nickname (kosongkan untuk reset) |
710
- | `$clear[jumlah]` | Hapus 1-100 pesan terakhir (maks umur 14 hari). Mengembalikan jumlah terhapus |
711
- | `$slowmode[detik]` | Atur slowmode channel (0 = mati, maks 21600) |
712
-
713
- ### Pesan, lampiran, polling, thread & webhook
714
-
715
- | Fungsi | Keterangan |
814
+ | `$sendMessage[channelID;text]` | Send a message to another channel |
815
+ | `$sendDM[userID;text]` | Send a DM to a user |
816
+ | `$react[emoji1;emoji2;...]` | Add reactions to the command message |
817
+ | `$ban[userID;reason?;deleteMessageDays?]` | Ban a user (delete messages 0-7 days) |
818
+ | `$kick[userID;reason?]` | Kick a member |
819
+ | `$timeout[userID;duration;reason?]` | Timeout a member (max 28 days) |
820
+ | `$untimeout[userID;reason?]` | Remove timeout from a member |
821
+ | `$addRole[userID;roleID;reason?]` | Give a role to a member |
822
+ | `$removeRole[userID;roleID;reason?]` | Remove a role from a member |
823
+ | `$setNickname[userID;nickname]` | Change nickname (leave empty to reset) |
824
+ | `$clear[amount]` | Purge last 1-100 messages (max 14 days old). Returns count of deleted messages |
825
+ | `$slowmode[seconds]` | Set channel slowmode rate (0 = disabled, max 21600) |
826
+
827
+ ### Messages, Attachments, Polls, Threads & Webhooks
828
+
829
+ | Function | Description |
716
830
  |---|---|
717
- | `$editMessage[messageID;teks;channelID?]` | Edit pesan milik bot sendiri |
718
- | `$deleteMessage[messageID;channelID?]` | Hapus satu pesan |
719
- | `$pinMessage[messageID;channelID?]` | Sematkan (pin) pesan |
720
- | `$unpinMessage[messageID;channelID?]` | Lepas pin pesan |
721
- | `$addReaction[messageID;emoji;channelID?]` | Beri reaksi pada pesan tertentu |
722
- | `$messageContentOf[messageID;channelID?]` | Isi teks pesan tertentu |
723
- | `$messageAuthorOf[messageID;channelID?]` | ID pengirim pesan tertentu |
724
- | `$addAttachment[url;nama?]` | Lampirkan file dari URL http(s) ke jawaban (maks 10) |
725
- | `$addTextFile[namaFile;isi]` | Lampirkan file teks buatan sendiri (maks 1 MB) |
726
- | `$poll[pertanyaan;jam;multi;opsi1;opsi2;...]` | Buat polling (jam 1-768, multi = true/false, 2-10 opsi) |
727
- | `$sendWebhook[webhookURL;teks;username?;avatarURL?]` | Kirim pesan lewat URL webhook Discord |
728
- | `$createThread[nama;messageID?;arsipOtomatisMenit?]` | Buat thread (dari pesan bila messageID diisi). Arsip: 60/1440/4320/10080. Mengembalikan ID thread |
729
- | `$archiveThread[threadID?;kunci?]` | Arsipkan thread (kunci = true untuk sekalian dikunci) |
730
- | `$addThreadMember[userID;threadID?]` | Tambahkan user ke thread |
731
- | `$removeThreadMember[userID;threadID?]` | Keluarkan user dari thread |
732
- | `$createForumPost[forumID;judul;isi]` | Buat postingan di channel forum. Mengembalikan ID thread |
733
-
734
- ### Manajemen server (ban, channel, role, undangan, emoji, event, voice)
735
-
736
- | Fungsi | Keterangan |
831
+ | `$editMessage[messageID;text;channelID?]` | Edit a message belonging to the bot itself |
832
+ | `$deleteMessage[messageID;channelID?]` | Delete a single message |
833
+ | `$pinMessage[messageID;channelID?]` | Pin a message |
834
+ | `$unpinMessage[messageID;channelID?]` | Unpin a message |
835
+ | `$addReaction[messageID;emoji;channelID?]` | Add reaction to a specific message |
836
+ | `$messageContentOf[messageID;channelID?]` | Fetch text content of a specific message |
837
+ | `$messageAuthorOf[messageID;channelID?]` | Fetch author ID of a specific message |
838
+ | `$addAttachment[url;name?]` | Attach a file from a http(s) URL to the response (max 10) |
839
+ | `$addTextFile[fileName;content]` | Attach a custom text file generated on the fly (max 1 MB) |
840
+ | `$poll[question;hours;multi;option1;option2;...]` | Create a poll (hours 1-768, multi = true/false, 2-10 options) |
841
+ | `$sendWebhook[webhookURL;text;username?;avatarURL?]` | Send a message via a Discord Webhook URL |
842
+ | `$createThread[name;messageID?;autoArchiveMinutes?]` | Create a thread (from a message if messageID is provided). Archive: 60/1440/4320/10080. Returns thread ID |
843
+ | `$archiveThread[threadID?;lock?]` | Archive a thread (lock = true to also lock it) |
844
+ | `$addThreadMember[userID;threadID?]` | Add a user to a thread |
845
+ | `$removeThreadMember[userID;threadID?]` | Remove a user from a thread |
846
+ | `$createForumPost[forumID;title;content]` | Create a post inside a forum channel. Returns thread ID |
847
+
848
+ ### Server Management (Bans, Channels, Roles, Invites, Emojis, Events, Voice)
849
+
850
+ | Function | Description |
737
851
  |---|---|
738
- | `$unban[userID;alasan?]` | Cabut ban user |
739
- | `$isBanned[userID]` | true/false: user sedang di-ban di server ini |
740
- | `$banCount` | Jumlah user ter-ban (dibaca maks 1000 teratas) |
741
- | `$createChannel[nama;tipe?;parentID?;topik?]` | Buat channel. Tipe: text voice category announcement stage forum. Mengembalikan ID |
742
- | `$deleteChannel[channelID;alasan?]` | Hapus channel/thread (menghapus channel saat ini membuat jawaban gagal terkirim) |
743
- | `$setChannelName[channelID;nama;alasan?]` | Ubah nama channel |
744
- | `$setChannelTopic[channelID;topik;alasan?]` | Ubah topik channel |
745
- | `$lockChannel[channelID?;alasan?]` | Kunci channel: @everyone tidak bisa mengirim pesan |
746
- | `$unlockChannel[channelID?;alasan?]` | Buka kunci channel (kembali ke pengaturan semula) |
747
- | `$createInvite[channelID?;umurDetik?;maxPakai?]` | Buat link undangan. Umur 0-604800 (0 = selamanya), maxPakai 0-100. Mengembalikan URL |
748
- | `$channelType[channelID?]` | Tipe channel: text voice category announcement stage forum dst. |
749
- | `$createRole[nama;warna?;hoist?;mentionable?;alasan?]` | Buat role. Mengembalikan ID |
750
- | `$deleteRole[roleID;alasan?]` | Hapus role |
751
- | `$setRoleName[roleID;nama;alasan?]` | Ubah nama role |
752
- | `$setRoleColor[roleID;warna;alasan?]` | Ubah warna role (#hex / nama / random) |
753
- | `$memberRoles[userID?]` | Daftar ID role member, dipisah koma |
754
- | `$createEmoji[nama;url]` | Tambah emoji dari URL gambar. Mengembalikan emoji siap pakai |
755
- | `$deleteEmoji[emojiID]` | Hapus emoji server |
756
- | `$createEvent[nama;mulaiMs;selesaiMs;lokasi;deskripsi?]` | Buat scheduled event (di luar Discord). Waktu dalam ms (lihat $timestamp). Mengembalikan ID |
757
- | `$moveMember[userID;voiceChannelID]` | Pindahkan member ke voice channel lain |
758
- | `$disconnectMember[userID]` | Keluarkan member dari voice channel |
759
- | `$leaveServer[serverID?]` | Bot keluar dari server. Hanya untuk owner bot |
760
-
761
- ### Modal, autocomplete & sasaran
762
-
763
- | Fungsi | Keterangan |
852
+ | `$unban[userID;reason?]` | Revoke a user's ban |
853
+ | `$isBanned[userID]` | true/false: whether the user is currently banned in this server |
854
+ | `$banCount` | Number of banned users (reads max top 1000) |
855
+ | `$createChannel[name;type?;parentID?;topic?]` | Create a channel. Types: text voice category announcement stage forum. Returns ID |
856
+ | `$deleteChannel[channelID;reason?]` | Delete a channel/thread (deleting the active channel makes sending the reply fail) |
857
+ | `$setChannelName[channelID;name;reason?]` | Change channel name |
858
+ | `$setChannelTopic[channelID;topic;reason?]` | Change channel topic |
859
+ | `$lockChannel[channelID?;reason?]` | Lock a channel: @everyone will be unable to send messages |
860
+ | `$unlockChannel[channelID?;reason?]` | Unlock a channel (reverts to default configurations) |
861
+ | `$createInvite[channelID?;maxAgeSeconds?;maxUses?]` | Create an invite link. Age 0-604800 (0 = infinite), maxUses 0-100. Returns URL |
862
+ | `$channelType[channelID?]` | Channel type string: text voice category announcement stage forum etc. |
863
+ | `$createRole[name;color?;hoist?;mentionable?;reason?]` | Create a role. Returns ID |
864
+ | `$deleteRole[roleID;reason?]` | Delete a role |
865
+ | `$setRoleName[roleID;name;reason?]` | Change role name |
866
+ | `$setRoleColor[roleID;color;reason?]` | Change role color (#hex / name / random) |
867
+ | `$memberRoles[userID?]` | Comma-separated list of member role IDs |
868
+ | `$createEmoji[name;url]` | Create a guild emoji from an image URL. Returns the ready-to-use emoji string |
869
+ | `$deleteEmoji[emojiID]` | Delete a server emoji |
870
+ | `$createEvent[name;startMs;endMs;location;description?]` | Create a scheduled guild event (external location type). Time in ms. Returns ID |
871
+ | `$moveMember[userID;voiceChannelID]` | Move a member to another voice channel |
872
+ | `$disconnectMember[userID]` | Disconnect a member from a voice channel |
873
+ | `$leaveServer[serverID?]` | Force the bot to leave a server. Bot owners only |
874
+
875
+ ### Modals, Autocomplete & Target Scope
876
+
877
+ | Function | Description |
764
878
  |---|---|
765
- | `$addModal[customID;judul]` | Tampilkan form pop-up (modal). Jadi respons pertama; teks lain diabaikan. Isi dengan $addTextInput |
766
- | `$addTextInput[customID;label;gaya?;placeholder?;wajib?;min?;max?;nilaiAwal?]` | Tambah kolom isian ke modal (maks 5). Gaya: short / paragraph |
767
- | `$modalValue[customIDKolom]` | Isi kolom modal yang dikirim pengguna (dipakai di handler bot.modal) |
768
- | `$focusedValue` | Autocomplete: teks yang sedang diketik pengguna |
769
- | `$focusedOption` | Autocomplete: nama opsi yang sedang diisi |
770
- | `$addChoice[nama;nilai?]` | Autocomplete: tambah satu pilihan (maks 25). Nilai bawaan = nama |
771
- | `$targetID` | ID sasaran: user/pesan yang diklik kanan, atau objek event (channel/role/thread/voice/ban) |
772
- | `$targetName` | Nama sasaran (username / nama channel / nama role) |
773
- | `$targetContent` | Isi pesan yang diklik kanan (context menu pesan) |
774
- | `$messageFrom[nomor]` | Seluruh teks argumen mulai dari kata ke-N (spasi dan baris baru dipertahankan) |
775
-
776
- ### Eval (khusus owner)
777
-
778
- | Fungsi | Keterangan |
879
+ | `$addModal[customID;title]` | Show a pop-up form (modal). Must be the first response; other texts are ignored. Build inputs using $addTextInput |
880
+ | `$addTextInput[customID;label;style?;placeholder?;required?;min?;max?;initialValue?]` | Add an input field to a modal (max 5). Styles: short / paragraph |
881
+ | `$modalValue[columnCustomID]` | Retrieve submitted modal input text values (used inside bot.modal handlers) |
882
+ | `$focusedValue` | Autocomplete: text currently typed by the user |
883
+ | `$focusedOption` | Autocomplete: name of the option currently being focused |
884
+ | `$addChoice[name;value?]` | Autocomplete: add a dynamic choice (max 25). Default value = name |
885
+ | `$targetID` | Target ID: right-clicked user/message, or the target entity of an event (channel/role/thread/voice/ban) |
886
+ | `$targetName` | Target name (username / channel name / role name) |
887
+ | `$targetContent` | Target message content (right-click message context menu) |
888
+ | `$messageFrom[number]` | The entire message string starting from the N-th word (spaces and newlines are preserved) |
889
+
890
+ ### Eval (Owner Only)
891
+
892
+ | Function | Description |
779
893
  |---|---|
780
- | `$eval[kode]` | Jalankan kode versi port ($fungsi) dari teks saat berjalan. Khusus owner, butuh opsi eval: true |
781
- | `$jsEval[kodeJavaScript]` | Jalankan kode discord.js/JavaScript asli. Variabel: ctx client bot guild channel message user member interaction discord db require. Khusus owner, butuh opsi eval: true |
894
+ | `$eval[code]` | Dynamically execute wrapper-version ($function) syntax string during runtime. Requires eval: true and owner status |
895
+ | `$jsEval[javascriptCode]` | Dynamically execute native discord.js/JavaScript code. Variables: ctx client bot guild channel message user member interaction discord db require. Requires eval: true and owner status |
782
896
 
783
- <!-- FUNCTIONS:END -->
897
+ <!-- FUNCTIONS:START -->
784
898
 
785
899
  ---
786
900
 
787
- ## Yang belum didukung
901
+ ## What is Not Supported Yet
788
902
 
789
- Package ini belum mencakup seluruh discord.js. Belum ada: **voice/musik** (memutar audio), **sharding**, **AutoMod rules**, **stiker**, pengaturan permission per-channel yang rinci, dan Components V2. Untuk itu pakai `bot.client` (client discord.js asli) atau tambahkan fungsi lewat `bot.addFunction`.
903
+ This package does not cover 100% of discord.js capabilities. The following features are currently missing: database adapters other than JSON and MongoDB (SQLite, Redis, etc., though you can build your own adapter, see section 12), **voice/music support** (audio streaming), **sharding**, **AutoMod rules**, **stickers**, granular channel permission overrides, and Components V2. For these features, use `bot.client` (native discord.js client) or inject custom functionalities via `bot.addFunction`.
790
904
 
791
- ## Riwayat versi
905
+ ## Version History
792
906
 
793
- - **1.1.0**: `$unban` dan manajemen server (channel, role, undangan, emoji, event, voice), edit/hapus/pin pesan, lampiran, poll, webhook, thread & forum, modal, autocomplete, context menu, select user/role/channel, 9 event baru, `$eval` / `$jsEval` / `bot.evalCommand`. Intent bawaan bertambah `GuildModeration` dan `GuildVoiceStates`.
794
- - **1.0.0**: rilis pertama.
907
+ - **1.2.0**: Plugin system architecture (`bot.use`, `bot.setDatabase`), official **MongoDB** plugin support (`easydc-js/mongodb`), `copyDatabase` migration toolkit for JSON files, `$incUserVar` and relative wrapper extensions (atomic number adjustment). `bot.getVar/setVar/resetVar` are now asynchronous.
908
+ - **1.1.0**: Added `$unban` and full guild management suites (channels, roles, invites, emojis, events, voice actions), edit/delete/pin message commands, file attachment mechanisms, poll generation, webhook triggers, threads & forums integration, modal setups, autocomplete parameters, context menus, user/role/channel dedicated selector components, 9 brand new lifecycle events, and `$eval` / `$jsEval` / `bot.evalCommand`. Default intents expanded to include `GuildModeration` and `GuildVoiceStates`.
909
+ - **1.0.0**: Initial release.
795
910
 
796
- ## Lisensi
911
+ ## License
797
912
 
798
913
  MIT