157 lines
4.7 KiB
Go
157 lines
4.7 KiB
Go
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 {}
|
||
}
|