# Sticker System

## Overview
Players can upload custom stickers to use in chat messages. Stickers are uploaded as images, automatically processed (resized, compressed, converted to WebP), stored on Cloudinary, and can be sent in any chat channel. Each sticker costs **300 💵 Cash** to upload.

---

## How It Works

Stickers are managed entirely through the website UI (REST API), not through chat commands.

### Sticker Upload

**Endpoint:** `POST /api/stickers/upload`

**Cost:** 300 💵 Cash per sticker

**Accepted formats:** JPEG, PNG, WebP, GIF

**Max file size:** 500 KB

### Processing Pipeline
1. **Validate** — check file type and size
2. **Resize** — max 512×512px (fit inside, no enlargement)
3. **Convert** — all formats converted to WebP (quality 75)
4. **Animated GIF** — converted to animated WebP (max 10 loops)
5. **Upload** — stored on Cloudinary at `advenexus/stickers/{userId}_{uuid}`
6. **Deduct Cash** — only after successful upload (300 💵)
7. **Save** — sticker record stored in `user_stickers` table

### Sticker Record

| Field | Description |
|---|---|
| `id` | UUID |
| `user_id` | Owner's user ID |
| `sticker_url` | Cloudinary URL |
| `created_at` | Unix timestamp |

---

## API Endpoints

| Endpoint | Method | Description |
|---|---|---|
| `/api/stickers/upload` | POST | Upload a new sticker (multipart form, 300 💵) |
| `/api/stickers/mine` | GET | Get your own stickers |
| `/api/stickers/user/:userId` | GET | Get stickers for a specific user (for chat rendering) |
| `/api/stickers/:stickerId` | DELETE | Delete one of your stickers |

---

## Sending Stickers

Stickers are sent in chat messages via the client UI:
- Player selects a sticker from their collection
- The sticker URL is embedded in the message
- Other players see the sticker image rendered inline

---

## Deleting Stickers

- Players can delete their own stickers
- Deletion removes the record from `user_stickers`
- Cloudinary image is also cleaned up (non-critical — if cleanup fails, the DB record is still removed)
- **No Cash refund** on deletion

---

## Edge Cases

- Cash is only deducted **after** successful Cloudinary upload — if upload fails, no charge
- If the database save fails after upload, the Cloudinary image is cleaned up and no charge occurs
- Animated GIFs are supported but limited to 10 loop iterations
- Images larger than 512px are scaled down proportionally (no enlargement for small images)
- Each sticker gets a unique Cloudinary public ID: `advenexus/stickers/{userId}_{8-char-uuid}`
- Sticker spending is logged in `cash_transactions` (type: `spend`, description: `Sticker upload`)
