142 lines
8.1 KiB
Go
142 lines
8.1 KiB
Go
package main
|
||
|
||
import (
|
||
"context"
|
||
"errors"
|
||
"flag"
|
||
"fmt"
|
||
"os"
|
||
"time"
|
||
|
||
"bindbox-game/configs"
|
||
"bindbox-game/internal/pkg/env"
|
||
"bindbox-game/internal/pkg/logger"
|
||
"bindbox-game/internal/repository/mysql"
|
||
"bindbox-game/internal/repository/mysql/model"
|
||
douyin "bindbox-game/internal/service/douyin"
|
||
)
|
||
|
||
// staticSyscfg implements sysconfig.Service with fixed cookie
|
||
type staticSyscfg struct {
|
||
cookie string
|
||
}
|
||
|
||
func (s *staticSyscfg) GetByKey(ctx context.Context, key string) (*model.SystemConfigs, error) {
|
||
switch key {
|
||
case douyin.ConfigKeyDouyinCookie:
|
||
if s.cookie == "" {
|
||
return nil, errors.New("douyin cookie 未设置")
|
||
}
|
||
return &model.SystemConfigs{ConfigKey: key, ConfigValue: s.cookie}, nil
|
||
case douyin.ConfigKeyDouyinInterval:
|
||
return &model.SystemConfigs{ConfigKey: key, ConfigValue: "5"}, nil
|
||
default:
|
||
return nil, errors.New("暂不支持的配置 key: " + key)
|
||
}
|
||
}
|
||
|
||
func (s *staticSyscfg) UpsertByKey(ctx context.Context, key string, value string, remark string) (*model.SystemConfigs, error) {
|
||
return nil, errors.New("UpsertByKey 未实现")
|
||
}
|
||
func (s *staticSyscfg) ModifyByID(ctx context.Context, id int64, value *string, remark *string) error {
|
||
return errors.New("ModifyByID 未实现")
|
||
}
|
||
func (s *staticSyscfg) DeleteByID(ctx context.Context, id int64) error {
|
||
return errors.New("DeleteByID 未实现")
|
||
}
|
||
func (s *staticSyscfg) List(ctx context.Context, page int, pageSize int, keyword string) (items []*model.SystemConfigs, total int64, err error) {
|
||
return nil, 0, errors.New("List 未实现")
|
||
}
|
||
|
||
func main() {
|
||
minutes := flag.Int("minutes", 10, "同步最近多少分钟的订单")
|
||
useProxy := flag.Bool("proxy", false, "是否使用服务内置代理")
|
||
printLimit := flag.Int("print", 10, "同步后打印多少条订单 (0 表示不打印)")
|
||
mode := flag.String("mode", "sync-all", "同步模式: sync-all(默认增量)/fetch(按绑定用户)")
|
||
grantMinesweeper := flag.Bool("grant-minesweeper", false, "同步后执行 GrantMinesweeperQualifications")
|
||
fetchOnlyUnmatched := flag.Bool("fetch-only-unmatched", true, "按用户同步时是否仅同步未匹配订单的用户")
|
||
fetchMaxUsers := flag.Int("fetch-max-users", 200, "按用户同步时最多处理的用户数量 (50-1000)")
|
||
fetchBatchSize := flag.Int("fetch-batch-size", 20, "按用户同步时的单批次用户数量 (5-50)")
|
||
fetchConcurrency := flag.Int("fetch-concurrency", 5, "按用户同步时的并发抓取数 (<=批次大小)")
|
||
fetchDelay := flag.Int("fetch-delay-ms", 200, "批次之间的停顿时间 (毫秒)")
|
||
flag.Parse()
|
||
|
||
env.Active() // 初始化 env flag(依赖已有的全局 -env/ACTIVE_ENV 配置)
|
||
configs.Init()
|
||
|
||
cookie := "is_staff_user=false; SHOP_ID=156231010; PIGEON_CID=4339134776748827; bd_ticket_guard_web_domain=3; passport_mfa_token=CjcMUe8O6Zz52W9O1T3zlEkIxpWSHBCB4dHw9XBdiDU%2BIPU1pzwEXLpVjGth2W2nXGHC8OM6ffSmGkoKPAAAAAAAAAAAAABQK6uUDAbmPNiLgEkCaMWLdiWMpTEiK%2Fm1NGLpqOUmR4vBZtoNbJWrAhzjfim%2BBtfMlxCj6IsOGPax0WwgAiIBA8pTDDU%3D; bd_ticket_guard_server_data=eyJ0aWNrZXQiOiJoYXNoLk1SWGtrczRwYTZpWG91ODhuZENOT05idm9iSjI2SHlXOXRYN2JKNTdZMWM9IiwidHNfc2lnbiI6InRzLjIuMDg1MDhmMjljNWI2MjkzMjQ4ZTAwNGY0YjdiNjMwODI4ODk1YjFkZWQ1ZTRlYmFiZTc3NmYzZTUxYWJjZjZhNGM0ZmJlODdkMjMxOWNmMDUzMTg2MjRjZWRhMTQ5MTFjYTQwNmRlZGJlYmVkZGIyZTMwZmNlOGQ0ZmEwMjU3NWQiLCJjbGllbnRfY2VydCI6InB1Yi5CTHVTREdkVFRHWUdNMVY3ZDZKS2M4V2FwWGJ1K3JVYmVqRThONTZoeTI4SUJXdmVxZjBLMS9GczE0dWx5RTVRd2d4cjdnaDd6SXdMZjlsWDkwOFZQQWs9IiwibG9nX2lkIjoiMjAyNjAzMTExODE4NDBGQUVGNkZGMDBCMkUwQTJEQTU2QSIsImNyZWF0ZV90aW1lIjoxNzczMjI0MzIwfQ%3D%3D; passport_csrf_token=8a80d263a6af8795adf8692ddf2b0bd7; passport_csrf_token_default=8a80d263a6af8795adf8692ddf2b0bd7; s_v_web_id=verify_mmuhek92_2WWTTE1q_Nt89_4Uwc_An7s_aO5e3MjRRUH2; _tea_utm_cache_2631=undefined; Hm_lvt_b6520b076191ab4b36812da4c90f7a5e=1772107597,1772794481,1773223394,1773858658; ttwid=1%7CNnXcElGkMBE8UTpDOFYR5OfCUYkFjQaLyn1EagPBZgM%7C1773858585%7C74563a93a61ed33b1e9bd4697c260eb21177e46e87f72fddd86075bb903fa984; odin_tt=23564caa6c90cf80bbf73fe1d2a40f56b6c64bfaef87d2208db39c9d147b12ac7a28b422abddac143dee7a3ea2ee0fbd848d17f0ddcbe96db5dba6eca0e79fc2; passport_auth_status=28ac3ac0246ed02dd0776a5f51e7a3f1%2C581a8676e64d918c69ee3930f4dacf8b; passport_auth_status_ss=28ac3ac0246ed02dd0776a5f51e7a3f1%2C581a8676e64d918c69ee3930f4dacf8b; uid_tt=4086ea16cf4b601d9d9657f42419b53c; uid_tt_ss=4086ea16cf4b601d9d9657f42419b53c; sid_tt=6047a612c0e067f6c142d13bd87a9acc; sessionid=6047a612c0e067f6c142d13bd87a9acc; sessionid_ss=6047a612c0e067f6c142d13bd87a9acc; PHPSESSID=692181d913993eab8bc8bac1f6e26b1c; PHPSESSID_SS=692181d913993eab8bc8bac1f6e26b1c; ucas_c0=CkEKBTEuMC4wELaIh5S537vdaRjmJiD61rDnqc2DBCiwITCb1oDYuM3aB0Cf3uvNBkifkqjQBlC_vL6Ekt3t1GdYbhIUnz26j2aLNwC7K9D-UoY94GOoC_4; ucas_c0_ss=CkEKBTEuMC4wELaIh5S537vdaRjmJiD61rDnqc2DBCiwITCb1oDYuM3aB0Cf3uvNBkifkqjQBlC_vL6Ekt3t1GdYbhIUnz26j2aLNwC7K9D-UoY94GOoC_4; zsgw_business_data=%7B%22uuid%22%3A%226756720f-c380-4bda-ab81-3dd27ca08a2d%22%2C%22platform%22%3A%22pc%22%2C%22source%22%3A%22seo.fxg.jinritemai.com%22%7D; sid_guard=6047a612c0e067f6c142d13bd87a9acc%7C1773858597%7C5184000%7CSun%2C+17-May-2026+18%3A29%3A57+GMT; session_tlb_tag=sttt%7C10%7CYEemEsDgZ_bBQtE72HqazP________-jmJZ0rdd_Chl68Ti2aPyUgCao_SCeTs9hmqZrN0gLLeU%3D; sid_ucp_v1=1.0.0-KDE5ZGI2OTFkMTFkOGNlZGM5MDk0M2I4NTc5MzRjNzllMmM5MjBjMTUKGQib1oDYuM3aBxCl3uvNBhiwISAMOAZA9AcaAmxmIiA2MDQ3YTYxMmMwZTA2N2Y2YzE0MmQxM2JkODdhOWFjYw; ssid_ucp_v1=1.0.0-KDE5ZGI2OTFkMTFkOGNlZGM5MDk0M2I4NTc5MzRjNzllMmM5MjBjMTUKGQib1oDYuM3aBxCl3uvNBhiwISAMOAZA9AcaAmxmIiA2MDQ3YTYxMmMwZTA2N2Y2YzE0MmQxM2JkODdhOWFjYw; COMPASS_LUOPAN_DT=session_7618659644277604634; BUYIN_SASID=SID2_7618660342810313012; gfkadpd=4272,23756; csrf_session_id=e94f18f5f8c89da31caf1805f7fc4ac7; ecom_gray_shop_id=156231010"
|
||
if cookie == "" {
|
||
fmt.Println("请通过环境变量 DOUYIN_COOKIE 提供抖店 Cookie")
|
||
os.Exit(1)
|
||
}
|
||
|
||
log, err := logger.NewCustomLogger(logger.WithDebugLevel(), logger.WithOutputInConsole())
|
||
if err != nil {
|
||
panic(err)
|
||
}
|
||
|
||
repo, err := mysql.New()
|
||
if err != nil {
|
||
panic(err)
|
||
}
|
||
defer repo.DbRClose()
|
||
defer repo.DbWClose()
|
||
|
||
svc := douyin.New(log, repo, &staticSyscfg{cookie: cookie}, nil, nil, nil)
|
||
|
||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
|
||
defer cancel()
|
||
|
||
switch *mode {
|
||
case "fetch":
|
||
fmt.Println("开始 FetchAndSyncOrders(按绑定用户同步)...")
|
||
result, err := svc.FetchAndSyncOrders(ctx, &douyin.FetchOptions{
|
||
OnlyUnmatched: *fetchOnlyUnmatched,
|
||
MaxUsers: *fetchMaxUsers,
|
||
BatchSize: *fetchBatchSize,
|
||
Concurrency: *fetchConcurrency,
|
||
InterBatchDelay: time.Duration(*fetchDelay) * time.Millisecond,
|
||
})
|
||
if err != nil {
|
||
panic(err)
|
||
}
|
||
fmt.Printf("完成:抓取 %d,新订单 %d,匹配 %d,处理用户 %d/%d,跳过 %d,用时 %.2fs。\n",
|
||
result.TotalFetched, result.NewOrders, result.MatchedUsers,
|
||
result.ProcessedUsers, result.TotalUsers, result.SkippedUsers,
|
||
float64(result.ElapsedMS)/1000.0)
|
||
case "sync-all":
|
||
fallthrough
|
||
default:
|
||
duration := time.Duration(*minutes) * time.Minute
|
||
fmt.Printf("开始 SyncAllOrders,duration=%s proxy=%v ...\n", duration, *useProxy)
|
||
result, err := svc.SyncAllOrders(ctx, duration, *useProxy)
|
||
if err != nil {
|
||
panic(err)
|
||
}
|
||
fmt.Printf("完成:抓取 %d,新订单 %d,匹配 %d。\n", result.TotalFetched, result.NewOrders, result.MatchedUsers)
|
||
}
|
||
|
||
if *grantMinesweeper {
|
||
fmt.Println("执行 GrantMinesweeperQualifications ...")
|
||
if err := svc.GrantMinesweeperQualifications(ctx); err != nil {
|
||
fmt.Printf("GrantMinesweeperQualifications 失败: %v\n", err)
|
||
} else {
|
||
fmt.Println("GrantMinesweeperQualifications 完成。")
|
||
}
|
||
}
|
||
|
||
if *printLimit > 0 {
|
||
var orders []model.DouyinOrders
|
||
if err := repo.GetDbR().Order("id DESC").Limit(*printLimit).Find(&orders).Error; err != nil {
|
||
fmt.Printf("读取订单列表失败: %v\n", err)
|
||
return
|
||
}
|
||
fmt.Println("shop_order_id\torder_status\tdouyin_user_id\tlocal_user_id")
|
||
for _, o := range orders {
|
||
fmt.Printf("%s\t%d\t%s\t%s\n", o.ShopOrderID, o.OrderStatus, o.DouyinUserID, o.LocalUserID)
|
||
}
|
||
}
|
||
}
|
||
|
||
// go run cmd/douyin_sync_debug/main.go -env dev -mode fetch -fetch-only-unmatched=false -fetch-max-users=200 -fetch-batch-size=1 -fetch-concurrency=1 -fetch-delay-ms=0
|