158 lines
3.8 KiB
Go
158 lines
3.8 KiB
Go
package adminhandler
|
|
|
|
import (
|
|
"errors"
|
|
"net/http"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
modlogic "spark-server/internal/module/moderation/logic"
|
|
"spark-server/internal/pkg/errs"
|
|
"spark-server/internal/pkg/reqctx"
|
|
"spark-server/internal/pkg/validate"
|
|
"spark-server/internal/transport/http/respond"
|
|
)
|
|
|
|
type ModerationHandler struct {
|
|
svc *modlogic.Service
|
|
}
|
|
|
|
func NewModeration(svc *modlogic.Service) *ModerationHandler {
|
|
return &ModerationHandler{svc: svc}
|
|
}
|
|
|
|
func (h *ModerationHandler) ready(c *gin.Context) bool {
|
|
if h == nil || h.svc == nil || !h.svc.Ready() {
|
|
Fail(c, http.StatusServiceUnavailable, "moderation 服务未就绪")
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
func (h *ModerationHandler) ListWords(c *gin.Context) {
|
|
if !h.ready(c) {
|
|
return
|
|
}
|
|
page, _ := strconv.Atoi(c.DefaultQuery("page", "0"))
|
|
size, _ := strconv.Atoi(c.DefaultQuery("size", "50"))
|
|
cat, _ := strconv.Atoi(c.Query("category"))
|
|
var enabled *bool
|
|
if v := c.Query("enabled"); v == "1" || v == "true" {
|
|
enabled = ptrBool(true)
|
|
} else if v == "0" || v == "false" {
|
|
enabled = ptrBool(false)
|
|
}
|
|
list, total, err := h.svc.ListWords(c.Request.Context(), c.Query("q"), cat, enabled, page, size)
|
|
if err != nil {
|
|
Fail(c, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
OK(c, gin.H{"items": list, "total": total})
|
|
}
|
|
|
|
func (h *ModerationHandler) CreateWord(c *gin.Context) {
|
|
if !h.ready(c) {
|
|
return
|
|
}
|
|
var in modlogic.CreateWordInput
|
|
if err := respond.BindJSON(c, &in); err != nil {
|
|
return
|
|
}
|
|
if err := validate.StructLang(reqctx.Lang(c.Request.Context()), &in); err != nil {
|
|
respond.JSONError(c, err)
|
|
return
|
|
}
|
|
out, err := h.svc.CreateWord(c.Request.Context(), &in)
|
|
if err != nil {
|
|
failModeration(c, err)
|
|
return
|
|
}
|
|
OK(c, out)
|
|
}
|
|
|
|
func (h *ModerationHandler) PatchWord(c *gin.Context) {
|
|
if !h.ready(c) {
|
|
return
|
|
}
|
|
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
|
if err != nil || id <= 0 {
|
|
Fail(c, http.StatusBadRequest, "invalid id")
|
|
return
|
|
}
|
|
var in modlogic.PatchWordInput
|
|
if err := respond.BindJSON(c, &in); err != nil {
|
|
return
|
|
}
|
|
if err := h.svc.PatchWord(c.Request.Context(), id, &in); err != nil {
|
|
failModeration(c, err)
|
|
return
|
|
}
|
|
OK(c, gin.H{"ok": true})
|
|
}
|
|
|
|
func (h *ModerationHandler) DeleteWord(c *gin.Context) {
|
|
if !h.ready(c) {
|
|
return
|
|
}
|
|
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
|
if err != nil || id <= 0 {
|
|
Fail(c, http.StatusBadRequest, "invalid id")
|
|
return
|
|
}
|
|
if err := h.svc.DeleteWord(c.Request.Context(), id); err != nil {
|
|
failModeration(c, err)
|
|
return
|
|
}
|
|
OK(c, gin.H{"ok": true})
|
|
}
|
|
|
|
func (h *ModerationHandler) Reload(c *gin.Context) {
|
|
if !h.ready(c) {
|
|
return
|
|
}
|
|
if err := h.svc.Reload(c.Request.Context()); err != nil {
|
|
Fail(c, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
OK(c, gin.H{"ok": true})
|
|
}
|
|
|
|
func (h *ModerationHandler) ListHits(c *gin.Context) {
|
|
if !h.ready(c) {
|
|
return
|
|
}
|
|
page, _ := strconv.Atoi(c.DefaultQuery("page", "0"))
|
|
size, _ := strconv.Atoi(c.DefaultQuery("size", "50"))
|
|
uid, _ := strconv.ParseInt(c.Query("uid"), 10, 64)
|
|
cat, _ := strconv.Atoi(c.Query("category"))
|
|
var since, until *time.Time
|
|
if s := c.Query("since"); s != "" {
|
|
if t, err := time.Parse(time.RFC3339, s); err == nil {
|
|
since = &t
|
|
}
|
|
}
|
|
if s := c.Query("until"); s != "" {
|
|
if t, err := time.Parse(time.RFC3339, s); err == nil {
|
|
until = &t
|
|
}
|
|
}
|
|
list, total, err := h.svc.ListHits(c.Request.Context(), uid, cat, since, until, page, size)
|
|
if err != nil {
|
|
Fail(c, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
OK(c, gin.H{"items": list, "total": total})
|
|
}
|
|
|
|
func failModeration(c *gin.Context, err error) {
|
|
if errors.Is(err, errs.ErrInvalidArgument) || errors.Is(err, errs.ErrDuplicate) || errors.Is(err, errs.ErrNotFound) {
|
|
respond.JSONError(c, err)
|
|
return
|
|
}
|
|
Fail(c, http.StatusInternalServerError, err.Error())
|
|
}
|
|
|
|
func ptrBool(v bool) *bool { return &v }
|