From 91cf33910243ffee5a9c1e0566b6cbb65de14bee Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 29 Oct 2026 21:04:17 -0400 Subject: [PATCH] docs: rewrite the README around what the project is now One file, three roles; three steps to chat (title, password, safety code); a feature table; classic vs decentralized relays; five ways to run a relay from `node index.html` to Cloudflare; limits; security and privacy; FAQ; developer layout. Drops stale parts (web links limited to preset relays, old test counts, old button names). Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01PCUwNSXQdqfDSugmFo4qmM --- README.md | 226 ++++++++++++++++++++++++------------------------------ 1 file changed, 99 insertions(+), 127 deletions(-) diff --git a/README.md b/README.md index f1d7c4a..2b402e1 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,17 @@ # HTML Room -**一个不用注册、不用装软件的加密聊天室。** 打开网页点一下,就能建好一个房间,把文件或链接发给朋友,大家打开就能聊天。 +**一个文件就是一个加密聊天室。** 不用注册、不用装 App:打开网页点一下,得到一个 `index.html`,发给朋友,大家打开就能聊。断网也能创建房间;装了 Node.js 的电脑上运行同一个文件,它就是服务器。 [![Tests](https://github.com/Freecode100Year/htmlroom/actions/workflows/test.yml/badge.svg)](https://github.com/Freecode100Year/htmlroom/actions/workflows/test.yml) [![GitHub Pages](https://github.com/Freecode100Year/htmlroom/actions/workflows/pages.yml/badge.svg)](https://github.com/Freecode100Year/htmlroom/actions/workflows/pages.yml) +[![Release](https://img.shields.io/github/v/release/Freecode100Year/htmlroom)](https://github.com/Freecode100Year/htmlroom/releases) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) -👉 **[马上创建房间](https://freecode100year.github.io/htmlroom/)** (也可使用 [Vercel 入口](https://htmlroom6.vercel.app/) 或 [备用入口](https://chat.nya.je/)) +👉 **[马上创建房间](https://freecode100year.github.io/htmlroom/)**(也可使用 [Vercel 入口](https://htmlroom6.vercel.app/) 或 [备用入口](https://chat.nya.je/)) --- -## 它是什么? - -可以把它想象成一个**带锁的临时小房间**: - -- 🏠 **房间**:你在网页上点「创建房间」,就得到一个只属于你们的聊天室。 -- 🔑 **钥匙**:房间的钥匙就藏在你拿到的**文件**或**链接**里。谁拿到它,谁就能进门。 -- 🔒 **上锁的信**:你们发的每句话都会先“锁”起来再送出去。负责传话的服务器只能看到一堆乱码,看不到内容。 -- 💨 **说完就散**:本项目不会持久保存聊天记录。关掉网页,这个页面里的聊天内容就没了;对方仍可复制或截图。 - -### 一张图看懂 +## 一个文件,三种身份 整个项目就是一个 `index.html`:怎么打开它,它就扮演什么角色。 @@ -29,7 +21,7 @@ flowchart TD F --> A["空白文件 · 浏览器
创建器(可离线)"] F --> B["房间文件 · 浏览器
加密聊天室"] F --> C["node index.html
中继服务器"] - A --> G["生成房间文件
新钥匙,可设口令"] + A --> G["生成房间文件
新钥匙,可设口令和标题"] G -- 发给朋友 --> B B -. "↻ 每个房间文件也能再生新房间" .-> G B <--> R["中继(只转发密文)
wss:// 经典 · bc+ / nostr+ / mqtt+ 去中心化"] @@ -43,173 +35,153 @@ flowchart TD class C,R relay ``` -- **浏览器打开空白文件**:创建器,断网也能生成房间文件。 -- **浏览器打开房间文件**:加密聊天室;房间文件里也带着创建器,可以继续生成新房间。 -- **`node index.html`**:中继服务器;空白文件运行时还会提供创建页面,房间文件运行时不公开自己。 -- 聊天要经过中继,中继只看得到密文。 +- **浏览器打开空白文件**:创建器。网站本身就是它,底部可以「下载离线版」,以后断网也能创建房间。 +- **浏览器打开房间文件**:加密聊天室。文件里还带着创建器,可以离线生成钥匙不同的新房间。 +- **`node index.html`**:中继服务器,零依赖。空白文件运行时还会提供创建页面;房间文件运行时不公开自己,以免泄露钥匙。 +- 聊天时消息经过中继,中继只看得到密文。 ## 三步开始聊天 -**第 1 步:创建房间** -打开 [房间生成器](https://freecode100year.github.io/htmlroom/),直接点「创建房间」就行,其他设置都不用改。 -如果想多一层保险,可以点「随机生成口令」设个密码(相当于门上再加一把锁)。 -还可以给房间起个名字(「房间标题」,最多 60 字),它会显示在浏览器标签页和页面顶部;不填就是「聚众加密聊天房间」。持有房间文件的人以后也能在「生成新文件」里改名,房间和口令不变。 +**1. 创建房间** 打开[创建页面](https://freecode100year.github.io/htmlroom/),直接点「创建房间」。可选: +- **房间标题**:最多 60 字,显示在浏览器标签页和页面顶部;不填就是「聚众加密聊天房间」。 +- **口令**:相当于门上再加一把锁。建议点「随机生成口令」。 -**第 2 步:发给朋友** -点「创建房间」后,你可以: +**2. 发给朋友** 下载 `index.html` 发给朋友,或复制房间链接。设了口令的话,**口令请换一种方式告诉对方**(比如文件用微信发,口令打电话说)。 -- 下载一个叫 `index.html` 的文件,发给朋友;**或者** -- 复制房间链接,发给朋友。 +**3. 核对安全码** 进房后屏幕上会显示一串安全码。请用电话或当面互相念一遍,一致才说明没有人冒充。有人进出、换中继之后,再核对一次。 -如果设了密码,**请用另一种方式**把密码告诉朋友(比如链接用微信发,密码打电话说)。 +> 💡 每次「创建房间」都会生成一个**全新的**房间。就算口令一样,也进不了以前的房间。 -**第 3 步:核对安全码,开始聊天** -大家进入房间后,屏幕上会显示一个**安全码**。请用电话或当面互相念一遍,确认一致,有助于发现密钥被调换;仍需通过这个独立渠道确认对方身份。 +## 功能一览 -> 💡 每点一次「创建房间」都会生成一个**全新的**房间,就算密码一样,也进不了以前的房间。 +| 功能 | 说明 | +| --- | --- | +| 端到端加密 | 每对成员之间做 ECDH + ML-KEM-768 混合密钥交换(抗「先存后解」),每条消息都签名;中继看不到内容,也伪造不了消息 | +| 安全码 | 由全体成员的签名身份生成,用来发现密钥被调换 | +| 离线创建 | 空白文件和每个房间文件都能在断网时生成新房间,结果与官方构建逐字节一致 | +| 文件即服务器 | `node index.html` 直接运行中继,不用安装任何东西 | +| 房间标题 | 创建时可起名;持有文件的人以后可以改名,房间和口令不变 | +| 自定义中继 | 进房前可以改填任意 `wss://` 中继(只对这次打开有效);也能生成换了中继的新文件发给大家 | +| 去中心化中继 | 可以用任意转发服务器、Nostr 中继、MQTT 代理,消息同时走多个中继 | +| 一个房间最多 50 人 | 写死在代码里,所有中继和页面执行同一个数 | +| 不留记录 | 不保存聊天记录;关掉页面,聊天内容就没了(对方仍可截图) | -## 不联网也能创建:一个文件就是整个网站 +## 中继:消息怎么送过去 + +聊天需要中继帮忙转发密文。中继有两类,**不能混用**: + +| 类型 | 写法 | 特点 | +| --- | --- | --- | +| 经典中继 | `wss://relay.example.com`(1–3 个) | 由中继分配成员号、限流和把门;坏了按顺序自动换下一个,连到不同中继的成员暂时看不到彼此 | +| 去中心化中继 | `bc+wss://主机/bc/`、`nostr+wss://…`、`mqtt+wss://…/mqtt`(1–5 个) | 中继只转发,成员自己协商编号和名单;消息同时走全部中继,只要有一个还通就能聊 | -- **每个房间文件都能再生一个新房间。** 打开任意 `index.html`,展开「创建一个新房间」,就能生成钥匙不同、可设新口令的新房间文件。全程在文件里完成,**不需要联网,也不依赖任何网站**;生成的文件和官方构建逐字节一致。 -- **离线创建器。** 网站本身就是一个不带房间的 `index.html`。在网站底部点「下载离线版」保存下来,以后断网也能用它创建房间。 -- 只有聊天时需要连上中继。 +- **在文件里临时换中继**:新创建的房间文件默认允许自定义中继。进房前把「中继服务器」改成自己的地址即可,不改动文件。创建时取消勾选「允许在房间文件里自定义中继」,文件就只能连列出的中继,更严格。 +- **让所有人一起换**:打开房间文件,展开「生成新文件:换中继或改标题」,生成同一房间的新文件发给大家。旧文件也可以在创建页的「已经有房间文件?换一个中继服务器」里转换。 +- **去中心化房间的代价**:没有中继替你挡住乱发数据的人,他们解不开也伪造不了消息,但能浪费流量。公共 Nostr/MQTT 中继能看到 IP 和收发时间。去中心化中继只能广播,人多时流量增长很快,建议控制在 30 人左右;人多的房间用经典中继。 -## 房间文件同时是服务器 +## 自己当中继:从最简单到最完整 -同一个 `index.html`,用浏览器打开是聊天室;装了 [Node.js](https://nodejs.org/)(18 或更新)的电脑上运行它,就是中继服务器,什么都不用安装: +**① 用房间文件本身**(需要 [Node.js](https://nodejs.org/) 18+) ```sh node index.html # 本机中继 + 创建页面 http://127.0.0.1:8080/ node index.html --tunnel # 再加一个免费公网地址(需要 cloudflared) -node index.html --help # 全部选项 +node index.html --help # 全部选项(端口、TLS 证书、允许的来源……) ``` -- 空白创建器运行时,同时提供创建页面和中继,**一个文件就是一个完整的网站**。 -- 房间文件运行时只当中继,**不会把自己当网页公开**,以免泄露房间钥匙。 -- 支持经典房间(`wss://…`)和去中心化房间(`bc+wss://…/bc/`)。其他设备需要 `wss://`:加 `--tunnel`,或用 `--tls-cert`/`--tls-key`。 -- 如果提示 `Unknown file extension ".html"`,说明文件所在目录上层有声明 `"type": "module"` 的 package.json:换个目录,或复制成 `relay.cjs` 再运行 `node relay.cjs`。 -- 只运行你信任或核验过(`node scripts/verify-room-file.mjs 文件`)的文件:运行等于在电脑上执行文件里的代码。 - -## 能做什么,不能做什么 - -| ✅ 可以 | ❌ 不可以 | -| --- | --- | -| 发文字消息 | 发图片、文件、语音 | -| 一个房间最多 **50 人**(写死在代码里) | 保存聊天记录 | -| 每条消息最多 **500 字** | 不联网使用(聊天时必须有网) | -| 断网后自动重连 | 找回已关闭页面里的消息 | - -创建房间时可按优先级填写 **1–3 个经典中继**(以逗号或空格分隔),或改用下文的[去中心化中继](#去中心化房间不依赖任何一台服务器)。首选不可用时会尝试备用,并每 60 秒探测首选是否恢复。页面显示当前中继和在线人数;连到不同中继的成员暂时无法互通,切换后请重新核对安全码。所有成员须使用同一份房间配置。 +启动后会打印可以填进房间的中继地址。其他设备连接需要 `wss://`:加 `--tunnel`,或用 `--tls-cert` / `--tls-key`。 -**在房间文件里直接填自己的中继:** 新创建的房间文件默认允许自定义中继。打开文件后,进房间前可以把「中继服务器」改成任意 `wss://` 地址(也可以填去中心化中继),只对这次打开有效、不改动文件。大家要连同一个中继才能互相看到消息;去中心化中继只要有一个相同即可。创建时在「中继服务器(一般不用改)」里取消勾选「允许在房间文件里自定义中继」,文件就只能连列出的中继,更严格。 +**② 一条命令开单文件中继**:不要域名、不要公网 IP、不要 root -**想改用自己搭的中继?** 打开房间文件,展开「换一个中继服务器」,填入自己的 `wss://` 地址即可生成同一房间的新文件(密钥、口令不变,无需口令);也可在生成器页面的「已经有房间文件?换一个中继服务器」中转换旧文件。把新文件发给所有成员后,大家就在你的中继上聊天,并重新核对安全码。详见 [更换中继](docs/DEVELOPER.md#更换中继迁移到自建中继)。 - -多中继配置使用新版房间格式,旧文件/链接需重新生成。网页房间链接只支持站点预先允许的中继,其他组合请使用下载的房间文件。配置静态网页的多个中继见 [开发说明](docs/DEVELOPER.md#多中继房间)。 - -## 常见问题 - -**微信 / QQ / iPhone 里点开文件没反应怎么办?** -这些 App 的“预览”功能经常无法运行聊天室。请**复制房间链接**,粘贴到 Safari、Chrome 等浏览器的地址栏里打开。 -(目前还没有在 iPhone、安卓手机、微信、QQ 上做过完整的实机测试。) - -**这个文件 / 链接可以随便转发吗?** -**不可以。** 文件和链接就是房间钥匙,转给谁,谁就能进来。请只发给要聊天的人。 - -**设了密码就绝对安全了吗?** -密码越长越乱越好。像 `1234` 这样的短密码,别人拿到文件后可以慢慢猜出来,所以建议使用「随机生成」的密码。 - -**服务器能看到什么?** -看不到聊天内容。但它能知道「有人在某个时间连进了某个房间」以及传了多少数据,也可能因为故障导致消息发不出去。 - -**需要注意什么?** - -- 如果你的手机或电脑本身中了病毒,任何加密都保护不了你。 -- 本项目还没有经过第三方专业机构的安全审计。 -- 想要更放心,就一定要**核对安全码**。 - -## 去中心化房间:不依赖任何一台服务器 - -创建房间时,中继除了填经典的 `wss://…`,还可以填以下三种去中心化中继,最多 5 个,可以混用: - -| 写法 | 是什么 | 谁来提供 | -| --- | --- | --- | -| `bc+wss://主机/bc/` | 只负责转发的中继 | 本项目任何部署(Cloudflare、Docker、一键安装),或下面的单文件中继;任意「同一路径收到的消息转发给其他连接」的 WebSocket 服务器都兼容 | -| `nostr+wss://…` | Nostr 中继 | 公共 Nostr 网络中的中继,或自建 | -| `mqtt+wss://…/mqtt` | MQTT 代理(WebSocket) | mosquitto、EMQX 等,路由器、树莓派都能跑 | - -消息**同时发往全部中继**并自动去重:只要有一个还通,大家就能聊天,也不会出现连到不同中继的人互相看不到的情况。成员编号、在线名单都由各成员自己协商,中继只负责转发看不懂的密文;没有房间密钥的人发来的数据会被直接丢弃。旧房间文件可以用「换一个中继服务器」直接改成去中心化房间,密钥和口令不变。 +```sh +curl -fsSL https://raw.githubusercontent.com/Freecode100Year/htmlroom/main/scripts/relay-quickstart.sh | sh -s -- --tunnel +``` -> 代价:没有中继替你挡住乱发数据的人(他们只能浪费流量,解不开也伪造不了消息);公共 Nostr/MQTT 中继能看到你的 IP 和收发时间,规范要求不保存临时消息,但无法保证。成员变化后请重新核对安全码。部分公共 Nostr 中继要求登录或付费,会在页面上提示被拒绝,换一个即可。 +脚本下载对应平台的单文件中继(强制校验 SHA-256),并通过 Cloudflare 免费临时隧道得到公网地址,最后打印一行 `bc+wss://xxxx.trycloudflare.com/bc/`,填进房间即可。支持 Linux、macOS、FreeBSD、WSL、Termux 和 OpenWrt。Windows 请从 [Releases](https://github.com/Freecode100Year/htmlroom/releases) 下载 `htmlroom-relay-windows-amd64.exe`,装好 [cloudflared](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/) 后运行 `htmlroom-relay-windows-amd64.exe -tunnel`。临时隧道地址每次启动都会变;长期使用请配域名,见[单文件中继](docs/DEVELOPER.md#单文件中继go)。 -### 一条命令开一个中继:不要域名、不要公网 IP、不要 root +**③ 自己的服务器一键安装**:Debian/Ubuntu,需要一个已解析到本机的域名,开放 80/443 ```sh -curl -fsSL https://raw.githubusercontent.com/Freecode100Year/htmlroom/main/scripts/relay-quickstart.sh | sh -s -- --tunnel +curl -fsSL https://raw.githubusercontent.com/Freecode100Year/htmlroom/main/scripts/install.sh | sh -s -- --domain relay.example.com ``` -脚本下载对应平台的单文件中继(校验 SHA-256),并通过 Cloudflare 免费临时隧道得到公网地址,最后打印一行 `bc+wss://xxxx.trycloudflare.com/bc/`,把它填进房间即可。支持 Linux、macOS、FreeBSD、WSL、Termux 和 OpenWrt。Windows 可从 [Releases](https://github.com/Freecode100Year/htmlroom/releases) 下载 `htmlroom-relay-windows-amd64.exe`,安装 [cloudflared](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/) 后运行 `htmlroom-relay-windows-amd64.exe -tunnel`。临时隧道地址每次启动都会变化;长期使用请配域名和 HTTPS,详见 [单文件中继](docs/DEVELOPER.md#单文件中继go)。 - -## 部署自己的聊天室 +脚本检查 DNS、按需安装 Docker,用 Caddy 自动申请 HTTPS 证书,最后给出网页地址 `https://relay.example.com/` 和中继地址 `wss://relay.example.com`。重复运行即更新,`--uninstall` 卸载(保留证书和你自己的文件)。详见[服务器一键安装](docs/DEVELOPER.md#服务器一键安装ubuntudebian)。 -### Cloudflare:前端和中继一起部署(推荐) +**④ Cloudflare:网站和中继一起部署** [![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/Freecode100Year/htmlroom) -登录 Cloudflare,按页面提示创建仓库并部署。前端和 Durable Objects 中继在同一个 Worker 上,部署后打开分配的 `workers.dev` 地址即可创建房间,无需另配 Origin。 +网站和 Durable Objects 中继在同一个 Worker 上,部署后打开分配的 `workers.dev` 地址即可使用。仓库须公开。如果控制台不支持 `JOIN_LIMIT` 绑定,删掉 `wrangler.jsonc` 里的 `ratelimits` 后重新部署即可,人数和消息限制仍然生效。详见 [Cloudflare 部署说明](docs/DEVELOPER.md#cloudflare-workers)。 -仓库须公开。实测按钮可跳转至 Cloudflare 控制台,但当前测试环境被其验证页拦截(403),账户授权及 `JOIN_LIMIT` 绑定兼容性尚未完成线上验证;如果页面不支持该绑定,请在创建的仓库中移除 `wrangler.jsonc` 的 `ratelimits` 项后重新部署。代码已支持缺少该绑定时每个 Worker 实例仅记录一次不含请求信息的警告并跳过加入限流,房间人数和消息大小限制仍生效。详见 [Cloudflare 部署说明](docs/DEVELOPER.md#cloudflare-workers)。 +**⑤ Vercel:只部署网站** -### 有自己的服务器?一条命令搭建私人中继 +[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2FFreecode100Year%2Fhtmlroom&env=HR_PAGES_RELAY&envDescription=WebSocket%20relay%20origin%20such%20as%20wss%3A%2F%2Frelay.example.com&envLink=https%3A%2F%2Fgithub.com%2FFreecode100Year%2Fhtmlroom%2Fblob%2Fmain%2Fdocs%2FDEVELOPER.md) -准备一台 Debian/Ubuntu 服务器(x86_64 或 arm64)、root 或 sudo 权限,以及一个**已解析到服务器公网地址的域名**。域名的 A/AAAA 记录都须指向本机,开放 TCP 80/443。 +部署时填写 `HR_PAGES_RELAY`(例如 `wss://你的中继域名`),作为创建页的默认中继。这一步不会部署中继:要从网站链接进经典中继的房间,还需在中继的 `HR_ALLOWED_ORIGINS` 里加入网站的 HTTPS 来源。从文件打开不受影响。详见 [Vercel 部署说明](docs/DEVELOPER.md#部署前端到-vercel)。 -```sh -curl -fsSL https://raw.githubusercontent.com/Freecode100Year/htmlroom/main/scripts/install.sh | sh -s -- --domain relay.example.com -``` +## 能做什么,不能做什么 -将 `relay.example.com` 换成自己的域名;省略 `--domain` 可按提示输入。脚本检查 DNS、按需安装 Docker,通过 Caddy 自动申请 HTTPS 证书,最后给出网页地址 `https://relay.example.com/` 和中继地址 `wss://relay.example.com`。默认从 GHCR 拉取镜像,安装目录为 `/opt/htmlroom`;重复执行会更新配置并启动服务,不删除证书。 +| ✅ 可以 | ❌ 不可以 | +| --- | --- | +| 发文字消息,每条最多 **500 字** | 发图片、文件、语音 | +| 一个房间最多 **50 人** | 保存或找回聊天记录 | +| 断线后自动重连,消息有送达回执 | 不联网聊天(创建房间可以离线) | +| 每人约 6 秒发一条(防刷屏),多发的自动排队 | 防止对方截图或转述 | -首次镜像尚未发布、未开放匿名拉取,或服务器无法访问 GHCR 时,在命令末尾加 `--build` 从源码构建。仓库维护者可在合并后手动运行 **Publish relay image** 工作流发布首次镜像;需确认包的公开可见性及匿名拉取成功。后续每次推送 tag 会自动发布 amd64/arm64 镜像。源码构建仍需能访问 GitHub、Docker Hub 和 npm。 +## 安全与隐私 -卸载只需重新运行命令,把 `--domain relay.example.com` 换成 `--uninstall`;只移除有安装标记的本项目容器和生成配置,保留证书卷、源码和目录中的自有文件。详细的预检、更新与本机测试见 [服务器一键安装](docs/DEVELOPER.md#服务器一键安装ubuntudebian)。 +- **中继能看到什么**:看不到聊天内容;能看到谁在什么时间连进来、传了多少数据,也可能故意丢弃或延迟消息(回执会显示「未确认」)。 +- **文件和链接就是钥匙**:转给谁,谁就能进来。口令要足够长;像 `1234` 这样的短口令,别人拿到文件后可以离线慢慢猜。 +- **一定要核对安全码**:这是发现冒充和密钥被调换的唯一办法。 +- **核验文件**:`node scripts/verify-room-file.mjs index.html` 会把整个文件(包括内嵌的服务器代码)与可复现构建逐字节比对。用 `node index.html` 运行文件,等于在电脑上执行其中的代码,请只运行你信任或核验过的文件。 +- **局限**:设备本身中了病毒,任何加密都保护不了你。ML-KEM 代码尚未经过独立审计,所以只与 ECDH 混合使用,不单独依赖。本项目也还没有经过第三方安全审计。 -### Vercel:仅部署前端 +详见[安全模型](docs/html-room/security-model.md)和[协议说明](docs/html-room/protocol.md)。 -[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2FFreecode100Year%2Fhtmlroom&env=HR_PAGES_RELAY&envDescription=WebSocket%20relay%20origin%20such%20as%20wss%3A%2F%2Frelay.example.com&envLink=https%3A%2F%2Fgithub.com%2FFreecode100Year%2Fhtmlroom%2Fblob%2Fmain%2Fdocs%2FDEVELOPER.md) +## 常见问题 -部署时填写 `HR_PAGES_RELAY`(例如 `wss://你的中继域名`)。这不会部署聊天中继;请先准备 Cloudflare 或 Node 中继,并在中继的 `HR_ALLOWED_ORIGINS` 中加入 Vercel 网站的精确 HTTPS 来源。使用 `chat.nya.je` 也需要其运营者放行你的域名,不能保证复制前端后就能连接。详见 [Vercel 部署说明](docs/DEVELOPER.md#部署前端到-vercel)。 +**微信 / QQ / iPhone 里点开文件没反应?** +这些 App 的「预览」经常跑不了聊天室。请复制房间链接,粘贴到 Safari、Chrome 等浏览器打开。目前还没有在 iPhone、安卓、微信、QQ 上做过完整的实机测试。 -### 部署支持与验证结果 +**`node index.html` 提示 `Unknown file extension ".html"`?** +文件所在目录的上层有声明 `"type": "module"` 的 `package.json`。换个目录,或复制成 `relay.cjs` 再运行 `node relay.cjs`。 -已提供 Cloudflare 完整部署入口、Vercel 静态前端配置,以及 Ubuntu/Debian 的 Docker + Caddy 一键安装脚本。安装脚本支持 POSIX sh、`--check` 格式预检、DNS 校验、重复运行和 `--uninstall`,拒绝操作无本项目安装标记的已有目录,并通过 HTTPS `/healthz` 验证中继。 +**以前生成的房间文件还能用吗?** +能用。新功能(离线创建、文件里自定义中继、标题)只在新版生成的文件里有。用新版的「换一个中继服务器」转换一次即可,房间和口令都不变。很早的单中继旧版(version 1)文件需要重新创建房间。 -本地验证:38 项项目测试通过(默认跳过的 9 项 Worker 探针另行运行,全部通过),静态前端、网页/文件互通及双中继故障切换浏览器测试、构建检查和 Worker 打包检查通过。Docker 镜像构建与 Compose/Caddy 配置也已在部署功能加入时通过检查。这些检查不代表已完成公网服务器安装或云端部署;Cloudflare 按钮的登录后绑定兼容性仍待验证。 +**进房后一直显示「正在确认其他成员」?** +大家的房间文件要一致,中继也要能连通;用的是经典中继的话,每个人要连同一个。换中继或有人进出后,等几秒让大家重新交换钥匙。 ## 给开发者 -[![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/Freecode100Year/htmlroom) - -按钮将前端和中继部署到同一个 Worker。完成后在 Cloudflare 控制台的 **Workers & Pages** 中打开自己的项目,点击 **Visit / 访问** 或复制 `https://项目名.账户子域.workers.dev` 地址;打开这个网址即可创建房间,无需设置 `HR_ALLOWED_ORIGINS`。部署步骤见[开发文档](docs/DEVELOPER.md#cloudflare-workers),域名隐私与验证方法见 [ECH 说明](docs/ECH.md)。 - -想在自己电脑上运行、搭建自己的服务器,或者了解技术细节?请看: - -- [开发与部署说明](docs/DEVELOPER.md):本地运行、GitHub Pages、Node.js / Docker / Cloudflare Workers 中继、测试命令 -- [安全模型](docs/html-room/security-model.md) · [协议说明](docs/html-room/protocol.md) · [验证记录](docs/VALIDATION.md) - -快速体验(需要 Node.js 22 或更高版本): +需要 Node.js 22 或更新: ```sh git clone https://github.com/Freecode100Year/htmlroom.git cd htmlroom npm ci -npm start +npm start # http://localhost:8080/ +npm test # 单元与中继测试(含 50 人满员测试) +npm run test:browser # 浏览器端到端测试(Playwright) ``` -然后在浏览器打开 。 +主要目录: -## 来源与许可证 +- `html-room/`:客户端与单文件模板。`template.js` 生成整个文件,`file.js` 是浏览器入口,`serve.js` 是内嵌服务器,`mesh.js` 负责去中心化中继。 +- `lib/`:群组加密(`group.js`)。 +- `src/`:Cloudflare Worker 与中继共用的规则;人数上限只在 `limits.js` 定义一次。 +- `server/`:Node 中继。 +- `relay/go/`:零依赖的单文件中继。 +- `scripts/`:构建、核验、安装脚本。 -本项目从 [private-talk](https://github.com/Freecode100Year/private-talk) 中独立出来,详见 [来源说明](docs/PROVENANCE.md)。 +文档: + +- [开发与部署说明](docs/DEVELOPER.md) +- [协议说明](docs/html-room/protocol.md) +- [安全模型](docs/html-room/security-model.md) +- [ECH 与域名隐私](docs/ECH.md) +- [验证记录](docs/VALIDATION.md) + +## 来源与许可证 -采用 [MIT 许可证](LICENSE),保留原作者版权及 [第三方声明](THIRD_PARTY_NOTICES.md)。 +本项目从 [private-talk](https://github.com/Freecode100Year/private-talk) 中独立出来,详见[来源说明](docs/PROVENANCE.md)。采用 [MIT 许可证](LICENSE),保留原作者版权及[第三方声明](THIRD_PARTY_NOTICES.md)。