feat: Add automated ChatGPT account registration with backend API, TLS client, and fingerprinting, alongside new frontend pages for configuration, monitoring, and upload.
This commit is contained in:
@@ -125,6 +125,20 @@ func (d *DB) createTables() error {
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_batch_team_results_batch_id ON batch_team_results(batch_id);
|
||||
|
||||
-- CodexAuth 代理池表
|
||||
CREATE TABLE IF NOT EXISTS codex_auth_proxies (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
proxy_url TEXT NOT NULL UNIQUE,
|
||||
description TEXT,
|
||||
is_enabled INTEGER DEFAULT 1,
|
||||
last_used_at DATETIME,
|
||||
success_count INTEGER DEFAULT 0,
|
||||
fail_count INTEGER DEFAULT 0,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_codex_auth_proxies_enabled ON codex_auth_proxies(is_enabled);
|
||||
`)
|
||||
return err
|
||||
}
|
||||
@@ -737,6 +751,189 @@ func (d *DB) GetBatchRunWithResults(batchID int64) (*BatchRun, []BatchTeamResult
|
||||
return &run, results, nil
|
||||
}
|
||||
|
||||
// CodexProxy CodexAuth 代理配置
|
||||
type CodexProxy struct {
|
||||
ID int64 `json:"id"`
|
||||
ProxyURL string `json:"proxy_url"`
|
||||
Description string `json:"description"`
|
||||
IsEnabled bool `json:"is_enabled"`
|
||||
LastUsedAt *time.Time `json:"last_used_at,omitempty"`
|
||||
SuccessCount int `json:"success_count"`
|
||||
FailCount int `json:"fail_count"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
// AddCodexProxy 添加代理
|
||||
func (d *DB) AddCodexProxy(proxyURL, description string) (int64, error) {
|
||||
result, err := d.db.Exec(`
|
||||
INSERT INTO codex_auth_proxies (proxy_url, description, is_enabled, created_at)
|
||||
VALUES (?, ?, 1, CURRENT_TIMESTAMP)
|
||||
`, proxyURL, description)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return result.LastInsertId()
|
||||
}
|
||||
|
||||
// AddCodexProxies 批量添加代理
|
||||
func (d *DB) AddCodexProxies(proxies []string) (int, error) {
|
||||
tx, err := d.db.Begin()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer tx.Rollback()
|
||||
|
||||
stmt, err := tx.Prepare(`
|
||||
INSERT OR IGNORE INTO codex_auth_proxies (proxy_url, is_enabled, created_at)
|
||||
VALUES (?, 1, CURRENT_TIMESTAMP)
|
||||
`)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer stmt.Close()
|
||||
|
||||
count := 0
|
||||
for _, proxy := range proxies {
|
||||
result, err := stmt.Exec(proxy)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
affected, _ := result.RowsAffected()
|
||||
if affected > 0 {
|
||||
count++
|
||||
}
|
||||
}
|
||||
|
||||
if err := tx.Commit(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// GetCodexProxies 获取代理列表
|
||||
func (d *DB) GetCodexProxies() ([]CodexProxy, error) {
|
||||
rows, err := d.db.Query(`
|
||||
SELECT id, proxy_url, COALESCE(description, ''), is_enabled, last_used_at, success_count, fail_count, created_at
|
||||
FROM codex_auth_proxies
|
||||
ORDER BY created_at DESC
|
||||
`)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var proxies []CodexProxy
|
||||
for rows.Next() {
|
||||
var p CodexProxy
|
||||
var lastUsedAt sql.NullTime
|
||||
err := rows.Scan(&p.ID, &p.ProxyURL, &p.Description, &p.IsEnabled, &lastUsedAt, &p.SuccessCount, &p.FailCount, &p.CreatedAt)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if lastUsedAt.Valid {
|
||||
p.LastUsedAt = &lastUsedAt.Time
|
||||
}
|
||||
proxies = append(proxies, p)
|
||||
}
|
||||
return proxies, nil
|
||||
}
|
||||
|
||||
// GetEnabledCodexProxies 获取已启用的代理列表
|
||||
func (d *DB) GetEnabledCodexProxies() ([]CodexProxy, error) {
|
||||
rows, err := d.db.Query(`
|
||||
SELECT id, proxy_url, COALESCE(description, ''), is_enabled, last_used_at, success_count, fail_count, created_at
|
||||
FROM codex_auth_proxies
|
||||
WHERE is_enabled = 1
|
||||
ORDER BY success_count DESC, fail_count ASC
|
||||
`)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var proxies []CodexProxy
|
||||
for rows.Next() {
|
||||
var p CodexProxy
|
||||
var lastUsedAt sql.NullTime
|
||||
err := rows.Scan(&p.ID, &p.ProxyURL, &p.Description, &p.IsEnabled, &lastUsedAt, &p.SuccessCount, &p.FailCount, &p.CreatedAt)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if lastUsedAt.Valid {
|
||||
p.LastUsedAt = &lastUsedAt.Time
|
||||
}
|
||||
proxies = append(proxies, p)
|
||||
}
|
||||
return proxies, nil
|
||||
}
|
||||
|
||||
// GetRandomCodexProxy 随机获取一个已启用的代理
|
||||
func (d *DB) GetRandomCodexProxy() (string, error) {
|
||||
var proxyURL string
|
||||
err := d.db.QueryRow(`
|
||||
SELECT proxy_url FROM codex_auth_proxies
|
||||
WHERE is_enabled = 1
|
||||
ORDER BY RANDOM()
|
||||
LIMIT 1
|
||||
`).Scan(&proxyURL)
|
||||
if err == sql.ErrNoRows {
|
||||
return "", nil
|
||||
}
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// 更新最后使用时间
|
||||
d.db.Exec("UPDATE codex_auth_proxies SET last_used_at = CURRENT_TIMESTAMP WHERE proxy_url = ?", proxyURL)
|
||||
return proxyURL, nil
|
||||
}
|
||||
|
||||
// UpdateCodexProxyStats 更新代理统计
|
||||
func (d *DB) UpdateCodexProxyStats(proxyURL string, success bool) error {
|
||||
if success {
|
||||
_, err := d.db.Exec("UPDATE codex_auth_proxies SET success_count = success_count + 1, last_used_at = CURRENT_TIMESTAMP WHERE proxy_url = ?", proxyURL)
|
||||
return err
|
||||
}
|
||||
_, err := d.db.Exec("UPDATE codex_auth_proxies SET fail_count = fail_count + 1, last_used_at = CURRENT_TIMESTAMP WHERE proxy_url = ?", proxyURL)
|
||||
return err
|
||||
}
|
||||
|
||||
// ToggleCodexProxy 切换代理启用状态
|
||||
func (d *DB) ToggleCodexProxy(id int64) error {
|
||||
_, err := d.db.Exec("UPDATE codex_auth_proxies SET is_enabled = 1 - is_enabled WHERE id = ?", id)
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCodexProxy 删除代理
|
||||
func (d *DB) DeleteCodexProxy(id int64) error {
|
||||
_, err := d.db.Exec("DELETE FROM codex_auth_proxies WHERE id = ?", id)
|
||||
return err
|
||||
}
|
||||
|
||||
// ClearCodexProxies 清空所有代理
|
||||
func (d *DB) ClearCodexProxies() error {
|
||||
_, err := d.db.Exec("DELETE FROM codex_auth_proxies")
|
||||
return err
|
||||
}
|
||||
|
||||
// GetCodexProxyStats 获取代理统计
|
||||
func (d *DB) GetCodexProxyStats() map[string]int {
|
||||
stats := map[string]int{
|
||||
"total": 0,
|
||||
"enabled": 0,
|
||||
"disabled": 0,
|
||||
}
|
||||
|
||||
var total, enabled, disabled int
|
||||
d.db.QueryRow("SELECT COUNT(*) FROM codex_auth_proxies").Scan(&total)
|
||||
d.db.QueryRow("SELECT COUNT(*) FROM codex_auth_proxies WHERE is_enabled = 1").Scan(&enabled)
|
||||
d.db.QueryRow("SELECT COUNT(*) FROM codex_auth_proxies WHERE is_enabled = 0").Scan(&disabled)
|
||||
stats["total"] = total
|
||||
stats["enabled"] = enabled
|
||||
stats["disabled"] = disabled
|
||||
|
||||
return stats
|
||||
}
|
||||
|
||||
// Close 关闭数据库
|
||||
func (d *DB) Close() error {
|
||||
if d.db != nil {
|
||||
|
||||
Reference in New Issue
Block a user