feat: Implement initial full-stack application structure including frontend pages, components, hooks, API integration, and backend services for account pooling and management.

This commit is contained in:
2026-01-30 07:40:35 +08:00
commit f4448bbef2
106 changed files with 19282 additions and 0 deletions

View File

@@ -0,0 +1,194 @@
package auth
import (
"context"
"fmt"
"strings"
"time"
"github.com/chromedp/cdproto/network"
"github.com/chromedp/chromedp"
)
// CompleteWithChromedp 使用 chromedp 完成 S2A OAuth 授权
func CompleteWithChromedp(authURL, email, password, teamID string, headless bool, proxy string) (string, error) {
opts := append(chromedp.DefaultExecAllocatorOptions[:],
chromedp.Flag("headless", headless),
chromedp.Flag("disable-gpu", true),
chromedp.Flag("no-sandbox", true),
chromedp.Flag("disable-dev-shm-usage", true),
chromedp.Flag("disable-blink-features", "AutomationControlled"),
chromedp.UserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36"),
)
if proxy != "" {
opts = append(opts, chromedp.ProxyServer(proxy))
}
allocCtx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)
defer cancel()
ctx, cancel := chromedp.NewContext(allocCtx)
defer cancel()
ctx, cancel = context.WithTimeout(ctx, 120*time.Second)
defer cancel()
var callbackURL string
chromedp.ListenTarget(ctx, func(ev interface{}) {
if req, ok := ev.(*network.EventRequestWillBeSent); ok {
url := req.Request.URL
if strings.Contains(url, "localhost") && strings.Contains(url, "code=") {
callbackURL = url
}
}
})
err := chromedp.Run(ctx,
network.Enable(),
chromedp.Navigate(authURL),
chromedp.WaitReady("body"),
)
if err != nil {
return "", fmt.Errorf("访问失败: %v", err)
}
time.Sleep(2 * time.Second)
if callbackURL != "" {
return ExtractCodeFromCallbackURL(callbackURL), nil
}
var currentURL string
_ = chromedp.Run(ctx, chromedp.Location(&currentURL))
if strings.Contains(currentURL, "code=") {
return ExtractCodeFromCallbackURL(currentURL), nil
}
time.Sleep(1 * time.Second)
emailSelectors := []string{
`input[name="email"]`,
`input[type="email"]`,
`input[name="username"]`,
}
var emailFilled bool
for _, sel := range emailSelectors {
err = chromedp.Run(ctx, chromedp.WaitVisible(sel, chromedp.ByQuery))
if err == nil {
err = chromedp.Run(ctx,
chromedp.Clear(sel, chromedp.ByQuery),
chromedp.SendKeys(sel, email, chromedp.ByQuery),
)
if err == nil {
emailFilled = true
break
}
}
}
if !emailFilled {
return "", fmt.Errorf("未找到邮箱输入框")
}
time.Sleep(300 * time.Millisecond)
buttonSelectors := []string{
`button[type="submit"]`,
`button[data-testid="login-button"]`,
`button.continue-btn`,
`input[type="submit"]`,
}
for _, sel := range buttonSelectors {
err = chromedp.Run(ctx, chromedp.Click(sel, chromedp.ByQuery))
if err == nil {
break
}
}
time.Sleep(1500 * time.Millisecond)
if callbackURL != "" {
return ExtractCodeFromCallbackURL(callbackURL), nil
}
_ = chromedp.Run(ctx, chromedp.Location(&currentURL))
if strings.Contains(currentURL, "code=") {
return ExtractCodeFromCallbackURL(currentURL), nil
}
passwordSelectors := []string{
`input[name="current-password"]`,
`input[name="password"]`,
`input[type="password"]`,
}
var passwordFilled bool
for _, sel := range passwordSelectors {
err = chromedp.Run(ctx, chromedp.WaitVisible(sel, chromedp.ByQuery))
if err == nil {
err = chromedp.Run(ctx,
chromedp.Clear(sel, chromedp.ByQuery),
chromedp.SendKeys(sel, password, chromedp.ByQuery),
)
if err == nil {
passwordFilled = true
break
}
}
}
if !passwordFilled {
return "", fmt.Errorf("未找到密码输入框")
}
time.Sleep(300 * time.Millisecond)
for _, sel := range buttonSelectors {
err = chromedp.Run(ctx, chromedp.Click(sel, chromedp.ByQuery))
if err == nil {
break
}
}
for i := 0; i < 30; i++ {
time.Sleep(500 * time.Millisecond)
if callbackURL != "" {
return ExtractCodeFromCallbackURL(callbackURL), nil
}
var url string
if err := chromedp.Run(ctx, chromedp.Location(&url)); err == nil {
if strings.Contains(url, "code=") {
return ExtractCodeFromCallbackURL(url), nil
}
if strings.Contains(url, "consent") {
for _, sel := range buttonSelectors {
err = chromedp.Run(ctx, chromedp.Click(sel, chromedp.ByQuery))
if err == nil {
break
}
}
time.Sleep(1 * time.Second)
}
if strings.Contains(url, "authorize") && teamID != "" {
err = chromedp.Run(ctx,
chromedp.Click(fmt.Sprintf(`[data-workspace-id="%s"], [data-account-id="%s"]`, teamID, teamID), chromedp.ByQuery),
)
}
}
}
if callbackURL != "" {
return ExtractCodeFromCallbackURL(callbackURL), nil
}
return "", fmt.Errorf("授权超时")
}