Merge pull request #1299 from DaydreamCoding/feat/antigravity-privacy-and-subscription

feat(antigravity): 自动隐私设置 + 订阅状态检测
This commit is contained in:
Wesley Liddick
2026-03-26 11:30:24 +08:00
committed by GitHub
18 changed files with 728 additions and 36 deletions

View File

@@ -267,6 +267,9 @@ func (h *AccountHandler) importData(ctx context.Context, req DataImportRequest)
}
}
// 收集需要异步设置隐私的 Antigravity OAuth 账号
var privacyAccounts []*service.Account
for i := range dataPayload.Accounts {
item := dataPayload.Accounts[i]
if err := validateDataAccount(item); err != nil {
@@ -314,7 +317,8 @@ func (h *AccountHandler) importData(ctx context.Context, req DataImportRequest)
SkipDefaultGroupBind: skipDefaultGroupBind,
}
if _, err := h.adminService.CreateAccount(ctx, accountInput); err != nil {
created, err := h.adminService.CreateAccount(ctx, accountInput)
if err != nil {
result.AccountFailed++
result.Errors = append(result.Errors, DataImportError{
Kind: "account",
@@ -323,9 +327,30 @@ func (h *AccountHandler) importData(ctx context.Context, req DataImportRequest)
})
continue
}
// 收集 Antigravity OAuth 账号,稍后异步设置隐私
if created.Platform == service.PlatformAntigravity && created.Type == service.AccountTypeOAuth {
privacyAccounts = append(privacyAccounts, created)
}
result.AccountCreated++
}
// 异步设置 Antigravity 隐私,避免大量导入时阻塞请求
if len(privacyAccounts) > 0 {
adminSvc := h.adminService
go func() {
defer func() {
if r := recover(); r != nil {
slog.Error("import_antigravity_privacy_panic", "recover", r)
}
}()
bgCtx := context.Background()
for _, acc := range privacyAccounts {
adminSvc.ForceAntigravityPrivacy(bgCtx, acc)
}
slog.Info("import_antigravity_privacy_done", "count", len(privacyAccounts))
}()
}
return result, nil
}

View File

@@ -9,6 +9,7 @@ import (
"errors"
"fmt"
"log"
"log/slog"
"net/http"
"strconv"
"strings"
@@ -536,6 +537,8 @@ func (h *AccountHandler) Create(c *gin.Context) {
if execErr != nil {
return nil, execErr
}
// Antigravity OAuth: 新账号直接设置隐私
h.adminService.ForceAntigravityPrivacy(ctx, account)
return h.buildAccountResponseWithRuntime(ctx, account), nil
})
if err != nil {
@@ -883,6 +886,8 @@ func (h *AccountHandler) refreshSingleAccount(ctx context.Context, account *serv
// OpenAI OAuth: 刷新成功后检查并设置 privacy_mode
h.adminService.EnsureOpenAIPrivacy(ctx, updatedAccount)
// Antigravity OAuth: 刷新成功后检查并设置 privacy_mode
h.adminService.EnsureAntigravityPrivacy(ctx, updatedAccount)
return updatedAccount, "", nil
}
@@ -1154,6 +1159,8 @@ func (h *AccountHandler) BatchCreate(c *gin.Context) {
success := 0
failed := 0
results := make([]gin.H, 0, len(req.Accounts))
// 收集需要异步设置隐私的 Antigravity OAuth 账号
var privacyAccounts []*service.Account
for _, item := range req.Accounts {
if item.RateMultiplier != nil && *item.RateMultiplier < 0 {
@@ -1196,6 +1203,10 @@ func (h *AccountHandler) BatchCreate(c *gin.Context) {
})
continue
}
// 收集 Antigravity OAuth 账号,稍后异步设置隐私
if account.Platform == service.PlatformAntigravity && account.Type == service.AccountTypeOAuth {
privacyAccounts = append(privacyAccounts, account)
}
success++
results = append(results, gin.H{
"name": item.Name,
@@ -1204,6 +1215,22 @@ func (h *AccountHandler) BatchCreate(c *gin.Context) {
})
}
// 异步设置 Antigravity 隐私,避免批量创建时阻塞请求
if len(privacyAccounts) > 0 {
adminSvc := h.adminService
go func() {
defer func() {
if r := recover(); r != nil {
slog.Error("batch_create_antigravity_privacy_panic", "recover", r)
}
}()
bgCtx := context.Background()
for _, acc := range privacyAccounts {
adminSvc.ForceAntigravityPrivacy(bgCtx, acc)
}
}()
}
return gin.H{
"success": success,
"failed": failed,
@@ -1869,6 +1896,42 @@ func (h *AccountHandler) GetAvailableModels(c *gin.Context) {
response.Success(c, models)
}
// SetPrivacy handles setting privacy for a single Antigravity OAuth account
// POST /api/v1/admin/accounts/:id/set-privacy
func (h *AccountHandler) SetPrivacy(c *gin.Context) {
accountID, err := strconv.ParseInt(c.Param("id"), 10, 64)
if err != nil {
response.BadRequest(c, "Invalid account ID")
return
}
account, err := h.adminService.GetAccount(c.Request.Context(), accountID)
if err != nil {
response.NotFound(c, "Account not found")
return
}
if account.Platform != service.PlatformAntigravity || account.Type != service.AccountTypeOAuth {
response.BadRequest(c, "Only Antigravity OAuth accounts support privacy setting")
return
}
mode := h.adminService.ForceAntigravityPrivacy(c.Request.Context(), account)
if mode == "" {
response.BadRequest(c, "Cannot set privacy: missing access_token")
return
}
// 从 DB 重新读取以确保返回最新状态
updated, err := h.adminService.GetAccount(c.Request.Context(), accountID)
if err != nil {
// 隐私已设置成功但读取失败,回退到内存更新
if account.Extra == nil {
account.Extra = make(map[string]any)
}
account.Extra["privacy_mode"] = mode
response.Success(c, h.buildAccountResponseWithRuntime(c.Request.Context(), account))
return
}
response.Success(c, h.buildAccountResponseWithRuntime(c.Request.Context(), updated))
}
// RefreshTier handles refreshing Google One tier for a single account
// POST /api/v1/admin/accounts/:id/refresh-tier
func (h *AccountHandler) RefreshTier(c *gin.Context) {

View File

@@ -445,6 +445,14 @@ func (s *stubAdminService) EnsureOpenAIPrivacy(ctx context.Context, account *ser
return ""
}
func (s *stubAdminService) EnsureAntigravityPrivacy(ctx context.Context, account *service.Account) string {
return ""
}
func (s *stubAdminService) ForceAntigravityPrivacy(ctx context.Context, account *service.Account) string {
return ""
}
func (s *stubAdminService) ReplaceUserGroup(ctx context.Context, userID, oldGroupID, newGroupID int64) (*service.ReplaceUserGroupResult, error) {
return &service.ReplaceUserGroupResult{MigratedKeys: 0}, nil
}