Skip to content

Repository files navigation

🤖 Discord Bot — Vercel Serverless (Backup Engine)

Bot Discord berbasis HTTP Interactions, jalan sepenuhnya di Vercel Serverless Functions — tanpa gateway/WebSocket, tanpa server yang harus nyala 24/7.

platform commands queue storage economy license


🤔 Kenapa Ribet Amat? (Vercel + AI Gateway + Redis + QStash)

Wajar kalau nanya "kenapa nggak pakai BotGhost/Wick/dashboard bot instan aja?" — jawaban jujurnya:

Vercel, bukan BotGhost/dashboard bot instan — karena gw mau kontrol penuh atas kodenya, bukan dibatasin fitur yang di-lock di balik paywall. Semua yang ada di bot ini (blocklist, rate-limit, retry button, dst) gw yang tentuin sendiri kapan dan gimana caranya, bukan nunggu fitur itu di-approve sama provider dashboard. Plus, Vercel free tier ini beneran gratis buat skala bot personal kayak gini.

AI Gateway sendiri, bukan API 1 provider — biar bebas gonta-ganti Groq/Gemini/Cerebras/OpenRouter kapan aja tanpa bot-nya tau bedanya (tinggal ganti VERCEL_PROXY_URL/VERCEL_PROXY_MODEL). Banyak provider itu ada tier gratisnya, jadi gw bisa combine buat hemat kuota, dan kalau 1 provider down/limit, gampang pindah ke yang lain.

Redis + QStash, bukan cuma proses langsung — ini BUKAN pilihan gaya-gayaan, ini solusi dari masalah nyata yang gw temuin sendiri lewat trial-error (baca aja histori troubleshoot-nya, panjang 😅): Discord maksa balasan dalam 3 detik, tapi manggil AI bisa lebih lama dari itu. Vercel Serverless juga nggak jamin proses lanjut jalan di background setelah response pertama dikirim. QStash itu yang "nge-akalin" 2 masalah itu sekaligus (deferred + queue), dan Redis buat nyimpen state (history, blocklist, dll) karena serverless function itu sendiri nggak punya memory yang nempel.

Yang paling penting: semua ini BISA GRATIS kalau lo mau belajar. Vercel, Upstash Redis, Upstash QStash, provider AI gratisan — semuanya punya free tier yang lebih dari cukup buat bot personal. Bedanya cuma effort belajar di awal vs tinggal klik-klik di dashboard berbayar. Kalau lo baca repo ini dan mikir "kok ribet", ya emang — tapi itu harga dari ngerti apa yang sebenernya kejadian di balik layar, bukan cuma pencet tombol doang.


📑 Daftar Isi


📂 Struktur Project

package.json
vercel.json
deploy-commands.js
api/
  index.js                        <- Webhook endpoint (Discord Interactions URL)
  process-ai.js                    <- Dipanggil QStash -> eksekusi AI -> PATCH ke Discord
  process-status.js                 <- Dipanggil QStash -> eksekusi /status -> PATCH ke Discord
  process-remind.js                  <- Dipanggil QStash (setelah delay) -> kirim reminder
  process-export.js                   <- Dipanggil QStash -> build file -> PATCH ke Discord
  process-price-update.js              <- Dipanggil QStash SCHEDULE (cron 30 menit) -> random walk harga
  process-market-event.js               <- Dipanggil QStash (delay 60 detik) -> ubah harga event + eksekusi order pending
  process-market-event-trigger.js        <- Dipanggil QStash -> kirim pengumuman + jadwalkan process-market-event
scripts/
  setup-price-schedule.js                 <- Jalankan SEKALI dari Termux, daftarkan QStash Schedule
lib/
  config.js                        <- ENV terpusat
  aiEngine.js                        <- Client Saucepan Proxy (OpenAI-compatible)
  discordApi.js                        <- PATCH/POST/DM ke Discord API
  permissions.js                         <- Cek Owner / permission Discord (ManageMessages)
  ratelimit.js                             <- Rate-limit per user untuk command AI
  qstash.js                                  <- Publish job generik ke QStash (+ delay support)
  qstashVerify.js                              <- Shared verifikasi signature QStash
  errorLog.js                                    <- Notifikasi error ke channel + audit log
  timeParser.js                                    <- Parser waktu relatif & absolut (/remind)
  redis.js                                           <- Conversation, blocklist, stats, override, dst
  tradingAssets.js                                     <- Definisi 4 aset trading (NORA/VOLT/KRYN/PLUM)
  trading.js                                             <- Inti ekonomi ZYC: saldo, portfolio, pinjaman, event, shop
  shopItems.js                                             <- Katalog shop + validator syarat pembelian
  commands.js                                                <- processAiJob (eksekusi AI sesungguhnya)
  commands/
    avatar.js - userinfo.js - ping.js - say.js
    moderation.js         <- /block /unblock /blocklist /maintenance /reset
    aiJobs.js               <- /translate /ringkas (queue ke QStash)
    model.js                  <- /model (lihat & ganti model on-the-fly)
    riwayat.js                  <- /riwayat
    stats.js                      <- /stats
    status.js                       <- /status (queue ke QStash)
    fun.js                             <- /coinflip /roll
    leaderboard.js                       <- /leaderboard
    remind.js                              <- /remind (queue ke QStash + delay)
    exportChat.js                            <- /export (queue ke QStash)
    rate.js                                    <- /rate
    ship.js                                      <- /ship
    timezone.js                                    <- /timezone
    personality.js                                   <- /personality
    warn.js                                            <- /warn
    auditLog.js                                          <- /audit-log
    retryHandler.js                                        <- Handler tombol Retry
    trading/
      portfolio.js  <- /portfolio (saldo, aset, kosmetik, koleksi mewah)
      market.js       <- /market (harga & tren 4 aset)
      buysell.js         <- /buy /sell (instan di harga sekarang)
      posisi.js             <- /posisi (order pending, ancang-ancang sebelum event)
      debt.js                 <- /pinjam /bayar-utang /debt /debt-approve
      grant.js                  <- /grant (Owner, koreksi saldo/aset manual)
      trade.js                    <- /trade-* (barter antar-user)
      shop.js                        <- /shop /shop-buy /leak (belanja & consumable)

📜 Daftar Command

💬 AI & Percakapan
Command Akses Butuh AI? Keterangan
/tanya {pesan} {mode?} Semua Chat bebas, pakai history. mode: singkat/detail/kreatif
/translate {teks} {bahasa?} Semua Terjemahan, tanpa history
/ringkas {teks} Semua Ringkas teks, tanpa history
/rate {sesuatu} {mode?} Semua Opsional mode:random instan gratis, mode:ai lewat AI
/reset {user?} {scope?} Semua* Hapus riwayat percakapan. Owner bisa target user lain / seluruh channel / ALL
/riwayat Semua Lihat ringkasan riwayat percakapanmu di channel ini
🎉 Fun & Utility
Command Akses Keterangan
/avatar {user?} Semua Tampilkan avatar user
/userinfo {user?} Semua Info akun: dibuat kapan, join kapan, role
/ping Semua Cek bot hidup & latency
/coinflip Semua Lempar koin
/roll {dice} Semua Lempar dadu, format d20, 2d6, dst
/ship {user1} {user2} Semua Persentase kecocokan + progress bar visual
/timezone {waktu} {dari} {ke} Semua Konversi waktu antar zona (nama populer/IANA)
/remind {waktu} {pesan} Semua Jadwalkan pengingat -- relatif (10m,2h,1d) atau absolut
/leaderboard {periode?} {metric?} Semua Top user pemakaian bot (sepanjang waktu / hari ini)
💹 Trading & Ekonomi ZYC
Command Akses Keterangan
/portfolio Semua Saldo, kepemilikan aset, kosmetik profil, koleksi mewah
/market Semua Harga & tren 4 aset (NORA/VOLT/KRYN/PLUM) saat ini
/buy {aset} {jumlah} Semua Beli aset instan di harga sekarang
/sell {aset} {jumlah} Semua Jual aset instan di harga sekarang
/posisi {aset} {jumlah?} Semua Pasang/batalkan order pending -- ancang-ancang sebelum event pasar
/pinjam {jumlah} Semua Pinjam ZYC tanpa bunga, tenor 7 hari (default)
/bayar-utang {jumlah} Semua Cicil/lunasi pinjaman aktif
/debt Semua Lihat status pinjaman & bad debt milikmu
/debt-approve {user} Owner Hapus bad debt user yang tidak bisa ditagih lagi
/grant {user} {tipe} {kode?} {jumlah} Owner Koreksi manual saldo/aset (boleh negatif)
/trade-add-item, /trade-request-item, /trade-send, /trade-accept, /trade-reject, /trade-clear Semua Barter antar-user via keranjang bertahap, TTL 10 menit
/market-event {tipe} {aset?} Owner Picu event pasar manual (pengumuman T-1 menit)
/market-set-price {aset} {harga} Owner Set harga aset manual (override random walk)
🛍️ Shop & Kosmetik
Command Akses Keterangan
/shop {kategori?} Semua Lihat katalog shop -- utilitas, kosmetik, atau kategori luxury tertentu
/shop-buy {item} Semua Beli item dari shop. Item luxury bersifat permanen, tidak bisa dijual balik
/leak Semua Pakai 1x 🕵️ Sinyal Orang Dalam untuk mengintip arah event pasar aktif
🛡️ Moderasi & Owner
Command Akses Keterangan
/model {set?} Owner Lihat/ganti model AI aktif on-the-fly
/personality {set?} Owner Lihat/ganti kepribadian bot on-the-fly
/say {pesan} {channel?} Owner atau ManageMessages Bot kirim pesan atas nama bot, dual-logged
/warn {user} {alasan} Owner atau ManageMessages Kirim peringatan + DM konsekuensi ke user
/block {user} {alasan?} Owner Blokir user dari semua fitur bot
/unblock {user} Owner Buka blokir user
/blocklist Owner Lihat daftar user yang sedang diblokir
/maintenance {status?} Owner Cek/ubah mode maintenance
/export {user} {format?} Owner Ekspor riwayat percakapan user ke file (.md/.txt)
/stats Owner Statistik pemakaian bot hari ini (panggilan, token, top user)
/status Owner Cek kesehatan Redis, QStash, AI Gateway
/audit-log {tipe?} Owner Timeline gabungan block/say/warn/error

⏱️ Command AI (/tanya, /translate, /ringkas, /rate) kena rate-limit per user (default 5x/60 detik) -- Owner dikecualikan. 🔄 /tanya, /translate, dan /ringkas yang gagal akan menampilkan tombol Coba Lagi -- klik untuk mengulang tanpa ketik ulang command.


🔑 Environment Variables

Klik untuk buka tabel lengkap ENV
Key Wajib Keterangan
DISCORD_PUBLIC_KEY Dari Discord Developer Portal -> General Information
DISCORD_TOKEN Bot Token -> Bot tab
DISCORD_APPLICATION_ID Application ID -> General Information
OWNER_ID opsional Default 1091901409668124805
VERCEL_PROXY_URL Base URL proxy AI OpenAI-compatible kamu
VERCEL_PROXY_KEY API key proxy AI kamu (isi bebas kalau gateway kamu sendiri tidak mewajibkan key)
VERCEL_PROXY_MODEL opsional Default gpt-4o-mini. Bisa dioverride runtime lewat /model set
MAX_HISTORY opsional Default 6 -- jumlah pasangan pesan yang disimpan per channel
AI_TIMEOUT_MS opsional Default 25000
SYSTEM_PROMPT opsional Override system prompt default untuk /tanya. Bisa dioverride runtime lewat /personality set
DISCORD_GUILD_ID opsional, hanya untuk deploy-commands.js Kalau diisi, command register instan ke 1 guild
UPSTASH_REDIS_REST_URL opsional* Dari Upstash Console -> Redis DB -> REST API
UPSTASH_REDIS_REST_TOKEN opsional* Dari Upstash Console -> Redis DB -> REST API
CONVERSATION_TTL_SECONDS opsional Default 3600
RATE_LIMIT_MAX opsional Default 5
RATE_LIMIT_WINDOW_SECONDS opsional Default 60
LOG_CHANNEL_ID opsional Channel Discord untuk log real-time /say, /warn, dan error otomatis
SAY_LOG_TTL_SECONDS opsional Default 2592000 (30 hari)
QSTASH_TOKEN Dari Upstash Console -> QStash
QSTASH_CURRENT_SIGNING_KEY Dari Upstash Console -> QStash
QSTASH_NEXT_SIGNING_KEY Dari Upstash Console -> QStash
QSTASH_URL opsional Default https://qstash-eu-central-1.upstash.io. Ganti ke https://qstash.upstash.io untuk region US
PUBLIC_BASE_URL URL project Vercel ini sendiri, tanpa trailing slash
STARTING_BALANCE opsional Default 10000 -- modal awal ZYC untuk user baru
LOAN_DUE_DAYS opsional Default 7 -- tenor pinjaman sebelum aset disita otomatis
MARKET_ANNOUNCEMENT_CHANNEL_ID opsional Channel pengumuman event pasar (fallback ke LOG_CHANNEL_ID)
RANDOM_EVENT_CHANCE opsional Default 0.15 (15%) -- peluang event pasar acak tiap price-update

*Redis opsional secara teknis (fail-open), tapi wajib untuk blocklist, rate-limit, /say logging, conversation memory, /stats, /model set, /personality set, /riwayat, /leaderboard, /warn, /audit-log, /export, /remind, tombol Retry, dan seluruh sistem trading ZYC & shop -- tanpa Redis, fitur-fitur itu senyap tidak aktif (bot inti tetap jalan).


✨ Fitur-Fitur Utama

📊 Stats & Token Usage

/stats mencatat jumlah panggilan command AI per hari dan, kalau gateway AI kamu meneruskan field usage.total_tokens di response (format OpenAI-compatible standar), juga mencatat total token terpakai dan top user berdasarkan token. Ini best-effort -- kalau gateway kamu tidak mengirim field itu, /stats tetap jalan normal, cuma bagian token-nya menampilkan "Tidak tersedia".

🔧 Model & Personality Override Runtime

/model set:<nama> dan /personality set:<teks> menyimpan nilai ke Redis, dibaca aiEngine.js tiap kali sebelum memanggil AI (prioritas di atas ENV). Nama model tidak divalidasi oleh bot -- kalau salah ketik, errornya muncul natural dari gateway AI kamu saat command AI berikutnya dipanggil. Pakai set:default di masing-masing command untuk kembali ke ENV.

Personality override cuma berlaku untuk /tanya -- /translate dan /ringkas selalu pakai instruksi presisi sendiri supaya outputnya tidak "terbawa" gaya kepribadian custom.

🔄 Retry Button

Kalau /tanya, /translate, atau /ringkas gagal (AI error atau gagal publish job), pesan error disertai tombol 🔄 Coba Lagi. Payload job asli disimpan sementara di Redis (TTL 15 menit, sama dengan masa berlaku interaction token Discord) -- klik tombol akan mengulang job yang sama tanpa perlu ketik command lagi.

⏰ Reminder via QStash Delay

/remind {waktu} {pesan} mendukung format waktu relatif (10m, 2h, 1d) maupun absolut (2026-08-22 15:00, diasumsikan WIB). Reminder dikirim lewat Bot Token langsung ke channel (bukan lewat interaction token, karena token itu expired setelah 15 menit -- sedangkan reminder bisa dijadwalkan sampai 30 hari ke depan).

📄 Export Percakapan

/export {user} {format?} mengekspor riwayat percakapan AI user tertentu di channel itu jadi file .md atau .txt yang bisa langsung didownload dari Discord -- pakai multipart upload asli (bukan sekadar teks panjang di embed).

📋 Audit Log Gabungan

/audit-log {tipe?} menampilkan timeline gabungan dari /block, /unblock, /say, /warn, dan error internal -- semua dalam satu command, bisa difilter per jenis. Berguna untuk lihat riwayat moderasi tanpa scroll channel log manual.

🚨 Error Logging Otomatis

Setiap error di processAiJob (AI gagal) atau di catch block utama api/index.js otomatis dikirim ke channel LOG_CHANNEL_ID (kalau diisi) -- berisi source error, user, channel, dan pesan error. Di-rate-limit sederhana (maks 1 notifikasi channel per 3 detik per warm instance) supaya error beruntun tidak spam channel -- tapi semua error tetap tercatat permanen ke audit log Redis, tidak ikut ter-rate-limit.


💹 Ekonomi Trading ZYC

Sistem ekonomi fiktif lengkap -- bukan sekadar "poin klaim harian". Ada 4 aset dengan karakter beda, event pasar acak, pinjaman, sampai bad debt. Semuanya jalan murni di atas Redis, tanpa exchange rate ke uang asli apa pun.

📈 4 Aset & Random Walk Harga
Aset Karakter Cocok Untuk
🟡 NORA (Norium) Volatilitas rendah, stabil Main aman, parkir modal
VOLT (Voltacoin) Volatilitas tinggi, ekstrem Spekulasi jangka pendek
📊 KRYN Trending, ada trendBias musiman Baca tren jangka menengah
💜 PLUM Paling sensitif terhadap event pasar Gambling seputar pengumuman

Harga tiap aset di-random-walk otomatis lewat process-price-update.js, dipicu QStash Schedule (cron, bukan job biasa) setiap 30 menit. Tiap update juga punya 15% kemungkinan (RANDOM_EVENT_CHANCE) memicu event pasar acak.

🎲 Event Pasar & Order Pending (`/posisi`)

Event pasar (naik/turun tajam pada aset tertentu) bisa terjadi otomatis (random) atau dipicu manual Owner lewat /market-event. Begitu event terpicu, bot mengumumkan T-1 menit ke MARKET_ANNOUNCEMENT_CHANNEL_ID lengkap dengan "prediksi" -- yang sengaja acak dan tidak terkait event asli, murni elemen gambling.

/posisi memungkinkan user pasang ancang-ancang sebelum tahu hasil event: order dieksekusi di harga setelah event berlangsung, bukan saat dipasang. Maksimal 1 order aktif per aset per user, dan divalidasi ulang saat eksekusi (order bisa batal kalau saldo berubah di antara pemasangan dan eksekusi).

💳 Pinjaman, Sita Otomatis & Bad Debt

/pinjam {jumlah} -- bebas nominal, tanpa bunga, tenor LOAN_DUE_DAYS hari (default 7). Status nunggak dicek setiap kali user memanggil command trading apa pun (bukan cron terpisah) -- begitu terdeteksi lewat tenor:

  1. Aset disita otomatis, dimulai dari yang termahal.
  2. Kalau nilai sitaan cukup menutup utang -- lunas, sisa aset (kalau ada) tetap milik user.
  3. Kalau tidak cukup -- sisa utang berubah jadi bad debt, butuh /debt-approve (Owner) untuk dihapuskan secara manual.
🤝 Trade Antar-User (Barter)

Sistem barter pakai keranjang bertahap: /trade-add-item (barang yang kamu tawarkan) dan /trade-request-item (barang yang kamu minta), maksimal 5 item per sisi. Hanya boleh 1 keranjang aktif per user secara global. Setelah siap, /trade-send mengirim penawaran ke user tujuan, yang membalas lewat /trade-accept atau /trade-reject (command terpisah, bukan tombol) -- penawaran kedaluwarsa otomatis dalam 10 menit. Sisi "minta" boleh dikosongkan untuk memberi barang secara cuma-cuma (gift sepihak).


🛍️ Shop, Kosmetik & Money Sink

Tempat ZYC "menguap" dari peredaran. Prinsipnya sederhana: item luxury tidak pernah bisa dijual balik -- begitu dibeli, ZYC-nya hilang permanen dari ekonomi, mencegah inflasi tanpa perlu mengubah sistem trading/utang inti.

🕵️ Utilitas & Consumable

Saat ini baru 🕵️ Sinyal Orang Dalam (LEAK_TOKEN) -- item sekali pakai. Dipakai lewat /leak, membaca event pasar aktif (data sesungguhnya, bukan prediksi acak seperti pengumuman publik) dan menampilkan arah pergerakannya sebelum diumumkan. Kalau belum ada event aktif, bot jujur bilang belum ada sinyal -- tidak ada info palsu yang dipaksakan.

🎨 Kosmetik Profil (Social Flexing)

Item equipable (warna tema embed, gelar/title) langsung tampil di header /portfolio begitu dipasang -- tidak butuh Discord Role sama sekali, murni disimpan di hash trading:cosmetics:{userId}. Contoh: 🎨 Tema Eclair Gold/Cyber Neon (ganti warna border embed), 🐋 Zypto Whale / 📉 Bear Market Survivor (gelar di judul portfolio).

🏎️ Luxury Collectibles & Validator Bertingkat

Kategori terbesar: supercar, superbike, motorsport, properti, fleet mewah, flex-art, sampai Ultimate Flex (Space Station). Semua permanen begitu dibeli -- tidak ada mekanisme jual balik, murni piala kekayaan yang tampil di field "🏝️ Koleksi Mewah" pada /portfolio.

Beberapa item flagship punya syarat berlapis sebelum bisa dibeli lewat /shop-buy, dicek berurutan di lib/shopItems.js:

  1. Saldo cukup -- gerbang paling dasar, semua item kena ini.
  2. Bebas utang (requiresDebtFree) -- dealer barang mewah "menolak" transaksi kalau kamu masih punya pinjaman aktif.
  3. Prasyarat kepemilikan (requiredItems) -- misal Ferrari LaFerrari/F80 mewajibkan sudah punya Ferrari Roma lebih dulu; Ninja H2R cukup salah satu dari 3 motor entry-level.
  4. Liquidity check (minReserveCash) -- sisa saldo setelah checkout wajib menyisakan persentase minimum dari harga barang (mis. Bugatti Chiron wajib sisa 15%), supaya user tidak checkout sampai saldo minus mepet.
  5. Syarat kategori (requiredCategories) -- misal Private Jet mewajibkan sudah punya minimal 1 Properti; Space Station mewajibkan kombinasi Jet/Yacht dan Properti sekaligus.

Semua barang di shop tidak menyentuh logika inti trading/utang -- checkout cuma memotong saldo cash lewat jalur adjustBalance yang sudah ada, tidak pernah mengubah harga aset, saldo pinjaman, atau state Redis lain di luar trading:inventory:{userId} dan trading:cosmetics:{userId}.


🏗️ Arsitektur QStash (kenapa ribet amat?)

Command yang butuh network call lama (panggil AI, atau beberapa network check paralel untuk /status) tidak bisa diproses langsung di request pertama -- Vercel Node Functions tidak menjamin kerja async lanjut berjalan setelah response HTTP pertama terkirim ke client. Solusinya, alurnya dipecah jadi dua request independen:

Discord --> POST /api                                    (request #1)
              |
              +- cek maintenance & blocklist & rate-limit (khusus command AI)
              +- publish job ke QStash (cepat, <1 detik)
              +- balas Type 5 (DEFERRED) ke Discord
                 ^ function #1 SELESAI di sini, tidak ada kerja lanjutan

QStash --> POST /api/process-ai . process-status . process-remind . process-export
              |                                            (request #2, independen)
              +- verifikasi signature QStash
              +- proses sesungguhnya, di-await penuh (aman karena request independen)
              +- PATCH hasil ke Discord webhook @original
                 ^ function #2 baru exit setelah semua tuntas

Command instan (/model, /avatar, /userinfo, /ping, /say, /stats, /riwayat, /coinflip, /roll, /ship, /timezone, /warn, /audit-log, /personality, dan semua command moderasi) tidak lewat alur ini -- dijawab langsung (Type 4) dalam response pertama.

⏰ QStash Schedule vs QStash Job biasa (klik untuk detail)

process-price-update.js dipanggil lewat QStash Schedule (cron */30 * * * *), bukan publishJob() biasa seperti job lainnya -- bedanya penting: Schedule tidak pernah mengirim body request (selalu kosong), sementara job biasa selalu membawa payload JSON.

Ini sempat jadi bug nyata: verifyAndParseQStashRequest di lib/qstashVerify.js awalnya langsung JSON.parse() raw body tanpa cek dulu, jadi meledak "Invalid JSON body" tiap Schedule terpanggil (signature-nya valid, cuma body-nya memang kosong). Fix-nya: cek dulu apakah raw body (setelah di-trim) panjangnya 0 -- kalau iya, langsung fallback ke {} tanpa pernah masuk JSON.parse(). Endpoint yang memang butuh payload asli tetap divalidasi normal; yang berubah cuma perlakuan untuk body yang memang seharusnya kosong.

🕒 QStash Schedule perlu didaftarkan manual sekali (klik untuk detail)

Beda dengan job biasa yang dipublish otomatis dari kode saat dibutuhkan, QStash Schedule harus didaftarkan sekali secara manual lewat scripts/setup-price-schedule.js (dijalankan langsung dari Termux/local, bukan bagian dari deploy otomatis):

QSTASH_TOKEN=xxx PUBLIC_BASE_URL=https://xxx.vercel.app node scripts/setup-price-schedule.js

Sekali terdaftar, Schedule ini permanen jalan di sisi Upstash tanpa perlu didaftarkan ulang -- kecuali kamu ganti PUBLIC_BASE_URL (redeploy ke domain baru) atau sengaja mau ubah interval cron-nya.

Perilaku tanpa Redis dikonfigurasi (klik untuk detail)

Semua fitur berbasis Redis fail-open:

  • Conversation memory, /riwayat -> kosong.
  • Blocklist -> tidak ada user yang diblokir.
  • Rate-limit -> tidak ada limit.
  • Maintenance switch -> selalu OFF.
  • /say & /warn logging ke Redis -> tidak tersimpan (log channel tetap jalan kalau LOG_CHANNEL_ID diisi).
  • /stats, /leaderboard, /audit-log -> menampilkan pesan "tidak tersedia" / kosong.
  • /model set, /personality set -> gagal dengan pesan error, tetap pakai ENV default.
  • Tombol Retry -> tidak muncul (pesan error tanpa tombol).
  • Seluruh sistem trading & shop (/portfolio, /buy, /sell, /pinjam, /shop-buy, dst) -> gagal dengan pesan error eksplisit, tidak fail-silent (uang fiktif tetap butuh integritas data, tidak boleh diam-diam kosong).
Sistem Permission /say & /warn (klik untuk detail)
  • Owner -> selalu boleh, di server manapun.
  • User dengan izin Discord Manage Messages -> boleh, cuma di server itu.
  • Setiap pemakaian /say tercatat dual: channel LOG_CHANNEL_ID (real-time) + Redis (permanen, lewat /audit-log).

🚀 Langkah Deploy

  1. Push project ini ke Vercel (vercel deploy atau via GitHub import).
  2. Isi semua ENV di atas pada Vercel Project Settings.
  3. Set Interactions Endpoint URL di Discord Developer Portal dengan URL /api project kamu.
  4. Register slash commands (jalankan sekali dari local/Termux):
    DISCORD_TOKEN=xxx DISCORD_APPLICATION_ID=xxx node deploy-commands.js
    Tambahkan DISCORD_GUILD_ID=xxx untuk testing instan di 1 server. Opsional, tapi sangat berguna untuk men-deploy slash-commands baru dengan cepat (misal untuk testing di 1 server khusus) -- kalau tidak diisi, maka hapus saja, tapi kalau bot sudah ada di beberapa server, slash-commands mungkin bisa memakan waktu ~1 jam untuk diperbarui dan muncul oleh Discord. Murni ketentuan Discord, bukan masalah kode.
  5. Undang bot ke server dengan scope applications.commands + bot.

🌍 Catatan Region QStash

Setiap akun QStash terikat permanen ke satu region (US atau EU) sejak pembuatan akun -- toggle tampilan di Upstash Console tidak memindahkan akun, cuma mengubah token mana yang ditampilkan.

Kalau muncul error user not found in this region, ambil ulang QSTASH_TOKEN + QSTASH_CURRENT_SIGNING_KEY + QSTASH_NEXT_SIGNING_KEY dari toggle yang sesuai region akun kamu, dan pastikan QSTASH_URL cocok. Ketiga nilai harus diambil bersamaan dari toggle yang sama -- jangan campur token region A dengan signing key region B.


🧭 Rencana Fitur (belum dikerjakan)

  • Auto-block sementara setelah kena rate-limit berkali-kali
  • /serverinfo, /banner {user}
  • /remind list -- lihat semua reminder aktif milik user
  • Persona per-channel (bukan cuma 1 slot global)
  • /whoami -- status blocked/rate-limit/permission milik pemanggil
  • Konfirmasi tombol sebelum aksi destruktif (/reset scope:all)
  • Buff temporer trading (mis. badge "Insider" sementara, fee waiver)
  • /flex terpisah kalau daftar koleksi luxury makin panjang untuk ditampilkan di /portfolio
  • Retry button saat AI gagal selesai
  • /leaderboard, /coinflip, /roll selesai
  • /remind {waktu} {pesan} selesai
  • Export percakapan ke file selesai
  • /rate, /ship, /timezone, /personality, /warn, /audit-log selesai
  • Sistem trading ZYC: 4 aset, event pasar, pinjaman + bad debt, barter antar-user selesai
  • Shop: utilitas (/leak), kosmetik profil, luxury collectibles money sink selesai
  • "thinking..." lebih informatif -- dilewati (Discord tidak izinkan custom teks deferred, dan PATCH ganda dianggap tidak worth it)

👨‍💻 Catatan pengembangan kode

Seluruh kode ini dibuat dan diuji langsung oleh owner, BoltZy. Dilengkapi dengan penalaran Claude Sonnet 5 untuk troubleshoot masalah dan penambahan fitur slash commands, dan beberapa menggunakan Gemini 3.6 flash untuk memecahkan sebagian kecil masalah dan merancang struktur prompting untuk menghemat token Claude. Semua struktur kode itu adalah hasil vibe coding dari BoltZy dari hp langsung menggunakan QuickEdit dan Termux, disempurnakan dengan AI. 90% kodenya adalah hasil AI, so jangan berharap kesempurnaan mutlak.

⚠️ Penting

Jangan pernah hardcoded .env yang berisi API, token, dan hal sensitif lainnya lalu upload ke repo/fork github. Gunakan logika sync saja agar bisa menarik .env dari penyedia host (Vercel di environment and variable).

📄 Lisensi

Project ini dirilis di bawah MIT License — bebas dipakai, diubah, di-fork, bahkan dikomersialkan siapa saja, TAPI disediakan apa adanya ("AS IS") tanpa jaminan apa pun. Kalau lo fork ini terus ada yang error, rusak, atau nimbulin masalah di server lo — itu tanggung jawab lo sendiri, bukan gw. Baca lengkapnya di file LICENSE. Pake translate kalo lu ga paham bahasa inggris, atau langsung tanya AI aja, gausah dipersulit.

Klik untuk lihat isi lengkap lisensi
MIT License

Copyright (c) 2026 BoltZyy

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

💬 Catatan Owner (BoltZy)

Kalau bot down di server gw, berarti sedang maintenance kode atau troubleshoot. Jangan nanya kapan beresnya, gw pun gatau karena project ini memang cuman ide iseng yang akhirnya jadi bot Discord di waktu senggang gw. Gw ngerjain kode ini purely karena gw seneng dan ada kemauan, bukan karena tuntutan semata. Kalo mau bikin bot sendiri berbasis repo ini, fork aja trus belajar gimana caranya hosting Vercel, ngerti Upstash redis kalo mau nyimpen history chat (opsional), QStash wajib biar bisa nipu ketentuan "3 detik" balasan discord (deferred type:5, queue QStash pas AI proses jawaban), masukin variabel ENV lgsg di dashboard hosting, troubleshoot (bisa pakai AI gratisan, asal mau comply sama usage limit mereka), dan yang pasti minimal ngerti struktur kodenya aja dulu (download .zip repo ini, terus lempar ke AI, suruh jelasin apa aja yg perlu diubah).

About

Multi-purpose Serverless Discord Bot featuring AI Chat, Market & Economy Engine, Utilities, and Moderation — built on Node.js, Redis, and QStash.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages