Files
dygou_go/state.go
T
2026-06-19 12:10:55 +08:00

151 lines
3.7 KiB
Go

package main
import (
"bufio"
"os"
"strings"
"time"
)
// loadAccounts 从账号文件加载账号,格式为“账号----密码----Cookie”。
func (s *appState) loadAccounts() {
path := s.paths.AccountFile
if path == "" {
path = defaultAccountFile
}
f, err := os.Open(path)
if err != nil {
logEvent("账号", "error", "读取账号文件失败: %s: %v", path, err)
s.accountsMu.Lock()
s.accounts = nil
s.accountsMu.Unlock()
return
}
defer f.Close()
var list []Account
scanner := bufio.NewScanner(f)
scanner.Buffer(make([]byte, 1024), 1024*1024)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if line == "" || strings.HasPrefix(line, "#") {
continue
}
parts := strings.SplitN(line, "----", 3)
if len(parts) != 3 {
logEvent("账号", "warn", "账号行格式错误,已跳过: %s", line)
continue
}
list = append(list, Account{
Name: strings.TrimSpace(parts[0]),
Password: strings.TrimSpace(parts[1]),
Cookie: strings.TrimSpace(parts[2]),
})
}
if err := scanner.Err(); err != nil {
logEvent("账号", "error", "读取账号文件中断: %v", err)
}
s.accountsMu.Lock()
s.accounts = list
s.accountsMu.Unlock()
logEvent("账号", "success", "账号加载完成: %d 个,来源=%s", len(list), path)
}
// accountCount 返回当前账号数。
func (s *appState) accountCount() int {
s.accountsMu.RLock()
defer s.accountsMu.RUnlock()
return len(s.accounts)
}
// accountSnapshot 复制一份账号列表,避免执行任务时长时间持锁。
func (s *appState) accountSnapshot() []Account {
s.accountsMu.RLock()
defer s.accountsMu.RUnlock()
list := make([]Account, len(s.accounts))
copy(list, s.accounts)
return list
}
// accountCookieByName 按账号名查找真实 Cookie,仅在后端内部使用。
func (s *appState) accountCookieByName(name string) (string, bool) {
s.accountsMu.RLock()
defer s.accountsMu.RUnlock()
for _, account := range s.accounts {
if account.Name == name {
return account.Cookie, true
}
}
return "", false
}
// productSnapshot 复制一份商品列表和对应的刷新时间。
func (s *appState) productSnapshot() ([]Product, time.Time) {
s.productsMu.RLock()
defer s.productsMu.RUnlock()
list := make([]Product, len(s.products))
copy(list, s.products)
return list, s.productsAt
}
// setProducts 替换商品缓存,并记录这批库存数据的刷新时间。
func (s *appState) setProducts(products []Product, fetchedAt time.Time) {
s.productsMu.Lock()
defer s.productsMu.Unlock()
s.products = products
s.productsAt = fetchedAt
}
// productPayload 根据当前缓存生成前端商品响应。
func (s *appState) productPayload(source string) ProductPayload {
products, fetchedAt := s.productSnapshot()
payload := ProductPayload{
Success: true,
Source: source,
Products: products,
Count: len(products),
}
if !fetchedAt.IsZero() {
age := time.Since(fetchedAt)
if age < 0 {
age = 0
}
payload.FetchedAt = fetchedAt.In(cst).Format("2006-01-02 15:04:05.000")
payload.AgeSecond = int(age.Seconds())
payload.Stale = age > productCacheTTL
} else {
payload.Stale = true
}
return payload
}
// clearResults 清空抢购结果。
func (s *appState) clearResults() {
s.resultsMu.Lock()
defer s.resultsMu.Unlock()
s.results = make(map[string]string)
}
// setResult 写入单次兑换结果。
func (s *appState) setResult(key, value string) {
s.resultsMu.Lock()
defer s.resultsMu.Unlock()
s.results[key] = value
}
// resultsSnapshot 复制当前结果。
func (s *appState) resultsSnapshot() map[string]string {
s.resultsMu.RLock()
defer s.resultsMu.RUnlock()
out := make(map[string]string, len(s.results))
for k, v := range s.results {
out[k] = v
}
return out
}