package main import ( "flag" "fmt" "log" "os" "time" "go-taobao/config" "go-taobao/libs" "go-taobao/services" "go-taobao/utils" ) var ( mode = flag.String("mode", "", "运行模式: login(登录) | rush(抢购)") ) func main() { flag.Parse() cfg := config.DefaultConfig() switch *mode { case "login": runLogin(cfg) case "rush": runRush(cfg) default: fmt.Println("淘宝抢购脚本") fmt.Println("用法:") fmt.Println(" -mode login 扫码登录并保存 Cookie") fmt.Println(" -mode rush 启动定时抢购") fmt.Printf("\n当前抢购目标时间: %s\n", cfg.TargetTime.Format("2006-01-02 15:04:05")) os.Exit(1) } } // runLogin 登录模式:扫码登录并保存 Cookie func runLogin(cfg *config.RushConfig) { log.Println("========== 登录模式 ==========") auth := services.NewAuth(cfg) if err := auth.Login(); err != nil { log.Fatalf("[错误] 登录失败: %v", err) } log.Println("[完成] 登录成功,Cookie 已保存") } // runRush 抢购模式:定时抢购主流程 // 流程: 提前进购物车 → 全选 → 结算 → 进入订单确认页 → 到点刷新 → 检测可购买 → 提交 func runRush(cfg *config.RushConfig) { log.Println("========== 抢购模式 ==========") log.Printf("[配置] 目标时间: %s", cfg.TargetTime.Format("2006-01-02 15:04:05")) log.Printf("[配置] 最大重试: %d 次", cfg.MaxRetry) log.Printf("[配置] 提前量: %v", cfg.SubmitAdvance) // 1. 同步服务器时间 log.Println("\n--- 第1步: 同步服务器时间 ---") timeSync, err := utils.NewTimeSync(5) if err != nil { log.Fatalf("[错误] 时间同步失败: %v", err) } log.Printf("[时间] 本地时间: %s", time.Now().Format("15:04:05.000")) log.Printf("[时间] 服务器时间: %s", timeSync.Now().Format("15:04:05.000")) log.Printf("[时间] 偏移量: %v", timeSync.Offset) remaining := timeSync.UntilTarget(cfg.TargetTime) if remaining <= 0 { log.Println("[警告] 抢购时间已过!") return } log.Printf("[时间] 距离抢购还有: %v", remaining.Round(time.Second)) // 2. 加载 Cookie & 启动浏览器 log.Println("\n--- 第2步: 启动浏览器 ---") auth := services.NewAuth(cfg) cookies, err := auth.LoadCookies() if err != nil { log.Fatalf("[错误] 加载 Cookie 失败: %v (请先运行 -mode login)", err) } var browserMgr libs.Browser browserInfo := browserMgr.GetBrowser(cfg.AccountID, &libs.Fingerprint{}) if err := auth.InjectCookies(browserInfo.Browser, cookies); err != nil { log.Fatalf("[错误] 注入 Cookie 失败: %v", err) } log.Println("[浏览器] Cookie 注入成功") // 3. 提前打开购物车,全选商品,点击结算进入订单页 log.Println("\n--- 第3步: 进入购物车并结算 ---") cart := services.NewCart(browserInfo.Page) cart.Open() cart.DisableAnimations() cart.SelectAll() log.Println("[购物车] 点击结算,进入订单确认页...") if err := cart.ClickCheckout(); err != nil { log.Fatalf("[错误] 结算失败: %v", err) } // 4. 等待进入订单确认页 order := services.NewOrder(browserInfo.Page) if err := order.WaitForConfirmPage(15 * time.Second); err != nil { log.Fatalf("[错误] 进入订单确认页失败: %v", err) } log.Println("[订单] 已停留在订单确认页,等待抢购时间...") // 5. 创建定时器 & 启动倒计时 timer := services.NewTimer(cfg, timeSync) countdownDone := make(chan struct{}) go timer.PrintCountdown(countdownDone) // 6. 精确等待到抢购时间(目标时间 - 提前量) log.Println("\n--- 第4步: 等待抢购时间 ---") timer.WaitUntilRush() close(countdownDone) // 7. 到点! 刷新订单页 → 检测是否可提交 → 提交 log.Println("\n--- 第5步: 开始抢购! ---") for attempt := 1; attempt <= cfg.MaxRetry; attempt++ { log.Printf("[抢购] 第 %d/%d 次尝试", attempt, cfg.MaxRetry) // 刷新订单确认页 order.Refresh() // 检测是否可以提交 if !order.CanSubmit() { log.Println("[抢购] 当前仍不可购买") if attempt < cfg.MaxRetry { time.Sleep(cfg.RetryInterval) } continue } // 可以购买,立即提交! result := order.Submit() if result.Success { log.Println("🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉") log.Printf("[成功] %s", result.Message) log.Println("🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉") log.Println("[提示] 浏览器保持打开,请尽快完成付款!") select {} } log.Printf("[抢购] 提交失败: %s", result.Message) if attempt < cfg.MaxRetry { time.Sleep(cfg.RetryInterval) } } log.Println("[结束] 已达最大重试次数") log.Println("[提示] 浏览器保持打开,你可以手动操作") select {} }