🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

QQ 聊天记录导出 ariyflow/dsh-qqnt-chat-export

DeepSeek Harness
ariyflow2 天前有提交已提供中文文档扫描:含敏感能力

读取、搜索并导出 NTQQ 群聊与私聊记录

29.9/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/11/2 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add ariyflow/dsh-qqnt-chat-export
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:仅索引
是什么
dsh 原生插件 · platform
装得上吗
本站尚未做安装检查
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 2 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 114 处,展示前 68 条)
  • 读取本地文件
    index.js:93
    const match = /^XDG_DOWNLOAD_DIR="(.*)"$/m.exec(readFileSync(file, 'utf8'))
  • 执行外部命令来自配置/变量
    index.js:162
    const child = spawn(command, argv, {
  • 读取本地文件
    index.js:245
    const key = readFileSync(keyFile, 'utf8').trim()
  • 读取本地文件
    index.js:265
    if (!existsSync(CLI)) throw new Error(`bundled helper is missing: ${CLI}`)
  • 写入本地文件
    index.js:266
    mkdirSync(settings.workDir, { recursive: true, mode: 0o700 })
  • 读取本地文件
    index.js:282
    if (!existsSync(QUERY_CLI)) throw new Error(`bundled helper is missing: ${QUERY_CLI}`)
  • 写入本地文件
    index.js:283
    mkdirSync(settings.workDir, { recursive: true, mode: 0o700 })
  • 读取本地文件
    index.js:363
    for (let index = 2; existsSync(target); index += 1) {
  • 读取本地文件
    index.js:579
    if (!existsSync(indexPath(settings))) return missingIndex(settings)
  • 写入本地文件
    index.js:973
    mkdirSync(outDir, { recursive: true, mode: 0o700 })
  • 写入本地文件
    index.js:993
    renameSync(payload.path, target)
  • 写入本地文件
    index.js:996
    copyFileSync(payload.path, target)
  • 删除本地文件
    index.js:998
    rmSync(payload.path)
  • 写入本地文件
    index.js:1142
    mkdirSync(outDir, { recursive: true, mode: 0o700 })
  • 删除本地文件
    index.js:1179
    rmSync(payload.path)
  • 删除本地文件递归
    index.js:3096
    rmSync(venvDir, { recursive: true, force: true })
  • 删除本地文件递归
    index.js:3139
    rmSync(venvDir, { recursive: true, force: true })
  • 执行外部命令来自配置/变量
    index.js:3232
    child = spawn(settings.python, argv, {
  • 发起网络请求
    index.js:3452
    const reply = await fetch(`${webUrl}api/status`, { signal: AbortSignal.timeout(2000) })
  • 发起网络请求
    client.js:94
    fetch(ROUTE, { headers: { accept: 'application/json' } })
  • 读取本地文件
    settings.js:75
    .some((name) => existsSync(path.join(dir, name)))
  • 读取本地文件
    settings.js:184
    if (!existsSync(persistent) && looksLikeWorkDir(legacy)) {
  • 读取本地文件
    settings.js:217
    data = JSON.parse(readFileSync(file, 'utf8'))
  • 写入本地文件
    settings.js:236
    mkdirSync(dir, { recursive: true, mode: 0o700 })
  • 写入本地文件
    settings.js:239
    chmodSync(dir, 0o700)
  • 写入本地文件
    settings.js:245
    writeFileSync(tmp, `${JSON.stringify(clean, null, 2)}\n`, 'utf8')
  • 写入本地文件
    settings.js:248
    chmodSync(tmp, 0o600)
  • 写入本地文件
    settings.js:253
    renameSync(tmp, file)
  • 删除本地文件
    settings.js:258
    unlinkSync(file)
  • 读取本地文件
    storage.js:67
    const st = lstatSync(target)
  • 读取本地文件
    storage.js:80
    return readdirSync(workDir).filter((name) => CACHE_RE.test(name)).sort()
  • 读取本地文件
    storage.js:106
    if (!lstatSync(dir).isDirectory()) return []
  • 读取本地文件
    storage.js:107
    return readdirSync(dir)
  • 读取本地文件
    storage.js:120
    status = JSON.parse(readFileSync(statusFile, 'utf8'))
  • 读取本地文件
    storage.js:126
    lockAge = Date.now() - lstatSync(path.join(workDir, 'build.lock')).mtimeMs
  • 删除本地文件
    storage.js:206
    unlinkSync(target)
  • 写入本地文件
    storage.js:271
    await mkdir(target, { recursive: true, mode: 0o700 })
  • 删除本地文件
    storage.js:302
    await rm(path.join(target, name), { force: true })
  • 删除本地文件递归
    storage.js:305
    for (const name of copied) await rm(path.join(target, name), { recursive: true, force: true })
  • 删除本地文件递归
    storage.js:317
    await rm(path.join(dir, name), { recursive: true, force: true })
  • 读取本地文件
    presets.js:57
    const rows = JSON.parse(readFileSync(presetFile(workDir), 'utf8'))
  • 写入本地文件
    presets.js:71
    writeFileSync(tmp, `${JSON.stringify(list, null, 2)}\n`, { encoding: 'utf8', mode: 0o600 })
  • 写入本地文件
    presets.js:72
    renameSync(tmp, file)
  • 执行外部命令来自配置/变量
    runners.js:61
    const child = spawn(settings.python, helperArgv(settings, queryCli, args), {
  • 执行外部命令来自配置/变量
    runners.js:250
    const child = spawn(settings.python, argv, {
  • 删除本地文件
    runners.js:275
    try { unlinkSync(out) } catch { }
  • 读取本地文件
    web.js:76
    return String(JSON.parse(readFileSync(path.join(HERE, 'package.json'), 'utf8')).version || '')
  • 执行外部命令来自配置/变量
    web.js:172
    child = spawn(settings.python, argv, {
  • 执行外部命令来自配置/变量
    web.js:217
    const child = spawn(settings.python, argv, {
  • 执行外部命令来自配置/变量
    web.js:273
    const child = spawn(settings.python, argv, {
  • 读取本地文件
    web.js:383
    info = statSync(target.file)
  • 读取本地文件
    web.js:410
    const stream = createReadStream(target.file)
  • 读取本地文件
    web.js:481
    const info = statSync(file)
  • 读取本地文件
    web.js:495
    const value = JSON.parse(readFileSync(chatStateFile(workDir), 'utf8'))
  • 写入本地文件
    web.js:505
    writeFileSync(tmp, JSON.stringify(value, null, 2))
  • 写入本地文件
    web.js:506
    renameSync(tmp, file)
  • 读取本地文件
    web.js:536
    const value = JSON.parse(readFileSync(path.join(workDir, 'build-status.json'), 'utf8'))
  • 删除本地文件递归
    web.js:564
    if (info.isDirectory()) rmSync(file, { recursive: true, force: true })
  • 删除本地文件
    web.js:565
    else unlinkSync(file)
  • 执行外部命令来自配置/变量
    web.js:818
    const child = spawn(settings.python, argv, { stdio: ['ignore', 'pipe', 'pipe'] })
  • 写入本地文件
    jobs.js:101
    mkdirSync(path.dirname(target), { recursive: true })
  • 写入本地文件
    jobs.js:104
    writeFileSync(temp, JSON.stringify(rows, null, 2))
  • 写入本地文件
    jobs.js:105
    renameSync(temp, target)
  • 读取本地文件
    jobs.js:114
    rows = JSON.parse(readFileSync(file(), 'utf8'))
  • 写入本地文件
    jobs.js:163
    mkdirSync(logDir(), { recursive: true })
  • 写入本地文件
    jobs.js:164
    writeFileSync(logFile(job.id), `${job.log.join('\n')}\n`)
  • 读取本地文件
    jobs.js:370
    if (existsSync(logFile(job.id))) unlinkSync(logFile(job.id))
  • 删除本地文件
    jobs.js:370
    if (existsSync(logFile(job.id))) unlinkSync(logFile(job.id))
扫描于 2026/11/2(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

deepseek-harness ntqq聊天记录导出插件

README

由 DeepSeek 最新模型翻译生成
dsh-qqnt-chat-export 把 Windows / Linux 上的 NTQQ(QQ NT / 9.9.x)聊天记录读出来、搜出来、导出来 —— 一个 DeepSeek Harness 插件包:十六个模型工具 + 一个本地网页界面,支持群聊和私聊,可导出 6 种格式,还能识别截图里的文字、转写语音,并按问题检索聊天记录、给出可点回的引用。 在 Windows 或 Linux 上,从 DeepSeek Harness 会话或本地网页读取、搜索、导出 NTQQ 聊天记录。 界面截图 截图使用虚构数据渲染,不含任何真实聊天内容。 功能 - 十六个模型工具:体检与排障(qqnt_doctor)、建索引(qqnt_index)、统计(qqnt_stats)、后台任务(qqnt_jobs)、取图(qqnt_media)、存储盘点与清理(qqnt_storage)、提取密钥、群列表、会话列表、跨会话搜索、单群 / 单会话 / 批量导出,以及问答检索(qqnt_ask)与主题回看(qqnt_recall); - 本地网页界面(http://127.0.0.1:46728):全部会话列表、组合查询与高亮、图片预览 / 相册、统计、批量导出、导出预设;窄屏(<720px)自动切成单栏——列表与阅读器一次只显示一个,标题旁有「‹ 会话」返回;
展开完整文档(README 剩余 1 节)
dsh-qqnt-chat-export

把 Windows / Linux 上的 NTQQ(QQ NT / 9.9.x)聊天记录读出来、搜出来、导出来 —— 一个 DeepSeek Harness 插件包:十六个模型工具 + 一个本地网页界面,支持群聊和私聊,可导出 6 种格式,还能识别截图里的文字、转写语音,并按问题检索聊天记录、给出可点回的引用。

在 Windows 或 Linux 上,从 DeepSeek Harness 会话或本地网页读取、搜索、导出 NTQQ 聊天记录。

界面截图

截图使用虚构数据渲染,不含任何真实聊天内容。

功能

- 十六个模型工具:体检与排障(qqnt_doctor)、建索引(qqnt_index)、统计(qqnt_stats)、后台任务(qqnt_jobs)、取图(qqnt_media)、存储盘点与清理(qqnt_storage)、提取密钥、群列表、会话列表、跨会话搜索、单群 / 单会话 / 批量导出,以及问答检索(qqnt_ask)与主题回看(qqnt_recall);
- 本地网页界面(http://127.0.0.1:46728):全部会话列表、组合查询与高亮、图片预览 / 相册、统计、批量导出、导出预设;窄屏(<720px)自动切成单栏——列表与阅读器一次只显示一个,标题旁有「‹ 会话」返回;
- 索引与搜索:首次同步建旁路明文索引 index.sqlite,之后查询与导出只读它;关键词走 FTS5 trigram,中文子串也是索引查找;支持多账号索引缓存;
- 看得懂内容:截图里的文字可以 OCR 成可搜索文本,语音消息可以转写成文字,两者都进入搜索与问答的文本池;模型文件按需下载、在「模型与组件」里逐个删除,OCR/转写/向量需要的 Python 组件也在那里一键安装;
- 问得清问题:把会话切成带上下文的片段并做本地嵌入,qqnt_ask 返回「最可能回答这个问题的几段对话 + 引用」,答案由宿主模型(或你自己)来写,引用永远能点回原文;不装嵌入模型也能用关键词检索;
- 分享与保护:昵称 / QQ 脱敏、媒体打包、按天分文件、AES-256 密码 ZIP;
- DSH 侧边栏面板:左侧栏多一个「QQ 聊天记录」图标,主区直接打开同一个页面,不用切浏览器标签。
- 界面:会话列表与阅读、搜索、问答、导出、统计、模型与组件、设置、任务面板全在同一个单页应用里(/ 与 /app/ 是同一页,无构建步骤)。

新界面

同样用虚构数据渲染。

详细功能、面板行为与每个导出选项见 docs/features.md。

安装

dsh plugin 只是把参数转给 profile 目录里的 pnpm,所以直接把 GitHub 仓库当依赖装:

dsh plugin --profile web add github:ariyflow/dsh-qqnt-chat-export

web 换成你要装进去的 profile 名。装好后插件行 qqnt-chat-export 自动启用,八个工具立刻可见,网页在 http://127.0.0.1:46728/。

也可以先克隆到本地,再按目录装(改源码调试时更顺手):

git clone https://github.com/ariyflow/dsh-qqnt-chat-export.git
dsh plugin --profile web add /path/to/dsh-qqnt-chat-export

卸载:

dsh plugin --profile web remove dsh-qqnt-chat-export

插件行的 id 固定为 qqnt-chat-export。如果之前装过旧的 @local/qqnt-chat-export 本地包,先把它 remove 掉,否则两个包会抢同一个行 id。装完重启 DSH,GET /api/qqnt/panel 返回 200 就说明宿主半边已加载。

快速开始

第一次(QQ 保持登录,别关):

1. 打开网页(默认 http://127.0.0.1:46728/),进「设置」看运行环境;
2. 缺依赖时点「默认源安装」或「清华镜像安装」,等独立虚拟环境装好(不碰系统 Python);
3. 点「提取密钥」—— 首次约 1~3 分钟,请耐心等待,期间保持 QQ 登录;也可以在对话里运行 qqnt_extract_key;
4. 回到顶栏点「从 QQ 同步」,约 1 分钟建好索引;
5. 之后随便查、随便导。

以后:默认每 60 分钟自动同步一次(设置页可关或改间隔),也可以随时点「从 QQ 同步」。同步会连 -wal/-shm 一起复制并回放,所以 QQ 一直开着也能拿到最新几条;没有新消息时不重建索引,源库出现删除、回溯或换账号时按数量校验退回全量重建。

环境安装、设置项与清理的细节见 docs/setup.md。

工具

| 工具 | 作用 |
| qqnt_status | 体检:QQ 进程、各账号数据库体积、密钥缓存、Python / SQLCipher / 内存读取权限 |
| qqnt_doctor | 一条命令说清「为什么用不了」:版本、解释器与依赖、密钥、ptrace、索引、派生库 + 下一步该做什么;deep: true 再查组件与模型 |
| qqnt_index | 查索引状态或直接建立/刷新索引(action: "build")。构建在后台跑,超时只回进度、不杀进程 |
| qqnt_extract_key | 从已登录的 QQ 进程内存里取出数据库密钥并缓存 |
| qqnt_list_groups | 群列表:消息数、时间范围、群名 |
| qqnt_export_group | 导出单个群为 txt / sqlite / csv;群可给 group(群号)或 chat(群名,重名时不导出并返回候选)。读的是数据库本体,索引还没建也能用 |
| qqnt_list_chats | 索引里的全部会话(群聊 + 私聊):类型、id、名称、消息数、最后时间;query 可按名字/别名/群号/QQ 过滤 |
| qqnt_search | 跨会话关键词搜索(可限定会话、发送者、日期;senderRegex 把发送者当正则) |
| qqnt_stats | 聚合统计:总量、会话数、发言人数、月度、Top 发言人 / 会话、24 小时分布;过滤条件与搜索同名 |
| qqnt_jobs | 查看 / 启动 / 取消 / 重试后台任务(图片识别、语音转写、分块嵌入、下载模型、安装组件);和网页共用一条队列,两边看到的是同一批任务,缺组件 / 模型时先说缺什么,而不是排一个注定失败的任务 |
| qqnt_media | 某个会话的图片:list 分页列表、get 给出原图路径(不复制)、export 按时间范围拷到下载目录;只算本机已经下载过的图片,不会联网补 |
| qqnt_storage | 盘点工作目录体积(副本 / 索引 / 密钥 / 临时导出 / 构建状态 / 派生库 / 账号缓存 / 模型);cleanup 先预演,confirm: true 才删,删的是网页同一个白名单 |
| qqnt_export_chat | 导出任意会话为 txt / csv / json / md / html / sqlite;chat 可直接给名字(有歧义时拒绝并返回候选),dryRun 先预演,keyword/sender/since/until 只导一部分 |
| qqnt_export_batch | 一次导出最多 200 个会话到一个 ZIP(每会话一份文件 + manifest.json);chatNames 可直接给名字列表,keyword/sender/since/until 对每个会话同时生效 |

qqnt_list_chats / qqnt_stats / qqnt_search / 两个导出工具读的是旁路索引,因此能覆盖私聊和跨会话搜索;索引不在时不用去网页点「从 QQ 同步」,直接调 qqnt_index(action: "build")就行,它会把构建放到后台并把进度报回来。两份导出预设由工具和网页共用(workDir/presets.json),预设名字写错时会列出可用的那几个。

要求

- Windows 10/11 或 Linux(x86_64 / arm64);不支持 macOS;
- 已安装并登录的 NTQQ(QQ 9.9.x / NT 架构);
- 64 位 Python 3,sqlcipher3 装在本插件自己的虚拟环境里即可(密码 ZIP 另需 pyzipper);推荐装 uv,装了就优先用它创建环境;
- Linux 取密钥要能读 qq 进程内存:sudo sysctl -w kernel.yama.ptrace_scope=0 临时放开,导完改回 1。被拒绝时 qqnt_status 会显示状态,qqnt_extract_key 会打印修复命令。

数据目录、手动创建环境、安装引擎与 ptrace 细节见 docs/setup.md。

隐私与安全

- workDir 里是明文:key.txt(明文密钥)、nt_msg.db(约 1 GB 解密副本)、index.sqlite(全部消息的明文副本)。用完建议整个删掉;把 key.txt 给别人等于把整个 QQ 数据库给别人;
- 对 QQ 原始数据只读,不结束 QQ 进程;媒体默认不复制,勾选「含媒体」才把本机已下载的文件复制进 ZIP;
- 网页只绑 127.0.0.1,拒绝非本机 Host 与跨站 POST;侧边栏面板路由也只接受本机回环;
- 密码 ZIP 的密码只经环境变量传给子进程,不出现在命令行、任务列表和日志里;ZIP 内的文件名仍是明文;
- 脱敏只作用于发送者、QQ 号、会话名与清单,不改写正文;诊断包不含消息、昵称、群名、会话 id 和 QQ 号明文。

完整清单(诊断包字段、导出转义、任务列表内容、媒体与 ptrace 的影响)见 docs/security.md。

已知限制

- 只支持本机已登录的 QQ;WSL 里读不到 Windows 侧 QQ 的内存,需要在 WSL 内装 Linux 版 QQ;
- 增量同步不感知「消息被编辑」;QQ 侧删除或回溯会触发一次全量重建;
- 索引占空间:32 万条时 index.sqlite 约 93 MB(含 FTS),账号索引缓存默认再留 2 份;
- 媒体只导出本机已下载的文件,QQ 清理过的找不回来;语音导出 .amr 原文件,不转写;表情不导出;
- 侧边栏面板是 iframe:切走再切回会重新加载,页面状态不保留;DSH 用 HTTPS 打开时浏览器会拦混合内容,面板给提示而不是白屏。

其余边界(多账号、FTS 回退、in: 匹配、端口设为 0、升级迁移等)见 docs/limitations.md。

文档

- docs/features.md — 网页界面、侧边栏面板、导出选项
- docs/setup.md — 安装环境、设置与清理、Linux ptrace
- docs/configuration.md — cordis.patch.yml 字段与设置项
- docs/security.md — 隐私与安全、诊断包字段
- docs/limitations.md — 已知限制与注意事项
- docs/how-it-works.md — 密钥、SQLCipher、Protobuf 与索引
- docs/development.md — 目录结构、测试、file: / link: 安装方式
- docs/wal-notes.md · docs/media-notes.md — WAL 与媒体的实测笔记
- docs/agent-tools-plan.md — 给 Agent 调用的工具扩展计划(未实现)

许可

MIT,见 LICENSE。

本项目仅供学习参考,未获腾讯授权。对于任何用途所造成的一切后果,本人不承担任何责任。

特别感谢

- https://github.com/JackHanXyz/qq-nt-decrypt
- https://github.com/QQBackup/qq-win-db-key
- https://github.com/QQBackup/QQDecrypt
预览分享卡片长什么样 ↓ariyflow/dsh-qqnt-chat-export
分享 · DeepSeek Harness Hub
ariyflow/dsh-qqnt-chat-export

读取、搜索并导出 NTQQ 群聊与私聊记录

这是你的仓库?认领条目

回到顶部