Files
go-taobao/cmd/main.go
2026-02-09 16:05:56 +08:00

157 lines
4.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 {}
}