File size: 3,747 Bytes
6d60378 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | // trial 一次性批量领取 global trial 加油包:遍历 auths 下全部账号,
// 仅对 global 账号执行 /billing/ide/trial(CN 无此端点,明确提示不适用)。
//
// 用法:
//
// # 本地:在项目根目录(需 config.json + auths/ + data/)直接 run
// go run ./cmd/trial
//
// # 容器内:先 cp 进去再 exec
// docker cp trial workbuddy2api:/tmp/trial
// docker exec -w /app workbuddy2api /tmp/trial
//
// 结果逐账号输出到 stdout:
//
// uid | nick | status | detail
// ----+------+--------+-------
// ... | GLOBAL | OK | trial granted
// ... | GLOBAL | ALREADY | 已领取过(幂等,不算失败)
// ... | CN | N/A | not applicable
package main
import (
"fmt"
"os"
"path/filepath"
"sort"
"github.com/linguo2625469/workbuddy2api-panel/internal/auth"
"github.com/linguo2625469/workbuddy2api-panel/internal/upstream"
)
// classifyTrial 归一化 ClaimTrial 结果(纯函数,供 main 循环与测试直接断言):
// err → FAIL;claimed → OK;否则(幂等码已领)→ ALREADY。
func classifyTrial(claimed bool, err error) (trialStatus, string) {
switch {
case err != nil:
return trialFailed, err.Error()
case claimed:
return trialOK, "trial granted"
default:
return trialAlready, "already claimed (idempotent)"
}
}
// trialStatus 单账号 trial 领取结果状态。
type trialStatus string
const (
trialOK trialStatus = "OK"
trialAlready trialStatus = "ALREADY"
trialNotApp trialStatus = "N/A" // CN 账号不适用
trialFailed trialStatus = "FAIL"
)
type trialRow struct {
uid string
nick string
status trialStatus
detail string
}
func main() {
authDir := "auths"
if len(os.Args) > 1 {
authDir = os.Args[1]
}
files, err := filepath.Glob(filepath.Join(authDir, "workbuddy-*.json"))
if err != nil || len(files) == 0 {
fmt.Fprintf(os.Stderr, "no auth files in %s\n", authDir)
os.Exit(1)
}
sort.Strings(files)
up := upstream.New()
// trial 是 global 专属端点:必须开启 global realm 路由,否则 upstream.New() 的
// GlobalEnabled 零值 false 会把请求路由到 CN base(codebuddy.cn)而必然失败。
up.GlobalEnabled = true
var rows []trialRow
for _, f := range files {
r := trialRow{uid: filepath.Base(f)}
raw, err := os.ReadFile(f)
if err != nil {
r.status, r.detail = trialFailed, "load: "+err.Error()
rows = append(rows, r)
continue
}
a, err := auth.Parse(raw)
if err != nil {
r.status, r.detail = trialFailed, "parse: "+err.Error()
rows = append(rows, r)
continue
}
a.FilePath = f
r.uid, r.nick = a.UID, a.Nickname
// 仅 global 账号适用:CN 明确提示不适用,不发任何请求。
if !a.IsGlobal() {
r.status, r.detail = trialNotApp, "CN account not applicable"
rows = append(rows, r)
continue
}
r.status, r.detail = classifyTrial(up.ClaimTrial(a))
rows = append(rows, r)
}
var okN, alreadyN, notAppN, failN int
fmt.Printf("uid | nick | status | detail\n")
fmt.Printf("-------------------------------------+-------------+---------+------------------------------\n")
for _, r := range rows {
fmt.Printf("%-36s | %-11s | %-7s | %s\n",
trunc(r.uid, 36), trunc(r.nick, 11), r.status, r.detail)
switch r.status {
case trialOK:
okN++
case trialAlready:
alreadyN++
case trialNotApp:
notAppN++
default:
failN++
}
}
fmt.Printf("\ntotal=%d ok=%d already=%d na=%d fail=%d\n",
len(rows), okN, alreadyN, notAppN, failN)
}
func trunc(s string, n int) string {
if len(s) > n {
return s[:n]
}
return s
}
|