Files
AskaEth 99a644d545 feat(channel): 微信 iLink 账号状态三态(诚实口径)
state ∈ 有效 / 被拒(需重扫)/ 未知;🔴 -14 是**被拒不是过期**,且**未知原因绝不写成「过期」**
(面板文案与错误码都如实)。三态判定为纯函数 + 三态各有用例。

⚠️ 未做(如实登记):每账号逐条三态(accounts[] 数组上的三态)本片未做。
2026-10-06 09:03:53 +08:00

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),
}
}