Skip to content

配置说明

应用从工作目录下的 config.yaml 加载配置,随后用 ICQQ_* 环境变量覆盖其中的敏感/常用 字段。把 config.example.yaml 复制为 config.yaml 再填值即可。

sh
cp config.example.yaml config.yaml
cargo run -p icqq-app

顶层运行参数

字段默认值说明
data_dir"./data"数据根目录。0.2 起按账号分目录,每个 uin 的数据落在 data_dir/<uin>/ 下(见数据目录布局与迁移)。
heartbeat_interval15000meta_event 心跳周期(毫秒,对应 go-cqhttp 的 heartbeat.interval)。据此推算心跳超时。设为 0(或任意 <= 0)则完全关闭心跳(不启动心跳任务)。
cache_group_membertrue是否缓存群成员列表。开启后收到某群首条消息会在后台拉取该群成员名册,之后 @某人(仅带 QQ 的 @ 段)可解析出群名片/昵称而非裸号。
report_self_messagetrue(0.4.0 起) 是否上报「自身消息」。登录号自己发出(含其他设备同步来)的消息以 post_type: "message_sent" 上报;设为 false 则丢弃这些事件、不下发(对齐 go-cqhttp 的 report-self-message,避免 bot 自发消息触发回环)。
captcha_port0(0.4.0 起) 过滑块「本地 webui」的监听端口。0 = 由操作系统随机分配(每次登录都可能变化);设为固定值则始终绑定该端口,便于反向代理 / 端口转发 / 收藏固定地址。也可用环境变量 ICQQ_CAPTCHA_PORT 覆盖。

数据目录布局与迁移

0.2 起,每个账号的全部本地数据独占一个以 uin 命名的子目录,互不干扰:

data/
└── <uin>/
    ├── device.json   # 设备信息(权威、可读、可备份/迁移)
    ├── icqq.db       # SQLite:token / 会话 / 名册 / 文件缓存
    └── logs/         # 日志(见 log.dir,留空时默认在此)

按 uin 分目录后,多个账号 / 多份 config.yaml 各写各的目录,不再争抢同一份 device.json / icqq.db

自动迁移

首次以 0.2 启动某账号时,若 data/<uin>/ 还不存在、而 data_dir 根目录里发现旧数据,会自动迁移data/<uin>/,并把根目录的原文件改名为 *.migrated 作为备份(非破坏、可回滚)。识别两类来源:

来源触发条件处理
0.1 版 icqq-rs(扁平布局)data_dir/icqq.db 存在复制 icqq.db(含 -wal/-shm)+ device.json 进子目录;格式不变,免重新登录
上游 TypeScript icqqdata_dir/icqq.db,但有 device.json<uin>_*_tokendevice.json 由 ShortDevice 展开为全量设备;token 文件与本项目字节同构,原样导入新库,免重新登录

怎么从上游 icqq 迁过来

把上游 icqq 的 data 目录下的 device.json<uin>_*_token 放进本项目的 data/(根目录),用同一个 uin 启动一次即可。迁移是幂等的:data/<uin>/ 一旦建立,后续启动不再重复导入。

0.1 → 0.2 变更

  • 旧版写出的 login_challenge.json 在 0.2 已移除(过滑块/验证码仍用终端粘贴或 ./ticket.txt 回填,行为不变)。
  • 扫码登录的 qrcode.png 现保存在 data/<uin>/ 下。

单实例锁(<uin>.pid

(0.4.1 起) 进程启动时会在运行目录(启动 bot 的当前目录,非 data_dir)创建一个 以配置 QQ 号命名的 <uin>.pid 文件(如 2717576556.pid),并对它加 OS 级排他文件锁 (Windows LockFileEx / Unix flock),防止同一个 QQ 被多个进程同时启动——多开会导致 互相踢下线、并发写坏 data/<uin>/icqq.db、以及事件重复上报。

  • 若该 QQ 已有一个实例在运行,新进程会在登录前立即报「QQ <uin> 已有一个实例在 运行」并退出(不会连服务器)。不同 QQ 号各生成各自的 <uin>.pid、互不影响;同号才互斥。
  • 锁随进程结束由操作系统自动释放(正常退出 / Ctrl+C / 崩溃都一样),无需也不要手动 实现解锁。
  • <uin>.pid 文件可能在 Ctrl+C / 崩溃退出后残留——这是正常的、无需手动清理:下次启动 会重新加锁并覆盖它,残留文件不会被误判为"已在运行"。

TIP

该文件无需配置、不入库(已在 .gitignore 忽略 *.pid);纯运行期状态。

log —— 日志

字段默认值说明
level"info"日志等级:trace / debug / info / warn / error。也可用环境变量 RUST_LOG 覆盖(env 优先)。
dir见说明日志文件目录(每日轮转),三态:注释掉/不写 => 默认落到账号目录 data/<uin>/logs""(空串)=> 关闭文件日志、仅控制台;"/某/路径" => 写到指定目录。
retention_days7自动清理超过该天数的日志文件(过期先压缩为 .gz 再删)。0 = 不清理。

渲染另由环境变量控制(不在 config.yaml 配置)

  • ICQQ_LOG_FORMAT = compact / pretty / auto(默认 auto:终端用 pretty、文件/非终端用 compact)。
  • NO_COLOR(任意非空)或 CLICOLOR=0 关闭控制台颜色;CLICOLOR_FORCE 强制开启。

版本变化

版本变化
v0.6.0修复 retention_days 的过期日志压缩/清理从未生效的问题(启动即扫一次,旧日志按期压成 .gz、超期删除);每日轮转的日志文件名日期改用 UTC+8,与日志行时间戳一致;写入磁盘的日志会把多媒体下载 URL 精简为仅 appid+fileid(去掉临时凭据 rkey 等,控制台仍打印完整 URL)。

account —— 凭据 + sign server(必填)

字段必填默认/示例说明
uin<your-uin>QQ 号(整数)。
password<your-password>明文,或 32 位小写 MD5 十六进制。留空/注释掉则改用扫码登录。
sign_api_url是*<sign-server-url>sign-server API 基址(qsign / unidbg-fetch-qsign / 兼容 T544)。留空 => 无签名器 => 无法 LIVE 登录(仅离线启动)。
platform1平台代码(整数),见下方平台代码表。
apk_ver"9.2.0"使用哪个 apk 档案 / QQ 版本。从该平台的 apk 列表里选版本匹配的;必须与 sign server 白盒支持的版本一致。省略则用平台默认 apk。
login_method"qr" / "password"登录方式。省略时由 bridge 推断:有密码 => 密码;有 sign server 但无密码 => 扫码;否则离线。
login_protocol"nt"(默认)登录协议:"nt"(现代 QQNT EcdhService 登录,需 sign server)或 "wt"(旧版 wtlogin)。iMac/Watch 等非 NT 平台走 NT 会被服务端以「设备不支持」拒绝,须改 "wt""wt" 也允许密码登录在无 sign server 时进行。省略 = "nt"

* 仅离线启动可省略 sign_api_url;真实登录必填。

平台代码表

代码平台说明
1Android(安卓手机)最常用,大多数 sign server 支持此平台
2aPad(安卓平板)常用平台之一
3Watch(手表)QQ 轻量版
4iMac(macOS 桌面)桌面客户端
5iPadiPad 原生客户端
6TimTIM 轻聊版

TIP

不同平台对应不同的 apk 档案和协议特征。apk_ver 必须与所选平台的 sign server 白盒支持版本一致,否则登录会被拒绝。常用组合为 platform: 1(Android)或 platform: 2(aPad)配合 apk_ver: "9.2.0"

通信端:多实例

四种通信端 —— http / http_post / ws / ws_reverse —— 每一种都支持多实例:写成一个 YAML 列表(- ...),即可同时启动多个服务端 / 客户端(如同时监听多个端口、同时上报多个上游)。列表 里每一项都有独立的 enable,可单独开关某一项。

兼容旧格式

每一种也仍可写成单个对象(旧格式),等价于只有一项的列表。所以你已有的单对象 config.yaml 无需改动即可继续工作。

默认全部关闭

生成的 config.yaml所有通信端默认 enable: false。请按需把要用的那一项改成 enable: true,否则 bot 启动后不对外暴露任何接口(仅离线处理 action + 心跳)。

http —— OneBot 11 HTTP API 服务端

客户端 POST 一个 action,取回信封。可配置多个监听地址。

字段默认值说明
enablefalse是否启用该 HTTP 服务端。
host"127.0.0.1"监听地址。
port0监听端口(示例用 5700)。
access_token""Bearer token;非空时请求需带 Authorization: Bearer <token>

http_post —— OneBot 11 HTTP 事件上报(HTTP-POST)

已从 http拆分独立。把每条事件 JSON POST 到 url;若设了 secret,则用标准 OneBot 11 算法 X-Signature: sha1=<HMAC-SHA1(secret, body)> 对请求体签名。可配置多个上报目标,事件会同时 投递给每一个。

字段默认值说明
enablefalse是否启用该上报目标。
url""事件 POST 目标地址。旧键 post_url 作为别名仍被接受。
secret可选:HMAC-SHA1 签名密钥(标准鉴权算法)。留空则不签名。

旧格式自动迁移

旧版把 post_url/secret 写在 http 块里的配置仍可工作:加载时会自动迁移成一个 http_post 条目(跟随该 http 块的 enable)。建议改用独立的 http_post 段。

ws —— 正向 WebSocket 服务端

客户端连到 bot。可配置多个监听地址。

字段默认值说明
enablefalse是否启用该正向 WS 服务端。
host"127.0.0.1"监听地址。
port0监听端口(示例用 6700)。
access_token""鉴权 token。

ws_reverse —— 反向 WebSocket 客户端

bot 主动连出到上游。可配置多个上游。

字段默认值说明
enablefalse是否启用该反向 WS 客户端。
url""要连接的上游地址(如 ws://127.0.0.1:8080/onebot)。
access_token""鉴权 token。
reconnect_interval3000重连退避(毫秒)。

notify —— 掉线/登录带外通知(可选)

当 Bot 被踢下线自动重登彻底失败重新上线、或需要登录交互(扫码 / 滑块 / 短信 / 设备锁 / 风控)时,主动把消息推送到下列渠道,方便人不在 OneBot 客户端旁也能第一 时间知道。所有渠道默认关闭,整套系统受 notify.enable 主开关约束。

字段默认值说明
enablefalse通知系统主开关。
proxy""外网渠道(如 Telegram)使用的代理;留空直连。支持 http(s)://socks5://
events[]仅在这些时机通知:offline / relogin / online / login。空 = 全部。

每个渠道都支持「多个」:写成 YAML 列表即可(单个对象也兼容),各渠道项都有独立的 enable(默认 true)。各渠道字段:

渠道关键字段
email(SMTP)smtp_host / smtp_port(默认 465) / tls(465 隐式 TLS;false 走 STARTTLS) / username / password / from / to(列表)
webhookurl(POST JSON {event,self_id,time,time_str,title,body})/ use_proxy / headers["K: V"]
serverchankey(SendKey)
dingtalkwebhook / secret(可选,开启「加签」时填,HMAC-SHA256)
feishuwebhook / secret(可选,开启「签名校验」时填)
wecomwebhook(群机器人地址)
barkserver(默认 https://api.day.app) / key
telegrambot_token / chat_id / use_proxy(默认 true)

自测

配好后运行 ./icqq-app notify-selftest,会给所有启用渠道发一条测试消息并打印 逐渠道成功/失败,便于在等到真实掉线前先验证配置。

体积

邮件渠道经 lettre(SMTP),位于默认开启的 cargo feature notify-email 之后;用 --no-default-features 构建可裁掉它,二进制不链接 lettre(其余 7 个 HTTP 渠道复用现有 reqwest,零额外依赖)。

版本变化

版本变化
v0.6.0通知正文里的「时间:」改为渲染 UTC+8 可读时间(YYYY-MM-DD HH:MM:SS);webhook 透传载荷新增 time_str 字段(UTC+8 可读时间),time(unix 秒)保留不变,两者并存。

完整配置示例

下面是一份覆盖全部字段的 config.yaml(通信端均演示了多实例的列表写法,且默认全部关闭):

yaml
# 顶层运行参数
data_dir: "./data"
heartbeat_interval: 15000          # meta_event 心跳周期(毫秒);<= 0 关闭心跳
cache_group_member: true           # 缓存群成员名册,@某人 可解析名片/昵称
report_self_message: true          # 自身消息是否以 message_sent 上报;false 不下发
captcha_port: 0                    # 过滑块本地 webui 端口;0=随机,固定值=绑定该端口

# 日志
log:
  level: "info"                    # trace / debug / info / warn / error
  # dir 三态:注释掉 => 默认 data/<uin>/logs;"" => 仅控制台;"/某/路径" => 指定目录
  # dir: "./logs"
  retention_days: 7                # 0 = 不自动清理

# 凭据 + sign server
account:
  uin: 10001
  password: "your-password-or-md5-hex"
  sign_api_url: "http://127.0.0.1:8080"
  platform: 1                      # 1=Android 2=aPad 3=Watch 4=iMac 5=iPad 6=Tim
  apk_ver: "9.2.0"                 # 必须与 sign server 白盒版本一致
  login_method: "password"         # "qr" | "password",省略则自动推断
  login_protocol: "nt"             # "nt"(默认) | "wt"(iMac/Watch 等非 NT 平台)

# HTTP API 服务端(可多个)
http:
  - enable: false
    host: "127.0.0.1"
    port: 5700
    access_token: "change-me-secret-token"
  # 再加一个监听:
  # - enable: false
  #   host: "0.0.0.0"
  #   port: 5800
  #   access_token: "another-token"

# HTTP 事件上报(可多个,事件同时投递给每一个)
http_post:
  - enable: false
    url: "http://127.0.0.1:5701/onebot/event"
    secret: "change-me-hmac-secret"   # 留空则不签名
  # - enable: false
  #   url: "http://127.0.0.1:5702/onebot/event"
  #   secret: ""

# 正向 WebSocket 服务端(可多个)
ws:
  - enable: false
    host: "127.0.0.1"
    port: 6700
    access_token: "change-me-secret-token"

# 反向 WebSocket 客户端(可多个)
ws_reverse:
  - enable: false
    url: "ws://127.0.0.1:8080/onebot"
    access_token: "change-me-secret-token"
    reconnect_interval: 3000

# 掉线/登录带外通知(各渠道均可多个;默认全部关闭)
notify:
  enable: false
  proxy: ""                          # 如 socks5://127.0.0.1:7890;留空直连
  events: []                         # 空=全部;可选 offline/relogin/online/login
  email:
    - enable: false
      smtp_host: "smtp.example.com"
      smtp_port: 465                 # 465 隐式 TLS;587 等配 tls:false 走 STARTTLS
      tls: true
      username: "you@example.com"
      password: "your-mail-token"
      from: "you@example.com"
      to: ["dest@example.com"]
  webhook:
    - enable: false
      url: "https://example.com/hook"
      use_proxy: false
      headers: []                    # 如 ["Authorization: Bearer xxx"]
  serverchan:
    - enable: false
      key: "SCT-your-sendkey"
  dingtalk:
    - enable: false
      webhook: "https://oapi.dingtalk.com/robot/send?access_token=xxx"
      secret: ""                     # 开启「加签」时填
  feishu:
    - enable: false
      webhook: "https://open.feishu.cn/open-apis/bot/v2/hook/xxx"
      secret: ""
  wecom:
    - enable: false
      webhook: "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx"
  bark:
    - enable: false
      server: "https://api.day.app"
      key: "your-device-key"
  telegram:
    - enable: false
      bot_token: "123456:ABC-DEF"
      chat_id: "123456789"
      use_proxy: true

ICQQ_* 环境变量覆盖

以下环境变量存在即覆盖 config.yaml 中的对应值(env 优先),便于把密码 / sign server 等敏感值从配置文件移到环境,避免明文落盘。实现见 crates/icqq-app/src/config.rsapply_env_overrides

环境变量覆盖的配置字段解析
ICQQ_UINaccount.uin解析为整数;解析失败则忽略,保留原值。
ICQQ_PASSWORDaccount.password原样字符串。
ICQQ_SIGN_API_URLaccount.sign_api_url原样字符串。
ICQQ_PLATFORMaccount.platform解析为整数;解析失败则忽略。
ICQQ_APK_VERaccount.apk_ver原样字符串。
ICQQ_LOGIN_METHODaccount.login_method原样字符串("qr" / "password")。
ICQQ_DATA_DIRdata_dir原样字符串。
ICQQ_HTTP_ACCESS_TOKENhttp[*].access_token原样字符串;应用到全部 HTTP API 服务端。
ICQQ_LOGIN_PROTOCOLaccount.login_protocol原样字符串("nt" / "wt")。
ICQQ_CAPTCHA_PORTcaptcha_port解析为端口整数;解析失败则忽略。

未设置的变量保留 config.yaml 的原值;设置了才覆盖。