Skip to content

Repository files navigation

chat-share-proxy

把 Claude / ChatGPT 的分享对话,完整搬进你的内网与离线环境。

自托管的 AI 对话存档与高保真阅读器 —— 连同图片、附件、思考过程、可视化工件,以及 20+ 种文件格式的浏览器内预览。

Kotlin Ktor Vue Vite TypeScript SQLite Chrome MV3


这是什么

很多团队的内网用户无法直接访问公网,却需要查阅 claude.ai(及 chatgpt.com)上的对话;个人也常希望把有价值的 AI 对话永久留存、离线可读,而不是任由分享链接过期。

chat-share-proxy 解决的就是这件事:一个浏览器扩展在你已登录的源站标签页里,通过官方 API 取回对话的原生分享 JSON(连同图片、附件、工具产物),上传到你自己部署的服务端;内网/离线用户登录后,由一个 Vue 3 单页应用在浏览器端把它逐字高保真地重新渲染出来 —— Markdown、代码高亮、数学公式、思考过程、可视化工件,乃至几十种文件的在线预览,一个不少。

一句话架构:对话 = 源站原生 JSON 原样入库,服务端零转换,渲染全在浏览器。


✨ 亮点

  • 🗂️ 完整存档,而非截图 —— 抓取的是对话的原生 JSON,结构化保存。换模型、改 UI、链接过期都不影响你已存下的内容。
  • 🎨 高保真渲染 —— 手写的 Markdown 渲染器(GFM)、highlight.js 代码高亮、KaTeX 数学公式、思考过程(thinking)折叠时间线、visualize 可视化工件、图片缩略图 + 灯箱、网页引用悬浮卡片,逐一对齐源站观感。
  • 📂 20+ 种文件预览,全在浏览器内 —— 代码、Office、PDF、压缩包、数据库、医学影像、抓包、邮件、网页存档……点开即看,无需下载,字节从不在服务端解析或内联执行(详见下表)。
  • 🤖 同时支持 Claude 与 ChatGPT —— 两套独立解析栈,复用同一套渲染与文件预览,含分支切换、思考过程、网页引用。
  • 🏠 公开首页 —— 无需登录即可了解项目、浏览公开会话,支持标题/摘要搜索、Claude / ChatGPT 筛选和分页。登录后的会话库位于 /conversations。
  • 🔗 一键公开分享 —— 所有者开启分享后,会话自动展示在首页,并生成独立的分享链接;访客免登录只读访问。取消分享会立即移出公开目录并使旧链接失效。
  • 🔄 多环境同步 —— 把开发环境备份好的对话,一键推送到线上环境(复用对端 ingest 接口,对端零改动)。
  • 📦 标准 ZIP 批量导出 —— 列表中多选会话,一次导出原始 JSON、已转存文件、SHA-256 与逐消息文件绑定;下游无需按文件名猜关联。协议见 docs/session-export-format.md。
  • 👥 用户与权限管理 —— Session + Bearer 双鉴权、自助 API Token、管理员后台(建号 / 启停 / 改角色 / 重置密码),外加按用户私有的标签体系。
  • 📊 访问分析 —— 公开分享打开、登录查看、登录成功三类有意义访问的离线统计(ip2region 区域解析 + 零依赖 UA 解析),fire-and-forget 不阻塞响应。
  • 🔒 安全优先 —— 上游字节一律按附件下载、绝不内联;沙箱 iframe + 注入 CSP 渲染 HTML;严格的路径穿越防护;公开分享是唯一免鉴权数据面,仅靠能力令牌(详见安全设计)。
  • 🧩 零内容脚本的扩展 —— 读取源站只走它自己的 API(同源 fetch + 你的登录 cookie),不注入内容脚本、不抓取 / 解析页面 DOM。

📂 文件预览能力

对话里的任何附件、工具产物、交付文件,只要是下表中的类型,都能在右侧分栏直接预览 —— 全部在浏览器端解析渲染,服务端零转换,上游字节只当数据解码、绝不内联执行。

类别 支持格式 预览方式
代码 / 文本 30+ 种语言(js/ts/py/rs/kt/java/c/cpp/go/php/swift/scala/sql/sh/yaml/toml/json/xml…),及 txt/log/csv/env/Dockerfile/Makefile 等 语法高亮(highlight.js)+ 行号栏
Markdown .md .markdown 文档渲染(手写 GFM)+ KaTeX 数学公式 + YAML frontmatter 卡片 + 渲染/源码切换
HTML .html .htm 沙箱 iframe 渲染(注入 script-src 'none' CSP)+ 源码切换 + 新标签页全屏
SVG .svg 图片渲染 + XML 源码切换
图片 png · jpg · gif · webp · bmp · ico · avif · apng · jfif 缩略图 + 灯箱缩放/拖动
视频 mp4 · webm · mov · mkv · avi · m4v · ogv 弹窗播放
压缩包 zip · 7z · tar 家族(tar/gz/tgz/xz/bz2/br)· rar 浏览器内解压、浏览目录、递归预览包内文件(含包内 PDF / 图片)
PDF .pdf 逐页渲染到 canvas(pdfjs-dist),垂直滚动
Word .docx 分页、纸张式渲染(docx-preview)
Excel .xlsx .xlsm 每个工作表一张表格 + 标签栏(exceljs)
PowerPoint .pptx .pptm .ppsx 可滚动的幻灯片列表(@aiden0z/pptx-renderer)
SQLite 数据库 sqlite · db · sqlite3 · db3 · sqlitedb 表选择器 + 分页数据网格 + SQL 控制台(sql.js WASM)
医学影像 DICOM .dcm .dicom canvas 渲染 + window/level 调窗(dicom-parser + WASM 编解码)
抓包 HAR .har 可筛选的请求列表 + 每请求 headers / query / cookies / bodies
网页存档 .mht .mhtml 还原保存的整页(资源改写为 blob URL,沙箱 iframe)
邮件 .eml 头部卡片 + 正文(HTML 沙箱)+ 附件
思维导图 .opml · .mm(FreeMind / Freeplane) 交互式 SVG 思维导图 + 源码切换
二进制对象 .so(含 libfoo.so.1.2.3)· .dll 解析 ELF / PE,列出函数符号(可搜索)

💡 想先体验文件预览?点击首页导航的「文件预览」或页面下方的「打开文件预览」即可进入 /dev/viewer,无需登录,把本地文件拖进去即可 —— 纯客户端解析,不上传所选本地文件。也可只运行 pnpm dev 独立使用,无需部署后端。

🛠️ 大量解析器是零依赖手写的(zip / 7z+LZMA / bzip2 / ELF/PE / HAR / MIME(eml·mht) / 思维导图),重型依赖(Office、PDF、DICOM、Brotli/RAR/SQLite 的 WASM)则全部按需懒加载 —— 不打开对应文件就不会下载,主包保持精简。


🖼️ 截图

截图待补充。建议展示:会话列表 · 对话明细(思考过程 + 数学公式 + 工件)· 文件预览分栏 · 公开分享页。


🏗️ 架构

三个解耦组件:

组件 技术栈 职责
server/ Kotlin 2.4 · Ktor 3.5 · Exposed 1.3 · SQLite 鉴权、ingest、存储,提供纯 JSON 接口 + 同源托管前端构建产物(不直出任何 HTML)
frontend/ Vue 3.5 · Vite 8 · TypeScript 线上 viewer 本体:列表 + 明细 + 登录 + 分享 + 后台 SPA,渲染全在浏览器
extension/ Chrome MV3(免构建) 在源站标签页内同源抓取原生分享 JSON 与文件,上传至服务端;支持单页备份、粘贴上传、批量全量备份

数据流:

flowchart LR
    A["claude.ai / chatgpt.com<br/>分享对话"] -->|"扩展在源站标签页内<br/>同源 fetch(带登录 cookie)"| B["Chrome 扩展"]
    B -->|"POST /api/ingest<br/>原生 JSON + 文件字节"| C["server<br/>(Kotlin · Ktor)"]
    C -->|"raw.json 落盘<br/>header 列入库<br/>文件字节落盘"| D[("SQLite + 磁盘")]
    U["内网 / 离线用户"] -->|"登录 (session)"| C
    C -->|"同源托管 SPA"| F["Vue 3 Viewer"]
    F -->|"fetch 原生 JSON"| C
    F -->|"浏览器端高保真渲染"| G["对话 + 文件预览"]
Loading
  • 服务端把对话的原生 JSON 落盘({dbDir}/conversations/{uuid}/raw.json),数据库只存顶层 header 字段列;文件字节落盘({dbDir}/files/{uuid}/{path})。主键就是对话自己的 uuid,无 slug、无代理 id。
  • 登录用户可在会话列表复用批量选择模式下载 ZIP(POST /api/conversations/export):服务端先整批校验权限与大小,再逐项流式写出;根目录 import-metadata.json 固定记录 provider key、消息 binding、实际路径、大小和 SHA-256。
  • 前端 pnpm build 产物在 frontend/dist,由 server 的 Gradle 构建自动同步进 server/src/main/resources/web/,Ktor 用 staticResources 同源托管,未匹配的非 API 路径 history 回退到 index.html。
  • 更完整的架构、数据模型、端点与踩坑见 AGENTS.md;前端渲染管线见 frontend/ARCHITECTURE.md。

🚀 快速开始

需要 JDK 21、Node.js + pnpm、以及 Chrome / Chromium。

1. 后端 server

cd server
./gradlew build        # 前端 pnpm build + 编译 + 测试 + 打 fat jar(SPA 一起打进去)
java -jar build/libs/*-all.jar   # 启动,默认 http://localhost:8080 ,/health 返回 "ok"

./gradlew build 会先在 frontend/ 跑一次 pnpm build(首次自动 pnpm install),把产物同步进 server/src/main/resources/web/ 再打包,所以拿到的 jar 总是带最新 viewer。前端没改动就跳过(Gradle UP-TO-DATE);机器上没有 Node 时加 -Pfrontend=false 只构建后端。

首次启动可用环境变量引导第一个管理员(见配置):

CSP_SESSION_KEY=$(openssl rand -hex 32) \
ADMIN_USERNAME=admin ADMIN_PASSWORD='change-me' \
java -jar build/libs/*-all.jar

2. 前端 frontend

cd frontend
pnpm install
pnpm dev      # 开发预览 http://localhost:5173 (/api 代理到后端 :8080)
pnpm build    # 产物到 dist/ —— server 的 Gradle 构建会同步进 resources/web 供后端同源托管

想更新线上 viewer:直接 ./gradlew build(自动跑前端构建并把产物打进 fat jar),不必先手动 pnpm build。 无后端时前端会回退内置样例对话,可直接预览;/dev/viewer 还能拖本地文件试各类文件预览。

3. 浏览器扩展 extension

  1. 打开 chrome://extensions,开启右上角 开发者模式。
  2. 点 加载已解压的扩展程序,选择本仓库的 extension/ 目录。
  3. 在扩展选项里配置一个或多个目标环境(服务器地址 + API Token),Claude 文件转存还需填一次组织 ID。
  4. 在 claude.ai 对话页打开扩展 → 备份本页对话,或粘贴 JSON 上传,或批量全量备份。

获取 API Token:登录内网 viewer 后,在浏览器 Console 执行 fetch('/api/tokens',{method:'POST',headers:{'content-type':'application/x-www-form-urlencoded'},body:'name=extension'}).then(r=>r.json()).then(t=>console.log(t.token)),把返回的 csp_…(只显示一次)填入扩展。详见 extension/README.md。


⚙️ 配置

服务端通过环境变量配置:

变量 默认 说明
CSP_PORT 8080 监听端口
CSP_DB_PATH ./data/chat-share-proxy.sqlite SQLite 路径;其所在目录还存放 conversations/、files/ 与 ip2region 数据
CSP_SESSION_KEY (随机) 会话 cookie 加密密钥,生产务必固定设置
CSP_COOKIE_SECURE true 纯 HTTP 部署需设为 false
CSP_PUBLIC_BASE_URL — 对外基础地址(用于拼接公开分享链接等)
CSP_IP2REGION_XDB_V4 / _V6 {dbDir}/ip2region_v4.xdb·_v6.xdb ip2region 离线区域库路径,缺失则访问分析的区域留空
CSP_EXPORT_MAX_CONVERSATIONS 200 单次 ZIP 最多导出的会话数(请求会先去空、去重)
CSP_EXPORT_MAX_FILE_BYTES 104857600 ZIP 中单个实际文件的最大字节数(默认 100 MiB)
CSP_EXPORT_MAX_TOTAL_BYTES 2147483648 单次导出的逻辑总字节上限(原始 JSON + 文件 + metadata,默认 2 GiB)
ADMIN_USERNAME / ADMIN_PASSWORD — 冷启动种子:仅当二者非空且该用户名不存在时创建一个管理员(幂等、只增不改)。日常增删改用户走 /admin 后台

🔒 安全设计

这是一个会把外部不可信字节搬进内网的工具,安全是第一性的:

  • 上游文件字节永不内联渲染 —— 下载端点强制 application/octet-stream + attachment + Content-Security-Policy: sandbox。所有预览都在浏览器端把字节当数据解码,HTML/SVG/邮件正文/网页存档一律在 sandbox iframe(无 allow-scripts)+ 注入 CSP 下渲染,脚本绝不执行。
  • 严格的路径穿越防护 —— 上游 uuid 与文件 path 均不可信,任何"路径 → 磁盘位置"的映射都经过统一的词法 + canonical 双重校验(拒 ..、分隔符、盘符冒号、控制字符,兼防符号链接逃逸)。
  • 导出归档同样防穿越 —— ZIP entry 独立规范化并处理重名,禁止绝对路径、.. 与控制字符;原始 provider key 只写入 JSON metadata,不直接作为未经检查的 entry 名。
  • 鉴权取信于服务端 —— Session(加密 cookie)+ Bearer(Token,仅存 SHA-256 哈希)双方案;提交者身份永远取自 principal,绝不信任客户端字段;管理员接口在每个 handler 二次校验角色,并有"不能停用/降级/删除自己或最后一个管理员"等护栏。
  • 公开分享是唯一免鉴权数据面 —— /api/share 仅列出已开启分享的会话,返回分享令牌、标题、来源、摘要和分享时间。详情仍按独立随机令牌寻址,与真实 uuid 解耦,吊销即删行;未分享会话、管理接口仍需鉴权。开启分享即允许访客从首页发现该会话。
  • 扩展不碰页面 DOM —— 只调用源站自己的 API(同源 fetch + 你的登录 cookie),无内容脚本。

🧰 技术栈

  • 后端:Kotlin 2.4 · Ktor 3.5(Netty)· Exposed 1.3(DSL)· SQLite + HikariCP · BCrypt · kotlinx.serialization · ip2region
  • 前端:Vue 3.5 · Vite 8(Vite+/Rolldown/Oxc)· TypeScript 5.8 · vue-router · 手写 Markdown 渲染器 · highlight.js · KaTeX;按需懒加载 pdfjs-dist / docx-preview / exceljs / @aiden0z/pptx-renderer / dicom-parser / sql.js / brotli-dec-wasm / node-unrar-js
  • 扩展:Chrome MV3,原生 JS,无构建步骤

⚖️ 免责声明

本项目是个人备份 / 内网阅读工具,仅用于抓取你自己有权访问的分享对话:通过源站官方 API、在你已登录的浏览器标签页内同源请求、携带你自己的 cookie 完成,不破解、不绕过任何鉴权、不注入内容脚本、不抓取页面 DOM。

本项目与 Anthropic、OpenAI 无任何关联,不代表其官方立场。请遵守相关平台的服务条款与你所在地的法律法规,使用风险自负。


📄 许可

本仓库尚未附带 LICENSE 文件。若计划开源推广,建议补充一个许可证(如 MIT)后再公开。


🙏 致谢

感谢以下开源项目:Ktor · Exposed · Vue · Vite · highlight.js · KaTeX · pdf.js · docx-preview · ExcelJS · sql.js · dicom-parser · ip2region 等。

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages