Files
gpt-plus-gpt/internal/service/export_svc.go
2026-03-15 20:48:19 +08:00

122 lines
2.8 KiB
Go

package service
import (
"archive/zip"
"bytes"
"encoding/json"
"fmt"
"time"
"gpt-plus/internal/db"
"gorm.io/gorm"
)
type authFile struct {
OpenAIAPIKey string `json:"OPENAI_API_KEY"`
AccessToken string `json:"access_token"`
IDToken string `json:"id_token"`
LastRefresh string `json:"last_refresh"`
RefreshToken string `json:"refresh_token"`
Tokens authTokens `json:"tokens"`
}
type authTokens struct {
AccessToken string `json:"access_token"`
AccountID string `json:"account_id"`
IDToken string `json:"id_token"`
LastRefresh string `json:"last_refresh"`
RefreshToken string `json:"refresh_token"`
}
func buildAuthFile(acct *db.Account) *authFile {
now := time.Now().UTC().Format("2006-01-02T15:04:05Z")
token := acct.AccessToken
if acct.WorkspaceToken != "" {
token = acct.WorkspaceToken
}
accountID := acct.AccountID
if acct.TeamWorkspaceID != "" {
accountID = acct.TeamWorkspaceID
}
return &authFile{
AccessToken: token,
IDToken: acct.IDToken,
LastRefresh: now,
RefreshToken: acct.RefreshToken,
Tokens: authTokens{
AccessToken: token,
AccountID: accountID,
IDToken: acct.IDToken,
LastRefresh: now,
RefreshToken: acct.RefreshToken,
},
}
}
// ExportAccounts exports accounts as auth.json files.
// If multiple files, returns a zip archive.
func ExportAccounts(d *gorm.DB, ids []uint, note string) ([]byte, string, error) {
var accounts []db.Account
d.Where("id IN ?", ids).Find(&accounts)
if len(accounts) == 0 {
return nil, "", fmt.Errorf("未找到账号")
}
// Collect all files to export
type exportFile struct {
Name string
Data []byte
}
var files []exportFile
for _, acct := range accounts {
auth := buildAuthFile(&acct)
data, _ := json.MarshalIndent(auth, "", " ")
files = append(files, exportFile{
Name: acct.Email + ".auth.json",
Data: data,
})
// If team_owner, also export sub-accounts
if acct.Plan == "team_owner" {
var subs []db.Account
d.Where("parent_id = ?", acct.ID).Find(&subs)
for _, sub := range subs {
subAuth := buildAuthFile(&sub)
subData, _ := json.MarshalIndent(subAuth, "", " ")
files = append(files, exportFile{
Name: sub.Email + ".auth.json",
Data: subData,
})
}
}
}
// Single file — return directly
if len(files) == 1 {
return files[0].Data, files[0].Name, nil
}
// Multiple files — zip archive
var buf bytes.Buffer
zw := zip.NewWriter(&buf)
for _, f := range files {
w, err := zw.Create(f.Name)
if err != nil {
return nil, "", err
}
w.Write(f.Data)
}
zw.Close()
ts := time.Now().Format("20060102_150405")
filename := fmt.Sprintf("export_%s_%s.zip", note, ts)
if note == "" {
filename = fmt.Sprintf("export_%s.zip", ts)
}
return buf.Bytes(), filename, nil
}