Files
dygou_go/internal/app/app_products.go
T

99 lines
2.7 KiB
Go

package app
import (
"fmt"
"strings"
"time"
"douyu_go/internal/constants"
"douyu_go/internal/logger"
"douyu_go/internal/types"
"douyu_go/internal/utils"
)
// LoadProducts 刷新商品列表。refresh=true 时从斗鱼实时拉取。
func (a *App) LoadProducts(refresh bool) types.ProductPayload {
if refresh {
cfg := a.getCfg()
options := types.XiaodianProductListOptions{PageSize: cfg.XiaodianPageSize}
var products []types.Product
err := fmt.Errorf("没有可用账号 Cookie")
accounts := a.scheduler.AccountSnapshot()
for _, account := range accounts {
if strings.TrimSpace(account.Cookie) == "" {
continue
}
products, err = a.getClient().Products(account.Cookie, options)
if err == nil {
break
}
logger.LogEvent("商品", "warn", "账号 %s 获取和平小店角色失败,尝试下一个账号: %v", account.Name, err)
}
if err != nil {
logger.LogEvent("商品", "error", "商品刷新失败: %v", err)
return types.ProductPayload{Success: false}
}
fetchedAt := time.Now()
a.setProducts(products, fetchedAt)
logger.LogEvent("商品", "success", "商品刷新完成: %d 个,刷新时间=%s", len(products), fetchedAt.In(constants.CST).Format("15:04:05.000"))
return a.productPayload("live")
}
return a.productPayload("cache")
}
// GetAccounts 返回账号列表。
func (a *App) GetAccounts() []types.AccountView {
accounts := a.scheduler.AccountSnapshot()
list := make([]types.AccountView, 0, len(accounts))
for i, account := range accounts {
list = append(list, types.AccountView{
Index: i,
Name: account.Name,
Cookie: utils.MaskCookie(account.Cookie),
})
}
return list
}
// ReloadAccounts 重新加载内部账号库。
func (a *App) ReloadAccounts() types.ReloadAccountsResult {
a.scheduler.LoadAccounts()
return types.ReloadAccountsResult{Success: true, Count: a.scheduler.AccountCount()}
}
// ==================== 内部辅助方法 ====================
func (a *App) setProducts(products []types.Product, fetchedAt time.Time) {
a.productsMu.Lock()
a.products = products
a.productsAt = fetchedAt
a.productsMu.Unlock()
if a.scheduler != nil {
a.scheduler.UpdateProducts(products)
}
}
func (a *App) productPayload(source string) types.ProductPayload {
a.productsMu.RLock()
defer a.productsMu.RUnlock()
payload := types.ProductPayload{
Success: true,
Source: source,
Products: a.products,
Count: len(a.products),
}
if !a.productsAt.IsZero() {
age := time.Since(a.productsAt)
if age < 0 {
age = 0
}
payload.FetchedAt = a.productsAt.In(constants.CST).Format("2006-01-02 15:04:05.000")
payload.AgeSecond = int(age.Seconds())
payload.Stale = age > constants.ProductCacheTTL
} else {
payload.Stale = true
}
return payload
}