# dc_mbahdesmond

Discord bot + API untuk duty log, upload media, dan rekap statistik duty.

## Fitur

- Upload media dari channel khusus ke API tujuan.
- Auto delete pesan non-media di channel upload.
- Deteksi spam dan pemberian role spam.
- Command Discord untuk rekap duty mingguan, bulanan, user, dan on-duty.
- REST API untuk ambil data duty dari MySQL.
- Duty webhook handler untuk menyimpan log `on duty` dan `off duty`.

## Setup

1. Install dependency:

```bash
npm install
```

2. Copy `.env.example` ke `.env`, lalu isi nilainya.

3. Jalankan bot:

```bash
node index.js
```

## Environment

```env
DISCORD_TOKEN=
CHANNEL_ID=
API_UPLOAD_URL=
COOKIE=
SPAM_ROLE_ID=
DUTY_CHANNEL_ID=
DUTY_CHANNELS=
DUTY_JOB=
MYSQL_HOST=
MYSQL_USER=
MYSQL_PASS=
MYSQL_DB=
PORT=3000
```

### Keterangan singkat

- `CHANNEL_ID`: channel upload media.
- `API_UPLOAD_URL`: endpoint upload gambar/video.
- `COOKIE`: cookie untuk request upload jika dibutuhkan.
- `SPAM_ROLE_ID`: role yang diberikan ke user spam.
- `DUTY_CHANNEL_ID` / `DUTY_CHANNELS`: channel webhook duty.
- `MYSQL_*`: koneksi database duty log.
- `PORT`: port API Express.

## Discord Commands

Command bisa dipanggil dengan prefix `!` atau `?`.

### `!top-week [job]`

Menampilkan total duty minggu berjalan.

Contoh:

```text
!top-week
!top-week usms
!top-week doj
```

### `!bulan <bulan> [job]`

Menampilkan total duty per bulan.

Contoh:

```text
!bulan april
!bulan april usms
```

### `!user <@mention|discord_id> [job]`

Menampilkan total duty dan 5 riwayat duty terakhir untuk user tertentu.

Contoh:

```text
!user @username
!user 123456789012345678
!user @username usms
```

### `!duty [job]`

Menampilkan user yang sedang on duty.

Contoh:

```text
!duty
!duty usms
```

### Catatan command

- Filter `job` bersifat case-insensitive.
- Output panjang otomatis dipecah agar tidak kena batas 2000 karakter Discord.
- Jika command gagal, bot akan membalas `Terjadi error saat memproses command.`

## API

Base path: `/api`

Semua request memakai `POST` dengan header `Content-Type: application/json`.

### `POST /api`

Body umum:

```json
{
  "type": "top-week",
  "job": "usms",
  "week": "week17",
  "date": "current"
}
```

#### `type: top-week`

Body:

```json
{
  "type": "top-week",
  "job": "usms",
  "week": "week17"
}
```

#### `type: month`

Body:

```json
{
  "type": "month",
  "month": "april",
  "job": "usms"
}
```

#### `type: online-duty`

Body:

```json
{
  "type": "online-duty",
  "job": "usms"
}
```

#### `type: user`

Body:

```json
{
  "type": "user",
  "id": "123456789012345678",
  "job": "usms"
}
```

#### `type: payroll`

Current:

```json
{
  "type": "payroll",
  "date": "current",
  "job": "usms"
}
```

Custom:

```json
{
  "type": "payroll",
  "date": "custom",
  "start": "2026-05-01T00:00:00Z",
  "end": "2026-05-07T23:59:59Z",
  "job": "usms"
}
```

### Response umum

```json
{
  "status": true,
  "message": "success",
  "type": "top-week",
  "data": []
}
```

### Response top-week

```json
{
  "status": true,
  "message": "success",
  "type": "top-week",
  "week": {
    "key": "2026/week17",
    "label": "2026/Week 17",
    "year": 2026,
    "number": 17
  },
  "filter": {
    "job": "usms"
  },
  "data": []
}
```

### Response payroll current

```json
{
  "status": true,
  "message": "success",
  "type": "payroll",
  "date": "current",
  "period": {},
  "filter": {
    "job": "usms"
  },
  "data": []
}
```

### Response payroll custom

```json
{
  "status": true,
  "message": "success",
  "type": "payroll",
  "date": "custom",
  "period": {},
  "filter": {
    "job": "usms"
  },
  "data": []
}
```

### Catatan

- `type` mendukung: `top-week`, `month`, `online-duty`, `user`, `payroll`.
- `month` juga menerima typo lama `mounth`.
- `week` bisa diisi `week17` atau `2026/week17`.
- Kalau `type=user`, isi `id` wajib ada.
- Kalau `type=payroll` dan `date=custom`, `start` dan `end` wajib ada.
- Route GET lama sudah dihapus supaya API lebih rapi dan satu pintu.

## Duty Webhook Flow

Bot membaca pesan webhook di channel duty yang terdaftar, lalu:

- mendeteksi event `Going On Duty`
- menyimpan data ke `active_duty`
- mendeteksi event `Shift Duration`
- memindahkan data ke `duty_logs`
- menghapus data aktif dari `active_duty`

## Catatan penting

- `top-week` memakai week key rolling berbasis Sabtu 18:00 WIB dengan format `YYYY/weekN`.
- `month_name` disimpan dalam bahasa Indonesia.
- Job filter menggunakan pencocokan case-insensitive.
- Command output panjang akan dikirim dalam beberapa pesan jika perlu.
