state ∈ 有效 / 被拒(需重扫)/ 未知;🔴 -14 是**被拒不是过期**,且**未知原因绝不写成「过期」** (面板文案与错误码都如实)。三态判定为纯函数 + 三态各有用例。 ⚠️ 未做(如实登记):每账号逐条三态(accounts[] 数组上的三态)本片未做。
67 lines
2.9 KiB
Go
67 lines
2.9 KiB
Go
package events
|
|
|
|
// 本文件是**一条事件行到线上的投影**(design/26 §4.5;切片 E7)。
|
|
//
|
|
// 为什么投影住在 events 包而不是网关:同一条事件有**两个**线上出口 ——
|
|
// 管理 REST 的列表端点(`admin_channel_events.go`)与实时 WS 帧(`channel.event`
|
|
// 主题,见 watcher.go / publish_store.go)。两处若各写一份结构,迟早会漂移成
|
|
// 「帧里有这个键、列表里没有」这类无从察觉的差异(正是 §9.2 反复强调的那类债)。
|
|
// 因此投影只写一次:**REST 的 DTO 是它的类型别名,实时帧的载荷也是它**。
|
|
//
|
|
// 列与 `Event` 一一对应且不多不少:**没有**承载平台原文、媒体 URL、凭据或 OneBot
|
|
// `flag` 的字段(§4.2 红线)。`summary` 是适配器或本包生成的固定文案,已净化,
|
|
// 查不出原始文本。
|
|
|
|
import "time"
|
|
|
|
// ChannelEventJSON 是一条 `channel_events` 行的线上投影(键名 camelCase,与契约
|
|
// v0.67 登记的 `events[]` 逐字一致)。
|
|
type ChannelEventJSON struct {
|
|
// ID 是数据库自增主键。**可缺席**:实时帧里的事件行是**刚落库、id 还没回读**的
|
|
// 那一行,此时它被整个省略(而不是写一个 0)—— 0 会让客户端以为「所有实时帧
|
|
// 是同一行」。列表端点读的是已落盘的行,id 恒有值。
|
|
ID int64 `json:"id,omitempty"`
|
|
Platform string `json:"platform"`
|
|
AccountID string `json:"accountId"`
|
|
Tier string `json:"tier"`
|
|
Category string `json:"category"`
|
|
PlatformType string `json:"platformType"`
|
|
ChannelID string `json:"channelId"`
|
|
ChannelType string `json:"channelType"`
|
|
GroupID string `json:"groupId"`
|
|
ActorID string `json:"actorId"`
|
|
ActorRole string `json:"actorRole"`
|
|
TargetID string `json:"targetId"`
|
|
SelfRelated bool `json:"selfRelated"`
|
|
MessageID string `json:"messageId"`
|
|
Summary string `json:"summary"`
|
|
CreatedAt string `json:"createdAt"`
|
|
UpdatedAt string `json:"updatedAt"`
|
|
}
|
|
|
|
// JSON 把一条事件行投影成线上结构。时间一律以 **UTC RFC3339** 回显(与 `llm/usage`
|
|
// 同口径):本地时区偏移会让同一行的两个出口显示出不同的时刻。
|
|
//
|
|
// id 为 0 时留空(见 ID 的注释):写侧不知道刚插入的行的 id,如实缺席比编一个强。
|
|
func (ev Event) JSON() ChannelEventJSON {
|
|
return ChannelEventJSON{
|
|
ID: ev.ID,
|
|
Platform: ev.Platform,
|
|
AccountID: ev.AccountID,
|
|
Tier: string(ev.Tier),
|
|
Category: string(ev.Category),
|
|
PlatformType: ev.PlatformType,
|
|
ChannelID: ev.ChannelID,
|
|
ChannelType: ev.ChannelType,
|
|
GroupID: ev.GroupID,
|
|
ActorID: ev.ActorID,
|
|
ActorRole: ev.ActorRole,
|
|
TargetID: ev.TargetID,
|
|
SelfRelated: ev.SelfRelated,
|
|
MessageID: ev.MessageID,
|
|
Summary: ev.Summary,
|
|
CreatedAt: ev.CreatedAt.UTC().Format(time.RFC3339),
|
|
UpdatedAt: ev.UpdatedAt.UTC().Format(time.RFC3339),
|
|
}
|
|
}
|