diff --git a/CLAUDE.md b/CLAUDE.md index 8733bbe..d9fd14e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -68,9 +68,8 @@ AI Moderation: Express 5 + Helmet HTTP server with WebSocket (ws) on port 3001 (default). -**REST API endpoints:** +**REST API endpoints (all public):** - `GET /api/health` — Health check with optional `?verbose=true` -- `POST /api/auth/login` — Admin authentication - `GET /api/config` — App configuration - `GET /api/messages` — List messages (cursor pagination) - `GET /api/messages/:channelId` — Messages by channel @@ -102,7 +101,6 @@ Express 5 + Helmet HTTP server with WebSocket (ws) on port 3001 (default). **Modules (feature-based, under `src/modules/`):** - `health/` — Database connectivity check -- `auth/` — Admin password auth - `messages/` — Message + attachment CRUD, review, reanalyze - `voice/` — Voice connection, guilds, channels - `media/` — Music/screenshare player control @@ -397,7 +395,7 @@ pnpm run install:yt-dlp # Deploy to VPS (build + hot-patch running containers) ./deploy.sh # Build + deploy all services -./deploy.sh --frontend # Frontend WASM only +./deploy.sh --frontend # Frontend (Next.js) only ./deploy.sh --backend # Backend TypeScript only ./deploy.sh --no-build # Skip build, just copy files ``` @@ -463,7 +461,7 @@ Configuration via `.env` (see `.env.example`). Managed by Zod schemas: - `OPENAI_MODERATION_API_KEY`, `OPENAI_MODERATION_BASE_URL`, `OPENAI_MODERATION_MODEL` ### Backend -- `WEBSERVER_PORT` (3001), `ADMIN_PASSWORD` (admin123) +- `WEBSERVER_PORT` (3001) - `BACKLOG_SYNC_HOURS` (24), `BACKLOG_SYNC_BATCH_SIZE` (100) ### Retention @@ -552,9 +550,9 @@ discord-gateway handles SIGINT/SIGTERM/uncaughtException/unhandledRejection: 5. Destroy Discord client 6. Exit process -### Admin Authentication +### Public API -Backend endpoints are protected by `X-Admin-Password` header matching `ADMIN_PASSWORD` env var. The frontend stores the password in `localStorage`. +All backend endpoints are publicly accessible — no authentication required. ## Recording Structure diff --git a/README.md b/README.md index eae5b09..7c466ad 100644 --- a/README.md +++ b/README.md @@ -1,215 +1,118 @@ -# Discord Moderation Watcher Bot +# Bete — Discord Moderation Dashboard -Bot monitoring Discord yang merekam voice channel, menangkap pesan teks, menyimpan attachment, menjalankan analisis opsional, dan menyediakan dashboard web real-time. +Bot monitoring Discord yang merekam voice channel, menangkap pesan teks, menyimpan attachment, menjalankan analisis AI opsional, dan menyediakan dashboard web real-time. -Stack utama: Node.js, pnpm, TypeScript, `discord.js-selfbot-v13`, `@discordjs/voice`, Express, WebSocket, Drizzle ORM, SQLite/PostgreSQL, React, Vite, Vitest, dan Biome. +**Stack utama:** Node.js (Express 5), pnpm, TypeScript, React 19 (Next.js 16), Tailwind v4, shadcn/ui, Drizzle ORM, PostgreSQL, WebSocket, Redis pub/sub. ## Prasyarat -- Node.js versi modern yang kompatibel dengan TypeScript dan Vite. -- pnpm 10.x. Repo ini dipin ke `pnpm@10.25.0`. -- FFmpeg tersedia di `PATH` untuk proses muxing audio dan playback media. -- `yt-dlp` tersedia di `PATH` untuk resolve audio YouTube, search result YouTube, dan Spotify track. -- Native audio dependencies dapat dibuild di mesin lokal (`@discordjs/opus`, `better-sqlite3`, `sodium-native`). - -Install FFmpeg: - -```bash -# Ubuntu/Debian -sudo apt install ffmpeg - -# Arch -sudo pacman -S ffmpeg -``` - -Install `yt-dlp`: - -```bash -pnpm run install:yt-dlp -``` - -Script installer akan memakai package manager yang tersedia (`pacman`, `apt-get`, `dnf`, `brew`) atau fallback ke `pipx`/`pip`. +- Node.js 22+ +- pnpm 11.x +- FFmpeg di `PATH` (untuk audio muxing dan playback media) +- `yt-dlp` di `PATH` (untuk resolve audio YouTube/Spotify) +- Bun (untuk frontend dev — opsional, bisa pake pnpm) +- PostgreSQL 15+ ## Setup ```bash pnpm install cp .env.example .env +# Edit .env sesuai konfigurasi server ``` -Edit `.env` sesuai server yang dimonitor: - -```env -DISCORD_TOKEN=your_token_here -MONITOR_GUILD_ID=your_guild_id_here -RECORDINGS_DIR=./recordings -WEBSERVER_PORT=3000 -DATABASE_TYPE=sqlite -``` - -Catatan: project ini memakai selfbot library, bukan bot token Discord standar. Pastikan penggunaan sesuai risiko dan aturan platform yang berlaku. - ## Menjalankan ```bash -# Bot/server utama dengan auto-restart -pnpm run dev +# Backend (port 3001) +pnpm run dev:backend -# Production-style start -pnpm run start +# Discord Gateway (capture messages, voice, dll) +pnpm run dev:discord-gateway -# Dashboard frontend dev server +# Frontend (port 3000) pnpm run dev:web ``` -Dashboard build production disajikan dari `public/app` setelah menjalankan: +## Build ```bash -pnpm run build:web +pnpm run build:backend +pnpm run build:discord-gateway +pnpm run build:web # next build — static export ke out/ +pnpm run build # build semua service ``` -## Command Development +## Deploy ```bash -# Type checking -pnpm run typecheck - -# Lint -pnpm run lint - -# Format -pnpm run format - -# Test -pnpm run test - -# Build frontend + TypeScript -pnpm run build - -# Install external yt-dlp CLI for YouTube/search/Spotify track playback -pnpm run install:yt-dlp +./deploy.sh # Build + deploy semua service ke VPS +./deploy.sh --frontend # Frontend only +./deploy.sh --backend # Backend only +./deploy.sh --no-build # Skip build, copy files aja ``` -## Database +## Service Architecture -Default database adalah SQLite di `.muxer-queue.db`. PostgreSQL dapat dipakai dengan `DATABASE_TYPE=postgres` dan konfigurasi `DATABASE_URL` atau variabel `POSTGRES_*`. - -Jika aplikasi dijalankan di PostgreSQL production, migrasi dapat dijalankan otomatis saat startup dengan `AUTO_MIGRATE_ON_STARTUP=true`. Jalur ini memakai advisory lock supaya hanya satu instance yang memigrasi schema pada satu waktu. - -```bash -# Generate migration Drizzle -pnpm run db:generate - -# Jalankan migration via drizzle-kit -pnpm run db:migrate - -# Jalankan migration programmatic -pnpm run db:migrate:programmatic - -# Buka Drizzle Studio -pnpm run db:studio +``` +Discord + | + v +discord-gateway ←→ Redis ←→ backend (Express 5) ←→ frontend (Next.js) + | pub/sub | | + | +— REST API (/api/*) | + | +— WebSocket (/ws) | + +— message capture +— AI moderation | + +— voice recording +— dashboard data +— dashboard UI + +— attachment upload +— real-time updates ``` ## Fitur -- Voice recording ke segment `.ogg` per user. -- Metadata JSON per segment audio. -- Text message capture untuk pesan baru, edit, dan delete. -- Attachment capture dan upload ke endpoint Picser. -- SQLite/PostgreSQL via Drizzle ORM. -- REST API dan WebSocket untuk dashboard. -- Dashboard React untuk pesan, gambar, voice, media playback, dan moderation review. -- Media playback dari direct URL, file lokal, YouTube URL, search terms, dan Spotify track URL. -- Metrics Prometheus di endpoint server. -- Retry dengan backoff untuk operasi eksternal. -- AI moderation analysis opsional via konfigurasi `AI_*`. - -## Struktur Rekaman - -```text -recordings/ - / - --0.ogg - --0.json - --1.ogg - --1.json -``` - -Segment duration dikontrol oleh `RECORDING_SEGMENT_MS`. +- **Message capture**: Capture pesan baru, edit, dan delete dari Discord +- **Voice recording**: Rekam voice channel ke segmen OGG per user, streaming PCM real-time ke WebSocket +- **Attachment upload**: Download + upload attachment ke external storage +- **AI moderation**: Analisis pesan opsional via LLM, auto-delete, queue management +- **Dashboard**: Messages feed, AI analysis review, voice connection, music player, recordings, user/channel stats +- **Media playback**: Playback dari URL, file lokal, YouTube, Spotify +- **WebSocket**: Real-time event streaming untuk semua aktivitas +- **Public API**: Semua endpoint REST dan WebSocket dapat diakses tanpa autentikasi ## Struktur Proyek -```text -src/ - index.ts Entry point Discord client dan server - recorder.ts Voice recording pipeline - recorder/ Audio stream, decoder, segment metadata - moderation/ Message capture, storage, uploads, AI review - database/ Drizzle setup, schema, migrations - routes/ Express route modules - webserver.ts Express + WebSocket server - retry.ts Retry helper berbasis p-retry - audio/ffmpegProcess.ts Direct ffmpeg process wrapper -frontend/ React dashboard source -public/app/ Dashboard build output -tests/ Vitest tests -drizzle/migrations/ Database migrations +``` +services/ +├── backend/ # Express 5 REST API + WebSocket server +│ ├── src/modules/ # Feature modules (messages, voice, media, dll) +│ └── src/http/ # Express app setup, middleware +├── discord-gateway/ # Discord client, voice recording, AI analysis +│ ├── src/modules/ # message-capture, voice-recording, ai-moderation +│ └── src/shared/ # Config, database, Discord client +└── frontend/ # Next.js 16 dashboard (static export) + ├── src/app/ # Pages (login, dashboard tabs) + ├── src/features/ # Feature components (dashboard, live, messages) + └── src/lib/ # API client, WebSocket, types +packages/ +└── shared/ # Shared types, errors, logger, utilities ``` -## Konfigurasi Penting +## Database -Lihat `.env.example` untuk daftar lengkap. Variabel utama: - -- `DISCORD_TOKEN` — token akun/client yang dipakai selfbot. -- `MONITOR_GUILD_ID` — guild yang dimonitor untuk moderation capture. -- `RECORDINGS_DIR` — direktori output audio. -- `WEBSERVER_PORT` — port HTTP/WebSocket. -- `DATABASE_TYPE` — `sqlite` atau `postgres`. -- `PICSER_UPLOAD_URL` — endpoint upload attachment. -- `AI_ANALYSIS_ENABLED` — aktifkan/nonaktifkan analisis AI. -- `AI_LLM_API_KEY`, `AI_LLM_BASE_URL`, `AI_LLM_MODEL` — konfigurasi provider LLM. - -## Deploy ke VPS - -Project menggunakan `deploy.sh` untuk build + deploy manual ke VPS. Script ini -membangun backend (TypeScript) dan frontend (WASM Leptos) lalu menyalinnya ke -dalam container Docker yang sudah berjalan di VPS. +PostgreSQL via Drizzle ORM. Migrasi: ```bash -# Build + deploy semua service -./deploy.sh - -# Deploy frontend saja (setelah perubahan UI) -./deploy.sh --frontend - -# Deploy backend saja -./deploy.sh --backend - -# Deploy tanpa rebuild (file sudah terbuild sebelumnya) -./deploy.sh --no-build +pnpm run db:generate # Generate migration +pnpm run db:migrate # Apply migration +pnpm run db:studio # Drizzle Studio ``` -Credentials diambil otomatis dari GitLab CI variables via `glab`. Atau set manual: +## WebSocket Events -```bash -export VPS_HOST="your-vps-ip" -export VPS_USER="root" -export VPS_SSH_KEY="~/.ssh/id_ed25519" -./deploy.sh -``` +Backend broadcast event berikut ke frontend via WebSocket: -## Verifikasi Setelah Perubahan - -Sebelum menjalankan lama atau deploy, jalankan: - -```bash -pnpm install -pnpm run typecheck -pnpm run lint -pnpm run test -pnpm run build -``` - -## Catatan Library Modernization - -Project memakai Zod untuk validasi runtime, Drizzle untuk database, dan wrapper `node:child_process` langsung untuk FFmpeg. Library lama `class-transformer`, `class-validator`, dan `fluent-ffmpeg` sudah tidak dipakai. +- `message_created`, `message_updated`, `message_deleted`, `message_analyzed` +- `attachment_created`, `attachment_uploaded` +- `voice_recording_started`, `voice_recording_stopped`, `voice_recording_uploaded` +- `voice_active_user`, `voice_pcm_data` +- `media_state` +- `reaction_*`, `thread_*`, `presence_updated`, `guild_member_*` diff --git a/services/backend/ARCHITECTURE.md b/services/backend/ARCHITECTURE.md index 0af93e2..d00e812 100644 --- a/services/backend/ARCHITECTURE.md +++ b/services/backend/ARCHITECTURE.md @@ -15,7 +15,7 @@ services/backend/ │ │ ├── logger/ │ │ │ └── index.ts # Pino logger with child context support │ │ ├── middlewares/ -│ │ │ └── index.ts # Express middleware (errorHandler, asyncHandler, adminAuth) +│ │ │ └── index.ts # Express middleware (errorHandler, asyncHandler, rateLimit) │ │ └── utils/ # Utility functions (placeholder) │ │ │ ├── modules/ # Feature modules (Modular MVC pattern) diff --git a/services/frontend/AGENTS.md b/services/frontend/AGENTS.md index 8bd0e39..a76bc50 100644 --- a/services/frontend/AGENTS.md +++ b/services/frontend/AGENTS.md @@ -1,5 +1,10 @@ - -# This is NOT the Next.js you know +# Bete Frontend — Project Overview -This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` before writing any code. Heed deprecation notices. - +Next.js 16 (App Router), React 19, TypeScript strict, Tailwind v4, shadcn/ui, base-ui. + +Key points: +- **All pages** are `"use client"` — the dashboard is fully client-rendered +- **API client** at `src/lib/api/` — fetch-based, covers all 30+ backend endpoints +- **WebSocket** at `src/lib/ws/` — auto-reconnecting client with typed event subscriptions +- **Static export**: `output: "export"` in next.config.ts, served via nginx +- **No authentication**: all endpoints are public diff --git a/services/frontend/README.md b/services/frontend/README.md index e215bc4..a0370b4 100644 --- a/services/frontend/README.md +++ b/services/frontend/README.md @@ -1,36 +1,41 @@ -This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). +# Bete Frontend -## Getting Started +Next.js 16 (React 19) dashboard untuk Discord Moderation Watcher. -First, run the development server: +**Stack:** Next.js 16 (App Router, static export), React 19, TypeScript strict, Tailwind v4, shadcn/ui, base-ui, lucide-react. + +## Dev ```bash -npm run dev -# or -yarn dev -# or -pnpm dev -# or -bun dev +bun run dev # next dev — port 3000 +bun run build # next build — static export ke out/ +bun run lint # Biome check ``` -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. +## Architecture -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. +``` +src/ +├── app/ # Pages +│ ├── page.tsx # Redirect ke /dashboard +│ └── dashboard/ # Dashboard layout + tabs +│ ├── layout.tsx # Sidebar, header, WS provider, chatbot +│ └── page.tsx # Tab routing (messages/live/dashboard) +├── features/ +│ ├── messages/ # Message feed, search, review, detail modal +│ ├── live/ # Voice connection, music player, recordings +│ ├── dashboard/ # Stats, users, channels overview +│ └── mascot/ # AI chatbot +├── lib/ +│ ├── api/ # Fetch-based API client (all BE endpoints) +│ ├── ws/ # WebSocket client + React context +│ └── hooks/ # Shared hooks (config, auth) +└── components/ + └── layout/ # Sidebar, header, mobile tab bar +``` -This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. +## API -## Learn More +Backend berjalan di port 3001. Frontend mengakses API via `window.location` (same-origin atau proxy). -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. - -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. +WebSocket terhubung otomatis ke `/ws` di host yang sama.