Skip to content

Releases

v2.1.0

Choose a tag to compare

@github-actions github-actions released this 03 Nov 13:53

v2.1 全新设计了网页 UI:房源浏览、账号设置和管理后台统一成收件箱式界面,公共页面
换成单独的外壳,并补齐手机端、键盘操作和中英文文案。另外区分了官方站点与自部署
副本,简化了本机自用的启动方式。监控、抓取与预订逻辑没有变化;OurDomain、
OurCampus 与 Xior 的预订验证移到 v2.2。

全新设计的网页 UI

  • 收件箱式工作区(e52a89a)

    收件箱、日历、地图和统计共用「侧栏 + 列表 + 详情」的外壳,首页就是收件箱,
    未登录时以访客身份进入。普通用户可以在「我的匹配」和「全部房源」之间切换,
    已读状态按用户单独保存。旧的 /listings 列表页已删除。

  • 账号设置与管理后台(e52a89a)

    账号设置按分组和条目编辑筛选、通知、账号与偏好。用户、公告、运行设置、客户端、
    数据健康、日志、崩溃和系统信息页迁到同一外壳,公告管理拆成独立页面;运行设置
    区分已保存、已应用、被环境变量覆盖和需要重启。

  • 公共页面(e52a89a、da2535f)

    登录、分享、邮箱验证、错误页、帮助、法律、赞助和使用指南改用公共页外壳。
    使用指南按新界面重写。字体、图标与 Chart.js 改为自托管,CSP 随之收紧。

  • 手机端与可访问性(cb04487)

    手机侧栏关闭时不再进入 Tab 顺序,展开时锁定焦点,Esc 关闭并回到菜单按钮;
    房源和用户详情在刷新、返回时保持正确状态;日历窄屏完整显示「今天」,日期的
    辅助名称标明今天;登录密码字段使用独立标签。

  • 语言与细节(e52a89a、cb04487)

    数据健康的原因说明、英文房源状态(Book 显示为 Available)、邮箱验证页、
    登录失败与限流提示、用户管理提示都按界面语言显示。登录失败后保留原本要去的页面;
    启停、调整用户优先级后继续选中该用户。分享页不再显示占位的入住日期。

自部署

  • 官方站点与自部署的区分(e52a89a、74a7ee3)

    不在 flatradar.app 上运行的副本,会在品牌名和页面标题后标注「自部署版本」,
    管理员首次进入时看到免责与禁止商用的提示。自部署副本不显示赞助入口(/donate
    返回 404)和 App 推送设置;入站邮件转发按实际收件地址显示,不再写死官方邮箱。

  • 本机一条命令启动(83588b6)

    python launcher.py 会在首次运行时生成 .env、下载浏览器内核,并同时启动面板与
    监控;关闭终端时一起停止。README 与使用指南的快速开始分成「在自己电脑上用」
    (Python)和「公网部署」(Docker)两种。

条款与隐私

  • 使用条款明确禁止商用和再分发房源数据,第 9 节限定为以商业目的修改、转售、再许可
    或再分发;条款与隐私政策中的「收藏」改为「房源已读记录」。
  • App 不再支持用 Holland2Stay 网站账号密码登录,只认本地 App 密码。

测试

  • 删除只检查页面标记的测试,按新界面重写数据测试,保留行为测试,并新增覆盖三种
    身份 × 两种语言的页面冒烟测试(1ce706c、8b54235)。

升级注意

  • 数据库迁移在启动时自动执行:新增 listing_reads 表,删除 user_configs 的
    allow_h2s_login 列。
  • API 契约升到 1.26.0:/me/export 增加 listing_reads[],用户配置去掉
    allow_h2s_login。曾用 Holland2Stay 账号登录 App 的用户需要先设置 App 密码。
  • 条款文本在启动时读入,部署后需要重启 Web 进程(重建容器即可)。
  • 官方站点按请求 Host 或 PUBLIC_BASE_URL 识别;反代改写了 Host 的官方部署,
    需要确认 PUBLIC_BASE_URL 设置正确。

已知限制

  • Xior、OurDomain、OurCampus 的 RENTCafe 预订仍未开放,验证移到 v2.2。
  • 新界面只在桌面与模拟手机视口的 Chromium 中验收过;Safari、Firefox、真实手机和
    屏幕阅读器尚未验证。
  • 英文数量文案仍有单复数问题(如 1 listings)。
  • Holland2Stay 取消预留的路径尚未用真实操作验证;Plaza 的 DTH 房源不自动应征。
  • 单机 SQLite,不支持多实例水平扩展。

v2.0.0

Choose a tag to compare

@github-actions github-actions released this 01 Nov 19:08

v2.0 以监控正确性、可维护性和回归保障为目标,不新增平台或客户端功能。主要变化
是把 monitor 的单体实现按阶段拆成独立模块、统一配置解析与运行时快照、补齐通知与
预订的故障边界,并把 CI 与文档纳入发布流程。自动预订仍只开放 Holland2Stay 与
Plaza(Plaza 需用户单独启用)。

架构与可维护性

  • monitor 按阶段拆分(79e7a0d、32207ae、57f5afd、0ab2195、5e4d3f3)

    run_once() 拆成抓取、预热、后处理三段;startup / stale / dispatch / telemetry
    各自独立;抓取失败处置移到 round_failures,预订流程移到 booking_round,
    通知与事件重放移到 notify_round。平台标识、显示名、抓取器入口和基础能力统一
    登记在 SourceSpec。monitor.py 只剩主循环与阶段编排。

  • 运行时状态收进 RuntimeState(57f5afd)

    熔断、自适应节流、持久化退避、预加载缓存与竞败重试队列有了单一归属;热重载和
    测试隔离不再依赖直接修改模块全局。

  • 配置解析收口(7de759d、f65de0f、8de2c73、38e926f、5677216)

    load_config() 改走 target_config 严格解析,布尔与整数统一到 env_utils,
    已登记平台的解析器补齐。热重载先构造并校验候选配置,失败保留旧配置;坏配置由
    测试矩阵覆盖,不再静默回落到默认值。

  • 存储层收口(25663bf、1ebbe4d)

    路由中散落的 SQL 与 feedback 建表移入 mstorage;GDPR 导出与反馈写入成为
    存储层方法。Web 侧的登录、注册、测试通知、访客房源、崩溃上传与用户名枚举统一
    到 app/rate_limit.py,空闲键定期清理。

  • 测试与 CI(0fa476a、f42b0b7、4467480)

    合并重复测试、参数化规则表、清理失效用例;push / PR 运行 Ruff 与 pytest;
    CI 安装 Node,使浏览器端 JS 的执行路径不再被跳过。

监控正确性

  • H2S REST 快速通道(09f253e、83d3ddb)

    在自家线路上按可配间隔观察 REST 信号,发现新放出的房源时叫醒主循环,只补抓
    Holland2Stay,而不是等下一轮全量调度。

  • 首次全量扫描计时(5dc89ce):计时器在全量扫描真正完成后才推进,避免第一轮
    把「计划做全量」当成「已经做完全量」。

  • 阶段边界与故障隔离(faaeb55、dcba13e、c86f8b6、dc0d905)

    抓取、预订提交、通知与收尾的异常不再互相带走;平台调度与浏览器工作进程超时后
    可回收恢复。

通知与预订

  • 状态变更按事件主键标记(5487294):未完成通知可重放,影子平台过滤在重放
    之后执行,不再依赖 listing 级的 notified 标志。

  • SSE 短期票据(fdcebbb):EventSource 客户端用 60 秒票据连接,不再接受 URL
    中的长期 token。

  • 公告投递记录(7d4f9a4):逐用户、逐渠道记录投递结果,失败与未完成项可精确
    补发。

  • 预订保护与结果等待(002ae15、08f6f51):Holland2Stay 按账号、Plaza 按
    账号和房源保留不确定结果保护;预订结果等待增加墙钟上限,后台任务卡住时不会拖住
    整轮。

  • Holland2Stay 当前 /api/booking 路径已用真实账号走通到付款链接。Xior /
    OurDomain / OurCampus 的 RENTCafe 预订仍未对用户开放,验证列入 v2.1。

部署与文档

  • docker-compose.yml 默认传 TRUSTED_PROXY_HOPS=1,反代后限流与日志能看到真实
    客户端 IP;直接暴露端口时应在 .env 设为 0。新增
    DEPLOYMENT.md 说明 Caddy、TLS、端口、日志与自有反代。
  • 文档重写:ARCHITECTURE、H2S、SCRAPING_RECON、XIOR、OURDOMAIN、PLAZA
    改为当前状态;新增 RENTCAFE.md 承接三平台共用预订流程;API.md 增加目录并
    修正响应字段漂移,openapi.json 升到 1.25.0;FUTURE_PLAN 只保留未完成项,
    并新增 v2.1–v2.5 的 Web 界面规划。

升级注意

  • 数据库迁移在启动时自动执行(新增 feedback 表),无需手工操作。
  • API 契约 1.25.0 为增量变更,既有客户端不受影响。
  • 部署方式与数据库位置未变;仍是单机 SQLite 与 Web / monitor 双进程。

已知限制

  • Xior、OurDomain、OurCampus 的 RENTCafe 预订未开放,验证在 v2.1 进行。
  • Holland2Stay 的取消预留路径尚未用真实操作验证。
  • Plaza 的 DTH 房源不自动应征(确认框的影响范围未查明)。
  • 单机 SQLite,不支持多实例水平扩展。

v1.44.0

Choose a tag to compare

@github-actions github-actions released this 21 Sep 19:40
Release v1.44.0

v1.40.0

Choose a tag to compare

@github-actions github-actions released this 15 Sep 15:59
v1.40.0 — OurCampus 预订侧就绪(未开放);TLS 指纹按实测重排

OurCampusBooker 写好,止于开始申请,未注册:「开始申请能占住单元」还没实测。
对照真实响应修掉 onclick 双引号解析缺陷、抽签单元不开始申请、单元表 403 时冷却
指纹重开会话。

SecureRC 此刻只放 chrome150 这一个桌面 Chrome,146 及以前全部 403;指纹池改为
Safari 打底,curl_cffi 升到 0.16.3。

v1.39.0

Choose a tag to compare

@github-actions github-actions released this 15 Sep 14:34
v1.39.0 — 楼盘过滤;OurCampus 抽签不再报成可订

过滤器加「楼盘」:只要这栋楼里的任何一间,通知与自动预订两侧都生效。

自动预订的「能通知到」把推送也算进去——只用 App 的用户此前永远产生不了候选;
启动摘要的三条假警告改为与闸同一判据。

OurCampus 先到先得与抽签并存,两者只差按钮文字;判据此前只看按钮在不在,
Join Lottery 的单元因此按可订推送。留档文件改为只记变化、满了轮转。

v1.38.0

Choose a tag to compare

@github-actions github-actions released this 10 Sep 12:07
v1.38.0 — Plaza 自动应征

先修掉抓取侧「一多半房源报错了状态」的缺陷(49 条荷兰住宅里 31 条根本应征不了,
却按可预订推送),再把自动应征做到端到端跑通并放进面板,默认关。

DTH 一律不应征且刻意没做成开关:确认框那句「不再收到其它 offer」的范围站点没有
说明,事实未知时两边代价不对称。

过程中有五处「错了不报错」的实现缺陷,全部由真实账号的端到端验证暴露——在那之前
单元测试是全绿的。

另含运河屋图标、登录页无底色标识、README 平台数修正。

v1.37.0

Choose a tag to compare

@github-actions github-actions released this 09 Sep 21:49
常驻浏览器泄漏事故,及它暴露出的 close() 根因

自 v1.36.0 以来六次提交,六条,覆盖浏览器资源、API 契约与规划。

主线是一次生产事故与两层修复。v1.36.0 上线的下单常驻浏览器在生产里泄漏 Chromium:
每次建立成功后 5–6 分钟被判死,而 close() 收不掉进程。18 小时泄漏 5 套,容器内存
1.14 → 1.73 GiB(上限 2 GiB),随后 Holland2Stay 熔断、Xior 渲染器每轮卡死 600 秒。
它没能加快下单,反而拖垮了两个抓取源。

第一层是关掉它——开关放 RUNTIME_KEYS 而不是 TUNING_KEYS,因为只有前者能在不重新
部署的情况下关闭;一个救火用的开关,如果关它本身要走一次部署,它在最需要的时候就
是没用的。

第二层是根因:close() 对着一根已经断掉的通道调用,既不报错也不生效,紧接着却把
profile 槽位锁放了,于是下一次开浏览器拿到同一个目录、删掉还活着那个实例的单实例
锁,两个 Chromium 同开一个 profile。这条链子自我维持,且不属于常驻浏览器——它属于
所有 BrowserFetcher 使用者,抓取侧只是重建频率低得多而一直没暴露。

另有一次 API 文档全量核对:查出四处漂移,无一会使既有测试变红。以及 GET /listings
的 sort,连带把「默认顺序」和「id 兜底」写进契约——分页此前建在一个从未被承诺的
顺序上。

v1.36.0

Choose a tag to compare

@github-actions github-actions released this 08 Sep 09:07
下单不再在房源翻牌那一刻现过 Cloudflare

自 v1.35.0 以来二十二次提交,十九条,覆盖自动预订、容量与会话、客户端仓库拆分、
抓取平台、配置一致性与 App Store 发布。

主线是自动预订:过 CF 挑战属于浏览器(中位 16.5s),登录属于用户(~1.5s),而
此前每次抢房都在房源翻牌那一瞬间从零现过一次挑战。留存日志里快速通道触发 4 次、
prewarmed=no 4 次、成功 0 次。现在常驻一个已过挑战的浏览器,只借给本轮优先级最高
的那个用户,其余维持原行为。

本批多数条目共享同一种缺陷形状:判据成立,但它无法与故障区分。8 线程的 gunicorn
在零错误日志下让全站打不开;只查子串的链接测试对换仓库完全无感;Plaza 的
「未登记城市」WARNING 会被修复动作本身关掉;注册表加了城市而订阅串没跟上时,抓取
不发生而警告已消失。逐条的修复方式统一为:先构造一个复现原缺陷的变异,确认判据
变红,再提交。

v1.34.0

Choose a tag to compare

@github-actions github-actions released this 02 Sep 13:52
缺陷清理:二十一处修复,零新功能

横跨主循环、存储、抓取、预订、通知与 Web 六层。会造成静默数据损坏或静默漏推的
十一处,外部可触发的四处——全部不报错。

三种共同形状:「认不出」被当成一个确定的答案;爆炸半径没有边界;同一段逻辑写两遍
只改一处。

其中四处的测试原本是绿的,因为它们把 bug 钉成了期望行为。

3982 → 4062 条测试,每处修复都做过变异验证。

v1.33.0

Choose a tag to compare

@github-actions github-actions released this 02 Sep 10:19
接入 Plaza(影子期)

第七个平台,也是第一个非自营运营商的来源——多家机构把房源挂在同一套 Zig/Hexia
系统上,一个匿名 POST 就覆盖十个荷兰城市。

接它的理由是分配机制:荷兰住宅 49 条里 31 条是当场成交,站点自己的确认框写着
「definitief boeken…geen andere aanbieding meer krijgt」——点下去房子就是你的,
代价是放弃其它全部 offer。另 18 条是「Snelle reageerder」,明写不设等候名单。
两类都奖励速度。

上线走影子模式:照常抓取入库、参与收敛与统计,不发任何用户渠道通知。

顺带把仪表盘的覆盖范围横幅按平台分组,并标出影子来源——分组之后才看出十七个
城市里有十一个只由影子 source 覆盖,横幅却在承诺一个不会兑现的推送。