docs(comments): 注释中文化 · plugins/channels/weixin_ilink(20 文件,纯替换)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled

- 只翻注释/文档字符串:剥掉行尾注释后,每条「-」都有逐字节相同的「+」对应行(8 组,代码零改动)
- 保留协议/线上标识符原文:errcode、bot_token、context_token、getupdates、binded_redirect、PKCS#7、ECB 等
- 术语对齐既有译法:owner→主人、peer→对端、long poll→长轮询、backoff→退避、sentinel error→哨兵错误
- 已知既有欠债(未顺手修):login_reuse_test.go 在 HEAD 上就未 gofmt 干净;login_test.go 的 TestStartLogin_ScanStatusTransition 91 行 >80(HEAD 同为 91 行)
This commit is contained in:
AskaEth committed 2026-10-04 12:29:05 +08:00
1 parent 09fba77f87
commit 95f97f5df3
20 files changed
+488 -590

No files matched your search

+20 -25
View File
@@ -1,9 +1,8 @@
package weixin_ilink
// This file holds the HTTP plumbing for the iLink adapter (request building and
// response decoding). It is split from adapter.go so that file stays under the
// project's ≤500-line source-file limit. Nothing here exports a symbol the
// rest of the package or its tests rely on being in a specific file.
// 本文件承载 iLink 适配器的 HTTP 管道(请求构造与响应解码)。它从 adapter.go
// 拆出,以便那个文件保持在项目 ≤500 行的单文件上限之内。这里不放任何「包内其余
// 代码或其测试依赖其位于某个特定文件」的导出符号。
import (
"context"
@@ -19,9 +18,8 @@ import (
"strings"
)
// authorizationHeader decorates req with the iLink common headers: JSON
// content type, the bearer token, the auth type, a fresh random
// X-WECHAT-UIN replay guard, and the App identify headers.
// authorizationHeader 为 req 装上 iLink 通用请求头:JSON 内容类型、bearer
// token、认证类型、每次新生成的随机 X-WECHAT-UIN 防重放值,以及 App 标识头。
func (a *Adapter) authorizationHeader(req *http.Request) {
req.Header.Set("Content-Type", "application/json")
req.Header.Set("AuthorizationType", "ilink_bot_token")
@@ -36,8 +34,8 @@ func (a *Adapter) authorizationHeader(req *http.Request) {
}
}
// randomUIN returns a base64-encoded decimal uint32, minted fresh per request
// as iLink's anti-replay value.
// randomUIN 返回 base64 编码的十进制 uint32,每次请求都新生成,作为 iLink 的
// 防重放值。
func randomUIN() string {
var b [4]byte
_, _ = rand.Read(b[:])
@@ -45,9 +43,8 @@ func randomUIN() string {
return base64.StdEncoding.EncodeToString([]byte(fmt.Sprint(n)))
}
// doJSON performs an HTTP request and decodes the JSON response into out. It
// closes the response body and wraps network/decode errors. A nil out skips
// decoding (used for PUTs whose body is opaque bytes).
// doJSON 发起一次 HTTP 请求并把 JSON 响应解码进 out。它关闭响应体,并用 %w
// 包裹网络/解码错误。out 为 nil 时跳过解码(用于响应体是不透明字节的 PUT)。
func (a *Adapter) doJSON(ctx context.Context, method, rawURL string, body io.Reader, out any) error {
req, err := http.NewRequestWithContext(ctx, method, rawURL, body)
if err != nil {
@@ -76,19 +73,18 @@ func (a *Adapter) doJSON(ctx context.Context, method, rawURL string, body io.Rea
return nil
}
// apiURL joins a path with the configured base URL.
// apiURL 把路径与已配置的基础 URL 拼接起来。
func (a *Adapter) apiURL(path string) string {
return joinURL(a.cfg.BaseURL, path)
}
// joinURL joins a base URL with a leading-slash path, tolerating a trailing slash
// on the base.
// joinURL 把基础 URL 与以斜杠开头的路径拼接起来,并容忍基础 URL 末尾带斜杠。
func joinURL(base, path string) string {
return strings.TrimRight(base, "/") + path
}
// pollBase returns the base URL for get_qrcode_status: the IDC redirect host when
// one was recorded (scaned_but_redirect), else the configured base URL.
// pollBase 返回 get_qrcode_status 使用的基础 URL:已记录 IDC 重定向主机
// (scaned_but_redirect)时用它,否则用已配置的基础 URL。
func (a *Adapter) pollBase() string {
a.mu.RLock()
defer a.mu.RUnlock()
@@ -98,9 +94,8 @@ func (a *Adapter) pollBase() string {
return a.cfg.BaseURL
}
// setPollBaseURL records an IDC redirect host (https://<redirect_host>) for
// subsequent get_qrcode_status polls, per the official currentApiBaseUrl logic.
// An empty host clears the override.
// setPollBaseURL 按官方 currentApiBaseUrl 的逻辑,为后续的 get_qrcode_status
// 轮询记录一个 IDC 重定向主机(https://<redirect_host>)。host 为空则清除该覆盖。
func (a *Adapter) setPollBaseURL(host string) {
a.mu.Lock()
defer a.mu.Unlock()
@@ -111,9 +106,9 @@ func (a *Adapter) setPollBaseURL(host string) {
a.pollBaseURL = "https://" + host
}
// buildClientVersion encodes a semantic version into the iLink App-ClientVersion
// wire value 0x00MMNNPP = (major&0xff)<<16 | (minor&0xff)<<8 | (patch&0xff), as
// the official api.ts does. e.g. "2.4.8" -> "132104" (a decimal string, not "1").
// buildClientVersion 按官方 api.ts 的做法,把语义化版本编码成 iLink
// App-ClientVersion 的线上值 0x00MMNNPP = (major&0xff)<<16 | (minor&0xff)<<8 |
// (patch&0xff)。例如 "2.4.8" -> "132104"(十进制字符串,而不是 "1")。
func buildClientVersion(version string) string {
parts := strings.Split(version, ".")
at := func(i int) int {
@@ -130,8 +125,8 @@ func buildClientVersion(version string) string {
return strconv.Itoa(v)
}
// cdnURL joins a path with the configured CDN base URL, escaping raw query
// strings that some CDN references carry.
// cdnURL 把路径与已配置的 CDN 基础 URL 拼接起来,并转义部分 CDN 引用携带的原始
// 查询串。
func (a *Adapter) cdnURL(raw string) string {
if u, err := url.Parse(raw); err == nil && u.IsAbs() {
return raw