@tryty/easydc-js 1.1.0 → 1.2.2

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,9 +1,9 @@
1
- # easydc-js
1
+ # @tryty/easydc-js
2
2
 
3
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.
4
4
 
5
5
  ```js
6
- const { Bot } = require('easydc-js');
6
+ const { Bot } = require('@tryty/easydc-js');
7
7
 
8
8
  const bot = new Bot({ token: process.env.TOKEN, prefix: '!' });
9
9
 
@@ -21,6 +21,7 @@ Ketik `!ping` di Discord → bot menjawab `🏓 Pong! 42 ms`.
21
21
  ## Daftar isi
22
22
 
23
23
  1. [Instalasi](#1-instalasi)
24
+ - [Tanpa publish ke npm (file lokal)](#1b-memakai-tanpa-publish-ke-npm-file-lokal--host-panel)
24
25
  2. [Membuat bot di Discord](#2-membuat-bot-di-discord)
25
26
  3. [Bot pertama](#3-bot-pertama)
26
27
  4. [Cara kerja sintaks `$fungsi`](#4-cara-kerja-sintaks-fungsi)
@@ -31,11 +32,12 @@ Ketik `!ping` di Discord → bot menjawab `🏓 Pong! 42 ms`.
31
32
  9. [Embed, tombol, select menu](#9-embed-tombol-select-menu)
32
33
  10. [Fitur lanjutan: modal, autocomplete, menu klik-kanan, poll, thread, webhook](#10-fitur-lanjutan)
33
34
  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)
35
+ 12. [Database & plugin (MongoDB)](#12-database--plugin-mongodb)
36
+ 13. [Membuat fungsi sendiri](#13-membuat-fungsi-sendiri)
37
+ 14. [Memisah command ke banyak file](#14-memisah-command-ke-banyak-file)
38
+ 15. [Keamanan](#15-keamanan)
39
+ 16. [Pemecahan masalah](#16-pemecahan-masalah)
40
+ 17. [Daftar semua fungsi](#17-daftar-semua-fungsi)
39
41
 
40
42
  ---
41
43
 
@@ -44,9 +46,40 @@ Ketik `!ping` di Discord → bot menjawab `🏓 Pong! 42 ms`.
44
46
  Butuh **Node.js 18.17 atau lebih baru**.
45
47
 
46
48
  ```bash
47
- npm install easydc-js discord.js
49
+ npm install @tryty/easydc-js discord.js
48
50
  ```
49
51
 
52
+ ## 1b. Memakai tanpa publish ke npm (file lokal / host panel)
53
+
54
+ Kalau package ini belum dipublish tetapi kode Anda sudah memakai `require('@tryty/easydc-js')`, pasang dari file lokal. Ada dua cara.
55
+
56
+ **Cara A: dependensi `file:` (disarankan, tahan restart panel)**
57
+
58
+ 1. Ekstrak zip, lalu letakkan folder package di dalam proyek bot, misalnya `bot/vendor/easydc-js/` (isinya `src`, `package.json`, dst.).
59
+ 2. Di `package.json` **proyek bot** (bukan package-nya), tambahkan:
60
+ ```json
61
+ {
62
+ "dependencies": {
63
+ "@tryty/easydc-js": "file:./vendor/easydc-js",
64
+ "discord.js": "^14.16.0",
65
+ "mongodb": "^6.0.0"
66
+ }
67
+ }
68
+ ```
69
+ 3. Jalankan `npm install`. Sekarang `require('@tryty/easydc-js')` dan `require('@tryty/easydc-js/mongodb')` berfungsi persis seperti setelah publish.
70
+
71
+ **Cara B: dari file `.tgz`**
72
+
73
+ ```bash
74
+ npm install ./tryty-easydc-js-1.3.0.tgz discord.js mongodb
75
+ ```
76
+
77
+ Jangan hanya menyalin folder ke `node_modules/@tryty/easydc-js` dengan tangan: panel yang menjalankan `npm install` saat start akan menghapus folder yang tidak tercatat di `package.json`.
78
+
79
+ Nama di `require` harus sama persis dengan nama di `dependencies`. Jika Anda tidak memakai nama ber-scope, ganti `"name"` di `package.json` package-nya dan semua `require`.
80
+
81
+ ---
82
+
50
83
  ## 2. Membuat bot di Discord
51
84
 
52
85
  1. Buka <https://discord.com/developers/applications> → **New Application**.
@@ -70,7 +103,7 @@ $env:TOKEN="token_kamu"; node index.js
70
103
  Buat `index.js`:
71
104
 
72
105
  ```js
73
- const { Bot } = require('easydc-js');
106
+ const { Bot } = require('@tryty/easydc-js');
74
107
 
75
108
  const bot = new Bot({
76
109
  token: process.env.TOKEN,
@@ -255,6 +288,7 @@ bot.variables({ uang: 0, bio: 'Belum diisi' });
255
288
  Semua nilai tersimpan sebagai **teks**. Gunakan `$math[...]` untuk berhitung.
256
289
  Variabel sementara selama satu command: `$let[nama;nilai]` dan `$get[nama]`.
257
290
 
291
+ - Untuk memakai MongoDB lihat [bagian 12](#12-database--plugin-mongodb).
258
292
  - Berkas database ditulis secara aman dan otomatis. Jika file rusak, ia **dicadangkan** (`*.corrupt-<waktu>`) dan bot mulai dari kosong, bukan crash.
259
293
  - Untuk bot besar (ribuan user aktif) pertimbangkan database sungguhan; `Database` bawaan cocok untuk bot kecil sampai menengah.
260
294
  - **Satu file database hanya boleh dipakai satu proses bot.**
@@ -401,7 +435,7 @@ $createRole[VIP;#ff0000;true] $createInvite[;3600;10]
401
435
  $createEvent[Nobar;MULAI_MS;SELESAI_MS;Voice 1;Deskripsi]
402
436
  ```
403
437
 
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).
438
+ Fungsi manajemen memakai **izin bot**, jadi lindungi dengan `$onlyPerms[...]` seperti di bagian [Keamanan](#15-keamanan). Daftar lengkapnya ada di bagian [Daftar semua fungsi](#17-daftar-semua-fungsi).
405
439
 
406
440
  ---
407
441
 
@@ -443,6 +477,29 @@ Hasil dikirim dalam blok kode (maksimal ±1800 karakter), error ditampilkan seba
443
477
 
444
478
  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).
445
479
 
480
+ ### Tes semua fitur dengan satu command (selftest)
481
+
482
+ Setelah bot online di server Anda, jalankan tes otomatis langsung di Discord asli. Ini cara tercepat untuk tahu apakah semuanya benar-benar jalan di bot Anda (bukan hanya di tes tiruan):
483
+
484
+ ```js
485
+ const bot = new Bot({ token: process.env.TOKEN, owners: ['ID_KAMU'] });
486
+ bot.selfTestCommand(); // atau bot.selfTestCommand({ ui: true })
487
+ bot.connect();
488
+ ```
489
+
490
+ | Ketik | Yang diuji |
491
+ |---|---|
492
+ | `!selftest` | Fungsi dasar (`$math`, `$if`, `$date`, dll.), **database** (simpan, baca, tambah, reset), dan **pengiriman** embed + tombol + select menu + select user, lampiran file, dan polling. Pesan uji lampiran dan polling dihapus otomatis. |
493
+ | `!selftest full` | Semua di atas, ditambah membuat lalu **menghapus** channel dan role sementara (nama, topik, kunci channel, undangan, edit/pin/reaksi pesan, thread). Channel/role sementara selalu dihapus walaupun ada langkah yang gagal. |
494
+
495
+ Hasilnya berupa daftar `✅` (lulus), `❌` (gagal, lengkap dengan pesan penyebabnya), dan `⚠️` (dilewati karena bot kurang izin). Kirim isi daftar `❌` ke pengembang untuk diperbaiki.
496
+
497
+ Yang tidak bisa diuji otomatis karena butuh klik manusia: tombol, modal, dan select menu pada pesan uji. Klik sendiri, masing-masing akan membalas `✅ ... berfungsi`. Dengan `ui: true` Anda juga mendapat `/tesauto` (ketik di opsi `buah` untuk melihat autocomplete) dan dua menu klik-kanan **Tes Profil** (klik kanan user) dan **Tes Pesan** (klik kanan pesan).
498
+
499
+ Command ini khusus owner dan punya jeda 10 detik. Hapus `bot.selfTestCommand()` bila sudah tidak diperlukan, terutama `ui: true` yang meninggalkan slash command dan menu klik-kanan di server.
500
+
501
+ Untuk menguji **kode package itu sendiri** (tanpa Discord) pakai `npm test` di folder package.
502
+
446
503
  ### ⚠️ Peringatan keamanan
447
504
 
448
505
  - **`$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.
@@ -454,7 +511,112 @@ Bisa juga dipakai di command buatan sendiri: `$eval[$message]` dan `$jsEval[$mes
454
511
 
455
512
  ---
456
513
 
457
- ## 12. Membuat fungsi sendiri
514
+ ## 12. Database & plugin (MongoDB)
515
+
516
+ Secara bawaan data variabel disimpan di file `easydc-data.json`. Untuk bot yang lebih serius (data tidak hilang saat hosting menghapus file, atau lebih dari satu server), pakai **MongoDB** lewat plugin.
517
+
518
+ ### Pasang plugin MongoDB
519
+
520
+ ```bash
521
+ npm install @tryty/easydc-js discord.js mongodb
522
+ ```
523
+
524
+ ```js
525
+ const { Bot } = require('@tryty/easydc-js');
526
+ const { mongodb } = require('@tryty/easydc-js/mongodb');
527
+
528
+ const bot = new Bot({ token: process.env.TOKEN, prefix: '!' });
529
+
530
+ bot.use(mongodb({
531
+ uri: process.env.MONGO_URI, // mis. mongodb+srv://user:sandi@cluster0.xxxx.mongodb.net
532
+ dbName: 'botku', // nama database (dibuat otomatis oleh MongoDB)
533
+ }));
534
+
535
+ bot.variables({ uang: 100 });
536
+ bot.command({ name: 'kerja', code: '$incUserVar[uang;25]Uangmu sekarang $getUserVar[uang]' });
537
+
538
+ bot.connect();
539
+ ```
540
+
541
+ Hanya itu yang berubah: semua `$getUserVar`, `$setUserVar`, dll. otomatis memakai MongoDB. `bot.use(...)` harus dipanggil **sebelum** `bot.connect()`.
542
+
543
+ Cara mendapatkan MongoDB gratis: buat cluster di MongoDB Atlas (paket M0), buat user database, izinkan IP hosting Anda di *Network Access*, lalu salin *connection string*. Simpan di variabel lingkungan `MONGO_URI`, **jangan ditulis di kode**.
544
+
545
+ ### Opsi plugin
546
+
547
+ | Opsi | Keterangan |
548
+ |---|---|
549
+ | `uri` | Alamat MongoDB (wajib). |
550
+ | `dbName` | Nama database. Jika kosong dipakai nama dari URI, atau `test`. |
551
+ | `collection` | Nama collection, bawaan `easydc`. Tiap variabel = satu dokumen `{ _id, v, t }`. |
552
+ | `cache` | Bawaan `true`: data yang sudah dibaca disimpan di RAM supaya cepat. **Ubah ke `false` jika lebih dari satu proses bot memakai database yang sama**, kalau tidak data bisa basi. |
553
+ | `cacheLimit` | Maksimal kunci di cache (bawaan 10000). |
554
+ | `client` | `MongoClient` buatan sendiri (tidak ditutup otomatis oleh bot). |
555
+ | `clientOptions` | Opsi tambahan untuk `new MongoClient(uri, opsi)`. |
556
+
557
+ Jika MongoDB tidak bisa dihubungi, bot **tidak login** dan menampilkan pesan `Gagal terhubung ke database: ...` (batas tunggu 10 detik).
558
+
559
+ ### Memindahkan data lama (JSON → MongoDB)
560
+
561
+ Skrip sekali jalan, jalankan di folder bot sebelum memakai plugin:
562
+
563
+ ```js
564
+ const { Database, copyDatabase } = require('@tryty/easydc-js');
565
+ const { MongoDatabase } = require('@tryty/easydc-js/mongodb');
566
+
567
+ (async () => {
568
+ const lama = new Database({ path: './easydc-data.json' });
569
+ const baru = new MongoDatabase({ uri: process.env.MONGO_URI, dbName: 'botku' });
570
+ await baru.connect();
571
+ console.log(await copyDatabase(lama, baru)); // { copied: 120, skipped: 0 }
572
+ await baru.close();
573
+ })();
574
+ ```
575
+
576
+ Data yang sudah ada di MongoDB tidak ditimpa. Tambahkan `{ overwrite: true }` sebagai argumen ketiga bila ingin menimpa.
577
+
578
+ ### `$inc...Var`: tambah angka dengan aman
579
+
580
+ Pola `$setUserVar[uang;$math[$getUserVar[uang]+10]]` bisa **kehilangan data** jika dua command berjalan bersamaan (keduanya membaca nilai lama). Gunakan:
581
+
582
+ ```
583
+ $incUserVar[uang;10] $incUserVar[uang;-5] (kurangi)
584
+ $incServerVar $incChannelVar $incGlobalVar
585
+ ```
586
+
587
+ `$incUserVar[nama;jumlah;userID?]` berjalan berurutan per variabel sehingga tidak saling menimpa. Perlindungan ini berlaku di dalam **satu proses bot**; jika Anda menjalankan beberapa proses bot pada database yang sama, tabrakan antar proses masih mungkin.
588
+
589
+ ### Membuat plugin / adapter database sendiri
590
+
591
+ Plugin adalah function atau object `{ name, install(bot, opsi) }`; `install` harus sinkron.
592
+
593
+ ```js
594
+ bot.use({
595
+ name: 'halo',
596
+ install(bot) {
597
+ bot.addFunction({ name: '$halo', params: 0, run: () => 'Halo dari plugin!' });
598
+ },
599
+ });
600
+ ```
601
+
602
+ Adapter database (untuk Redis, SQLite, dll.) cukup berupa object dengan method berikut; semuanya boleh `async`:
603
+
604
+ | Method | Wajib | Keterangan |
605
+ |---|---|---|
606
+ | `get(key)` | ya | Kembalikan nilai (teks) atau `undefined` jika tidak ada. |
607
+ | `set(key, value)` | ya | Simpan nilai teks. |
608
+ | `delete(key)` | ya | Hapus kunci. |
609
+ | `keys(prefix?)` | tidak | Dibutuhkan oleh `copyDatabase`. |
610
+ | `connect()` / `close()` | tidak | Dipanggil sebelum login Discord / saat bot dimatikan. |
611
+ | `flush()` | tidak | Simpan data yang tertunda. |
612
+
613
+ Pasang dengan `bot.setDatabase(adapter)` atau `new Bot({ database: adapter })`.
614
+
615
+ > **Perubahan dari versi 1.1:** `bot.getVar`, `bot.setVar`, `bot.resetVar` kini mengembalikan **Promise** (pakai `await`). Command bergaya `$fungsi` tidak terpengaruh.
616
+
617
+ ---
618
+
619
+ ## 13. Membuat fungsi sendiri
458
620
 
459
621
  ```js
460
622
  bot.addFunction({
@@ -470,7 +632,7 @@ bot.command({ name: 'tes', code: '$salam[Budi]' });
470
632
  `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
633
  Opsi `override: true` mengganti fungsi bawaan.
472
634
 
473
- ## 13. Memisah command ke banyak file
635
+ ## 14. Memisah command ke banyak file
474
636
 
475
637
  ```
476
638
  proyek/
@@ -495,7 +657,7 @@ module.exports = [
495
657
  ];
496
658
  ```
497
659
 
498
- ## 14. Keamanan
660
+ ## 15. Keamanan
499
661
 
500
662
  - **Jangan taruh token di kode** atau di GitHub. Pakai variabel lingkungan. Jika token bocor, segera *Reset Token* di Developer Portal.
501
663
  - 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.
@@ -503,7 +665,7 @@ module.exports = [
503
665
  - Kalkulator `$math` tidak memakai `eval`, jadi aman dari eksekusi kode.
504
666
  - Biarkan `debug: false` di produksi supaya detail error tidak tampil ke pengguna (tetap tercatat di konsol).
505
667
 
506
- ## 15. Pemecahan masalah
668
+ ## 16. Pemecahan masalah
507
669
 
508
670
  | Masalah | Penyebab / solusi |
509
671
  |---|---|
@@ -520,12 +682,16 @@ module.exports = [
520
682
  | Interaksi gagal ("This interaction failed") | Proses > 3 detik. Taruh `$defer` di awal. |
521
683
  | 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
684
  | Autocomplete kosong | Opsi harus dibuat dengan `autocomplete: true`, dan handler `bot.autocomplete({ command, option })` cocok. Proses harus selesai < 3 detik. |
685
+ | `Package "mongodb" tidak ditemukan` | Jalankan `npm install mongodb` (di host panel: tambahkan `mongodb` ke *Additional Node Packages*). |
686
+ | `Gagal terhubung ke database` | Periksa `MONGO_URI`, user & sandi, dan izinkan IP hosting di MongoDB Atlas (*Network Access*). Sandi dengan karakter khusus (`@ : /`) harus di-URL-encode. |
687
+ | Data di MongoDB tidak berubah / terlihat basi | Ada lebih dari satu proses bot pada database yang sama: set `cache: false`. |
688
+ | "Hanya untuk owner" padahal sudah isi ID | (1) ID **wajib pakai tanda kutip**: `owners: ['123456789012345678']`; tanpa kutip angkanya membulat dan tidak cocok (versi 1.2.3+ langsung memberi error). (2) Salin **User ID** akunmu (Developer Mode → klik kanan profil → Copy User ID), bukan ID server/bot. (3) Lihat konsol panel: tertulis `[easydc] ... ID pengirim = "..."`, salin ID itu ke `owners`. |
523
689
  | `$eval ... dimatikan` | Tambahkan `eval: true` dan `owners: ['ID_KAMU']` pada `new Bot({...})`. |
524
690
  | Event ban / voice tidak jalan | Intent `GuildModeration` / `GuildVoiceStates` sudah aktif secara bawaan; jika kamu mengatur `intents` sendiri, tambahkan keduanya. |
525
691
 
526
692
  ---
527
693
 
528
- ## 16. Daftar semua fungsi
694
+ ## 17. Daftar semua fungsi
529
695
 
530
696
  Tanda `?` berarti argumen opsional. Daftar ini dibuat otomatis dari kode (`npm run docs`).
531
697
 
@@ -654,15 +820,19 @@ Tanda `?` berarti argumen opsional. Daftar ini dibuat otomatis dari kode (`npm r
654
820
  | `$setUserVar[nama;nilai;userID?]` | Simpan variabel user (harus dideklarasikan dengan bot.variables) |
655
821
  | `$getUserVar[nama;userID?]` | Baca variabel user |
656
822
  | `$resetUserVar[nama;userID?]` | Kembalikan variabel user ke nilai awal |
823
+ | `$incUserVar[nama;jumlah;userID?]` | Tambah variabel user berupa angka (jumlah negatif = kurangi). Aman dari tabrakan antar command. Tidak menampilkan apa pun |
657
824
  | `$setServerVar[nama;nilai;serverID?]` | Simpan variabel server (harus dideklarasikan dengan bot.variables) |
658
825
  | `$getServerVar[nama;serverID?]` | Baca variabel server |
659
826
  | `$resetServerVar[nama;serverID?]` | Kembalikan variabel server ke nilai awal |
827
+ | `$incServerVar[nama;jumlah;serverID?]` | Tambah variabel server berupa angka (jumlah negatif = kurangi). Aman dari tabrakan antar command. Tidak menampilkan apa pun |
660
828
  | `$setChannelVar[nama;nilai;channelID?]` | Simpan variabel channel (harus dideklarasikan dengan bot.variables) |
661
829
  | `$getChannelVar[nama;channelID?]` | Baca variabel channel |
662
830
  | `$resetChannelVar[nama;channelID?]` | Kembalikan variabel channel ke nilai awal |
831
+ | `$incChannelVar[nama;jumlah;channelID?]` | Tambah variabel channel berupa angka (jumlah negatif = kurangi). Aman dari tabrakan antar command. Tidak menampilkan apa pun |
663
832
  | `$setGlobalVar[nama;nilai]` | Simpan variabel global |
664
833
  | `$getGlobalVar[nama]` | Baca variabel global |
665
834
  | `$resetGlobalVar[nama]` | Kembalikan variabel global ke nilai awal |
835
+ | `$incGlobalVar[nama;jumlah]` | Tambah variabel global berupa angka (jumlah negatif = kurangi) |
666
836
 
667
837
  ### Embed
668
838
 
@@ -725,7 +895,7 @@ Tanda `?` berarti argumen opsional. Daftar ini dibuat otomatis dari kode (`npm r
725
895
  | `$addTextFile[namaFile;isi]` | Lampirkan file teks buatan sendiri (maks 1 MB) |
726
896
  | `$poll[pertanyaan;jam;multi;opsi1;opsi2;...]` | Buat polling (jam 1-768, multi = true/false, 2-10 opsi) |
727
897
  | `$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 |
898
+ | `$createThread[nama;messageID?;arsipOtomatisMenit?;channelID?]` | Buat thread (dari pesan bila messageID diisi; channelID = channel tempat pesan itu, bawaan channel ini). Arsip: 60/1440/4320/10080. Mengembalikan ID thread |
729
899
  | `$archiveThread[threadID?;kunci?]` | Arsipkan thread (kunci = true untuk sekalian dikunci) |
730
900
  | `$addThreadMember[userID;threadID?]` | Tambahkan user ke thread |
731
901
  | `$removeThreadMember[userID;threadID?]` | Keluarkan user dari thread |
@@ -786,10 +956,15 @@ Tanda `?` berarti argumen opsional. Daftar ini dibuat otomatis dari kode (`npm r
786
956
 
787
957
  ## Yang belum didukung
788
958
 
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`.
959
+ Package ini belum mencakup seluruh discord.js. Belum ada: adapter database selain JSON dan MongoDB (SQLite, Redis, dll.; bisa dibuat sendiri, lihat bagian 12), **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`.
790
960
 
791
961
  ## Riwayat versi
792
962
 
963
+ - **1.3.0**: plugin voice/musik (`@tryty/easydc-js/voice`, butuh Lavalink + `shoukaku`). Fungsi stop musik bernama `$stopMusic` karena `$stop` sudah dipakai fungsi inti.
964
+ - **1.2.3**: `owners` divalidasi (angka besar ditolak, mention/spasi dirapikan); penolakan owner mencatat ID pengirim ke konsol.
965
+ - **1.2.2**: nama package menjadi `@tryty/easydc-js`; panduan pemasangan dari file lokal.
966
+ - **1.2.1**: `bot.selfTestCommand()` (`!selftest`, tes otomatis di Discord asli); `$createThread` bisa membuat thread dari pesan di channel lain (argumen ke-4).
967
+ - **1.2.0**: sistem plugin (`bot.use`, `bot.setDatabase`), plugin **MongoDB** (`@tryty/easydc-js/mongodb`), `copyDatabase` untuk migrasi dari JSON, `$incUserVar` dan kawan-kawannya (tambah angka dengan aman). `bot.getVar/setVar/resetVar` kini async.
793
968
  - **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
969
  - **1.0.0**: rilis pertama.
795
970
 
package/examples/basic.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // Jalankan: TOKEN=token_bot_kamu node examples/basic.js
2
- const { Bot } = require('easydc-js'); // saat dicoba dari folder ini: require('../src')
2
+ const { Bot } = require('@tryty/easydc-js'); // saat dicoba dari folder ini: require('../src')
3
3
 
4
4
  const bot = new Bot({
5
5
  token: process.env.TOKEN,
@@ -0,0 +1,44 @@
1
+ // Bot dengan database MongoDB.
2
+ // Pasang dulu: npm install @tryty/easydc-js discord.js mongodb
3
+ // Jalankan: TOKEN=token_bot MONGO_URI="mongodb+srv://..." node examples/mongo.js
4
+ const { Bot } = require('@tryty/easydc-js'); // saat dicoba dari folder ini: require('../src')
5
+ const { mongodb } = require('@tryty/easydc-js/mongodb'); // saat dicoba dari folder ini: require('../src/plugins/mongodb')
6
+
7
+ const bot = new Bot({ token: process.env.TOKEN, prefix: '!', timezone: 'Asia/Jakarta' });
8
+
9
+ bot.use(mongodb({
10
+ uri: process.env.MONGO_URI,
11
+ dbName: 'botku',
12
+ // cache: false, // aktifkan baris ini jika bot dijalankan di lebih dari satu proses/server
13
+ }));
14
+
15
+ bot.variables({ uang: 100 });
16
+
17
+ bot.command({ name: 'uang', code: '💰 $username punya $numberSeparator[$getUserVar[uang];.] koin' });
18
+
19
+ bot.command({
20
+ name: 'kerja',
21
+ code: `
22
+ $cooldown[1m;Istirahat dulu, tunggu %time%.]
23
+ $incUserVar[uang;$random[10;50]]
24
+ Kamu bekerja! Uangmu sekarang $getUserVar[uang]
25
+ `,
26
+ });
27
+
28
+ bot.command({
29
+ name: 'kirim',
30
+ code: `
31
+ $argsCheck[2;Format: !kirim @user jumlah]
32
+ $onlyIf[$mentioned[1]!=;Mention user tujuan.]
33
+ $onlyIf[$isNumber[$message[2]]==true&&$message[2]>0;Jumlah harus angka lebih dari 0.]
34
+ $onlyIf[$getUserVar[uang]>=$message[2];Uangmu tidak cukup.]
35
+ $incUserVar[uang;-$message[2]]
36
+ $incUserVar[uang;$message[2];$mentioned[1]]
37
+ ✅ Terkirim $message[2] koin ke <@$mentioned[1]>
38
+ `,
39
+ });
40
+
41
+ bot.connect().then(() => console.log('Bot online, database terhubung.')).catch((e) => {
42
+ console.error(e.message);
43
+ process.exit(1);
44
+ });
package/index.d.ts CHANGED
@@ -15,7 +15,7 @@ export interface BotOptions {
15
15
  handleSignals?: boolean;
16
16
  /** Nyalakan $eval / $jsEval / bot.evalCommand (hanya untuk ID di `owners`). Bawaan: false */
17
17
  eval?: boolean;
18
- database?: { path?: string; memory?: boolean; saveDelay?: number } | Database;
18
+ database?: { path?: string; memory?: boolean; saveDelay?: number } | DatabaseAdapter;
19
19
  messages?: { cooldown?: string; error?: string };
20
20
  status?: { text: string; type?: 'Playing' | 'Streaming' | 'Listening' | 'Watching' | 'Competing'; status?: 'online' | 'idle' | 'dnd' | 'invisible' };
21
21
  onError?: (error: Error, ctx: Context) => unknown;
@@ -70,7 +70,19 @@ export class Context {
70
70
  rawArgs: string;
71
71
  }
72
72
 
73
- export class Database {
73
+ /** Adapter database: hanya get/set/delete yang wajib. Nilai balik boleh Promise. */
74
+ export interface DatabaseAdapter {
75
+ get(key: string): unknown | Promise<unknown>;
76
+ set(key: string, value: unknown): unknown | Promise<unknown>;
77
+ delete(key: string): unknown | Promise<unknown>;
78
+ has?(key: string): boolean | Promise<boolean>;
79
+ keys?(prefix?: string): string[] | Promise<string[]>;
80
+ flush?(): unknown | Promise<unknown>;
81
+ connect?(): Promise<void>;
82
+ close?(): unknown | Promise<unknown>;
83
+ }
84
+
85
+ export class Database implements DatabaseAdapter {
74
86
  constructor(options?: { path?: string; memory?: boolean; saveDelay?: number });
75
87
  get(key: string): unknown;
76
88
  set(key: string, value: unknown): void;
@@ -78,12 +90,18 @@ export class Database {
78
90
  delete(key: string): boolean;
79
91
  keys(prefix?: string): string[];
80
92
  flush(): void;
93
+ close(): void;
81
94
  }
82
95
 
96
+ export function copyDatabase(from: DatabaseAdapter, to: DatabaseAdapter, options?: { overwrite?: boolean; prefix?: string }): Promise<{ copied: number; skipped: number }>;
97
+
98
+ export type Plugin = ((bot: Bot, options?: unknown) => void) | { name?: string; install(bot: Bot, options?: unknown): void };
99
+
83
100
  export class Bot {
84
101
  constructor(options?: BotOptions);
85
102
  client: Client | null;
86
- db: Database;
103
+ db: DatabaseAdapter;
104
+ plugins: Map<string, unknown>;
87
105
  command(def: CommandDef): this;
88
106
  slashCommand(def: SlashDef): this;
89
107
  button(def: ComponentDef): this;
@@ -93,6 +111,8 @@ export class Bot {
93
111
  contextMenu(def: ContextMenuDef): this;
94
112
  /** Pasang command eval siap pakai (butuh `eval: true` dan `owners`). */
95
113
  evalCommand(def?: { name?: string; aliases?: string[] }): this;
114
+ /** Pasang command tes otomatis di Discord asli (butuh `owners`). `ui: true` menambah /tesauto & menu klik-kanan uji. */
115
+ selfTestCommand(def?: { name?: string; aliases?: string[]; ui?: boolean }): this;
96
116
  event(def: EventDef): this;
97
117
  onMemberBan(code: string | Omit<EventDef, 'type'>): this;
98
118
  onMemberUnban(code: string | Omit<EventDef, 'type'>): this;
@@ -117,9 +137,12 @@ export class Bot {
117
137
  addFunction(fn: CustomFunction): this;
118
138
  loadCommands(dir: string): this;
119
139
  validate(): true;
120
- getVar(scope: 'user' | 'server' | 'channel' | 'global', name: string, id?: string | null): string;
121
- setVar(scope: 'user' | 'server' | 'channel' | 'global', name: string, value: unknown, id?: string | null): void;
122
- resetVar(scope: 'user' | 'server' | 'channel' | 'global', name: string, id?: string | null): void;
140
+ use(plugin: Plugin, options?: unknown): this;
141
+ setDatabase(adapter: DatabaseAdapter): this;
142
+ getVar(scope: 'user' | 'server' | 'channel' | 'global', name: string, id?: string | null): Promise<string>;
143
+ setVar(scope: 'user' | 'server' | 'channel' | 'global', name: string, value: unknown, id?: string | null): Promise<void>;
144
+ resetVar(scope: 'user' | 'server' | 'channel' | 'global', name: string, id?: string | null): Promise<void>;
145
+ incVar(scope: 'user' | 'server' | 'channel' | 'global', name: string, amount: number | string, id?: string | null): Promise<string>;
123
146
  connect(token?: string): Promise<this>;
124
147
  destroy(): Promise<void>;
125
148
  }
package/mongodb.d.ts ADDED
@@ -0,0 +1,31 @@
1
+ import type { Database } from './index';
2
+
3
+ export interface MongoOptions {
4
+ /** Alamat MongoDB, mis. process.env.MONGO_URI. Wajib kecuali `client` diisi. */
5
+ uri?: string;
6
+ dbName?: string;
7
+ /** Bawaan: "easydc" */
8
+ collection?: string;
9
+ /** Bawaan true. Matikan bila lebih dari satu proses bot memakai database yang sama. */
10
+ cache?: boolean;
11
+ cacheLimit?: number;
12
+ /** MongoClient milik sendiri (tidak ditutup otomatis). */
13
+ client?: unknown;
14
+ driver?: unknown;
15
+ clientOptions?: Record<string, unknown>;
16
+ }
17
+
18
+ export class MongoDatabase {
19
+ constructor(options: MongoOptions);
20
+ connect(): Promise<void>;
21
+ get(key: string): Promise<string | undefined>;
22
+ has(key: string): Promise<boolean>;
23
+ set(key: string, value: unknown): Promise<void>;
24
+ delete(key: string): Promise<boolean>;
25
+ keys(prefix?: string): Promise<string[]>;
26
+ flush(): Promise<void>;
27
+ close(): Promise<void>;
28
+ }
29
+
30
+ /** Plugin: bot.use(mongodb({ uri, dbName })) */
31
+ export function mongodb(options: MongoOptions): { name: string; install(bot: unknown): void };
package/package.json CHANGED
@@ -1,13 +1,15 @@
1
1
  {
2
2
  "name": "@tryty/easydc-js",
3
- "version": "1.1.0",
4
- "description": "Bot Discord super mudah di atas discord.js: tulis perintah dengan sintaks $fungsi[arg] ala aoi.js.",
3
+ "version": "1.2.2",
4
+ "description": "Super easy Discord bot on top of discord.js: write commands with $function[arg] syntax.",
5
5
  "main": "src/index.js",
6
6
  "types": "index.d.ts",
7
7
  "files": [
8
8
  "src",
9
9
  "examples",
10
10
  "index.d.ts",
11
+ "mongodb.d.ts",
12
+ "voice.d.ts",
11
13
  "README.md",
12
14
  "LICENSE"
13
15
  ],
@@ -16,11 +18,15 @@
16
18
  "docs": "node scripts/gen-docs.js"
17
19
  },
18
20
  "keywords": [
21
+ "bot",
19
22
  "discord",
20
23
  "discord.js",
21
- "bot",
22
- "aoi.js",
23
24
  "easy",
25
+ "lavalink",
26
+ "mongodb",
27
+ "music",
28
+ "plugin",
29
+ "voice",
24
30
  "wrapper"
25
31
  ],
26
32
  "author": "",
@@ -30,5 +36,32 @@
30
36
  },
31
37
  "dependencies": {
32
38
  "discord.js": "^14.16.0"
39
+ },
40
+ "exports": {
41
+ ".": {
42
+ "types": "./index.d.ts",
43
+ "default": "./src/index.js"
44
+ },
45
+ "./mongodb": {
46
+ "types": "./mongodb.d.ts",
47
+ "default": "./src/plugins/mongodb.js"
48
+ },
49
+ "./package.json": "./package.json",
50
+ "./voice": {
51
+ "types": "./voice.d.ts",
52
+ "default": "./src/plugins/voice.js"
53
+ }
54
+ },
55
+ "peerDependencies": {
56
+ "mongodb": ">=5.0.0",
57
+ "shoukaku": ">=4.0.0"
58
+ },
59
+ "peerDependenciesMeta": {
60
+ "mongodb": {
61
+ "optional": true
62
+ },
63
+ "shoukaku": {
64
+ "optional": true
65
+ }
33
66
  }
34
67
  }