mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-10-14 12:02:27 +08:00
145 lines
4.1 KiB
Go
145 lines
4.1 KiB
Go
package admin
|
|
|
|
import (
|
|
"strconv"
|
|
|
|
infraerrors "github.com/Wei-Shaw/sub2api/internal/pkg/errors"
|
|
"github.com/Wei-Shaw/sub2api/internal/pkg/response"
|
|
"github.com/Wei-Shaw/sub2api/internal/service"
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
const (
|
|
grokMediaEligibilityModeAuto = "auto"
|
|
grokMediaEligibilityModeEnabled = "enabled"
|
|
grokMediaEligibilityModeDisabled = "disabled"
|
|
)
|
|
|
|
type grokMediaEligibilityResponse struct {
|
|
AccountID int64 `json:"account_id"`
|
|
Mode string `json:"mode"`
|
|
Eligible bool `json:"eligible"`
|
|
Reason string `json:"reason"`
|
|
}
|
|
|
|
type updateGrokMediaEligibilityRequest struct {
|
|
Mode string `json:"mode" binding:"required"`
|
|
}
|
|
|
|
// GetGrokMediaEligibility returns the current manual override and evaluated
|
|
// media-routing decision for a Grok OAuth account.
|
|
// GET /api/v1/admin/accounts/:id/grok-media-eligibility
|
|
func (h *AccountHandler) GetGrokMediaEligibility(c *gin.Context) {
|
|
account, err := h.getGrokOAuthAccount(c)
|
|
if err != nil {
|
|
response.ErrorFrom(c, err)
|
|
return
|
|
}
|
|
response.Success(c, buildGrokMediaEligibilityResponse(account))
|
|
}
|
|
|
|
// UpdateGrokMediaEligibility updates only the manual media eligibility
|
|
// override. It deliberately uses UpdateAccountExtra so unrelated account
|
|
// extra fields are preserved.
|
|
// PUT /api/v1/admin/accounts/:id/grok-media-eligibility
|
|
func (h *AccountHandler) UpdateGrokMediaEligibility(c *gin.Context) {
|
|
account, err := h.getGrokOAuthAccount(c)
|
|
if err != nil {
|
|
response.ErrorFrom(c, err)
|
|
return
|
|
}
|
|
|
|
var req updateGrokMediaEligibilityRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.BadRequest(c, "Invalid request: "+err.Error())
|
|
return
|
|
}
|
|
|
|
var value any
|
|
switch req.Mode {
|
|
case grokMediaEligibilityModeAuto:
|
|
value = nil
|
|
case grokMediaEligibilityModeEnabled:
|
|
value = true
|
|
case grokMediaEligibilityModeDisabled:
|
|
value = false
|
|
default:
|
|
response.ErrorFrom(c, infraerrors.BadRequest(
|
|
"GROK_MEDIA_ELIGIBILITY_INVALID_MODE",
|
|
"mode must be one of auto, enabled, disabled",
|
|
))
|
|
return
|
|
}
|
|
|
|
updates := map[string]any{service.GrokMediaEligibleExtraKey: value}
|
|
if err := service.ValidateGrokMediaEligibilityExtra(account.Platform, updates); err != nil {
|
|
response.ErrorFrom(c, err)
|
|
return
|
|
}
|
|
if err := h.adminService.UpdateAccountExtra(c.Request.Context(), account.ID, updates); err != nil {
|
|
response.ErrorFrom(c, err)
|
|
return
|
|
}
|
|
|
|
updated, err := h.adminService.GetAccount(c.Request.Context(), account.ID)
|
|
if err != nil {
|
|
response.ErrorFrom(c, err)
|
|
return
|
|
}
|
|
if err := ensureGrokOAuthAccount(updated); err != nil {
|
|
response.ErrorFrom(c, err)
|
|
return
|
|
}
|
|
response.Success(c, buildGrokMediaEligibilityResponse(updated))
|
|
}
|
|
|
|
func (h *AccountHandler) getGrokOAuthAccount(c *gin.Context) (*service.Account, error) {
|
|
accountID, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
|
if err != nil {
|
|
return nil, infraerrors.BadRequest("INVALID_ACCOUNT_ID", "Invalid account ID")
|
|
}
|
|
account, err := h.adminService.GetAccount(c.Request.Context(), accountID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err := ensureGrokOAuthAccount(account); err != nil {
|
|
return nil, err
|
|
}
|
|
return account, nil
|
|
}
|
|
|
|
func ensureGrokOAuthAccount(account *service.Account) error {
|
|
if account == nil {
|
|
return infraerrors.NotFound("ACCOUNT_NOT_FOUND", "account not found")
|
|
}
|
|
if account.Platform != service.PlatformGrok || account.Type != service.AccountTypeOAuth {
|
|
return infraerrors.BadRequest(
|
|
"GROK_MEDIA_ELIGIBILITY_UNSUPPORTED_ACCOUNT",
|
|
"media eligibility is only supported for Grok OAuth accounts",
|
|
)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func buildGrokMediaEligibilityResponse(account *service.Account) grokMediaEligibilityResponse {
|
|
eligible, reason := account.GrokMediaGenerationEligibility()
|
|
return grokMediaEligibilityResponse{
|
|
AccountID: account.ID,
|
|
Mode: grokMediaEligibilityModeFromExtra(account.Extra),
|
|
Eligible: eligible,
|
|
Reason: reason,
|
|
}
|
|
}
|
|
|
|
func grokMediaEligibilityModeFromExtra(extra map[string]any) string {
|
|
if extra != nil {
|
|
if enabled, ok := extra[service.GrokMediaEligibleExtraKey].(bool); ok {
|
|
if enabled {
|
|
return grokMediaEligibilityModeEnabled
|
|
}
|
|
return grokMediaEligibilityModeDisabled
|
|
}
|
|
}
|
|
return grokMediaEligibilityModeAuto
|
|
}
|