package handler import ( "database/sql" "encoding/json" "net/http" "strconv" "time" "gpt-manager-go/internal/models" "gpt-manager-go/internal/repository" "gpt-manager-go/internal/service" ) // ChatGPTAccountHandler ChatGPT 账号处理器 type ChatGPTAccountHandler struct { repo *repository.ChatGPTAccountRepository chatgptService *service.ChatGPTService } // NewChatGPTAccountHandler 创建处理器 func NewChatGPTAccountHandler(repo *repository.ChatGPTAccountRepository, chatgptService *service.ChatGPTService) *ChatGPTAccountHandler { return &ChatGPTAccountHandler{ repo: repo, chatgptService: chatgptService, } } // CreateAccountRequest 创建账号请求 type CreateAccountRequest struct { Name string `json:"name"` TeamAccountID string `json:"team_account_id"` AuthToken string `json:"auth_token"` } // AccountResponse 账号响应 type AccountResponse struct { Success bool `json:"success"` Message string `json:"message"` Data *models.ChatGPTAccount `json:"data,omitempty"` } // ListResponse 列表响应 type ListResponse struct { Success bool `json:"success"` Message string `json:"message"` Data []*models.ChatGPTAccount `json:"data,omitempty"` } // Create 创建账号 func (h *ChatGPTAccountHandler) Create(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { respondJSON(w, http.StatusMethodNotAllowed, AccountResponse{ Success: false, Message: "Method not allowed", }) return } var req CreateAccountRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { respondJSON(w, http.StatusBadRequest, AccountResponse{ Success: false, Message: "Invalid request body", }) return } // 验证必填字段 if req.TeamAccountID == "" || req.AuthToken == "" { respondJSON(w, http.StatusBadRequest, AccountResponse{ Success: false, Message: "team_account_id and auth_token are required", }) return } // 检查是否已存在 existing, err := h.repo.FindByTeamAccountID(req.TeamAccountID) if err != nil { respondJSON(w, http.StatusInternalServerError, AccountResponse{ Success: false, Message: "Database error: " + err.Error(), }) return } if existing != nil { respondJSON(w, http.StatusConflict, AccountResponse{ Success: false, Message: "Team account already exists", }) return } // 调用 ChatGPT API 获取订阅信息 subInfo, err := h.chatgptService.GetSubscription(req.TeamAccountID, req.AuthToken) if err != nil { respondJSON(w, http.StatusInternalServerError, AccountResponse{ Success: false, Message: "Failed to verify team account: " + err.Error(), }) return } // 设置账号名称 name := req.Name if name == "" { name = "Team-" + req.TeamAccountID[:8] } // 创建账号 account := &models.ChatGPTAccount{ Name: name, AuthToken: req.AuthToken, TeamAccountID: req.TeamAccountID, SeatsInUse: subInfo.SeatsInUse, SeatsEntitled: subInfo.SeatsEntitled, IsActive: subInfo.IsValid, } // 设置时间 if subInfo.IsValid { account.ActiveStart = sql.NullTime{Time: subInfo.ActiveStart, Valid: !subInfo.ActiveStart.IsZero()} account.ActiveUntil = sql.NullTime{Time: subInfo.ActiveUntil, Valid: !subInfo.ActiveUntil.IsZero()} account.LastCheck = sql.NullTime{Time: time.Now(), Valid: true} } if err := h.repo.Create(account); err != nil { respondJSON(w, http.StatusInternalServerError, AccountResponse{ Success: false, Message: "Failed to create account: " + err.Error(), }) return } // 隐藏敏感信息 account.AuthToken = "" respondJSON(w, http.StatusCreated, AccountResponse{ Success: true, Message: "Account created successfully", Data: account, }) } // List 获取账号列表 func (h *ChatGPTAccountHandler) List(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet { respondJSON(w, http.StatusMethodNotAllowed, ListResponse{ Success: false, Message: "Method not allowed", }) return } accounts, err := h.repo.FindAll() if err != nil { respondJSON(w, http.StatusInternalServerError, ListResponse{ Success: false, Message: "Failed to fetch accounts", }) return } // 隐藏敏感信息 for _, a := range accounts { a.AuthToken = "" } respondJSON(w, http.StatusOK, ListResponse{ Success: true, Message: "OK", Data: accounts, }) } // Refresh 刷新账号信息 func (h *ChatGPTAccountHandler) Refresh(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { respondJSON(w, http.StatusMethodNotAllowed, AccountResponse{ Success: false, Message: "Method not allowed", }) return } // 获取账号 ID idStr := r.URL.Query().Get("id") id, err := strconv.Atoi(idStr) if err != nil { respondJSON(w, http.StatusBadRequest, AccountResponse{ Success: false, Message: "Invalid account ID", }) return } account, err := h.repo.FindByID(id) if err != nil || account == nil { respondJSON(w, http.StatusNotFound, AccountResponse{ Success: false, Message: "Account not found", }) return } // 调用 ChatGPT API 获取订阅信息 subInfo, err := h.chatgptService.GetSubscription(account.TeamAccountID, account.AuthToken) if err != nil { // API 调用失败,增加失败计数并设为不活跃 account.ConsecutiveFailures++ account.IsActive = false account.LastCheck = sql.NullTime{Time: time.Now(), Valid: true} h.repo.Update(account) respondJSON(w, http.StatusInternalServerError, AccountResponse{ Success: false, Message: "Failed to refresh: " + err.Error(), }) return } // 更新账号信息 if subInfo.IsValid { account.SeatsInUse = subInfo.SeatsInUse account.SeatsEntitled = subInfo.SeatsEntitled account.ActiveStart = sql.NullTime{Time: subInfo.ActiveStart, Valid: !subInfo.ActiveStart.IsZero()} account.ActiveUntil = sql.NullTime{Time: subInfo.ActiveUntil, Valid: !subInfo.ActiveUntil.IsZero()} account.IsActive = true account.ConsecutiveFailures = 0 } else { account.IsActive = false account.ConsecutiveFailures++ } account.LastCheck = sql.NullTime{Time: time.Now(), Valid: true} if err := h.repo.Update(account); err != nil { respondJSON(w, http.StatusInternalServerError, AccountResponse{ Success: false, Message: "Failed to update account", }) return } // 隐藏敏感信息 account.AuthToken = "" respondJSON(w, http.StatusOK, AccountResponse{ Success: true, Message: "Account refreshed successfully", Data: account, }) } // Delete 删除账号 func (h *ChatGPTAccountHandler) Delete(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodDelete { respondJSON(w, http.StatusMethodNotAllowed, AccountResponse{ Success: false, Message: "Method not allowed", }) return } idStr := r.URL.Query().Get("id") id, err := strconv.Atoi(idStr) if err != nil { respondJSON(w, http.StatusBadRequest, AccountResponse{ Success: false, Message: "Invalid account ID", }) return } if err := h.repo.Delete(id); err != nil { respondJSON(w, http.StatusInternalServerError, AccountResponse{ Success: false, Message: "Failed to delete account", }) return } respondJSON(w, http.StatusOK, AccountResponse{ Success: true, Message: "Account deleted successfully", }) }