- 兑换请求增加独立的 RequestTimeout 上下文超时熔断(默认 1500ms),防止微服务卡死吃掉 5 秒 - 剥离 CategoryRoleUnbound(角色未绑定/抖动),不再计入 sessionStreak 判死阈值,杜绝误杀有效账号 - 将 CategoryRoleUnbound 与 CategoryTooFrequent 纳入 sessionAliveCategory,正常回包可重置会话计数 - 补充单测 TestRunTargetsRoleUnboundDoesNotStopAccount 与 TestExchangeTargetFastTimeout
90 lines
2.4 KiB
Go
90 lines
2.4 KiB
Go
package sniper
|
||
|
||
import (
|
||
"fmt"
|
||
"strconv"
|
||
"strings"
|
||
)
|
||
|
||
// TargetSummary 把目标列表渲染成「13437(冠军之刃)」这样的单行摘要,供启动日志使用。
|
||
//
|
||
// 2026-10-16 的复盘正卡在「日志里没有目标 pid」:三台机器都只记了 sid 与 targets=1,
|
||
// 看不出各自打的是哪个奖品,也就无法解释为什么一台售罄、另一台库存完好。
|
||
func TargetSummary(targets []Target) string {
|
||
parts := make([]string, 0, len(targets))
|
||
for _, target := range targets {
|
||
name := strings.TrimSpace(target.Name)
|
||
switch {
|
||
case target.PID > 0 && name != "":
|
||
parts = append(parts, fmt.Sprintf("%d(%s)", target.PID, name))
|
||
case target.PID > 0:
|
||
parts = append(parts, strconv.FormatInt(int64(target.PID), 10))
|
||
case name != "":
|
||
parts = append(parts, name)
|
||
case target.Auto:
|
||
parts = append(parts, "自动选择")
|
||
}
|
||
}
|
||
if len(parts) == 0 {
|
||
return "未指定"
|
||
}
|
||
return strings.Join(parts, ",")
|
||
}
|
||
|
||
// CategoryLabel 返回结局分类的中文短标签,供任务结束时的结局日志使用。
|
||
func CategoryLabel(category string) string {
|
||
switch category {
|
||
case CategorySuccess:
|
||
return "已抢到"
|
||
case CategorySoldOut:
|
||
return "售罄"
|
||
case CategoryTooFrequent:
|
||
return "被限流"
|
||
case CategoryNotOpen:
|
||
return "未开放"
|
||
case CategoryNotEnough:
|
||
return "积分不足"
|
||
case CategoryAlreadyDone:
|
||
return "已兑换过"
|
||
case CategoryOffShelf:
|
||
return "已下架"
|
||
case CategorySessionLost:
|
||
return "会话失效"
|
||
case CategoryRoleUnbound:
|
||
return "角色未绑定/抖动"
|
||
case CategoryProtocol:
|
||
return "协议异常"
|
||
case CategoryCondition:
|
||
return "条件未达成"
|
||
case CategoryNotFound:
|
||
return "未匹配到奖品"
|
||
case CategoryError:
|
||
return "请求异常"
|
||
default:
|
||
return "失败"
|
||
}
|
||
}
|
||
|
||
// CategoryText 把类目限制渲染成日志文案(空串表示不限类目)。
|
||
func CategoryText(category string) string {
|
||
key := strings.TrimSpace(category)
|
||
if key == "" {
|
||
return "不限"
|
||
}
|
||
return key
|
||
}
|
||
|
||
// LogLevelForCategory 把结果分类映射成日志等级,供界面按等级高亮与筛选。
|
||
func LogLevelForCategory(category string) string {
|
||
switch category {
|
||
case CategorySuccess:
|
||
return "success"
|
||
case CategoryError, CategoryProtocol:
|
||
return "error"
|
||
case CategoryFailed, CategoryTooFrequent, CategoryCondition, CategoryRoleUnbound, CategorySessionLost:
|
||
return "warn"
|
||
default:
|
||
return "info"
|
||
}
|
||
}
|