feat: Implement browser-based OAuth authentication using Chromedp and Rod, add an upload page, and introduce team processing API.

This commit is contained in:
2026-02-02 04:19:53 +08:00
parent 3f1edc0b8f
commit c9e7a9adbf
5 changed files with 460 additions and 72 deletions

View File

@@ -16,6 +16,24 @@ import (
// CompleteWithChromedp 使用 chromedp 完成 S2A OAuth 授权
func CompleteWithChromedp(authURL, email, password, teamID string, headless bool, proxy string) (string, error) {
return CompleteWithChromedpLogged(authURL, email, password, teamID, headless, proxy, nil)
}
// CompleteWithChromedpLogged 使用 chromedp 完成 S2A OAuth 授权(带日志回调)
func CompleteWithChromedpLogged(authURL, email, password, teamID string, headless bool, proxy string, logger *AuthLogger) (string, error) {
// 日志辅助函数
logStep := func(step AuthStep, format string, args ...interface{}) {
if logger != nil {
logger.LogStep(step, format, args...)
}
}
logError := func(step AuthStep, format string, args ...interface{}) {
if logger != nil {
logger.LogError(step, format, args...)
}
}
logStep(StepBrowserStart, "正在启动 Chromedp 浏览器...")
// 获取随机浏览器配置
profile := GetRandomBrowserProfile()
@@ -132,14 +150,17 @@ func CompleteWithChromedp(authURL, email, password, teamID string, headless bool
tasks = append([]chromedp.Action{fetch.Enable().WithHandleAuthRequests(true)}, tasks...)
}
logStep(StepNavigate, "正在访问授权页面...")
err := chromedp.Run(ctx, tasks...)
if err != nil {
logError(StepNavigate, "访问失败: %v", err)
return "", fmt.Errorf("访问失败: %v", err)
}
time.Sleep(2 * time.Second)
if callbackURL != "" {
logStep(StepExtractCode, "已捕获授权码回调")
return ExtractCodeFromCallbackURL(callbackURL), nil
}
@@ -158,6 +179,7 @@ func CompleteWithChromedp(authURL, email, password, teamID string, headless bool
`input[name="username"]`,
}
logStep(StepInputEmail, "正在查找邮箱输入框...")
var emailFilled bool
for _, sel := range emailSelectors {
err = chromedp.Run(ctx, chromedp.WaitVisible(sel, chromedp.ByQuery))
@@ -168,12 +190,14 @@ func CompleteWithChromedp(authURL, email, password, teamID string, headless bool
)
if err == nil {
emailFilled = true
logStep(StepInputEmail, "已输入邮箱")
break
}
}
}
if !emailFilled {
logError(StepInputEmail, "未找到邮箱输入框")
return "", fmt.Errorf("未找到邮箱输入框")
}
@@ -186,6 +210,7 @@ func CompleteWithChromedp(authURL, email, password, teamID string, headless bool
`input[type="submit"]`,
}
logStep(StepSubmitEmail, "正在提交邮箱...")
for _, sel := range buttonSelectors {
err = chromedp.Run(ctx, chromedp.Click(sel, chromedp.ByQuery))
if err == nil {
@@ -196,14 +221,17 @@ func CompleteWithChromedp(authURL, email, password, teamID string, headless bool
time.Sleep(1500 * time.Millisecond)
if callbackURL != "" {
logStep(StepExtractCode, "已捕获授权码回调")
return ExtractCodeFromCallbackURL(callbackURL), nil
}
_ = chromedp.Run(ctx, chromedp.Location(&currentURL))
if strings.Contains(currentURL, "code=") {
logStep(StepExtractCode, "已获取授权码")
return ExtractCodeFromCallbackURL(currentURL), nil
}
logStep(StepInputPassword, "正在查找密码输入框...")
passwordSelectors := []string{
`input[name="current-password"]`,
`input[name="password"]`,
@@ -220,17 +248,20 @@ func CompleteWithChromedp(authURL, email, password, teamID string, headless bool
)
if err == nil {
passwordFilled = true
logStep(StepInputPassword, "已输入密码")
break
}
}
}
if !passwordFilled {
logError(StepInputPassword, "未找到密码输入框")
return "", fmt.Errorf("未找到密码输入框")
}
time.Sleep(300 * time.Millisecond)
logStep(StepSubmitPassword, "正在提交密码...")
for _, sel := range buttonSelectors {
err = chromedp.Run(ctx, chromedp.Click(sel, chromedp.ByQuery))
if err == nil {
@@ -238,6 +269,7 @@ func CompleteWithChromedp(authURL, email, password, teamID string, headless bool
}
}
logStep(StepWaitCallback, "等待授权回调...")
for i := 0; i < 30; i++ {
time.Sleep(500 * time.Millisecond)
@@ -248,10 +280,12 @@ func CompleteWithChromedp(authURL, email, password, teamID string, headless bool
var url string
if err := chromedp.Run(ctx, chromedp.Location(&url)); err == nil {
if strings.Contains(url, "code=") {
logStep(StepExtractCode, "已获取授权码")
return ExtractCodeFromCallbackURL(url), nil
}
if strings.Contains(url, "consent") {
logStep(StepConsent, "正在处理授权同意页面...")
for _, sel := range buttonSelectors {
err = chromedp.Run(ctx, chromedp.Click(sel, chromedp.ByQuery))
if err == nil {
@@ -262,6 +296,7 @@ func CompleteWithChromedp(authURL, email, password, teamID string, headless bool
}
if strings.Contains(url, "authorize") && teamID != "" {
logStep(StepSelectWorkspace, "正在选择工作区: %s", teamID)
err = chromedp.Run(ctx,
chromedp.Click(fmt.Sprintf(`[data-workspace-id="%s"], [data-account-id="%s"]`, teamID, teamID), chromedp.ByQuery),
)
@@ -270,8 +305,10 @@ func CompleteWithChromedp(authURL, email, password, teamID string, headless bool
}
if callbackURL != "" {
logStep(StepComplete, "授权完成")
return ExtractCodeFromCallbackURL(callbackURL), nil
}
logError(StepWaitCallback, "授权超时")
return "", fmt.Errorf("授权超时")
}