主人 2026-10-03 拍板「注释一律中文」;gateway 至此整包注释中文化完成(本会话共 3 批: 已推库 16 个文件 + 本批剩余文件)。 校验:机械校验(非注释改动行)= 空;剥注释后代码文本逐行比对全等(不一致文件数 0); 全树 go test ./... 58 包 ok / 0 FAIL;交叉编译绿。
63 lines
2.2 KiB
Go
63 lines
2.2 KiB
Go
package gateway
|
|
|
|
import "reflect"
|
|
|
|
// 本文件承载「适配器需要主人重新授权」这一可选能力,
|
|
// 由 GET /api/v1/admin/channels 浮现(v0.39)。它位于渠道摘要
|
|
// 本身之旁 —— 而非其内 —— 因为摘要列表是 admin.go 中较大的
|
|
// handler 之一,而拆包辅助函数可复用。
|
|
|
|
// rescanAware 是渠道适配器在会话需要主人重新授权、而重连
|
|
// 无法提供该授权时所暴露的可选能力。
|
|
// *weixin_ilink.Adapter 实现了它(RescanRequired):iLink 应答
|
|
// errcode=-14 意味着机器人 token 已失效,主人必须扫新的二维码。
|
|
// 核心的 adapter.PlatformAdapter 契约被刻意不扩展,因此不需要
|
|
// 该能力的适配器不受任何改动。
|
|
//
|
|
// 只有在适配器确实产出某值时才会报告它 —— 没有该能力的
|
|
// 平台保持字段省略,而不是送出一个猜测。
|
|
type rescanAware interface {
|
|
// RescanRequired 报告是否需要一次新的扫码登录,以及原因
|
|
// (不需要时 reason 为 "")。
|
|
RescanRequired() (required bool, reason string)
|
|
}
|
|
|
|
// asRescanAware 报告已注册的渠道值是否暴露 rescan 能力。
|
|
// 注册时会把适配器包进 cmd/cyrene 的 namedAdapter —— 一个内嵌
|
|
// adapter.PlatformAdapter 的未导出结构体 —— 它只提升接口的
|
|
// 方法,因此具体适配器多出的能力只能通过拆开被内嵌字段
|
|
// 才能抵达。直接的适配器值(测试、单账号注册)
|
|
// 按原样接受。
|
|
func asRescanAware(v any) (rescanAware, bool) {
|
|
if ra, ok := v.(rescanAware); ok {
|
|
return ra, true
|
|
}
|
|
inner, ok := unwrapNamedAdapter(v)
|
|
if !ok {
|
|
return nil, false
|
|
}
|
|
ra, ok := inner.(rescanAware)
|
|
return ra, ok
|
|
}
|
|
|
|
// unwrapNamedAdapter 返回注册包装器内嵌在其导出 PlatformAdapter
|
|
// 字段中的适配器。asKookAdmin 与 asWeixinLoginAdmin 为各自的
|
|
// 能力子集做同样的拆包,本可共用此辅助函数。
|
|
func unwrapNamedAdapter(v any) (any, bool) {
|
|
rv := reflect.ValueOf(v)
|
|
if !rv.IsValid() {
|
|
return nil, false
|
|
}
|
|
if rv.Kind() == reflect.Ptr {
|
|
rv = rv.Elem()
|
|
}
|
|
if rv.Kind() != reflect.Struct {
|
|
return nil, false
|
|
}
|
|
f := rv.FieldByName("PlatformAdapter")
|
|
if !f.IsValid() || !f.CanInterface() {
|
|
return nil, false
|
|
}
|
|
return f.Interface(), true
|
|
}
|