package service import ( "bytes" "encoding/json" "fmt" "io" "net/http" "time" ) // ChatGPTService ChatGPT API 服务 type ChatGPTService struct { client *http.Client baseURL string } // NewChatGPTService 创建 ChatGPT 服务 func NewChatGPTService() *ChatGPTService { return &ChatGPTService{ client: &http.Client{ Timeout: 30 * time.Second, }, baseURL: "https://chatgpt.com/backend-api", } } // SubscriptionInfo 订阅信息 type SubscriptionInfo struct { SeatsInUse int `json:"seats_in_use"` SeatsEntitled int `json:"seats_entitled"` ActiveStart time.Time `json:"active_start"` ActiveUntil time.Time `json:"active_until"` IsValid bool `json:"is_valid"` } // subscriptionResponse ChatGPT API 响应结构 type subscriptionResponse struct { SeatsInUse int `json:"seats_in_use"` SeatsEntitled int `json:"seats_entitled"` ActiveStart string `json:"active_start"` ActiveUntil string `json:"active_until"` } // GetSubscription 获取订阅信息 func (s *ChatGPTService) GetSubscription(teamAccountID, authToken string) (*SubscriptionInfo, error) { url := fmt.Sprintf("%s/subscriptions?account_id=%s", s.baseURL, teamAccountID) req, err := http.NewRequest("GET", url, nil) if err != nil { return nil, fmt.Errorf("failed to create request: %w", err) } // 设置请求头 req.Header.Set("Authorization", authToken) req.Header.Set("chatgpt-account-id", teamAccountID) req.Header.Set("Content-Type", "application/json") req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36") resp, err := s.client.Do(req) if err != nil { return nil, fmt.Errorf("failed to send request: %w", err) } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { return nil, fmt.Errorf("failed to read response: %w", err) } // 检查响应状态码 if resp.StatusCode != http.StatusOK { return &SubscriptionInfo{IsValid: false}, nil } var subResp subscriptionResponse if err := json.Unmarshal(body, &subResp); err != nil { return &SubscriptionInfo{IsValid: false}, nil } // 解析时间 info := &SubscriptionInfo{ SeatsInUse: subResp.SeatsInUse, SeatsEntitled: subResp.SeatsEntitled, IsValid: true, } if subResp.ActiveStart != "" { if t, err := time.Parse(time.RFC3339, subResp.ActiveStart); err == nil { info.ActiveStart = t } } if subResp.ActiveUntil != "" { if t, err := time.Parse(time.RFC3339, subResp.ActiveUntil); err == nil { info.ActiveUntil = t } } return info, nil } // InviteRequest 邀请请求结构 type InviteRequest struct { EmailAddresses []string `json:"email_addresses"` Role string `json:"role"` ResendEmails bool `json:"resend_emails"` } // InviteResponse 邀请响应 type InviteResponse struct { Success bool `json:"success"` Message string `json:"message,omitempty"` RawBody string `json:"-"` } // SendInvite 发送邀请到 ChatGPT Team func (s *ChatGPTService) SendInvite(teamAccountID, authToken, email string) (*InviteResponse, error) { url := fmt.Sprintf("%s/accounts/%s/invites", s.baseURL, teamAccountID) // 构建请求体 reqBody := InviteRequest{ EmailAddresses: []string{email}, Role: "standard-user", ResendEmails: true, } bodyBytes, err := json.Marshal(reqBody) if err != nil { return nil, fmt.Errorf("failed to marshal request: %w", err) } req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) if err != nil { return nil, fmt.Errorf("failed to create request: %w", err) } // 设置请求头 req.Header.Set("Authorization", authToken) req.Header.Set("chatgpt-account-id", teamAccountID) req.Header.Set("Content-Type", "application/json") req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36") resp, err := s.client.Do(req) if err != nil { return nil, fmt.Errorf("failed to send request: %w", err) } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { return nil, fmt.Errorf("failed to read response: %w", err) } // 检查响应状态码 if resp.StatusCode >= 200 && resp.StatusCode < 300 { return &InviteResponse{ Success: true, Message: "Invitation sent successfully", RawBody: string(body), }, nil } // 解析错误响应 return &InviteResponse{ Success: false, Message: fmt.Sprintf("API returned status %d: %s", resp.StatusCode, string(body)), RawBody: string(body), }, nil } // RemoveMemberResponse 移除成员响应 type RemoveMemberResponse struct { Success bool `json:"success"` Message string `json:"message,omitempty"` RawBody string `json:"-"` } // RemoveMember 从 ChatGPT Team 移除成员 func (s *ChatGPTService) RemoveMember(teamAccountID, authToken, email string) (*RemoveMemberResponse, error) { url := fmt.Sprintf("%s/accounts/%s/invites", s.baseURL, teamAccountID) // 构建请求体 - 只需要邮箱 reqBody := map[string]string{ "email_address": email, } bodyBytes, err := json.Marshal(reqBody) if err != nil { return nil, fmt.Errorf("failed to marshal request: %w", err) } req, err := http.NewRequest("DELETE", url, bytes.NewBuffer(bodyBytes)) if err != nil { return nil, fmt.Errorf("failed to create request: %w", err) } // 设置请求头 req.Header.Set("Authorization", authToken) req.Header.Set("chatgpt-account-id", teamAccountID) req.Header.Set("Content-Type", "application/json") req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36") resp, err := s.client.Do(req) if err != nil { return nil, fmt.Errorf("failed to send request: %w", err) } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { return nil, fmt.Errorf("failed to read response: %w", err) } // 检查响应状态码 if resp.StatusCode >= 200 && resp.StatusCode < 300 { return &RemoveMemberResponse{ Success: true, Message: "Member removed successfully", RawBody: string(body), }, nil } // 解析错误响应 return &RemoveMemberResponse{ Success: false, Message: fmt.Sprintf("API returned status %d: %s", resp.StatusCode, string(body)), RawBody: string(body), }, nil }