package bossraid import ( "log" "github.com/gofiber/fiber/v2" ) type Handler struct { svc *Service } func NewHandler(svc *Service) *Handler { return &Handler{svc: svc} } func bossError(c *fiber.Ctx, status int, userMsg string, err error) error { log.Printf("bossraid error: %s: %v", userMsg, err) return c.Status(status).JSON(fiber.Map{"error": userMsg}) } // RequestEntry handles POST /api/internal/bossraid/entry // Called by MMO server when a party requests boss raid entry. func (h *Handler) RequestEntry(c *fiber.Ctx) error { var req struct { Usernames []string `json:"usernames"` BossID int `json:"bossId"` } if err := c.BodyParser(&req); err != nil { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "잘못된 요청입니다"}) } if len(req.Usernames) == 0 || req.BossID <= 0 { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "usernames와 bossId는 필수입니다"}) } for _, u := range req.Usernames { if len(u) == 0 || len(u) > 50 { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "유효하지 않은 username입니다"}) } } room, err := h.svc.RequestEntry(req.Usernames, req.BossID) if err != nil { return bossError(c, fiber.StatusConflict, err.Error(), err) } return c.Status(fiber.StatusCreated).JSON(fiber.Map{ "roomId": room.ID, "sessionName": room.SessionName, "bossId": room.BossID, "players": req.Usernames, "status": room.Status, }) } // StartRaid handles POST /api/internal/bossraid/start // Called by dedicated server when the Fusion session begins. func (h *Handler) StartRaid(c *fiber.Ctx) error { var req struct { SessionName string `json:"sessionName"` } if err := c.BodyParser(&req); err != nil { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "잘못된 요청입니다"}) } if req.SessionName == "" { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "sessionName은 필수입니다"}) } room, err := h.svc.StartRaid(req.SessionName) if err != nil { return bossError(c, fiber.StatusBadRequest, err.Error(), err) } return c.JSON(fiber.Map{ "roomId": room.ID, "sessionName": room.SessionName, "status": room.Status, }) } // CompleteRaid handles POST /api/internal/bossraid/complete // Called by dedicated server when the boss is killed. Distributes rewards. func (h *Handler) CompleteRaid(c *fiber.Ctx) error { var req struct { SessionName string `json:"sessionName"` Rewards []PlayerReward `json:"rewards"` } if err := c.BodyParser(&req); err != nil { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "잘못된 요청입니다"}) } if req.SessionName == "" { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "sessionName은 필수입니다"}) } room, results, err := h.svc.CompleteRaid(req.SessionName, req.Rewards) if err != nil { return bossError(c, fiber.StatusBadRequest, err.Error(), err) } return c.JSON(fiber.Map{ "roomId": room.ID, "sessionName": room.SessionName, "status": room.Status, "rewardResults": results, }) } // FailRaid handles POST /api/internal/bossraid/fail // Called by dedicated server on timeout or party wipe. func (h *Handler) FailRaid(c *fiber.Ctx) error { var req struct { SessionName string `json:"sessionName"` } if err := c.BodyParser(&req); err != nil { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "잘못된 요청입니다"}) } if req.SessionName == "" { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "sessionName은 필수입니다"}) } room, err := h.svc.FailRaid(req.SessionName) if err != nil { return bossError(c, fiber.StatusBadRequest, err.Error(), err) } return c.JSON(fiber.Map{ "roomId": room.ID, "sessionName": room.SessionName, "status": room.Status, }) } // GetRoom handles GET /api/internal/bossraid/room // Query param: sessionName func (h *Handler) GetRoom(c *fiber.Ctx) error { sessionName := c.Query("sessionName") if sessionName == "" { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "sessionName은 필수입니다"}) } room, err := h.svc.GetRoom(sessionName) if err != nil { return bossError(c, fiber.StatusNotFound, "방을 찾을 수 없습니다", err) } return c.JSON(room) }